Page MenuHome GnuPG

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/LICENSES b/LICENSES
index f6733a69..8f953e2c 100644
--- a/LICENSES
+++ b/LICENSES
@@ -1,238 +1,238 @@
Additional license notices for Libgcrypt. -*- org -*-
This file contains the copying permission notices for various files in
the Libgcrypt distribution which are not covered by the GNU Lesser
General Public License (LGPL) or the GNU General Public License (GPL).
These notices all require that a copy of the notice be included
in the accompanying documentation and be distributed with binary
distributions of the code, so be sure to include this file along
with any binary distributions derived from the GNU C Library.
* BSD_3Clause
For files:
- cipher/sha256-avx-amd64.S
- cipher/sha256-avx2-bmi2-amd64.S
- cipher/sha256-ssse3-amd64.S
- cipher/sha512-avx-amd64.S
- cipher/sha512-avx2-bmi2-amd64.S
- cipher/sha512-ssse3-amd64.S
#+begin_quote
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.
#+end_quote
For files:
- random/jitterentropy-base.c
- 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.
#+end_quote
* X License
For files:
- install.sh
#+begin_quote
Copyright (C) 1994 X Consortium
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not
be used in advertising or otherwise to promote the sale, use or other deal-
ings in this Software without prior written authorization from the X Consor-
tium.
#+end_quote
* Public domain
For files:
- cipher/arcfour-amd64.S
#+begin_quote
Author: Marc Bevand <bevand_m (at) epita.fr>
Licence: I hereby disclaim the copyright on this code and place it
in the public domain.
#+end_quote
* OCB license 1
For files:
- cipher/cipher-ocb.c
#+begin_quote
OCB is covered by several patents but may be used freely by most
- software. See http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm .
+ software. See https://web.cs.ucdavis.edu/~rogaway/ocb/license.htm .
In particular license 1 is suitable for Libgcrypt: See
- http://web.cs.ucdavis.edu/~rogaway/ocb/license1.pdf for the full
+ https://web.cs.ucdavis.edu/~rogaway/ocb/license1.pdf for the full
license document; it basically says:
License 1 — License for Open-Source Software Implementations of OCB
(Jan 9, 2013)
Under this license, you are authorized to make, use, and
distribute open-source software implementations of OCB. This
license terminates for you if you sue someone over their
open-source software implementation of OCB claiming that you have
a patent covering their implementation.
License for Open Source Software Implementations of OCB
January 9, 2013
1 Definitions
1.1 “Licensor” means Phillip Rogaway.
1.2 “Licensed Patents” means any patent that claims priority to United
States Patent Application No. 09/918,615 entitled “Method and Apparatus
for Facilitating Efficient Authenticated Encryption,” and any utility,
divisional, provisional, continuation, continuations-in-part, reexamination,
reissue, or foreign counterpart patents that may issue with respect to the
aforesaid patent application. This includes, but is not limited to, United
States Patent No. 7,046,802; United States Patent No. 7,200,227; United
States Patent No. 7,949,129; United States Patent No. 8,321,675 ; and any
patent that issues out of United States Patent Application No. 13/669,114.
1.3 “Use” means any practice of any invention claimed in the Licensed Patents.
1.4 “Software Implementation” means any practice of any invention
claimed in the Licensed Patents that takes the form of software executing on
a user-programmable, general-purpose computer or that takes the form of a
computer-readable medium storing such software. Software Implementation does
not include, for example, application-specific integrated circuits (ASICs),
field-programmable gate arrays (FPGAs), embedded systems, or IP cores.
1.5 “Open Source Software” means software whose source code is published
and made available for inspection and use by anyone because either (a) the
source code is subject to a license that permits recipients to copy, modify,
and distribute the source code without payment of fees or royalties, or
(b) the source code is in the public domain, including code released for
public use through a CC0 waiver. All licenses certified by the Open Source
Initiative at opensource.org as of January 9, 2013 and all Creative Commons
licenses identified on the creativecommons.org website as of January 9,
2013, including the Public License Fallback of the CC0 waiver, satisfy these
requirements for the purposes of this license.
1.6 “Open Source Software Implementation” means a Software
Implementation in which the software implicating the Licensed Patents is
Open Source Software. Open Source Software Implementation does not include
any Software Implementation in which the software implicating the Licensed
Patents is combined, so as to form a larger program, with software that is
not Open Source Software.
2 License Grant
2.1 License. Subject to your compliance with the term s of this license,
including the restriction set forth in Section 2.2, Licensor hereby
grants to you a perpetual, worldwide, non-exclusive, non-transferable,
non-sublicenseable, no-charge, royalty-free, irrevocable license to practice
any invention claimed in the Licensed Patents in any Open Source Software
Implementation.
2.2 Restriction. If you or your affiliates institute patent litigation
(including, but not limited to, a cross-claim or counterclaim in a lawsuit)
against any entity alleging that any Use authorized by this license
infringes another patent, then any rights granted to you under this license
automatically terminate as of the date such litigation is filed.
3 Disclaimer
YOUR USE OF THE LICENSED PATENTS IS AT YOUR OWN RISK AND UNLESS REQUIRED
BY APPLICABLE LAW, LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE LICENSED PATENTS OR ANY PRODUCT EMBODYING ANY LICENSED
PATENT, EXPRESS OR IMPLIED, STATUT ORY OR OTHERWISE, INCLUDING, WITHOUT
LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NONINFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM OR RELATED TO ANY USE OF THE LICENSED PATENTS, INCLUDING,
WITHOUT LIMITATION, DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE
OR SPECIAL DAMAGES, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES PRIOR TO SUCH AN OCCURRENCE.
#+end_quote
diff --git a/Makefile.am b/Makefile.am
index 7fa4fa4d..a647ccee 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,146 +1,146 @@
## Process this file with automake to produce Makefile.in
# 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/>.
+# License along with this program; if not, see <https://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/libgcrypt/v1.9
# 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
if BUILD_DOC
doc = doc
else
doc =
endif
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 VERSION
DISTCLEANFILES =
# Add all the files listed in "distfiles" files to the distribution
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
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
gen_start_date = 2011-12-01T14:00:00
.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
# Macro to help the release target.
RELEASE_NAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
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 ' */' ;\
)
diff --git a/NEWS b/NEWS
index aa58fda8..3c241723 100644
--- a/NEWS
+++ b/NEWS
@@ -1,1227 +1,1227 @@
Noteworthy changes in version 1.9.0 (unreleased) [C22/A3/R0]
------------------------------------------------
* Bug fixes
- 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. [also in 1.8.2]
- Fix fatal out of secure memory status in the s-expression parser
on heavy loaded systems. [also in 1.8.2]
* Interface changes relative to the 1.8.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_mpi_get_ui NEW function.
GCRYCTL_AUTO_EXPAND_SECMEM NEW control code.
* 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)
Noteworthy changes in version 1.8.1 (2017-08-27) [C22/A2/R1]
------------------------------------------------
* Bug fixes:
- Mitigate a local side-channel attack on Curve25519 dubbed "May
the Fourth be With You". [CVE-2017-0379] [also in 1.7.9]
- Add more extra bytes to the pool after reading a seed file.
- Add the OID SHA384WithECDSA from RFC-7427 to SHA-384.
- Fix build problems with the Jitter RNG
- Fix assembler code build problems on Rasbian (ARMv8/AArch32-CE).
Noteworthy changes in version 1.8.0 (2017-07-18) [C22/A2/R0]
------------------------------------------------
* New interfaces:
- New cipher mode XTS
- New hash function Blake-2
- New function gcry_mpi_point_copy.
- New function gcry_get_config.
- GCRYCTL_REINIT_SYSCALL_CLAMP allows to init nPth after Libgcrypt.
- New global configuration file /etc/gcrypt/random.conf.
* Extended interfaces:
- GCRYCTL_PRINT_CONFIG does now also print build information for
libgpg-error and the used compiler version.
- GCRY_CIPHER_MODE_CFB8 is now supported.
- Add Stribog OIDs. [also in 1.7.4]
* Performance:
- A jitter based entropy collector is now used in addition to the
other entropy collectors.
- Optimized gcry_md_hash_buffers for SHA-256 and SHA-512.
- More ARMv8/AArch32 improvements for AES, GCM, SHA-256, and SHA-1.
[also in 1.7.4]
- Add ARMv8/AArch32 assembly implementation for Twofish and
Camellia. [also in 1.7.4]
- Add bulk processing implementation for ARMv8/AArch32.
[also in 1.7.4]
- Improve the DRBG performance and sync the code with the Linux
version. [also in 1.7.4]
* Internal changes:
- Libgpg-error 1.25 is now required. This avoids stalling of nPth
threads due to contention on internal Libgcrypt locks (e.g. the
random pool lock).
- The system call clamp of libgpg-error is now used to wrap the
blocking read of /dev/random. This allows other nPth threads to
run while Libgcrypt is gathering entropy.
- When secure memory is requested by the MPI functions or by
gcry_xmalloc_secure, they do not anymore lead to a fatal error if
the secure memory pool is used up. Instead new pools are
allocated as needed. These new pools are not protected against
being swapped out (mlock can't be used). However, these days
this is considered a minor issue and can easily be mitigated by
using encrypted swap space. [also in 1.7.4]
* Bug fixes:
- Fix AES CTR self-check detected failure in the SSSE3 based
implementation. [also in 1.7.6]
- Remove gratuitous select before the getrandom syscall.
[also in 1.7.6]
- Fix regression in mlock detection. [bug#2870] [also in 1.7.5]
- Fix GOST 28147 CryptoPro-B S-box. [also in 1.7.4]
- Fix error code handling of mlock calls. [also in 1.7.4]
- Fix possible timing attack on EdDSA session key. [also in 1.7.7]
- Fix long standing bug in secure memory implementation which could
lead to a segv on free. [bug#3027] [also in 1.7.7]
- Mitigate a flush+reload side-channel attack on RSA secret keys
dubbed "Sliding right into disaster". For details see
<https://eprint.iacr.org/2017/627>. [CVE-2017-7526] [also in 1.7.8]
* Interface changes relative to the 1.7.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_get_config NEW function.
gcry_mpi_point_copy NEW function.
GCRYCTL_REINIT_SYSCALL_CLAMP NEW macro.
GCRY_MD_BLAKE2B_512 NEW constant.
GCRY_MD_BLAKE2B_384 NEW constant.
GCRY_MD_BLAKE2B_256 NEW constant.
GCRY_MD_BLAKE2B_160 NEW constant.
GCRY_MD_BLAKE2S_256 NEW constant.
GCRY_MD_BLAKE2S_224 NEW constant.
GCRY_MD_BLAKE2S_160 NEW constant.
GCRY_MD_BLAKE2S_128 NEW constant.
GCRY_CIPHER_MODE_XTS NEW constant.
gcry_md_info DEPRECATED.
* Release dates of 1.7.x versions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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]
------------------------------------------------
* Bug fixes:
- Fix critical security bug in the RNG [CVE-2016-6313]. An
attacker who obtains 580 bytes from the standard RNG can
trivially predict the next 20 bytes of output. Problem
detected by Felix Dörre and Vladimir Klebanov, KIT.
- Fix building of some asm modules with older compilers and CPUs.
* Performance:
- ARMv8/AArch32 improvements for AES, GCM, SHA-256, and SHA-1.
Noteworthy changes in version 1.7.2 (2016-07-14) [C21/A1/R2]
------------------------------------------------
* Bug fixes:
- Fix setting of the ECC cofactor if parameters are specified.
- Fix memory leak in the ECC code.
- Remove debug message about unsupported getrandom syscall.
- Fix build problems related to AVX use.
- Fix bus errors on ARM for Poly1305, ChaCha20, AES, and SHA-512.
* Internal changes:
- Improved fatal error message for wrong use of gcry_md_read.
- Disallow symmetric encryption/decryption if key is not set.
Noteworthy changes in version 1.7.1 (2016-06-15) [C21/A1/R1]
------------------------------------------------
* Bug fixes:
- Fix ecc_verify for cofactor support.
- Fix portability bug when using gcc with Solaris 9 SPARC.
- Build fix for OpenBSD/amd64
- Add OIDs to the Serpent ciphers.
* Internal changes:
- Use getrandom system call on Linux if available.
- Blinding is now also used for RSA signature creation.
- Changed names of debug envvars
Noteworthy changes in version 1.7.0 (2016-04-15) [C21/A1/R0]
------------------------------------------------
* New algorithms and modes:
- SHA3-224, SHA3-256, SHA3-384, SHA3-512, and MD2 hash algorithms.
- SHAKE128 and SHAKE256 extendable-output hash algorithms.
- ChaCha20 stream cipher.
- Poly1305 message authentication algorithm
- ChaCha20-Poly1305 Authenticated Encryption with Associated Data
mode.
- OCB mode.
- HMAC-MD2 for use by legacy applications.
* New curves for ECC:
- Curve25519.
- sec256k1.
- GOST R 34.10-2001 and GOST R 34.10-2012.
* Performance:
- Improved performance of KDF functions.
- Assembler optimized implementations of Blowfish and Serpent on
ARM.
- Assembler optimized implementation of 3DES on x86.
- Improved AES using the SSSE3 based vector permutation method by
Mike Hamburg.
- AVX/BMI is used for SHA-1 and SHA-256 on x86. This is for SHA-1
about 20% faster than SSSE3 and more than 100% faster than the
generic C implementation.
- 40% speedup for SHA-512 and 72% for SHA-1 on ARM Cortex-A8.
- 60-90% speedup for Whirlpool on x86.
- 300% speedup for RIPE MD-160.
- Up to 11 times speedup for CRC functions on x86.
* Other features:
- Improved ECDSA and FIPS 186-4 compliance.
- Support for Montgomery curves.
- gcry_cipher_set_sbox to tweak S-boxes of the gost28147 cipher
algorithm.
- gcry_mpi_ec_sub to subtract two points on a curve.
- gcry_mpi_ec_decode_point to decode an MPI into a point object.
- Emulation for broken Whirlpool code prior to 1.6.0. [from 1.6.1]
- Flag "pkcs1-raw" to enable PCKS#1 padding with a user supplied
hash part.
- Parameter "saltlen" to set a non-default salt length for RSA PSS.
- A SP800-90A conforming DRNG replaces the former X9.31 alternative
random number generator.
- Map deprecated RSA algo number to the RSA algo number for better
backward compatibility. [from 1.6.2]
- Use ciphertext blinding for Elgamal decryption [CVE-2014-3591].
- See http://www.cs.tau.ac.il/~tromer/radioexp/ for details.
+ See https://www.cs.tau.ac.il/~tromer/radioexp/ for details.
[from 1.6.3]
- Fixed data-dependent timing variations in modular exponentiation
[related to CVE-2015-0837, Last-Level Cache Side-Channel Attacks
are Practical]. [from 1.6.3]
- Flag "no-keytest" for ECC key generation. Due to a bug in
the parser that flag will also be accepted but ignored by older
version of Libgcrypt. [from 1.6.4]
- Speed up the random number generator by requiring less extra
seeding. [from 1.6.4]
- Always verify a created RSA signature to avoid private key leaks
due to hardware failures. [from 1.6.4]
- Mitigate side-channel attack on ECDH with Weierstrass curves
- [CVE-2015-7511]. See http://www.cs.tau.ac.IL/~tromer/ecdh/ for
+ [CVE-2015-7511]. See https://www.cs.tau.ac.il/~tromer/ecdh/ for
details. [from 1.6.5]
* Internal changes:
- Moved locking out to libgpg-error.
- Support of the SYSROOT envvar in the build system.
- Refactor some code.
- The availability of a 64 bit integer type is now mandatory.
* Bug fixes:
- Fixed message digest lookup by OID (regression in 1.6.0).
- Fixed a build problem on NetBSD
- Fixed memory leaks in ECC code.
- Fixed some asm build problems and feature detection bugs.
* Interface changes relative to the 1.6.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_cipher_final NEW macro.
GCRY_CIPHER_MODE_CFB8 NEW constant.
GCRY_CIPHER_MODE_OCB NEW.
GCRY_CIPHER_MODE_POLY1305 NEW.
gcry_cipher_set_sbox NEW macro.
gcry_mac_get_algo NEW.
GCRY_MAC_HMAC_MD2 NEW.
GCRY_MAC_HMAC_SHA3_224 NEW.
GCRY_MAC_HMAC_SHA3_256 NEW.
GCRY_MAC_HMAC_SHA3_384 NEW.
GCRY_MAC_HMAC_SHA3_512 NEW.
GCRY_MAC_POLY1305 NEW.
GCRY_MAC_POLY1305_AES NEW.
GCRY_MAC_POLY1305_CAMELLIA NEW.
GCRY_MAC_POLY1305_SEED NEW.
GCRY_MAC_POLY1305_SERPENT NEW.
GCRY_MAC_POLY1305_TWOFISH NEW.
gcry_md_extract NEW.
GCRY_MD_FLAG_BUGEMU1 NEW [from 1.6.1].
GCRY_MD_GOSTR3411_CP NEW.
GCRY_MD_SHA3_224 NEW.
GCRY_MD_SHA3_256 NEW.
GCRY_MD_SHA3_384 NEW.
GCRY_MD_SHA3_512 NEW.
GCRY_MD_SHAKE128 NEW.
GCRY_MD_SHAKE256 NEW.
gcry_mpi_ec_decode_point NEW.
gcry_mpi_ec_sub NEW.
GCRY_PK_EDDSA NEW constant.
GCRYCTL_GET_TAGLEN NEW.
GCRYCTL_SET_SBOX NEW.
GCRYCTL_SET_TAGLEN NEW.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Version 1.6.5 (2016-02-09) [C20/A0/R5]
Version 1.6.4 (2015-09-08) [C20/A0/R4]
Version 1.6.3 (2015-02-27) [C20/A0/R3]
Version 1.6.2 (2014-08-21) [C20/A0/R2]
Version 1.6.1 (2014-01-29) [C20/A0/R1]
Noteworthy changes in version 1.6.0 (2013-12-16) [C20/A0/R0]
------------------------------------------------
* Removed the long deprecated gcry_ac interface. Thus Libgcrypt is
not anymore ABI compatible to previous versions if they used the ac
interface.
* Removed the module register subsystem.
* The deprecated message digest debug macros have been removed. Use
gcry_md_debug instead.
* Removed deprecated control codes.
* Improved performance of most cipher algorithms as well as for the
SHA family of hash functions.
* Added support for the IDEA cipher algorithm.
* Added support for the Salsa20 and reduced Salsa20/12 stream ciphers.
* Added limited support for the GOST 28147-89 cipher algorithm.
* Added support for the GOST R 34.11-94 and R 34.11-2012 (Stribog)
hash algorithms.
* Added a random number generator to directly use the system's RNG.
Also added an interface to prefer the use of a specified RNG.
* Added support for the SCRYPT algorithm.
* Mitigated the Yarom/Falkner flush+reload side-channel attack on RSA
- secret keys. See <http://eprint.iacr.org/2013/448> [CVE-2013-4242].
+ secret keys. See <https://eprint.iacr.org/2013/448> [CVE-2013-4242].
* Added support for Deterministic DSA as per RFC-6979.
* Added support for curve Ed25519.
* Added a scatter gather hash convenience function.
* Added several MPI amd SEXP helper functions.
* Added support for negative numbers to gcry_mpi_print,
gcry_mpi_aprint and gcry_mpi_scan.
* The algorithm ids GCRY_PK_ECDSA and GCRY_PK_ECDH are now
deprecated. Use GCRY_PK_ECC if you need an algorithm id.
* Changed gcry_pk_genkey for "ecc" to only include the curve name and
not the parameters. The flag "param" may be used to revert this.
* Added a feature to globally disable selected hardware features.
* Added debug helper functions.
* Interface changes relative to the 1.5.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_ac_* REMOVED.
GCRY_AC_* REMOVED.
gcry_module_t REMOVED.
gcry_cipher_register REMOVED.
gcry_cipher_unregister REMOVED.
gcry_cipher_list REMOVED.
gcry_pk_register REMOVED.
gcry_pk_unregister REMOVED.
gcry_pk_list REMOVED.
gcry_md_register REMOVED.
gcry_md_unregister REMOVED.
gcry_md_list REMOVED.
gcry_md_start_debug REMOVED (macro).
gcry_md_stop_debug REMOVED (macro).
GCRYCTL_SET_KEY REMOVED.
GCRYCTL_SET_IV REMOVED.
GCRYCTL_SET_CTR REMOVED.
GCRYCTL_DISABLE_ALGO CHANGED: Not anymore thread-safe.
gcry_pk_genkey CHANGED: ECC curve params not returned.
gcry_md_hash_buffers NEW.
gcry_buffer_t NEW.
GCRYCTL_SET_ENFORCED_FIPS_FLAG NEW.
GCRYCTL_SET_PREFERRED_RNG_TYPE NEW.
GCRYCTL_GET_CURRENT_RNG_TYPE NEW.
GCRYCTL_CLOSE_RANDOM_DEVICE NEW.
GCRY_RNG_TYPE_STANDARD NEW.
GCRY_RNG_TYPE_FIPS NEW.
GCRY_RNG_TYPE_SYSTEM NEW.
gcry_mpi_is_neg NEW.
gcry_mpi_neg NEW.
gcry_mpi_abs NEW.
gcry_mpi_snatch NEW.
gcry_mpi_set_opaque_copy NEW.
gcry_mpi_point_t NEW.
gcry_mpi_point_new NEW.
gcry_mpi_point_release NEW.
gcry_mpi_point_get NEW.
gcry_mpi_point_snatch_get NEW.
gcry_mpi_point_set NEW.
gcry_mpi_point_snatch_set NEW.
gcry_ctx_t NEW.
gcry_ctx_release NEW.
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.
gcry_mpi_ec_get_affine NEW.
gcry_mpi_ec_dup NEW.
gcry_mpi_ec_add NEW.
gcry_mpi_ec_mul NEW.
gcry_mpi_ec_curve_point NEW.
GCRYMPI_FLAG_IMMUTABLE NEW.
GCRYMPI_FLAG_CONST NEW.
GCRYMPI_FLAG_USER1 NEW.
GCRYMPI_FLAG_USER2 NEW.
GCRYMPI_FLAG_USER3 NEW.
GCRYMPI_FLAG_USER4 NEW.
GCRYMPI_CONST_ONE NEW.
GCRYMPI_CONST_TWO NEW.
GCRYMPI_CONST_THREE NEW.
GCRYMPI_CONST_FOUR NEW.
GCRYMPI_CONST_EIGHT NEW.
GCRYMPI_FMT_OPAQUE NEW.
GCRYPT_VERSION_NUMBER NEW.
GCRY_KDF_SCRYPT NEW.
gcry_pubkey_get_sexp NEW.
GCRYCTL_DISABLE_LOCKED_SECMEM NEW.
GCRYCTL_DISABLE_PRIV_DROP NEW.
GCRY_CIPHER_SALSA20 NEW.
gcry_sexp_nth_buffer NEW.
gcry_sexp_extract_param NEW.
GCRY_CIPHER_SALSA20R12 NEW.
GCRY_CIPHER_GOST28147 NEW.
GCRY_MD_GOSTR3411_94 NEW.
GCRY_MD_STRIBOG256 NEW.
GCRY_MD_STRIBOG512 NEW.
GCRY_PK_ECC NEW.
gcry_log_debug NEW.
gcry_log_debughex NEW.
gcry_log_debugmpi NEW.
gcry_log_debugpnt NEW.
Noteworthy changes in version 1.5.0 (2011-06-29)
------------------------------------------------
* New function gcry_kdf_derive implementing OpenPGP S2K algorithms
and PBKDF2.
* Support for WindowsCE.
* Support for ECDH.
* Support for OAEP and PSS methods as described by RFC-3447.
* Fixed PKCS v1.5 code to always return the leading zero.
* New format specifiers "%M" and "%u" for gcry_sexp_build.
* Support opaque MPIs with "%m" and "%M" in gcry_sexp_build.
* New functions gcry_pk_get_curve and gcry_pk_get_param to map ECC
parameters to a curve name and to retrieve parameter values.
* gcry_mpi_cmp applied to opaque values has a defined semantic now.
* Uses the Intel AES-NI instructions if available.
* The use of the deprecated Alternative Public Key Interface
(gcry_ac_*) will now print compile time warnings.
* The module register subsystem has been deprecated. This subsystem
is not flexible enough and would always require ABI changes to
extend the internal interfaces. It will eventually be removed.
Please contact us on the gcrypt-devel mailing list to discuss
whether you really need this feature or how it can be replaced by
an internal plugin mechanism.
* CTR mode may now be used with data chunks of arbitrary length.
* Changes also done in 1.4.6 (2010-07-13):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* New variants of the TIGER algorithm.
* New cipher algorithm mode for AES-WRAP.
* Changes also done in 1.4.5 (2009-12-11):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fixed minor memory leak in DSA key generation.
* No more switching to FIPS mode if /proc/version is not readable.
* Fixed sigill during Padlock detection on old CPUs.
* Fixed a hang on some W2000 machines.
* Boosted SHA-512 performance by 30% on ia32 boxes and gcc 4.3;
SHA-256 went up by 25%.
* Interface changes relative to the 1.4.6 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_PK_ECDH NEW.
gcry_pk_get_curve NEW.
gcry_pk_get_param NEW.
GCRYCTL_DISABLE_HWF NEW.
gcry_kdf_derive NEW.
gcry_pk_encrypt EXTENDED: Support OAEP.
gcry_pk_decrypt EXTENDED: Support OAEP.
gcry_pk_sign EXTENDED: Support PSS.
gcry_pk_verify EXTENDED: Support PSS.
gcry_sexp_build EXTENDED: Add format specifiers M and u.
* Interface changes relative to the 1.4.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_CIPHER_MODE_AESWRAP NEW.
GCRY_MD_TIGER1 NEW.
GCRY_MD_TIGER2 NEW.
Noteworthy changes in version 1.4.4 (2009-01-22)
------------------------------------------------
* Publish GCRY_MODULE_ID_USER and GCRY_MODULE_ID_USER_LAST constants.
This functionality has been in Libgcrypt since 1.3.0.
* MD5 may now be used in non-enforced fips mode.
* Fixed HMAC for SHA-384 and SHA-512 with keys longer than 64 bytes.
* In fips mode, RSA keys are now generated using the X9.31 algorithm
and DSA keys using the FIPS 186-2 algorithm.
* The transient-key flag is now also supported for DSA key
generation. DSA domain parameters may be given as well.
Noteworthy changes in version 1.4.3 (2008-09-18)
------------------------------------------------
* 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.
Noteworthy changes in version 1.4.2 (2008-09-08)
------------------------------------------------
* The long missing gcry_mpi_lshift function has been added.
* RSA key generation now supports a "transient-key" flag.
* The keygrip computation for ECDSA has been implemented thus ECDSA
is now fully supported.
* A few macros have been replaced by functions for better type
checking.
* The thread initialization structure now carries version
information.
* The manual describes more clearly how to initialize Libgcrypt.
* The library may now be switched into a FIPS mode.
* Interface changes relative to the 1.3.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRYCTL_OPERATIONAL_P NEW.
GCRYCTL_FIPS_MODE_P NEW.
GCRYCTL_FORCE_FIPS_MODE NEW.
gcry_cipher_setkey NEW: Replaces macro.
gcry_cipher_setiv NEW: Replaces macro.
gcry_cipher_setctr NEW: Replaces macro.
gcry_mpi_lshift NEW.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.4.1 (2008-04-25)
------------------------------------------------
* Fixed a bug introduced by 1.3.1 which led to the comsumption of far
too much entropy for the intial seeding.
* Improved AES performance for CFB and CBC modes.
* Removed build problems for the Padlock support.
Noteworthy changes in version 1.4.0 (2007-12-10)
------------------------------------------------
* New configure option --disable-padlock-support which is mostly
useful in case of build problems.
Noteworthy changes in version 1.3.2 (2007-12-03)
------------------------------------------------
* The visibility attribute is now used if supported by the toolchain.
* The ACE engine of VIA processors is now used for AES-128.
* The ASN.1 DER template for SHA-224 has been fixed.
Noteworthy changes in version 1.3.1 (2007-10-26)
------------------------------------------------
* The entire library is now under the LGPL. The helper programs and
the manual are under the GPL. Kudos to Peter Gutmann for giving
permissions to relicense the rndw32 and rndunix modules.
* The Camellia cipher is now under the LGPL and included by default.
* Fixed a bug in the detection of symbol prefixes which inhibited the
build of optimzied assembler code on certain systems.
* Updated the entropy gatherer for W32.
Noteworthy changes in version 1.3.0 (2007-05-04)
------------------------------------------------
* Changed the way the RNG gets initialized. This allows to keep it
uninitialized as long as no random numbers are used. To override
this, the new macro gcry_fast_random_poll may be used. It is in
general a good idea to spread this macro into the application code
to make sure that these polls happen often enough.
* 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.
* Support for SHA-224 and HMAC using SHA-384 and SHA-512.
* Support for the SEED cipher.
* Support for the Camellia cipher. Note that Camellia is disabled by
default, and that enabling it changes the license of libgcrypt from
LGPL to GPL.
* Support for OFB encryption mode.
* gcry_mpi_rshift does not anymore truncate the shift count.
* Reserved algorithm ranges for use by applications.
* Support for DSA2.
* The new function gcry_md_debug should be used instead of the
gcry_md_start_debug and gcry_md_stop_debug macros.
* 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.
* Non executable stack support is now used by default on systems
supporting it.
* Support for Microsoft Windows.
* Assembler support for the AMD64 architecture.
* New configure option --enable-mpi-path for optimized builds.
* Experimental support for ECDSA; should only be used for testing.
* New control code GCRYCTL_PRINT_CONFIG to print the build
configuration.
* 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_poll 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*.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.2.0 (2004-04-15)
------------------------------------------------
* First stable release.
Noteworthy changes in version 1.1.94 (2004-03-29)
-------------------------------------------------
* The support for multi-threaded users goes into its third
incarnation. We removed compile time support for thread libraries.
To support the thread library of your choice, you have to set up
callback handlers at initialization time. New data structures, a
new control command, and default initializers are provided for this
purpose.
* Interface changes relative to the 1.1.93 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libgcrypt-config --thread OBSOLETE
libgcrypt-pth.la REMOVED
libgcrypt-pthread.la REMOVED
GCRYCTL_SET_THREAD_CBS NEW
struct gcrypt_thread_cbs NEW
enum gcry_thread_option NEW
GCRY_THREAD_OPTION_PTH_IMPL NEW
GCRY_THREAD_OPTION_PTHREAD_IMPL NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.1.93 (2004-03-06)
-------------------------------------------------
* The automatic thread library detection has finally been removed.
From now on, only linking explicitely to libgcrypt, libgcrypt-pth
or libgcrypt-pthread is supported.
Noteworthy changes in version 1.1.92 (2004-02-20)
-------------------------------------------------
* Minor bug fixes.
* Included a limited implementation of RFC2268.
* Changed API of the gcry_ac_ functions. Only a very few programs
should be affected by this.
* Interface changes relative to the 1.1.91 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_CIPHER_RFC2268_40 NEW.
gcry_ac_data_set CHANGED: New argument FLAGS.
gcry_ac_data_get_name CHANGED: New argument FLAGS.
gcry_ac_data_get_index CHANGED: New argument FLAGS.
gcry_ac_key_pair_generate CHANGED: New and reordered arguments.
gcry_ac_key_test CHANGED: New argument HANDLE.
gcry_ac_key_get_nbits CHANGED: New argument HANDLE.
gcry_ac_key_get_grip CHANGED: New argument HANDLE.
gcry_ac_data_search REMOVED.
gcry_ac_data_add REMOVED.
GCRY_AC_DATA_FLAG_NO_BLINDING REMOVED.
GCRY_AC_FLAG_NO_BLINDING NEW: Replaces above.
Noteworthy changes in version 1.1.91 (2003-12-19)
-------------------------------------------------
* Code cleanups and minor bug fixes.
Noteworthy changes in version 1.1.90 (2003-11-14)
-------------------------------------------------
* The use of the GCRY_WEAK_RANDOM level is now deprecated in favor of
the new gcry_create_nonce function.
* gcry_sexp_build now supports a "%b" format to include a memory buffer.
* Minor configuration fixes.
* Interface changes relative to the 1.1.44 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_create_nonce NEW
gcry_sexp_build ENHANCED
Noteworthy changes in version 1.1.44 (2003-10-31)
-------------------------------------------------
* Bug fixes and more code cleanups.
* Enhanced the prime API.
* Interface changes relative to the 1.1.43 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_prime_group_generator NEW
gcry_prime_release_factors NEW
Noteworthy changes in version 1.1.43 (2003-09-04)
-------------------------------------------------
* Bug fixes and internal code cleanups.
* Support for the Serpent cipher algorithm.
* Interface changes relative to the 1.1.42 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_prime_generate NEW
gcry_prime_check NEW
Noteworthy changes in version 1.1.42 (2003-07-31)
-------------------------------------------------
* Major API cleanup. Applications need to be converted to the new
API. See README.apichanges for hints on how to do that. Backward
compatibility is provided where it was possible without too much
effort and did not collide with the overall sanitization effort.
However, this is only for ease of transition. NO DEPRECATED
FUNCTION OR DATA TYPE IS CONSIDERED A PART OF THE API OR ABI AND
WILL BE DROPPED IN THE FUTURE WITHOUT CHANGING THE SONAME OF THE
LIBRARY.
* If gcrypt.h is included in sources compiled by GCC 3.1 or later,
deprecated attributes will warn about use of obsolete functions and
type definitions. You can suppress these warnings by passing
-Wno-deprecated-declarations to the gcc command.
* gcry_check_version must be called from now on to initialize the
library, it is not longer optional.
* Removed `libgcrypt errno' concept.
* Libgcrypt depends on libgpg-error, a library that provides error
codes and according functions for all GnuPG components. Functions
that used to return error codes asa `int' have been changed to
return a code of type `gcry_error_t'. All GCRYERR_* error symbols
have been removed, since they are now contained in libgpg-error
(GPG_ERR_*). All functions and types in libgpg-error have also been
wrapped in Libgcrypt. The new types are gcry_err_code_t and
gcry_err_source_t. The new functions are gcry_err_code,
gcry_err_source, gcry_error, gcry_err_make, gcry_error_from_errno,
gcry_err_make_from_errno, gcry_err_code_from_errno,
gcry_err_code_to_errno, gcry_strsource.
* New function gcry_mpi_dump to help in debugging.
* Added alternative interface for asymmetric cryptography.
* CRC-32, CRC-32 a'la RFC 1510, CRC-24 a'la RFC 2440 are now
supported.
* SHA-256, SHA-384 and SHA-512 are now supported.
* 128 bit Twofish is now supported.
* The random module won't print the "not enough random bytes
available" anymore. A new progress status is issued instead.
* CBC-MAC for block ciphers is now supported, by using a
GCRY_CIPHER_CBC_MAC cipher flag.
* CTR mode for block ciphers is now supported.
* The public RSA exponent can now be specified in key generation.
* RSA blinding is now supported and is used automatically for RSA
decryption. It can be explicitely disabled by using the
`no-blinding' symbol in the `flags' S-Expression or by using the
GCRY_AC_FLAG_DATA_NO_BLINDING flag when using the ac interface.
* gcry_sexp_canon_len does not use a `historically encoded' error
code anymore.
* Interface changes relative to the 1.1.12 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRY_MPI DEPRECATED; Use: gcry_mpi_t
GcryMPI DEPRECATED; Use: gcry_mpi_t
GCRY_SEXP DEPRECATED; Use: gcry_sexp_t
GcrySexp DEPRECATED; Use: gcry_sexp_t
GCRY_CIPHER_HD DEPRECATED; Use: gcry_cipher_hd_t
GcryCipherHd DEPRECATED; Use: gcry_cipher_hd_t
GCRY_MD_HD DEPRECATED; Use: gcry_md_hd_t
GcryMDHd DEPRECATED; Use: gcry_md_hd_t
gcry_error_t NEW
gcry_err_code_t NEW
gcry_err_source_t NEW
gcry_err_make NEW
gcry_error NEW
gcry_err_code NEW
gcry_err_source NEW
gcry_err_code_from_errno NEW
gcry_err_code_to_errno NEW
gcry_err_make_from_errno NEW
gcry_error_from_errno NEW
gcry_strsource NEW
GCRYERR_{some error code} REMOVED; Use GPG_ERR_*
from libgpg-error instead.
gcry_errno REMOVED
gcry_sexp_canon_len CHANGED
gcry_sexp_build_array NEW
gcry_mpi_scan CHANGED: New argument to separate in/out args.
gcry_mpi_print CHANGED: Ditto.
gcry_mpi_dump NEW
gcry_cipher_open CHANGED
gcry_cipher_reset NEW
gcry_cipher_register NEW
gcry_cipher_unregister NEW
gcry_cipher_list NEW
gcry_cipher_algo_keylen REPLACED macro with function.
gcry_cipher_algo_blklen REPLACED macro with function.
gcry_pk_register NEW
gcry_pk_unregister NEW
gcry_pk_list NEW
gcry_pk_decrypt ENHANCED: Allows flag to return
complete S-expression.
gcry_md_open CHANGED
gcry_md_copy CHANGED
gcry_md_is_enabled NEW
gcry_md_is_secure NEW
gcry_md_register NEW
gcry_md_unregister NEW
gcry_md_list NEW
gcry_ac_data_t NEW
gcry_ac_key_t NEW
gcry_ac_key_pair_t NEW
gcry_ac_handle_t NEW
gcry_ac_key_spec_rsa_t NEW
gcry_ac_data_new NEW
gcry_ac_data_destroy NEW
gcry_ac_data_set NEW
gcry_ac_data_copy NEW
gcry_ac_data_length NEW
gcry_ac_data_get_name NEW
gcry_ac_data_get_index NEW
gcry_ac_data_clear NEW
gcry_ac_open NEW
gcry_ac_close NEW
gcry_ac_key_init NEW
gcry_ac_key_pair_generate NEW
gcry_ac_key_pair_extract NEW
gcry_ac_key_data_get NEW
gcry_ac_key_test NEW
gcry_ac_key_get_nbits NEW
gcry_ac_key_get_grip NEW
gcry_ac_key_destroy NEW
gcry_ac_key_pair_destroy NEW
gcry_ac_data_encrypt NEW
gcry_ac_data_decrypt NEW
gcry_ac_data_sign NEW
gcry_ac_data_verify NEW
gcry_ac_id_to_name NEW
gcry_ac_name_to_id NEW
gcry_handler_progress_t NEW
gcry_handler_alloc_t NEW
gcry_handler_secure_check_t NEW
gcry_handle_realloc_t NEW
gcry_handler_free_t NEW
gcry_handler_no_mem_t NEW
gcry_handler_error_t NEW
gcry_handler_log_t NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.1.12 (2003-01-20)
-------------------------------------------------
* gcry_pk_sign, gcry_pk_verify and gcry_pk_encrypt can now handle an
optional pkcs1 flags parameter in the S-expression. A similar flag
may be passed to gcry_pk_decrypt but it is only syntactically
implemented.
* New convenience macro gcry_md_get_asnoid.
* There is now some real stuff in the manual.
Noteworthy changes in version 1.1.11 (2002-12-21)
-------------------------------------------------
* Don't export internal symbols anymore (currently only for GNU systems)
* New algorithm: MD4
* Implemented ciphertext stealing.
* Smaller bugs fixes and a few new OIDs.
* Interface changes relative to the 1.1.8 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_cipher_cts NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.1.10 (2002-09-20)
-------------------------------------------------
* Fixed shared library builds for i386, PPC and Sparc.
* Added simple benchmark tool.
* Replaced the internal mutexes by code which automatically adapts to
the used threading library. Currently Pth and Pthread are
supported. For non-ELF systems the GNU toolchain is now required..
* Added untested support to build Windows DLLs.
Noteworthy changes in version 1.1.9 (2002-08-23)
------------------------------------------------
* Support for plain old DES.
Noteworthy changes in version 1.1.8 (2002-06-25)
------------------------------------------------
* Minor cleanups and exported a few new functions.
* Interface changes relative to the 1.1.7 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_mpi_div NEW
gcry_mpi_mod NEW
gcry_mpi_invm NEW
gcry_mpi_swap NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.1.7 (2002-05-21)
------------------------------------------------
* Libgcrypt is now distributed under the terms of the GNU Lesser
General Public License; see the README file for details.
* It is possible to use libgcrypt w/o intialized secure memory.
* Libgcrypt should now be thread safe after the initialization.
gcry_control (GCRYCRL_INITIALIZATION_FINISHED,NULL,0) should have
been called before creating additional threads.
* Interface changes relative to the 1.1.6 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GCRYCTL_DISABLE_INTERNAL_LOCKING NEW
GCRYCTL_DISABLE_SECMEM NEW
GCRYCTL_INITIALIZATION_FINISHED NEW
GCRYCTL_INITIALIZATION_FINISHED_P NEW
GCRYCTL_ANY_INITIALIZATION_P NEW
gcry_strdup NEW
gcry_sexp_create NEW
gcry_sexp_new NEW
gcry_set_progress_handler NEW
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noteworthy changes in version 1.1.6 (2002-02-07)
------------------------------------------------
* Enhanced the S-expression conversion functions.
Noteworthy changes in version 1.1.5 (2001-12-18)
------------------------------------------------
* gcry_{cipher,md}_map_name are now able to map stringified object IDs.
* New functions gcry_sexp_canon_len and gcry_cipher_mode_from_oid.
* Closed some memory leaks.
Noteworthy changes in version 1.1.4 (2001-08-03)
------------------------------------------------
* Arcfour does now work.
* Some minor fixes.
* Added a first test program
* Migrated to autoconf 2.52.
Noteworthy changes in version 1.1.3 (2001-05-31)
------------------------------------------------
* First release of Libgcrypt which is a result of splitting GnuPG
into into libgcrypt and GnuPG.
Copyright 2001, 2002, 2003, 2004, 2007, 2008,
2009, 2011 Free Software Foundation, Inc.
Copyright 2013 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
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.
diff --git a/build-aux/compile b/build-aux/compile
index 531136b0..52f8f943 100755
--- a/build-aux/compile
+++ b/build-aux/compile
@@ -1,347 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.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 2, 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 <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
diff --git a/build-aux/config.guess b/build-aux/config.guess
index c4bd827a..4d4d3701 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,1456 +1,1456 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2016 Free Software Foundation, Inc.
timestamp='2016-05-15'
# This file 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 <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2016 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."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
trap 'exit 1' 1 2 15
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
# use `HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
case $CC_FOR_BUILD,$HOST_CC,$CC in
,,) echo "int x;" > $dummy.c ;
for c in cc gcc c89 c99 ; do
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
CC_FOR_BUILD="$c"; break ;
fi ;
done ;
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found ;
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_SYSTEM}" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
eval $set_cc_for_build
cat <<-EOF > $dummy.c
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
LIBC=gnu
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
;;
esac
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
/sbin/$sysctl 2>/dev/null || \
/usr/sbin/$sysctl 2>/dev/null || \
echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
machine=${arch}${endian}-unknown
;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
case "${UNAME_MACHINE_ARCH}" in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# Determine ABI tags.
case "${UNAME_MACHINE_ARCH}" in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case "${UNAME_VERSION}" in
Debian*)
release='-gnu'
;;
*)
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}${abi}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
*:SolidBSD:*:*)
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:Sortix:*:*)
echo ${UNAME_MACHINE}-unknown-sortix
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
UNAME_MACHINE=alpha ;;
"EV5 (21164)")
UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit ;;
*:z/VM:*:*)
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
;;
sun4)
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c &&
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`$dummy $dummyarg` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
[ ${TARGET_BINARY_INTERFACE}x = x ]
then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
then
echo "$SYSTEM_NAME"
else
echo rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/lslpp ] ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = hppa2.0w ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH=hppa2.0w
else
HP_ARCH=hppa64
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
*:MINGW64*:*)
echo ${UNAME_MACHINE}-pc-mingw64
exit ;;
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
*:GNU:*:*)
# the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
e2k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
k1om:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
openrisc*:Linux:*:*)
echo or1k-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:* | or1k*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
*) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-${LIBC}
exit ;;
ppc64le:Linux:*:*)
echo powerpc64le-unknown-linux-${LIBC}
exit ;;
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
exit ;;
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
paragon:*:*:*)
echo i860-intel-osf1
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
exit ;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
echo ${UNAME_MACHINE}-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
x86_64:Haiku:*:*)
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
SX-ACE:SUPER-UX:*:*)
echo sxace-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
eval $set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
# that puts up a graphical alert prompting to install
# developer tools. Any system running Mac OS X 10.7 or
# later (Darwin 11 and later) is required to have a 64-bit
# processor. This is not true of the ARM version of Darwin
# that Apple uses in portable devices.
UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
amd64:Isilon\ OneFS:*:*)
echo x86_64-unknown-onefs
exit ;;
esac
cat >&2 <<EOF
$0: unable to guess system type
This script (version $timestamp), has failed to recognize the
operating system you are using. If your script is old, overwrite
config.guess and config.sub with the latest versions from:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
provide the necessary information to handle your system.
config.guess timestamp = $timestamp
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`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = ${UNAME_MACHINE}
UNAME_RELEASE = ${UNAME_RELEASE}
UNAME_SYSTEM = ${UNAME_SYSTEM}
UNAME_VERSION = ${UNAME_VERSION}
EOF
exit 1
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 9feb73bf..1948c6e2 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,1823 +1,1823 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2016 Free Software Foundation, Inc.
timestamp='2016-06-20'
# This file 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 <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2016 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."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| ba \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| e2k | epiphany \
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
leon|leon[3-9])
basic_machine=sparc-$basic_machine
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| ba-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| e2k-* | elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
asmjs)
basic_machine=asmjs-unknown
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | j90)
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
os=-tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
os=-tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
e500v[12])
basic_machine=powerpc-unknown
os=$os"spe"
;;
e500v[12]-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
os=$os"spe"
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
leon-*|leon[3-9]-*)
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
morphos)
basic_machine=powerpc-unknown
os=-morphos
;;
moxiebox)
basic_machine=moxie-unknown
os=-moxiebox
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
s390 | s390-*)
basic_machine=s390-ibm
;;
s390x | s390x-*)
basic_machine=s390x-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
;;
t90)
basic_machine=t90-cray
os=-unicos
;;
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
toad1)
basic_machine=pdp10-xkl
os=-tops20
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
| -onefs* | -tirtos* | -phoenix*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-nova*)
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-ios)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c8051-*)
os=-elf
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
;;
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or32-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-cnk*|-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
diff --git a/build-aux/depcomp b/build-aux/depcomp
index 4ebd5b3a..f0a474cd 100755
--- a/build-aux/depcomp
+++ b/build-aux/depcomp
@@ -1,791 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# 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, 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 <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
diff --git a/build-aux/ltmain.sh b/build-aux/ltmain.sh
index 859599aa..77963a93 100644
--- a/build-aux/ltmain.sh
+++ b/build-aux/ltmain.sh
@@ -1,9664 +1,9664 @@
# libtool (GNU libtool) 2.4.2
# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
# 2007, 2008, 2009, 2010, 2011 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.
# 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,
+# 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.
# Usage: $progname [OPTION]... [MODE-ARG]...
#
# Provide generalized library-building support services.
#
# --config show all configuration variables
# --debug enable verbose shell tracing
# -n, --dry-run display commands without modifying any files
# --features display basic configuration information and exit
# --mode=MODE use operation mode MODE
# --preserve-dup-deps don't remove duplicate dependency libraries
# --quiet, --silent don't print informational messages
# --no-quiet, --no-silent
# print informational messages (default)
# --no-warn don't display warning messages
# --tag=TAG use configuration variables from tag TAG
# -v, --verbose print more informational messages than default
# --no-verbose don't print the extra informational messages
# --version print version information
# -h, --help, --help-all print short, long, or detailed help message
#
# MODE must be one of the following:
#
# clean remove files from the build directory
# compile compile a source file into a libtool object
# execute automatically set library path, then run a program
# finish complete the installation of libtool libraries
# install install libraries or executables
# link create a library or an executable
# uninstall remove libraries from an installed directory
#
# MODE-ARGS vary depending on the MODE. When passed as first option,
# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
#
# When reporting a bug, please describe a test case to reproduce it and
# include the following information:
#
# host-triplet: $host
# shell: $SHELL
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1
# automake: $automake_version
# autoconf: $autoconf_version
#
# Report bugs to <bug-libtool@gnu.org>.
-# GNU libtool home page: <http://www.gnu.org/software/libtool/>.
-# General help using GNU software: <http://www.gnu.org/gethelp/>.
+# GNU libtool home page: <https://www.gnu.org/software/libtool/>.
+# General help using GNU software: <https://www.gnu.org/gethelp/>.
PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.2 Debian-2.4.2-1"
TIMESTAMP=""
package_revision=1.3337
# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs 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
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$1
_LTECHO_EOF'
}
# NLS nuisances: We save the old values to restore during execute mode.
lt_user_locale=
lt_safe_locale=
for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${$lt_var+set}\" = set; then
save_$lt_var=\$$lt_var
$lt_var=C
export $lt_var
lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
fi"
done
LC_ALL=C
LANGUAGE=C
export LANGUAGE LC_ALL
$lt_unset CDPATH
# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
# is ksh but when the shell is invoked as "sh" and the current value of
# the _XPG environment variable is not equal to 1 (one), the special
# positional parameter $0, within a function call, is the name of the
# function.
progpath="$0"
: ${CP="cp -f"}
test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
: ${MAKE="make"}
: ${MKDIR="mkdir"}
: ${MV="mv -f"}
: ${RM="rm -f"}
: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
: ${Xsed="$SED -e 1s/^X//"}
# Global variables:
EXIT_SUCCESS=0
EXIT_FAILURE=1
EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
exit_status=$EXIT_SUCCESS
# Make sure IFS has a sensible default
lt_nl='
'
IFS=" $lt_nl"
dirname="s,/[^/]*$,,"
basename="s,^.*/,,"
# func_dirname file append nondir_replacement
# Compute the dirname of FILE. If nonempty, add APPEND to the result,
# otherwise set result to NONDIR_REPLACEMENT.
func_dirname ()
{
func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
if test "X$func_dirname_result" = "X${1}"; then
func_dirname_result="${3}"
else
func_dirname_result="$func_dirname_result${2}"
fi
} # func_dirname may be replaced by extended shell implementation
# func_basename file
func_basename ()
{
func_basename_result=`$ECHO "${1}" | $SED "$basename"`
} # func_basename may be replaced by extended shell implementation
# func_dirname_and_basename file append nondir_replacement
# perform func_basename and func_dirname in a single function
# call:
# dirname: Compute the dirname of FILE. If nonempty,
# add APPEND to the result, otherwise set result
# to NONDIR_REPLACEMENT.
# value returned in "$func_dirname_result"
# basename: Compute filename of FILE.
# value retuned in "$func_basename_result"
# Implementation must be kept synchronized with func_dirname
# and func_basename. For efficiency, we do not delegate to
# those functions but instead duplicate the functionality here.
func_dirname_and_basename ()
{
# Extract subdirectory from the argument.
func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
if test "X$func_dirname_result" = "X${1}"; then
func_dirname_result="${3}"
else
func_dirname_result="$func_dirname_result${2}"
fi
func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
} # func_dirname_and_basename may be replaced by extended shell implementation
# func_stripname prefix suffix name
# strip PREFIX and SUFFIX off of NAME.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
# func_strip_suffix prefix name
func_stripname ()
{
case ${2} in
.*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
esac
} # func_stripname may be replaced by extended shell implementation
# These SED scripts presuppose an absolute path with a trailing slash.
pathcar='s,^/\([^/]*\).*$,\1,'
pathcdr='s,^/[^/]*,,'
removedotparts=':dotsl
s@/\./@/@g
t dotsl
s,/\.$,/,'
collapseslashes='s@/\{1,\}@/@g'
finalslash='s,/*$,/,'
# func_normal_abspath PATH
# Remove doubled-up and trailing slashes, "." path components,
# and cancel out any ".." path components in PATH after making
# it an absolute path.
# value returned in "$func_normal_abspath_result"
func_normal_abspath ()
{
# Start from root dir and reassemble the path.
func_normal_abspath_result=
func_normal_abspath_tpath=$1
func_normal_abspath_altnamespace=
case $func_normal_abspath_tpath in
"")
# Empty path, that just means $cwd.
func_stripname '' '/' "`pwd`"
func_normal_abspath_result=$func_stripname_result
return
;;
# The next three entries are used to spot a run of precisely
# two leading slashes without using negated character classes;
# we take advantage of case's first-match behaviour.
///*)
# Unusual form of absolute path, do nothing.
;;
//*)
# Not necessarily an ordinary path; POSIX reserves leading '//'
# and for example Cygwin uses it to access remote file shares
# over CIFS/SMB, so we conserve a leading double slash if found.
func_normal_abspath_altnamespace=/
;;
/*)
# Absolute path, do nothing.
;;
*)
# Relative path, prepend $cwd.
func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
;;
esac
# Cancel out all the simple stuff to save iterations. We also want
# the path to end with a slash for ease of parsing, so make sure
# there is one (and only one) here.
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
while :; do
# Processed it all yet?
if test "$func_normal_abspath_tpath" = / ; then
# If we ascended to the root using ".." the result may be empty now.
if test -z "$func_normal_abspath_result" ; then
func_normal_abspath_result=/
fi
break
fi
func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$pathcar"`
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$pathcdr"`
# Figure out what to do with it
case $func_normal_abspath_tcomponent in
"")
# Trailing empty path component, ignore it.
;;
..)
# Parent dir; strip last assembled component from result.
func_dirname "$func_normal_abspath_result"
func_normal_abspath_result=$func_dirname_result
;;
*)
# Actual path component, append it.
func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
;;
esac
done
# Restore leading double-slash if one was found on entry.
func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
}
# func_relative_path SRCDIR DSTDIR
# generates a relative path from SRCDIR to DSTDIR, with a trailing
# slash if non-empty, suitable for immediately appending a filename
# without needing to append a separator.
# value returned in "$func_relative_path_result"
func_relative_path ()
{
func_relative_path_result=
func_normal_abspath "$1"
func_relative_path_tlibdir=$func_normal_abspath_result
func_normal_abspath "$2"
func_relative_path_tbindir=$func_normal_abspath_result
# Ascend the tree starting from libdir
while :; do
# check if we have found a prefix of bindir
case $func_relative_path_tbindir in
$func_relative_path_tlibdir)
# found an exact match
func_relative_path_tcancelled=
break
;;
$func_relative_path_tlibdir*)
# found a matching prefix
func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
func_relative_path_tcancelled=$func_stripname_result
if test -z "$func_relative_path_result"; then
func_relative_path_result=.
fi
break
;;
*)
func_dirname $func_relative_path_tlibdir
func_relative_path_tlibdir=${func_dirname_result}
if test "x$func_relative_path_tlibdir" = x ; then
# Have to descend all the way to the root!
func_relative_path_result=../$func_relative_path_result
func_relative_path_tcancelled=$func_relative_path_tbindir
break
fi
func_relative_path_result=../$func_relative_path_result
;;
esac
done
# Now calculate path; take care to avoid doubling-up slashes.
func_stripname '' '/' "$func_relative_path_result"
func_relative_path_result=$func_stripname_result
func_stripname '/' '/' "$func_relative_path_tcancelled"
if test "x$func_stripname_result" != x ; then
func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
fi
# Normalisation. If bindir is libdir, return empty string,
# else relative path ending with a slash; either way, target
# file name can be directly appended.
if test ! -z "$func_relative_path_result"; then
func_stripname './' '' "$func_relative_path_result/"
func_relative_path_result=$func_stripname_result
fi
}
# The name of this program:
func_dirname_and_basename "$progpath"
progname=$func_basename_result
# Make sure we have an absolute path for reexecution:
case $progpath in
[\\/]*|[A-Za-z]:\\*) ;;
*[\\/]*)
progdir=$func_dirname_result
progdir=`cd "$progdir" && pwd`
progpath="$progdir/$progname"
;;
*)
save_IFS="$IFS"
IFS=${PATH_SEPARATOR-:}
for progdir in $PATH; do
IFS="$save_IFS"
test -x "$progdir/$progname" && break
done
IFS="$save_IFS"
test -n "$progdir" || progdir=`pwd`
progpath="$progdir/$progname"
;;
esac
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
Xsed="${SED}"' -e 1s/^X//'
sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
# Same as above, but do not quote variable references.
double_quote_subst='s/\(["`\\]\)/\\\1/g'
# Sed substitution that turns a string into a regex matching for the
# string literally.
sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
# Sed substitution that converts a w32 file name or path
# which contains forward slashes, into one that contains
# (escaped) backslashes. A very naive implementation.
lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
# Sed substitution to remove simple comments and empty
# lines from a Windows .def file.
sed_uncomment_deffile='/^;/d; /^[ ]*$/d'
# Re-`\' parameter expansions in output of double_quote_subst that were
# `\'-ed in input to the same. If an odd number of `\' preceded a '$'
# in input to double_quote_subst, that '$' was protected from expansion.
# Since each input `\' is now two `\'s, look for any number of runs of
# four `\'s followed by two `\'s and then a '$'. `\' that '$'.
bs='\\'
bs2='\\\\'
bs4='\\\\\\\\'
dollar='\$'
sed_double_backslash="\
s/$bs4/&\\
/g
s/^$bs2$dollar/$bs&/
s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
s/\n//g"
# Standard options:
opt_dry_run=false
opt_help=false
opt_quiet=false
opt_verbose=false
opt_warning=:
# func_echo arg...
# Echo program name prefixed message, along with the current mode
# name if it has been set yet.
func_echo ()
{
$ECHO "$progname: ${opt_mode+$opt_mode: }$*"
}
# func_verbose arg...
# Echo program name prefixed message in verbose mode only.
func_verbose ()
{
$opt_verbose && func_echo ${1+"$@"}
# A bug in bash halts the script if the last line of a function
# fails when set -e is in force, so we need another command to
# work around that:
:
}
# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO "$*"
}
# func_error arg...
# Echo program name prefixed message to standard error.
func_error ()
{
$ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
}
# func_warning arg...
# Echo program name prefixed warning message to standard error.
func_warning ()
{
$opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
# bash bug again:
:
}
# func_fatal_error arg...
# Echo program name prefixed message to standard error, and exit.
func_fatal_error ()
{
func_error ${1+"$@"}
exit $EXIT_FAILURE
}
# func_fatal_help arg...
# Echo program name prefixed message to standard error, followed by
# a help hint, and exit.
func_fatal_help ()
{
func_error ${1+"$@"}
func_fatal_error "$help"
}
help="Try \`$progname --help' for more information." ## default
# func_grep expression filename
# Check whether EXPRESSION matches any line of FILENAME, without output.
func_grep ()
{
$GREP "$1" "$2" >/dev/null 2>&1
}
# func_mkdir_p directory-path
# Make sure the entire path to DIRECTORY-PATH is available.
func_mkdir_p ()
{
my_directory_path="$1"
my_dir_list=
if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
# Protect directory names starting with `-'
case $my_directory_path in
-*) my_directory_path="./$my_directory_path" ;;
esac
# While some portion of DIR does not yet exist...
while test ! -d "$my_directory_path"; do
# ...make a list in topmost first order. Use a colon delimited
# list incase some portion of path contains whitespace.
my_dir_list="$my_directory_path:$my_dir_list"
# If the last portion added has no slash in it, the list is done
case $my_directory_path in */*) ;; *) break ;; esac
# ...otherwise throw away the child directory and loop
my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
done
my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
save_mkdir_p_IFS="$IFS"; IFS=':'
for my_dir in $my_dir_list; do
IFS="$save_mkdir_p_IFS"
# mkdir can fail with a `File exist' error if two processes
# try to create one of the directories concurrently. Don't
# stop in that case!
$MKDIR "$my_dir" 2>/dev/null || :
done
IFS="$save_mkdir_p_IFS"
# Bail out if we (or some other process) failed to create a directory.
test -d "$my_directory_path" || \
func_fatal_error "Failed to create \`$1'"
fi
}
# func_mktempdir [string]
# Make a temporary directory that won't clash with other running
# libtool processes, and avoids race conditions if possible. If
# given, STRING is the basename for that directory.
func_mktempdir ()
{
my_template="${TMPDIR-/tmp}/${1-$progname}"
if test "$opt_dry_run" = ":"; then
# Return a directory name, but don't create it in dry-run mode
my_tmpdir="${my_template}-$$"
else
# If mktemp works, use that first and foremost
my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
if test ! -d "$my_tmpdir"; then
# Failing that, at least try and use $RANDOM to avoid a race
my_tmpdir="${my_template}-${RANDOM-0}$$"
save_mktempdir_umask=`umask`
umask 0077
$MKDIR "$my_tmpdir"
umask $save_mktempdir_umask
fi
# If we're not in dry-run mode, bomb out on failure
test -d "$my_tmpdir" || \
func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
fi
$ECHO "$my_tmpdir"
}
# func_quote_for_eval arg
# Aesthetically quote ARG to be evaled later.
# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
# is double-quoted, suitable for a subsequent eval, whereas
# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
# which are still active within double quotes backslashified.
func_quote_for_eval ()
{
case $1 in
*[\\\`\"\$]*)
func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
*)
func_quote_for_eval_unquoted_result="$1" ;;
esac
case $func_quote_for_eval_unquoted_result in
# Double-quote args containing shell metacharacters to delay
# word splitting, command substitution and and variable
# expansion for a subsequent eval.
# Many Bourne shells cannot handle close brackets correctly
# in scan sets, so we specify it separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
;;
*)
func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
esac
}
# func_quote_for_expand arg
# Aesthetically quote ARG to be evaled later; same as above,
# but do not quote variable references.
func_quote_for_expand ()
{
case $1 in
*[\\\`\"]*)
my_arg=`$ECHO "$1" | $SED \
-e "$double_quote_subst" -e "$sed_double_backslash"` ;;
*)
my_arg="$1" ;;
esac
case $my_arg in
# Double-quote args containing shell metacharacters to delay
# word splitting and command substitution for a subsequent eval.
# Many Bourne shells cannot handle close brackets correctly
# in scan sets, so we specify it separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
my_arg="\"$my_arg\""
;;
esac
func_quote_for_expand_result="$my_arg"
}
# func_show_eval cmd [fail_exp]
# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it.
func_show_eval ()
{
my_cmd="$1"
my_fail_exp="${2-:}"
${opt_silent-false} || {
func_quote_for_expand "$my_cmd"
eval "func_echo $func_quote_for_expand_result"
}
if ${opt_dry_run-false}; then :; else
eval "$my_cmd"
my_status=$?
if test "$my_status" -eq 0; then :; else
eval "(exit $my_status); $my_fail_exp"
fi
fi
}
# func_show_eval_locale cmd [fail_exp]
# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it. Use the saved locale for evaluation.
func_show_eval_locale ()
{
my_cmd="$1"
my_fail_exp="${2-:}"
${opt_silent-false} || {
func_quote_for_expand "$my_cmd"
eval "func_echo $func_quote_for_expand_result"
}
if ${opt_dry_run-false}; then :; else
eval "$lt_user_locale
$my_cmd"
my_status=$?
eval "$lt_safe_locale"
if test "$my_status" -eq 0; then :; else
eval "(exit $my_status); $my_fail_exp"
fi
fi
}
# func_tr_sh
# Turn $1 into a string suitable for a shell variable name.
# Result is stored in $func_tr_sh_result. All characters
# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
# if $1 begins with a digit, a '_' is prepended as well.
func_tr_sh ()
{
case $1 in
[0-9]* | *[!a-zA-Z0-9_]*)
func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
;;
* )
func_tr_sh_result=$1
;;
esac
}
# func_version
# Echo version message to standard output and exit.
func_version ()
{
$opt_debug
$SED -n '/(C)/!b go
:more
/\./!{
N
s/\n# / /
b more
}
:go
/^# '$PROGRAM' (GNU /,/# warranty; / {
s/^# //
s/^# *$//
s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
p
}' < "$progpath"
exit $?
}
# func_usage
# Echo short help message to standard output and exit.
func_usage ()
{
$opt_debug
$SED -n '/^# Usage:/,/^# *.*--help/ {
s/^# //
s/^# *$//
s/\$progname/'$progname'/
p
}' < "$progpath"
echo
$ECHO "run \`$progname --help | more' for full usage"
exit $?
}
# func_help [NOEXIT]
# Echo long help message to standard output and exit,
# unless 'noexit' is passed as argument.
func_help ()
{
$opt_debug
$SED -n '/^# Usage:/,/# Report bugs to/ {
:print
s/^# //
s/^# *$//
s*\$progname*'$progname'*
s*\$host*'"$host"'*
s*\$SHELL*'"$SHELL"'*
s*\$LTCC*'"$LTCC"'*
s*\$LTCFLAGS*'"$LTCFLAGS"'*
s*\$LD*'"$LD"'*
s/\$with_gnu_ld/'"$with_gnu_ld"'/
s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/
s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/
p
d
}
/^# .* home page:/b print
/^# General help using/b print
' < "$progpath"
ret=$?
if test -z "$1"; then
exit $ret
fi
}
# func_missing_arg argname
# Echo program name prefixed message to standard error and set global
# exit_cmd.
func_missing_arg ()
{
$opt_debug
func_error "missing argument for $1."
exit_cmd=exit
}
# func_split_short_opt shortopt
# Set func_split_short_opt_name and func_split_short_opt_arg shell
# variables after splitting SHORTOPT after the 2nd character.
func_split_short_opt ()
{
my_sed_short_opt='1s/^\(..\).*$/\1/;q'
my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
} # func_split_short_opt may be replaced by extended shell implementation
# func_split_long_opt longopt
# Set func_split_long_opt_name and func_split_long_opt_arg shell
# variables after splitting LONGOPT at the `=' sign.
func_split_long_opt ()
{
my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
my_sed_long_arg='1s/^--[^=]*=//'
func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
} # func_split_long_opt may be replaced by extended shell implementation
exit_cmd=:
magic="%%%MAGIC variable%%%"
magic_exe="%%%MAGIC EXE variable%%%"
# Global variables.
nonopt=
preserve_args=
lo2o="s/\\.lo\$/.${objext}/"
o2lo="s/\\.${objext}\$/.lo/"
extracted_archives=
extracted_serial=0
# If this variable is set in any of the actions, the command in it
# will be execed at the end. This prevents here-documents from being
# left over by shells.
exec_cmd=
# func_append var value
# Append VALUE to the end of shell variable VAR.
func_append ()
{
eval "${1}=\$${1}\${2}"
} # func_append may be replaced by extended shell implementation
# func_append_quoted var value
# Quote VALUE and append to the end of shell variable VAR, separated
# by a space.
func_append_quoted ()
{
func_quote_for_eval "${2}"
eval "${1}=\$${1}\\ \$func_quote_for_eval_result"
} # func_append_quoted may be replaced by extended shell implementation
# func_arith arithmetic-term...
func_arith ()
{
func_arith_result=`expr "${@}"`
} # func_arith may be replaced by extended shell implementation
# func_len string
# STRING may not start with a hyphen.
func_len ()
{
func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len`
} # func_len may be replaced by extended shell implementation
# func_lo2o object
func_lo2o ()
{
func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
} # func_lo2o may be replaced by extended shell implementation
# func_xform libobj-or-source
func_xform ()
{
func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
} # func_xform may be replaced by extended shell implementation
# func_fatal_configuration arg...
# Echo program name prefixed message to standard error, followed by
# a configuration failure hint, and exit.
func_fatal_configuration ()
{
func_error ${1+"$@"}
func_error "See the $PACKAGE documentation for more information."
func_fatal_error "Fatal configuration error."
}
# func_config
# Display the configuration for all the tags in this script.
func_config ()
{
re_begincf='^# ### BEGIN LIBTOOL'
re_endcf='^# ### END LIBTOOL'
# Default configuration.
$SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
# Now print the configurations for the tags.
for tagname in $taglist; do
$SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
done
exit $?
}
# func_features
# Display the features supported by this script.
func_features ()
{
echo "host: $host"
if test "$build_libtool_libs" = yes; then
echo "enable shared libraries"
else
echo "disable shared libraries"
fi
if test "$build_old_libs" = yes; then
echo "enable static libraries"
else
echo "disable static libraries"
fi
exit $?
}
# func_enable_tag tagname
# Verify that TAGNAME is valid, and either flag an error and exit, or
# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
# variable here.
func_enable_tag ()
{
# Global variable:
tagname="$1"
re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
sed_extractcf="/$re_begincf/,/$re_endcf/p"
# Validate tagname.
case $tagname in
*[!-_A-Za-z0-9,/]*)
func_fatal_error "invalid tag name: $tagname"
;;
esac
# Don't test for the "default" C tag, as we know it's
# there but not specially marked.
case $tagname in
CC) ;;
*)
if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
taglist="$taglist $tagname"
# Evaluate the configuration. Be careful to quote the path
# and the sed script, to avoid splitting on whitespace, but
# also don't use non-portable quotes within backquotes within
# quotes we have to do it in 2 steps:
extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
eval "$extractedcf"
else
func_error "ignoring unknown tag $tagname"
fi
;;
esac
}
# func_check_version_match
# Ensure that we are using m4 macros, and libtool script from the same
# release of libtool.
func_check_version_match ()
{
if test "$package_revision" != "$macro_revision"; then
if test "$VERSION" != "$macro_version"; then
if test -z "$macro_version"; then
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from an older release.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
fi
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
$progname: but the definition of this LT_INIT comes from revision $macro_revision.
$progname: You should recreate aclocal.m4 with macros from revision $package_revision
$progname: of $PACKAGE $VERSION and run autoconf again.
_LT_EOF
fi
exit $EXIT_MISMATCH
fi
}
# Shorthand for --mode=foo, only valid as the first argument
case $1 in
clean|clea|cle|cl)
shift; set dummy --mode clean ${1+"$@"}; shift
;;
compile|compil|compi|comp|com|co|c)
shift; set dummy --mode compile ${1+"$@"}; shift
;;
execute|execut|execu|exec|exe|ex|e)
shift; set dummy --mode execute ${1+"$@"}; shift
;;
finish|finis|fini|fin|fi|f)
shift; set dummy --mode finish ${1+"$@"}; shift
;;
install|instal|insta|inst|ins|in|i)
shift; set dummy --mode install ${1+"$@"}; shift
;;
link|lin|li|l)
shift; set dummy --mode link ${1+"$@"}; shift
;;
uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
shift; set dummy --mode uninstall ${1+"$@"}; shift
;;
esac
# Option defaults:
opt_debug=:
opt_dry_run=false
opt_config=false
opt_preserve_dup_deps=false
opt_features=false
opt_finish=false
opt_help=false
opt_help_all=false
opt_silent=:
opt_warning=:
opt_verbose=:
opt_silent=false
opt_verbose=false
# Parse options once, thoroughly. This comes as soon as possible in the
# script to make things like `--version' happen as quickly as we can.
{
# this just eases exit handling
while test $# -gt 0; do
opt="$1"
shift
case $opt in
--debug|-x) opt_debug='set -x'
func_echo "enabling shell trace mode"
$opt_debug
;;
--dry-run|--dryrun|-n)
opt_dry_run=:
;;
--config)
opt_config=:
func_config
;;
--dlopen|-dlopen)
optarg="$1"
opt_dlopen="${opt_dlopen+$opt_dlopen
}$optarg"
shift
;;
--preserve-dup-deps)
opt_preserve_dup_deps=:
;;
--features)
opt_features=:
func_features
;;
--finish)
opt_finish=:
set dummy --mode finish ${1+"$@"}; shift
;;
--help)
opt_help=:
;;
--help-all)
opt_help_all=:
opt_help=': help-all'
;;
--mode)
test $# = 0 && func_missing_arg $opt && break
optarg="$1"
opt_mode="$optarg"
case $optarg in
# Valid mode arguments:
clean|compile|execute|finish|install|link|relink|uninstall) ;;
# Catch anything else as an error
*) func_error "invalid argument for $opt"
exit_cmd=exit
break
;;
esac
shift
;;
--no-silent|--no-quiet)
opt_silent=false
func_append preserve_args " $opt"
;;
--no-warning|--no-warn)
opt_warning=false
func_append preserve_args " $opt"
;;
--no-verbose)
opt_verbose=false
func_append preserve_args " $opt"
;;
--silent|--quiet)
opt_silent=:
func_append preserve_args " $opt"
opt_verbose=false
;;
--verbose|-v)
opt_verbose=:
func_append preserve_args " $opt"
opt_silent=false
;;
--tag)
test $# = 0 && func_missing_arg $opt && break
optarg="$1"
opt_tag="$optarg"
func_append preserve_args " $opt $optarg"
func_enable_tag "$optarg"
shift
;;
-\?|-h) func_usage ;;
--help) func_help ;;
--version) func_version ;;
# Separate optargs to long options:
--*=*)
func_split_long_opt "$opt"
set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
shift
;;
# Separate non-argument short options:
-\?*|-h*|-n*|-v*)
func_split_short_opt "$opt"
set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
shift
;;
--) break ;;
-*) func_fatal_help "unrecognized option \`$opt'" ;;
*) set dummy "$opt" ${1+"$@"}; shift; break ;;
esac
done
# Validate options:
# save first non-option argument
if test "$#" -gt 0; then
nonopt="$opt"
shift
fi
# preserve --debug
test "$opt_debug" = : || func_append preserve_args " --debug"
case $host in
*cygwin* | *mingw* | *pw32* | *cegcc*)
# don't eliminate duplications in $postdeps and $predeps
opt_duplicate_compiler_generated_deps=:
;;
*)
opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
;;
esac
$opt_help || {
# Sanity checks first:
func_check_version_match
if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
func_fatal_configuration "not configured to build any kind of library"
fi
# Darwin sucks
eval std_shrext=\"$shrext_cmds\"
# Only execute mode is allowed to have -dlopen flags.
if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
func_error "unrecognized option \`-dlopen'"
$ECHO "$help" 1>&2
exit $EXIT_FAILURE
fi
# Change the help message to a mode-specific one.
generic_help="$help"
help="Try \`$progname --help --mode=$opt_mode' for more information."
}
# Bail if the options were screwed
$exit_cmd $EXIT_FAILURE
}
## ----------- ##
## Main. ##
## ----------- ##
# func_lalib_p file
# True iff FILE is a libtool `.la' library or `.lo' object file.
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_lalib_p ()
{
test -f "$1" &&
$SED -e 4q "$1" 2>/dev/null \
| $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
}
# func_lalib_unsafe_p file
# True iff FILE is a libtool `.la' library or `.lo' object file.
# This function implements the same check as func_lalib_p without
# resorting to external programs. To this end, it redirects stdin and
# closes it afterwards, without saving the original file descriptor.
# As a safety measure, use it only where a negative result would be
# fatal anyway. Works if `file' does not exist.
func_lalib_unsafe_p ()
{
lalib_p=no
if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
for lalib_p_l in 1 2 3 4
do
read lalib_p_line
case "$lalib_p_line" in
\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
esac
done
exec 0<&5 5<&-
fi
test "$lalib_p" = yes
}
# func_ltwrapper_script_p file
# True iff FILE is a libtool wrapper script
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_script_p ()
{
func_lalib_p "$1"
}
# func_ltwrapper_executable_p file
# True iff FILE is a libtool wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_executable_p ()
{
func_ltwrapper_exec_suffix=
case $1 in
*.exe) ;;
*) func_ltwrapper_exec_suffix=.exe ;;
esac
$GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
}
# func_ltwrapper_scriptname file
# Assumes file is an ltwrapper_executable
# uses $file to determine the appropriate filename for a
# temporary ltwrapper_script.
func_ltwrapper_scriptname ()
{
func_dirname_and_basename "$1" "" "."
func_stripname '' '.exe' "$func_basename_result"
func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
}
# func_ltwrapper_p file
# True iff FILE is a libtool wrapper script or wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_p ()
{
func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
}
# func_execute_cmds commands fail_cmd
# Execute tilde-delimited COMMANDS.
# If FAIL_CMD is given, eval that upon failure.
# FAIL_CMD may read-access the current command in variable CMD!
func_execute_cmds ()
{
$opt_debug
save_ifs=$IFS; IFS='~'
for cmd in $1; do
IFS=$save_ifs
eval cmd=\"$cmd\"
func_show_eval "$cmd" "${2-:}"
done
IFS=$save_ifs
}
# func_source file
# Source FILE, adding directory component if necessary.
# Note that it is not necessary on cygwin/mingw to append a dot to
# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
# behavior happens only for exec(3), not for open(2)! Also, sourcing
# `FILE.' does not work on cygwin managed mounts.
func_source ()
{
$opt_debug
case $1 in
*/* | *\\*) . "$1" ;;
*) . "./$1" ;;
esac
}
# func_resolve_sysroot PATH
# Replace a leading = in PATH with a sysroot. Store the result into
# func_resolve_sysroot_result
func_resolve_sysroot ()
{
func_resolve_sysroot_result=$1
case $func_resolve_sysroot_result in
=*)
func_stripname '=' '' "$func_resolve_sysroot_result"
func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
;;
esac
}
# func_replace_sysroot PATH
# If PATH begins with the sysroot, replace it with = and
# store the result into func_replace_sysroot_result.
func_replace_sysroot ()
{
case "$lt_sysroot:$1" in
?*:"$lt_sysroot"*)
func_stripname "$lt_sysroot" '' "$1"
func_replace_sysroot_result="=$func_stripname_result"
;;
*)
# Including no sysroot.
func_replace_sysroot_result=$1
;;
esac
}
# func_infer_tag arg
# Infer tagged configuration to use if any are available and
# if one wasn't chosen via the "--tag" command line option.
# Only attempt this if the compiler in the base compile
# command doesn't match the default compiler.
# arg is usually of the form 'gcc ...'
func_infer_tag ()
{
$opt_debug
if test -n "$available_tags" && test -z "$tagname"; then
CC_quoted=
for arg in $CC; do
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case $@ in
# Blanks in the command may have been stripped by the calling shell,
# but not from the CC environment variable when configure was run.
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
# Blanks at the start of $base_compile will cause this to fail
# if we don't check for them as well.
*)
for z in $available_tags; do
if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
# Evaluate the configuration.
eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
CC_quoted=
for arg in $CC; do
# Double-quote args containing other shell metacharacters.
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case "$@ " in
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
# The compiler in the base compile command matches
# the one in the tagged configuration.
# Assume this is the tagged configuration we want.
tagname=$z
break
;;
esac
fi
done
# If $tagname still isn't set, then no tagged configuration
# was found and let the user know that the "--tag" command
# line option must be used.
if test -z "$tagname"; then
func_echo "unable to infer tagged configuration"
func_fatal_error "specify a tag with \`--tag'"
# else
# func_verbose "using $tagname tagged configuration"
fi
;;
esac
fi
}
# func_write_libtool_object output_name pic_name nonpic_name
# Create a libtool object file (analogous to a ".la" file),
# but don't create it if we're doing a dry run.
func_write_libtool_object ()
{
write_libobj=${1}
if test "$build_libtool_libs" = yes; then
write_lobj=\'${2}\'
else
write_lobj=none
fi
if test "$build_old_libs" = yes; then
write_oldobj=\'${3}\'
else
write_oldobj=none
fi
$opt_dry_run || {
cat >${write_libobj}T <<EOF
# $write_libobj - a libtool object file
# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# Name of the PIC object.
pic_object=$write_lobj
# Name of the non-PIC object
non_pic_object=$write_oldobj
EOF
$MV "${write_libobj}T" "${write_libobj}"
}
}
##################################################
# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
##################################################
# func_convert_core_file_wine_to_w32 ARG
# Helper function used by file name conversion functions when $build is *nix,
# and $host is mingw, cygwin, or some other w32 environment. Relies on a
# correctly configured wine environment available, with the winepath program
# in $build's $PATH.
#
# ARG is the $build file name to be converted to w32 format.
# Result is available in $func_convert_core_file_wine_to_w32_result, and will
# be empty on error (or when ARG is empty)
func_convert_core_file_wine_to_w32 ()
{
$opt_debug
func_convert_core_file_wine_to_w32_result="$1"
if test -n "$1"; then
# Unfortunately, winepath does not exit with a non-zero error code, so we
# are forced to check the contents of stdout. On the other hand, if the
# command is not found, the shell will set an exit code of 127 and print
# *an error message* to stdout. So we must check for both error code of
# zero AND non-empty stdout, which explains the odd construction:
func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
$SED -e "$lt_sed_naive_backslashify"`
else
func_convert_core_file_wine_to_w32_result=
fi
fi
}
# end: func_convert_core_file_wine_to_w32
# func_convert_core_path_wine_to_w32 ARG
# Helper function used by path conversion functions when $build is *nix, and
# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
# configured wine environment available, with the winepath program in $build's
# $PATH. Assumes ARG has no leading or trailing path separator characters.
#
# ARG is path to be converted from $build format to win32.
# Result is available in $func_convert_core_path_wine_to_w32_result.
# Unconvertible file (directory) names in ARG are skipped; if no directory names
# are convertible, then the result may be empty.
func_convert_core_path_wine_to_w32 ()
{
$opt_debug
# unfortunately, winepath doesn't convert paths, only file names
func_convert_core_path_wine_to_w32_result=""
if test -n "$1"; then
oldIFS=$IFS
IFS=:
for func_convert_core_path_wine_to_w32_f in $1; do
IFS=$oldIFS
func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
if test -n "$func_convert_core_file_wine_to_w32_result" ; then
if test -z "$func_convert_core_path_wine_to_w32_result"; then
func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
else
func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
fi
fi
done
IFS=$oldIFS
fi
}
# end: func_convert_core_path_wine_to_w32
# func_cygpath ARGS...
# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
# (2), returns the Cygwin file name or path in func_cygpath_result (input
# file name or path is assumed to be in w32 format, as previously converted
# from $build's *nix or MSYS format). In case (3), returns the w32 file name
# or path in func_cygpath_result (input file name or path is assumed to be in
# Cygwin format). Returns an empty string on error.
#
# ARGS are passed to cygpath, with the last one being the file name or path to
# be converted.
#
# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
# environment variable; do not put it in $PATH.
func_cygpath ()
{
$opt_debug
if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
if test "$?" -ne 0; then
# on failure, ensure result is empty
func_cygpath_result=
fi
else
func_cygpath_result=
func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
fi
}
#end: func_cygpath
# func_convert_core_msys_to_w32 ARG
# Convert file name or path ARG from MSYS format to w32 format. Return
# result in func_convert_core_msys_to_w32_result.
func_convert_core_msys_to_w32 ()
{
$opt_debug
# awkward: cmd appends spaces to result
func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
$SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
}
#end: func_convert_core_msys_to_w32
# func_convert_file_check ARG1 ARG2
# Verify that ARG1 (a file name in $build format) was converted to $host
# format in ARG2. Otherwise, emit an error message, but continue (resetting
# func_to_host_file_result to ARG1).
func_convert_file_check ()
{
$opt_debug
if test -z "$2" && test -n "$1" ; then
func_error "Could not determine host file name corresponding to"
func_error " \`$1'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback:
func_to_host_file_result="$1"
fi
}
# end func_convert_file_check
# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
# Verify that FROM_PATH (a path in $build format) was converted to $host
# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
# func_to_host_file_result to a simplistic fallback value (see below).
func_convert_path_check ()
{
$opt_debug
if test -z "$4" && test -n "$3"; then
func_error "Could not determine the host path corresponding to"
func_error " \`$3'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback. This is a deliberately simplistic "conversion" and
# should not be "improved". See libtool.info.
if test "x$1" != "x$2"; then
lt_replace_pathsep_chars="s|$1|$2|g"
func_to_host_path_result=`echo "$3" |
$SED -e "$lt_replace_pathsep_chars"`
else
func_to_host_path_result="$3"
fi
fi
}
# end func_convert_path_check
# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
# and appending REPL if ORIG matches BACKPAT.
func_convert_path_front_back_pathsep ()
{
$opt_debug
case $4 in
$1 ) func_to_host_path_result="$3$func_to_host_path_result"
;;
esac
case $4 in
$2 ) func_append func_to_host_path_result "$3"
;;
esac
}
# end func_convert_path_front_back_pathsep
##################################################
# $build to $host FILE NAME CONVERSION FUNCTIONS #
##################################################
# invoked via `$to_host_file_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# Result will be available in $func_to_host_file_result.
# func_to_host_file ARG
# Converts the file name ARG from $build format to $host format. Return result
# in func_to_host_file_result.
func_to_host_file ()
{
$opt_debug
$to_host_file_cmd "$1"
}
# end func_to_host_file
# func_to_tool_file ARG LAZY
# converts the file name ARG from $build format to toolchain format. Return
# result in func_to_tool_file_result. If the conversion in use is listed
# in (the comma separated) LAZY, no conversion takes place.
func_to_tool_file ()
{
$opt_debug
case ,$2, in
*,"$to_tool_file_cmd",*)
func_to_tool_file_result=$1
;;
*)
$to_tool_file_cmd "$1"
func_to_tool_file_result=$func_to_host_file_result
;;
esac
}
# end func_to_tool_file
# func_convert_file_noop ARG
# Copy ARG to func_to_host_file_result.
func_convert_file_noop ()
{
func_to_host_file_result="$1"
}
# end func_convert_file_noop
# func_convert_file_msys_to_w32 ARG
# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_file_result.
func_convert_file_msys_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_msys_to_w32 "$1"
func_to_host_file_result="$func_convert_core_msys_to_w32_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_w32
# func_convert_file_cygwin_to_w32 ARG
# Convert file name ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_file_cygwin_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
# because $build is cygwin, we call "the" cygpath in $PATH; no need to use
# LT_CYGPATH in this case.
func_to_host_file_result=`cygpath -m "$1"`
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_cygwin_to_w32
# func_convert_file_nix_to_w32 ARG
# Convert file name ARG from *nix to w32 format. Requires a wine environment
# and a working winepath. Returns result in func_to_host_file_result.
func_convert_file_nix_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_file_wine_to_w32 "$1"
func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_w32
# func_convert_file_msys_to_cygwin ARG
# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_file_msys_to_cygwin ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_msys_to_w32 "$1"
func_cygpath -u "$func_convert_core_msys_to_w32_result"
func_to_host_file_result="$func_cygpath_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_cygwin
# func_convert_file_nix_to_cygwin ARG
# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
# in func_to_host_file_result.
func_convert_file_nix_to_cygwin ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
# convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
func_convert_core_file_wine_to_w32 "$1"
func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
func_to_host_file_result="$func_cygpath_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_cygwin
#############################################
# $build to $host PATH CONVERSION FUNCTIONS #
#############################################
# invoked via `$to_host_path_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# The result will be available in $func_to_host_path_result.
#
# Path separators are also converted from $build format to $host format. If
# ARG begins or ends with a path separator character, it is preserved (but
# converted to $host format) on output.
#
# All path conversion functions are named using the following convention:
# file name conversion function : func_convert_file_X_to_Y ()
# path conversion function : func_convert_path_X_to_Y ()
# where, for any given $build/$host combination the 'X_to_Y' value is the
# same. If conversion functions are added for new $build/$host combinations,
# the two new functions must follow this pattern, or func_init_to_host_path_cmd
# will break.
# func_init_to_host_path_cmd
# Ensures that function "pointer" variable $to_host_path_cmd is set to the
# appropriate value, based on the value of $to_host_file_cmd.
to_host_path_cmd=
func_init_to_host_path_cmd ()
{
$opt_debug
if test -z "$to_host_path_cmd"; then
func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
to_host_path_cmd="func_convert_path_${func_stripname_result}"
fi
}
# func_to_host_path ARG
# Converts the path ARG from $build format to $host format. Return result
# in func_to_host_path_result.
func_to_host_path ()
{
$opt_debug
func_init_to_host_path_cmd
$to_host_path_cmd "$1"
}
# end func_to_host_path
# func_convert_path_noop ARG
# Copy ARG to func_to_host_path_result.
func_convert_path_noop ()
{
func_to_host_path_result="$1"
}
# end func_convert_path_noop
# func_convert_path_msys_to_w32 ARG
# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_path_result.
func_convert_path_msys_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# Remove leading and trailing path separator characters from ARG. MSYS
# behavior is inconsistent here; cygpath turns them into '.;' and ';.';
# and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result="$func_convert_core_msys_to_w32_result"
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_msys_to_w32
# func_convert_path_cygwin_to_w32 ARG
# Convert path ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_path_cygwin_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_cygwin_to_w32
# func_convert_path_nix_to_w32 ARG
# Convert path ARG from *nix to w32 format. Requires a wine environment and
# a working winepath. Returns result in func_to_host_file_result.
func_convert_path_nix_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_nix_to_w32
# func_convert_path_msys_to_cygwin ARG
# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_path_msys_to_cygwin ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
func_to_host_path_result="$func_cygpath_result"
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_msys_to_cygwin
# func_convert_path_nix_to_cygwin ARG
# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
# func_to_host_file_result.
func_convert_path_nix_to_cygwin ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# Remove leading and trailing path separator characters from
# ARG. msys behavior is inconsistent here, cygpath turns them
# into '.;' and ';.', and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
func_to_host_path_result="$func_cygpath_result"
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_nix_to_cygwin
# func_mode_compile arg...
func_mode_compile ()
{
$opt_debug
# Get the compilation command and the source file.
base_compile=
srcfile="$nonopt" # always keep a non-empty value in "srcfile"
suppress_opt=yes
suppress_output=
arg_mode=normal
libobj=
later=
pie_flag=
for arg
do
case $arg_mode in
arg )
# do not "continue". Instead, add this to base_compile
lastarg="$arg"
arg_mode=normal
;;
target )
libobj="$arg"
arg_mode=normal
continue
;;
normal )
# Accept any command-line options.
case $arg in
-o)
test -n "$libobj" && \
func_fatal_error "you cannot specify \`-o' more than once"
arg_mode=target
continue
;;
-pie | -fpie | -fPIE)
func_append pie_flag " $arg"
continue
;;
-shared | -static | -prefer-pic | -prefer-non-pic)
func_append later " $arg"
continue
;;
-no-suppress)
suppress_opt=no
continue
;;
-Xcompiler)
arg_mode=arg # the next one goes into the "base_compile" arg list
continue # The current "srcfile" will either be retained or
;; # replaced later. I would guess that would be a bug.
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
lastarg=
save_ifs="$IFS"; IFS=','
for arg in $args; do
IFS="$save_ifs"
func_append_quoted lastarg "$arg"
done
IFS="$save_ifs"
func_stripname ' ' '' "$lastarg"
lastarg=$func_stripname_result
# Add the arguments to base_compile.
func_append base_compile " $lastarg"
continue
;;
*)
# Accept the current argument as the source file.
# The previous "srcfile" becomes the current argument.
#
lastarg="$srcfile"
srcfile="$arg"
;;
esac # case $arg
;;
esac # case $arg_mode
# Aesthetically quote the previous argument.
func_append_quoted base_compile "$lastarg"
done # for arg
case $arg_mode in
arg)
func_fatal_error "you must specify an argument for -Xcompile"
;;
target)
func_fatal_error "you must specify a target with \`-o'"
;;
*)
# Get the name of the library object.
test -z "$libobj" && {
func_basename "$srcfile"
libobj="$func_basename_result"
}
;;
esac
# Recognize several different file suffixes.
# If the user specifies -o file.o, it is replaced with file.lo
case $libobj in
*.[cCFSifmso] | \
*.ada | *.adb | *.ads | *.asm | \
*.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
*.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
func_xform "$libobj"
libobj=$func_xform_result
;;
esac
case $libobj in
*.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
*)
func_fatal_error "cannot determine name of library object from \`$libobj'"
;;
esac
func_infer_tag $base_compile
for arg in $later; do
case $arg in
-shared)
test "$build_libtool_libs" != yes && \
func_fatal_configuration "can not build a shared library"
build_old_libs=no
continue
;;
-static)
build_libtool_libs=no
build_old_libs=yes
continue
;;
-prefer-pic)
pic_mode=yes
continue
;;
-prefer-non-pic)
pic_mode=no
continue
;;
esac
done
func_quote_for_eval "$libobj"
test "X$libobj" != "X$func_quote_for_eval_result" \
&& $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
&& func_warning "libobj name \`$libobj' may not contain shell special characters."
func_dirname_and_basename "$obj" "/" ""
objname="$func_basename_result"
xdir="$func_dirname_result"
lobj=${xdir}$objdir/$objname
test -z "$base_compile" && \
func_fatal_help "you must specify a compilation command"
# Delete any leftover library objects.
if test "$build_old_libs" = yes; then
removelist="$obj $lobj $libobj ${libobj}T"
else
removelist="$lobj $libobj ${libobj}T"
fi
# On Cygwin there's no "real" PIC flag so we must build both object types
case $host_os in
cygwin* | mingw* | pw32* | os2* | cegcc*)
pic_mode=default
;;
esac
if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
# non-PIC code in shared libraries is not supported
pic_mode=default
fi
# Calculate the filename of the output object if compiler does
# not support -o with -c
if test "$compiler_c_o" = no; then
output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
lockfile="$output_obj.lock"
else
output_obj=
need_locks=no
lockfile=
fi
# Lock this critical section if it is needed
# We use this script file to make the link, it avoids creating a new file
if test "$need_locks" = yes; then
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
elif test "$need_locks" = warn; then
if test -f "$lockfile"; then
$ECHO "\
*** ERROR, $lockfile exists and contains:
`cat $lockfile 2>/dev/null`
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
func_append removelist " $output_obj"
$ECHO "$srcfile" > "$lockfile"
fi
$opt_dry_run || $RM $removelist
func_append removelist " $lockfile"
trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
srcfile=$func_to_tool_file_result
func_quote_for_eval "$srcfile"
qsrcfile=$func_quote_for_eval_result
# Only build a PIC object if we are building libtool libraries.
if test "$build_libtool_libs" = yes; then
# Without this assignment, base_compile gets emptied.
fbsd_hideous_sh_bug=$base_compile
if test "$pic_mode" != no; then
command="$base_compile $qsrcfile $pic_flag"
else
# Don't build PIC code
command="$base_compile $qsrcfile"
fi
func_mkdir_p "$xdir$objdir"
if test -z "$output_obj"; then
# Place PIC objects in $objdir
func_append command " -o $lobj"
fi
func_show_eval_locale "$command" \
'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
if test "$need_locks" = warn &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed, then go on to compile the next one
if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
func_show_eval '$MV "$output_obj" "$lobj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
# Allow error messages only from the first compilation.
if test "$suppress_opt" = yes; then
suppress_output=' >/dev/null 2>&1'
fi
fi
# Only build a position-dependent object if we build old libraries.
if test "$build_old_libs" = yes; then
if test "$pic_mode" != yes; then
# Don't build PIC code
command="$base_compile $qsrcfile$pie_flag"
else
command="$base_compile $qsrcfile $pic_flag"
fi
if test "$compiler_c_o" = yes; then
func_append command " -o $obj"
fi
# Suppress compiler output if we already did a PIC compilation.
func_append command "$suppress_output"
func_show_eval_locale "$command" \
'$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
if test "$need_locks" = warn &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed
if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
func_show_eval '$MV "$output_obj" "$obj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
fi
$opt_dry_run || {
func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
# Unlock the critical section if it was locked
if test "$need_locks" != no; then
removelist=$lockfile
$RM "$lockfile"
fi
}
exit $EXIT_SUCCESS
}
$opt_help || {
test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
}
func_mode_help ()
{
# We need to display help for each of the modes.
case $opt_mode in
"")
# Generic help is extracted from the usage comments
# at the start of this file.
func_help
;;
clean)
$ECHO \
"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
Remove files from the build directory.
RM is the name of the program to use to delete files associated with each FILE
(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
to RM.
If FILE is a libtool library, object or program, all the files associated
with it are deleted. Otherwise, only FILE itself is deleted using RM."
;;
compile)
$ECHO \
"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
Compile a source file into a libtool library object.
This mode accepts the following additional options:
-o OUTPUT-FILE set the output file name to OUTPUT-FILE
-no-suppress do not suppress compiler output for multiple passes
-prefer-pic try to build PIC objects only
-prefer-non-pic try to build non-PIC objects only
-shared do not build a \`.o' file suitable for static linking
-static only build a \`.o' file suitable for static linking
-Wc,FLAG pass FLAG directly to the compiler
COMPILE-COMMAND is a command to be used in creating a \`standard' object file
from the given SOURCEFILE.
The output file name is determined by removing the directory component from
SOURCEFILE, then substituting the C source code suffix \`.c' with the
library object suffix, \`.lo'."
;;
execute)
$ECHO \
"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
Automatically set library path, then run a program.
This mode accepts the following additional options:
-dlopen FILE add the directory containing FILE to the library path
This mode sets the library path environment variable according to \`-dlopen'
flags.
If any of the ARGS are libtool executable wrappers, then they are translated
into their corresponding uninstalled binary, and any of their required library
directories are added to the library path.
Then, COMMAND is executed, with ARGS as arguments."
;;
finish)
$ECHO \
"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
Complete the installation of libtool libraries.
Each LIBDIR is a directory that contains libtool libraries.
The commands that this mode executes may require superuser privileges. Use
the \`--dry-run' option if you just want to see what would be executed."
;;
install)
$ECHO \
"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
Install executables or libraries.
INSTALL-COMMAND is the installation command. The first component should be
either the \`install' or \`cp' program.
The following components of INSTALL-COMMAND are treated specially:
-inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
The rest of the components are interpreted as arguments to that command (only
BSD-compatible install options are recognized)."
;;
link)
$ECHO \
"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
Link object files or libraries together to form another library, or to
create an executable program.
LINK-COMMAND is a command using the C compiler that you would use to create
a program from several object files.
The following components of LINK-COMMAND are treated specially:
-all-static do not do any dynamic linking at all
-avoid-version do not add a version suffix if possible
-bindir BINDIR specify path to binaries directory (for systems where
libraries must be found in the PATH setting at runtime)
-dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
-dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
-export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-export-symbols SYMFILE
try to export only the symbols listed in SYMFILE
-export-symbols-regex REGEX
try to export only the symbols matching REGEX
-LLIBDIR search LIBDIR for required installed libraries
-lNAME OUTPUT-FILE requires the installed library libNAME
-module build a library that can dlopened
-no-fast-install disable the fast-install mode
-no-install link a not-installable executable
-no-undefined declare that a library does not refer to external symbols
-o OUTPUT-FILE create OUTPUT-FILE from the specified objects
-objectlist FILE Use a list of object files found in FILE to specify objects
-precious-files-regex REGEX
don't remove output files matching REGEX
-release RELEASE specify package release information
-rpath LIBDIR the created library will eventually be installed in LIBDIR
-R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
-shared only do dynamic linking of libtool libraries
-shrext SUFFIX override the standard shared library file extension
-static do not do any dynamic linking of uninstalled libtool libraries
-static-libtool-libs
do not do any dynamic linking of libtool libraries
-version-info CURRENT[:REVISION[:AGE]]
specify library version info [each variable defaults to 0]
-weak LIBNAME declare that the target provides the LIBNAME interface
-Wc,FLAG
-Xcompiler FLAG pass linker-specific FLAG directly to the compiler
-Wl,FLAG
-Xlinker FLAG pass linker-specific FLAG directly to the linker
-XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
All other options (arguments beginning with \`-') are ignored.
Every other argument is treated as a filename. Files ending in \`.la' are
treated as uninstalled libtool libraries, other files are standard or library
object files.
If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
only library objects (\`.lo' files) may be specified, and \`-rpath' is
required, except when creating a convenience library.
If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
using \`ar' and \`ranlib', or on Windows using \`lib'.
If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
is created, otherwise an executable program is created."
;;
uninstall)
$ECHO \
"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
Remove libraries from an installation directory.
RM is the name of the program to use to delete files associated with each FILE
(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
to RM.
If FILE is a libtool library, all the files associated with it are deleted.
Otherwise, only FILE itself is deleted using RM."
;;
*)
func_fatal_help "invalid operation mode \`$opt_mode'"
;;
esac
echo
$ECHO "Try \`$progname --help' for more information about other modes."
}
# Now that we've collected a possible --mode arg, show help if necessary
if $opt_help; then
if test "$opt_help" = :; then
func_mode_help
else
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
func_mode_help
done
} | sed -n '1p; 2,$s/^Usage:/ or: /p'
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
echo
func_mode_help
done
} |
sed '1d
/^When reporting/,/^Report/{
H
d
}
$x
/information about other modes/d
/more detailed .*MODE/d
s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
fi
exit $?
fi
# func_mode_execute arg...
func_mode_execute ()
{
$opt_debug
# The first argument is the command name.
cmd="$nonopt"
test -z "$cmd" && \
func_fatal_help "you must specify a COMMAND"
# Handle -dlopen flags immediately.
for file in $opt_dlopen; do
test -f "$file" \
|| func_fatal_help "\`$file' is not a file"
dir=
case $file in
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "\`$lib' is not a valid libtool archive"
# Read the libtool library.
dlname=
library_names=
func_source "$file"
# Skip this library if it cannot be dlopened.
if test -z "$dlname"; then
# Warn if it was a shared library.
test -n "$library_names" && \
func_warning "\`$file' was not linked with \`-export-dynamic'"
continue
fi
func_dirname "$file" "" "."
dir="$func_dirname_result"
if test -f "$dir/$objdir/$dlname"; then
func_append dir "/$objdir"
else
if test ! -f "$dir/$dlname"; then
func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
fi
fi
;;
*.lo)
# Just add the directory containing the .lo file.
func_dirname "$file" "" "."
dir="$func_dirname_result"
;;
*)
func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
continue
;;
esac
# Get the absolute pathname.
absdir=`cd "$dir" && pwd`
test -n "$absdir" && dir="$absdir"
# Now add the directory to shlibpath_var.
if eval "test -z \"\$$shlibpath_var\""; then
eval "$shlibpath_var=\"\$dir\""
else
eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
fi
done
# This variable tells wrapper scripts just to set shlibpath_var
# rather than running their programs.
libtool_execute_magic="$magic"
# Check if any of the arguments is a wrapper script.
args=
for file
do
case $file in
-* | *.la | *.lo ) ;;
*)
# Do a test to see if this is really a libtool program.
if func_ltwrapper_script_p "$file"; then
func_source "$file"
# Transform arg to wrapped name.
file="$progdir/$program"
elif func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
func_source "$func_ltwrapper_scriptname_result"
# Transform arg to wrapped name.
file="$progdir/$program"
fi
;;
esac
# Quote arguments (to preserve shell metacharacters).
func_append_quoted args "$file"
done
if test "X$opt_dry_run" = Xfalse; then
if test -n "$shlibpath_var"; then
# Export the shlibpath_var.
eval "export $shlibpath_var"
fi
# Restore saved environment variables
for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${save_$lt_var+set}\" = set; then
$lt_var=\$save_$lt_var; export $lt_var
else
$lt_unset $lt_var
fi"
done
# Now prepare to actually exec the command.
exec_cmd="\$cmd$args"
else
# Display what would be done.
if test -n "$shlibpath_var"; then
eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
echo "export $shlibpath_var"
fi
$ECHO "$cmd$args"
exit $EXIT_SUCCESS
fi
}
test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
# func_mode_finish arg...
func_mode_finish ()
{
$opt_debug
libs=
libdirs=
admincmds=
for opt in "$nonopt" ${1+"$@"}
do
if test -d "$opt"; then
func_append libdirs " $opt"
elif test -f "$opt"; then
if func_lalib_unsafe_p "$opt"; then
func_append libs " $opt"
else
func_warning "\`$opt' is not a valid libtool archive"
fi
else
func_fatal_error "invalid argument \`$opt'"
fi
done
if test -n "$libs"; then
if test -n "$lt_sysroot"; then
sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
else
sysroot_cmd=
fi
# Remove sysroot references
if $opt_dry_run; then
for lib in $libs; do
echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
done
else
tmpdir=`func_mktempdir`
for lib in $libs; do
sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
> $tmpdir/tmp-la
mv -f $tmpdir/tmp-la $lib
done
${RM}r "$tmpdir"
fi
fi
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
for libdir in $libdirs; do
if test -n "$finish_cmds"; then
# Do each command in the finish commands.
func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
'"$cmd"'"'
fi
if test -n "$finish_eval"; then
# Do the single finish_eval.
eval cmds=\"$finish_eval\"
$opt_dry_run || eval "$cmds" || func_append admincmds "
$cmds"
fi
done
fi
# Exit here if they wanted silent mode.
$opt_silent && exit $EXIT_SUCCESS
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
echo "----------------------------------------------------------------------"
echo "Libraries have been installed in:"
for libdir in $libdirs; do
$ECHO " $libdir"
done
echo
echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and"
echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
echo "flag during linking and do at least one of the following:"
if test -n "$shlibpath_var"; then
echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
echo " during execution"
fi
if test -n "$runpath_var"; then
echo " - add LIBDIR to the \`$runpath_var' environment variable"
echo " during linking"
fi
if test -n "$hardcode_libdir_flag_spec"; then
libdir=LIBDIR
eval flag=\"$hardcode_libdir_flag_spec\"
$ECHO " - use the \`$flag' linker flag"
fi
if test -n "$admincmds"; then
$ECHO " - have your system administrator run these commands:$admincmds"
fi
if test -f /etc/ld.so.conf; then
echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
fi
echo
echo "See any operating system documentation about shared libraries for"
case $host in
solaris2.[6789]|solaris2.1[0-9])
echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
echo "pages."
;;
*)
echo "more information, such as the ld(1) and ld.so(8) manual pages."
;;
esac
echo "----------------------------------------------------------------------"
fi
exit $EXIT_SUCCESS
}
test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
# func_mode_install arg...
func_mode_install ()
{
$opt_debug
# There may be an optional sh(1) argument at the beginning of
# install_prog (especially on Windows NT).
if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
# Allow the use of GNU shtool's install command.
case $nonopt in *shtool*) :;; *) false;; esac; then
# Aesthetically quote it.
func_quote_for_eval "$nonopt"
install_prog="$func_quote_for_eval_result "
arg=$1
shift
else
install_prog=
arg=$nonopt
fi
# The real first argument should be the name of the installation program.
# Aesthetically quote it.
func_quote_for_eval "$arg"
func_append install_prog "$func_quote_for_eval_result"
install_shared_prog=$install_prog
case " $install_prog " in
*[\\\ /]cp\ *) install_cp=: ;;
*) install_cp=false ;;
esac
# We need to accept at least all the BSD install flags.
dest=
files=
opts=
prev=
install_type=
isdir=no
stripme=
no_mode=:
for arg
do
arg2=
if test -n "$dest"; then
func_append files " $dest"
dest=$arg
continue
fi
case $arg in
-d) isdir=yes ;;
-f)
if $install_cp; then :; else
prev=$arg
fi
;;
-g | -m | -o)
prev=$arg
;;
-s)
stripme=" -s"
continue
;;
-*)
;;
*)
# If the previous option needed an argument, then skip it.
if test -n "$prev"; then
if test "x$prev" = x-m && test -n "$install_override_mode"; then
arg2=$install_override_mode
no_mode=false
fi
prev=
else
dest=$arg
continue
fi
;;
esac
# Aesthetically quote the argument.
func_quote_for_eval "$arg"
func_append install_prog " $func_quote_for_eval_result"
if test -n "$arg2"; then
func_quote_for_eval "$arg2"
fi
func_append install_shared_prog " $func_quote_for_eval_result"
done
test -z "$install_prog" && \
func_fatal_help "you must specify an install program"
test -n "$prev" && \
func_fatal_help "the \`$prev' option requires an argument"
if test -n "$install_override_mode" && $no_mode; then
if $install_cp; then :; else
func_quote_for_eval "$install_override_mode"
func_append install_shared_prog " -m $func_quote_for_eval_result"
fi
fi
if test -z "$files"; then
if test -z "$dest"; then
func_fatal_help "no file or destination specified"
else
func_fatal_help "you must specify a destination"
fi
fi
# Strip any trailing slash from the destination.
func_stripname '' '/' "$dest"
dest=$func_stripname_result
# Check to see that the destination is a directory.
test -d "$dest" && isdir=yes
if test "$isdir" = yes; then
destdir="$dest"
destname=
else
func_dirname_and_basename "$dest" "" "."
destdir="$func_dirname_result"
destname="$func_basename_result"
# Not a directory, so check to see that there is only one file specified.
set dummy $files; shift
test "$#" -gt 1 && \
func_fatal_help "\`$dest' is not a directory"
fi
case $destdir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
for file in $files; do
case $file in
*.lo) ;;
*)
func_fatal_help "\`$destdir' must be an absolute directory name"
;;
esac
done
;;
esac
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic="$magic"
staticlibs=
future_libdirs=
current_libdirs=
for file in $files; do
# Do each installation.
case $file in
*.$libext)
# Do the static libraries later.
func_append staticlibs " $file"
;;
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "\`$file' is not a valid libtool archive"
library_names=
old_library=
relink_command=
func_source "$file"
# Add the libdir to current_libdirs if it is the destination.
if test "X$destdir" = "X$libdir"; then
case "$current_libdirs " in
*" $libdir "*) ;;
*) func_append current_libdirs " $libdir" ;;
esac
else
# Note the libdir as a future libdir.
case "$future_libdirs " in
*" $libdir "*) ;;
*) func_append future_libdirs " $libdir" ;;
esac
fi
func_dirname "$file" "/" ""
dir="$func_dirname_result"
func_append dir "$objdir"
if test -n "$relink_command"; then
# Determine the prefix the user has applied to our future dir.
inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
# Don't allow the user to place us outside of our expected
# location b/c this prevents finding dependent libraries that
# are installed to the same prefix.
# At present, this check doesn't affect windows .dll's that
# are installed into $libdir/../bin (currently, that works fine)
# but it's something to keep an eye on.
test "$inst_prefix_dir" = "$destdir" && \
func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
if test -n "$inst_prefix_dir"; then
# Stick the inst_prefix_dir data into the link command.
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
else
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
fi
func_warning "relinking \`$file'"
func_show_eval "$relink_command" \
'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
fi
# See the names of the shared library.
set dummy $library_names; shift
if test -n "$1"; then
realname="$1"
shift
srcname="$realname"
test -n "$relink_command" && srcname="$realname"T
# Install the shared library and build the symlinks.
func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
'exit $?'
tstripme="$stripme"
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
case $realname in
*.dll.a)
tstripme=""
;;
esac
;;
esac
if test -n "$tstripme" && test -n "$striplib"; then
func_show_eval "$striplib $destdir/$realname" 'exit $?'
fi
if test "$#" -gt 0; then
# Delete the old symlinks, and create new ones.
# Try `ln -sf' first, because the `ln' binary might depend on
# the symlink we replace! Solaris /bin/ln does not understand -f,
# so we also need to try rm && ln -s.
for linkname
do
test "$linkname" != "$realname" \
&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
done
fi
# Do each command in the postinstall commands.
lib="$destdir/$realname"
func_execute_cmds "$postinstall_cmds" 'exit $?'
fi
# Install the pseudo-library for information purposes.
func_basename "$file"
name="$func_basename_result"
instname="$dir/$name"i
func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
# Maybe install the static library, too.
test -n "$old_library" && func_append staticlibs " $dir/$old_library"
;;
*.lo)
# Install (i.e. copy) a libtool object.
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile="$destdir/$destname"
else
func_basename "$file"
destfile="$func_basename_result"
destfile="$destdir/$destfile"
fi
# Deduce the name of the destination old-style object file.
case $destfile in
*.lo)
func_lo2o "$destfile"
staticdest=$func_lo2o_result
;;
*.$objext)
staticdest="$destfile"
destfile=
;;
*)
func_fatal_help "cannot copy a libtool object to \`$destfile'"
;;
esac
# Install the libtool object if requested.
test -n "$destfile" && \
func_show_eval "$install_prog $file $destfile" 'exit $?'
# Install the old object if enabled.
if test "$build_old_libs" = yes; then
# Deduce the name of the old-style object file.
func_lo2o "$file"
staticobj=$func_lo2o_result
func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
fi
exit $EXIT_SUCCESS
;;
*)
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile="$destdir/$destname"
else
func_basename "$file"
destfile="$func_basename_result"
destfile="$destdir/$destfile"
fi
# If the file is missing, and there is a .exe on the end, strip it
# because it is most likely a libtool script we actually want to
# install
stripped_ext=""
case $file in
*.exe)
if test ! -f "$file"; then
func_stripname '' '.exe' "$file"
file=$func_stripname_result
stripped_ext=".exe"
fi
;;
esac
# Do a test to see if this is really a libtool program.
case $host in
*cygwin* | *mingw*)
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
wrapper=$func_ltwrapper_scriptname_result
else
func_stripname '' '.exe' "$file"
wrapper=$func_stripname_result
fi
;;
*)
wrapper=$file
;;
esac
if func_ltwrapper_script_p "$wrapper"; then
notinst_deplibs=
relink_command=
func_source "$wrapper"
# Check the variables that should have been set.
test -z "$generated_by_libtool_version" && \
func_fatal_error "invalid libtool wrapper script \`$wrapper'"
finalize=yes
for lib in $notinst_deplibs; do
# Check to see that each library is installed.
libdir=
if test -f "$lib"; then
func_source "$lib"
fi
libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
if test -n "$libdir" && test ! -f "$libfile"; then
func_warning "\`$lib' has not been installed in \`$libdir'"
finalize=no
fi
done
relink_command=
func_source "$wrapper"
outputname=
if test "$fast_install" = no && test -n "$relink_command"; then
$opt_dry_run || {
if test "$finalize" = yes; then
tmpdir=`func_mktempdir`
func_basename "$file$stripped_ext"
file="$func_basename_result"
outputname="$tmpdir/$file"
# Replace the output file specification.
relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
$opt_silent || {
func_quote_for_expand "$relink_command"
eval "func_echo $func_quote_for_expand_result"
}
if eval "$relink_command"; then :
else
func_error "error: relink \`$file' with the above command before installing it"
$opt_dry_run || ${RM}r "$tmpdir"
continue
fi
file="$outputname"
else
func_warning "cannot relink \`$file'"
fi
}
else
# Install the binary that we compiled earlier.
file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
fi
fi
# remove .exe since cygwin /usr/bin/install will append another
# one anyway
case $install_prog,$host in
*/usr/bin/install*,*cygwin*)
case $file:$destfile in
*.exe:*.exe)
# this is ok
;;
*.exe:*)
destfile=$destfile.exe
;;
*:*.exe)
func_stripname '' '.exe' "$destfile"
destfile=$func_stripname_result
;;
esac
;;
esac
func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
$opt_dry_run || if test -n "$outputname"; then
${RM}r "$tmpdir"
fi
;;
esac
done
for file in $staticlibs; do
func_basename "$file"
name="$func_basename_result"
# Set up the ranlib parameters.
oldlib="$destdir/$name"
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
if test -n "$stripme" && test -n "$old_striplib"; then
func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
fi
# Do each command in the postinstall commands.
func_execute_cmds "$old_postinstall_cmds" 'exit $?'
done
test -n "$future_libdirs" && \
func_warning "remember to run \`$progname --finish$future_libdirs'"
if test -n "$current_libdirs"; then
# Maybe just do a dry run.
$opt_dry_run && current_libdirs=" -n$current_libdirs"
exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
else
exit $EXIT_SUCCESS
fi
}
test "$opt_mode" = install && func_mode_install ${1+"$@"}
# func_generate_dlsyms outputname originator pic_p
# Extract symbols from dlprefiles and create ${outputname}S.o with
# a dlpreopen symbol table.
func_generate_dlsyms ()
{
$opt_debug
my_outputname="$1"
my_originator="$2"
my_pic_p="${3-no}"
my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
my_dlsyms=
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
if test -n "$NM" && test -n "$global_symbol_pipe"; then
my_dlsyms="${my_outputname}S.c"
else
func_error "not configured to extract global symbols from dlpreopened files"
fi
fi
if test -n "$my_dlsyms"; then
case $my_dlsyms in
"") ;;
*.c)
# Discover the nlist of each of the dlfiles.
nlist="$output_objdir/${my_outputname}.nm"
func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
# Parse the name list into a source file.
func_verbose "creating $output_objdir/$my_dlsyms"
$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
#ifdef __cplusplus
extern \"C\" {
#endif
#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
#endif
/* 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
/* External symbol declarations for the compiler. */\
"
if test "$dlself" = yes; then
func_verbose "generating symbol list for \`$output'"
$opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
# Add our own program objects to the symbol list.
progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
for progfile in $progfiles; do
func_to_tool_file "$progfile" func_convert_file_msys_to_w32
func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
$opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
done
if test -n "$exclude_expsyms"; then
$opt_dry_run || {
eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
if test -n "$export_symbols_regex"; then
$opt_dry_run || {
eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
export_symbols="$output_objdir/$outputname.exp"
$opt_dry_run || {
$RM $export_symbols
eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
case $host in
*cygwin* | *mingw* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
;;
esac
}
else
$opt_dry_run || {
eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
case $host in
*cygwin* | *mingw* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
;;
esac
}
fi
fi
for dlprefile in $dlprefiles; do
func_verbose "extracting global C symbols from \`$dlprefile'"
func_basename "$dlprefile"
name="$func_basename_result"
case $host in
*cygwin* | *mingw* | *cegcc* )
# if an import library, we need to obtain dlname
if func_win32_import_lib_p "$dlprefile"; then
func_tr_sh "$dlprefile"
eval "curr_lafile=\$libfile_$func_tr_sh_result"
dlprefile_dlbasename=""
if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
# Use subshell, to avoid clobbering current variable values
dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
if test -n "$dlprefile_dlname" ; then
func_basename "$dlprefile_dlname"
dlprefile_dlbasename="$func_basename_result"
else
# no lafile. user explicitly requested -dlpreopen <import library>.
$sharedlib_from_linklib_cmd "$dlprefile"
dlprefile_dlbasename=$sharedlib_from_linklib_result
fi
fi
$opt_dry_run || {
if test -n "$dlprefile_dlbasename" ; then
eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
else
func_warning "Could not compute DLL name from $name"
eval '$ECHO ": $name " >> "$nlist"'
fi
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
$SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
}
else # not an import lib
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
fi
;;
*)
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
;;
esac
done
$opt_dry_run || {
# Make sure we have at least an empty file.
test -f "$nlist" || : > "$nlist"
if test -n "$exclude_expsyms"; then
$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
$MV "$nlist"T "$nlist"
fi
# Try sorting and uniquifying the output.
if $GREP -v "^: " < "$nlist" |
if sort -k 3 </dev/null >/dev/null 2>&1; then
sort -k 3
else
sort +2
fi |
uniq > "$nlist"S; then
:
else
$GREP -v "^: " < "$nlist" > "$nlist"S
fi
if test -f "$nlist"S; then
eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
else
echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
fi
echo >> "$output_objdir/$my_dlsyms" "\
/* The mapping between symbol names and symbols. */
typedef struct {
const char *name;
void *address;
} lt_dlsymlist;
extern LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[];
LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[] =
{\
{ \"$my_originator\", (void *) 0 },"
case $need_lib_prefix in
no)
eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
*)
eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
esac
echo >> "$output_objdir/$my_dlsyms" "\
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt_${my_prefix}_LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif\
"
} # !$opt_dry_run
pic_flag_for_symtable=
case "$compile_command " in
*" -static "*) ;;
*)
case $host in
# compiling the symbol table file with pic_flag works around
# a FreeBSD bug that causes programs to crash when -lm is
# linked before any other PIC object. But we must not use
# pic_flag when linking with -static. The problem exists in
# FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
*-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
*-*-hpux*)
pic_flag_for_symtable=" $pic_flag" ;;
*)
if test "X$my_pic_p" != Xno; then
pic_flag_for_symtable=" $pic_flag"
fi
;;
esac
;;
esac
symtab_cflags=
for arg in $LTCFLAGS; do
case $arg in
-pie | -fpie | -fPIE) ;;
*) func_append symtab_cflags " $arg" ;;
esac
done
# Now compile the dynamic symbol file.
func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
# Clean up the generated files.
func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
# Transform the symbol file into the correct name.
symfileobj="$output_objdir/${my_outputname}S.$objext"
case $host in
*cygwin* | *mingw* | *cegcc* )
if test -f "$output_objdir/$my_outputname.def"; then
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
else
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
fi
;;
*)
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
;;
esac
;;
*)
func_fatal_error "unknown suffix for \`$my_dlsyms'"
;;
esac
else
# We keep going just in case the user didn't refer to
# lt_preloaded_symbols. The linker will fail if global_symbol_pipe
# really was required.
# Nullify the symbol file.
compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
fi
}
# func_win32_libid arg
# return the library type of file 'arg'
#
# Need a lot of goo to handle *both* DLLs and import libs
# Has to be a shell function in order to 'eat' the argument
# that is supplied when $file_magic_command is called.
# Despite the name, also deal with 64 bit binaries.
func_win32_libid ()
{
$opt_debug
win32_libid_type="unknown"
win32_fileres=`file -L $1 2>/dev/null`
case $win32_fileres in
*ar\ archive\ import\ library*) # definitely import
win32_libid_type="x86 archive import"
;;
*ar\ archive*) # could be an import, or static
# Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
$EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
func_to_tool_file "$1" func_convert_file_msys_to_w32
win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
$SED -n -e '
1,100{
/ I /{
s,.*,import,
p
q
}
}'`
case $win32_nmres in
import*) win32_libid_type="x86 archive import";;
*) win32_libid_type="x86 archive static";;
esac
fi
;;
*DLL*)
win32_libid_type="x86 DLL"
;;
*executable*) # but shell scripts are "executable" too...
case $win32_fileres in
*MS\ Windows\ PE\ Intel*)
win32_libid_type="x86 DLL"
;;
esac
;;
esac
$ECHO "$win32_libid_type"
}
# func_cygming_dll_for_implib ARG
#
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib ()
{
$opt_debug
sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
}
# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
#
# The is the core of a fallback implementation of a
# platform-specific function to extract the name of the
# DLL associated with the specified import library LIBNAME.
#
# SECTION_NAME is either .idata$6 or .idata$7, depending
# on the platform and compiler that created the implib.
#
# Echos the name of the DLL associated with the
# specified import library.
func_cygming_dll_for_implib_fallback_core ()
{
$opt_debug
match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
$OBJDUMP -s --section "$1" "$2" 2>/dev/null |
$SED '/^Contents of section '"$match_literal"':/{
# Place marker at beginning of archive member dllname section
s/.*/====MARK====/
p
d
}
# These lines can sometimes be longer than 43 characters, but
# are always uninteresting
/:[ ]*file format pe[i]\{,1\}-/d
/^In archive [^:]*:/d
# Ensure marker is printed
/^====MARK====/p
# Remove all lines with less than 43 characters
/^.\{43\}/!d
# From remaining lines, remove first 43 characters
s/^.\{43\}//' |
$SED -n '
# Join marker and all lines until next marker into a single line
/^====MARK====/ b para
H
$ b para
b
:para
x
s/\n//g
# Remove the marker
s/^====MARK====//
# Remove trailing dots and whitespace
s/[\. \t]*$//
# Print
/./p' |
# we now have a list, one entry per line, of the stringified
# contents of the appropriate section of all members of the
# archive which possess that section. Heuristic: eliminate
# all those which have a first or second character that is
# a '.' (that is, objdump's representation of an unprintable
# character.) This should work for all archives with less than
# 0x302f exports -- but will fail for DLLs whose name actually
# begins with a literal '.' or a single character followed by
# a '.'.
#
# Of those that remain, print the first one.
$SED -e '/^\./d;/^.\./d;q'
}
# func_cygming_gnu_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is a GNU/binutils-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_gnu_implib_p ()
{
$opt_debug
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
test -n "$func_cygming_gnu_implib_tmp"
}
# func_cygming_ms_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is an MS-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_ms_implib_p ()
{
$opt_debug
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
test -n "$func_cygming_ms_implib_tmp"
}
# func_cygming_dll_for_implib_fallback ARG
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
#
# This fallback implementation is for use when $DLLTOOL
# does not support the --identify-strict option.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib_fallback ()
{
$opt_debug
if func_cygming_gnu_implib_p "$1" ; then
# binutils import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
elif func_cygming_ms_implib_p "$1" ; then
# ms-generated import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
else
# unknown
sharedlib_from_linklib_result=""
fi
}
# func_extract_an_archive dir oldlib
func_extract_an_archive ()
{
$opt_debug
f_ex_an_ar_dir="$1"; shift
f_ex_an_ar_oldlib="$1"
if test "$lock_old_archive_extraction" = yes; then
lockfile=$f_ex_an_ar_oldlib.lock
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
fi
func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
'stat=$?; rm -f "$lockfile"; exit $stat'
if test "$lock_old_archive_extraction" = yes; then
$opt_dry_run || rm -f "$lockfile"
fi
if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
:
else
func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
fi
}
# func_extract_archives gentop oldlib ...
func_extract_archives ()
{
$opt_debug
my_gentop="$1"; shift
my_oldlibs=${1+"$@"}
my_oldobjs=""
my_xlib=""
my_xabs=""
my_xdir=""
for my_xlib in $my_oldlibs; do
# Extract the objects.
case $my_xlib in
[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
*) my_xabs=`pwd`"/$my_xlib" ;;
esac
func_basename "$my_xlib"
my_xlib="$func_basename_result"
my_xlib_u=$my_xlib
while :; do
case " $extracted_archives " in
*" $my_xlib_u "*)
func_arith $extracted_serial + 1
extracted_serial=$func_arith_result
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
done
extracted_archives="$extracted_archives $my_xlib_u"
my_xdir="$my_gentop/$my_xlib_u"
func_mkdir_p "$my_xdir"
case $host in
*-darwin*)
func_verbose "Extracting $my_xabs"
# Do not bother doing anything if just a dry run
$opt_dry_run || {
darwin_orig_dir=`pwd`
cd $my_xdir || exit $?
darwin_archive=$my_xabs
darwin_curdir=`pwd`
darwin_base_archive=`basename "$darwin_archive"`
darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
if test -n "$darwin_arches"; then
darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
darwin_arch=
func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
for darwin_arch in $darwin_arches ; do
func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
$LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
func_extract_an_archive "`pwd`" "${darwin_base_archive}"
cd "$darwin_curdir"
$RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
done # $darwin_arches
## Okay now we've a bunch of thin objects, gotta fatten them up :)
darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
darwin_file=
darwin_files=
for darwin_file in $darwin_filelist; do
darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
$LIPO -create -output "$darwin_file" $darwin_files
done # $darwin_filelist
$RM -rf unfat-$$
cd "$darwin_orig_dir"
else
cd $darwin_orig_dir
func_extract_an_archive "$my_xdir" "$my_xabs"
fi # $darwin_arches
} # !$opt_dry_run
;;
*)
func_extract_an_archive "$my_xdir" "$my_xabs"
;;
esac
my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
done
func_extract_archives_result="$my_oldobjs"
}
# func_emit_wrapper [arg=no]
#
# Emit a libtool wrapper script on stdout.
# Don't directly open a file because we may want to
# incorporate the script contents within a cygwin/mingw
# wrapper executable. Must ONLY be called from within
# func_mode_link because it depends on a number of variables
# set therein.
#
# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
# variable will take. If 'yes', then the emitted script
# will assume that the directory in which it is stored is
# the $objdir directory. This is a cygwin/mingw-specific
# behavior.
func_emit_wrapper ()
{
func_emit_wrapper_arg1=${1-no}
$ECHO "\
#! $SHELL
# $output - temporary wrapper script for $objdir/$outputname
# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
#
# The $output program cannot be directly executed until all the libtool
# libraries that it depends on are installed.
#
# This wrapper script should never be moved out of the build directory.
# If it is, it will not operate correctly.
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='$sed_quote_subst'
# Be Bourne compatible
if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs 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
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# 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
relink_command=\"$relink_command\"
# This environment variable determines our operation mode.
if test \"\$libtool_install_magic\" = \"$magic\"; then
# install mode needs the following variables:
generated_by_libtool_version='$macro_version'
notinst_deplibs='$notinst_deplibs'
else
# When we are sourced in execute mode, \$file and \$ECHO are already set.
if test \"\$libtool_execute_magic\" != \"$magic\"; then
file=\"\$0\""
qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
$ECHO "\
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$1
_LTECHO_EOF'
}
ECHO=\"$qECHO\"
fi
# Very basic option parsing. These options are (a) specific to
# the libtool wrapper, (b) are identical between the wrapper
# /script/ and the wrapper /executable/ which is used only on
# windows platforms, and (c) all begin with the string "--lt-"
# (application programs are unlikely to have options which match
# this pattern).
#
# There are only two supported options: --lt-debug and
# --lt-dump-script. There is, deliberately, no --lt-help.
#
# The first argument to this parsing function should be the
# script's $0 value, followed by "$@".
lt_option_debug=
func_parse_lt_options ()
{
lt_script_arg0=\$0
shift
for lt_opt
do
case \"\$lt_opt\" in
--lt-debug) lt_option_debug=1 ;;
--lt-dump-script)
lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
cat \"\$lt_dump_D/\$lt_dump_F\"
exit 0
;;
--lt-*)
\$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
exit 1
;;
esac
done
# Print the debug banner immediately:
if test -n \"\$lt_option_debug\"; then
echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
fi
}
# Used when --lt-debug. Prints its arguments to stdout
# (redirection is the responsibility of the caller)
func_lt_dump_args ()
{
lt_dump_args_N=1;
for lt_arg
do
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
done
}
# Core function for launching the target application
func_exec_program_core ()
{
"
case $host in
# Backslashes separate directories on plain windows
*-*-mingw | *-*-os2* | *-cegcc*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
"
;;
*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir/\$program\" \${1+\"\$@\"}
"
;;
esac
$ECHO "\
\$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
exit 1
}
# A function to encapsulate launching the target application
# Strips options in the --lt-* namespace from \$@ and
# launches target application with the remaining arguments.
func_exec_program ()
{
case \" \$* \" in
*\\ --lt-*)
for lt_wr_arg
do
case \$lt_wr_arg in
--lt-*) ;;
*) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
esac
shift
done ;;
esac
func_exec_program_core \${1+\"\$@\"}
}
# Parse options
func_parse_lt_options \"\$0\" \${1+\"\$@\"}
# Find the directory that this script lives in.
thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
test \"x\$thisdir\" = \"x\$file\" && thisdir=.
# Follow symbolic links until we get to the real thisdir.
file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
while test -n \"\$file\"; do
destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
# If there was a directory component, then change thisdir.
if test \"x\$destdir\" != \"x\$file\"; then
case \"\$destdir\" in
[\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
*) thisdir=\"\$thisdir/\$destdir\" ;;
esac
fi
file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
done
# Usually 'no', except on cygwin/mingw when embedded into
# the cwrapper.
WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
# special case for '.'
if test \"\$thisdir\" = \".\"; then
thisdir=\`pwd\`
fi
# remove .libs from thisdir
case \"\$thisdir\" in
*[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
$objdir ) thisdir=. ;;
esac
fi
# Try to get the absolute directory name.
absdir=\`cd \"\$thisdir\" && pwd\`
test -n \"\$absdir\" && thisdir=\"\$absdir\"
"
if test "$fast_install" = yes; then
$ECHO "\
program=lt-'$outputname'$exeext
progdir=\"\$thisdir/$objdir\"
if test ! -f \"\$progdir/\$program\" ||
{ file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
test \"X\$file\" != \"X\$progdir/\$program\"; }; then
file=\"\$\$-\$program\"
if test ! -d \"\$progdir\"; then
$MKDIR \"\$progdir\"
else
$RM \"\$progdir/\$file\"
fi"
$ECHO "\
# relink executable if necessary
if test -n \"\$relink_command\"; then
if relink_command_output=\`eval \$relink_command 2>&1\`; then :
else
$ECHO \"\$relink_command_output\" >&2
$RM \"\$progdir/\$file\"
exit 1
fi
fi
$MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
{ $RM \"\$progdir/\$program\";
$MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
$RM \"\$progdir/\$file\"
fi"
else
$ECHO "\
program='$outputname'
progdir=\"\$thisdir/$objdir\"
"
fi
$ECHO "\
if test -f \"\$progdir/\$program\"; then"
# fixup the dll searchpath if we need to.
#
# Fix the DLL searchpath if we need to. Do this before prepending
# to shlibpath, because on Windows, both are PATH and uninstalled
# libraries must come first.
if test -n "$dllsearchpath"; then
$ECHO "\
# Add the dll search path components to the executable PATH
PATH=$dllsearchpath:\$PATH
"
fi
# Export our shlibpath_var if we have one.
if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
$ECHO "\
# Add our own library path to $shlibpath_var
$shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
# Some systems cannot cope with colon-terminated $shlibpath_var
# The second colon is a workaround for a bug in BeOS R4 sed
$shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
export $shlibpath_var
"
fi
$ECHO "\
if test \"\$libtool_execute_magic\" != \"$magic\"; then
# Run the actual program with our arguments.
func_exec_program \${1+\"\$@\"}
fi
else
# The program doesn't exist.
\$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
\$ECHO \"This script is just a wrapper for \$program.\" 1>&2
\$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
exit 1
fi
fi\
"
}
# func_emit_cwrapperexe_src
# emit the source code for a wrapper executable on stdout
# Must ONLY be called from within func_mode_link because
# it depends on a number of variable set therein.
func_emit_cwrapperexe_src ()
{
cat <<EOF
/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
The $output program cannot be directly executed until all the libtool
libraries that it depends on are installed.
This wrapper executable should never be moved out of the build directory.
If it is, it will not operate correctly.
*/
EOF
cat <<"EOF"
#ifdef _MSC_VER
# define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef _MSC_VER
# include <direct.h>
# include <process.h>
# include <io.h>
#else
# include <unistd.h>
# include <stdint.h>
# ifdef __CYGWIN__
# include <io.h>
# endif
#endif
#include <malloc.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
/* declarations of non-ANSI functions */
#if defined(__MINGW32__)
# ifdef __STRICT_ANSI__
int _putenv (const char *);
# endif
#elif defined(__CYGWIN__)
# ifdef __STRICT_ANSI__
char *realpath (const char *, char *);
int putenv (char *);
int setenv (const char *, const char *, int);
# endif
/* #elif defined (other platforms) ... */
#endif
/* portability defines, excluding path handling macros */
#if defined(_MSC_VER)
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
# define S_IXUSR _S_IEXEC
# ifndef _INTPTR_T_DEFINED
# define _INTPTR_T_DEFINED
# define intptr_t int
# endif
#elif defined(__MINGW32__)
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
#elif defined(__CYGWIN__)
# define HAVE_SETENV
# define FOPEN_WB "wb"
/* #elif defined (other platforms) ... */
#endif
#if defined(PATH_MAX)
# define LT_PATHMAX PATH_MAX
#elif defined(MAXPATHLEN)
# define LT_PATHMAX MAXPATHLEN
#else
# define LT_PATHMAX 1024
#endif
#ifndef S_IXOTH
# define S_IXOTH 0
#endif
#ifndef S_IXGRP
# define S_IXGRP 0
#endif
/* path handling portability macros */
#ifndef DIR_SEPARATOR
# define DIR_SEPARATOR '/'
# define PATH_SEPARATOR ':'
#endif
#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
defined (__OS2__)
# define HAVE_DOS_BASED_FILE_SYSTEM
# define FOPEN_WB "wb"
# ifndef DIR_SEPARATOR_2
# define DIR_SEPARATOR_2 '\\'
# endif
# ifndef PATH_SEPARATOR_2
# define PATH_SEPARATOR_2 ';'
# endif
#endif
#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else /* DIR_SEPARATOR_2 */
# define IS_DIR_SEPARATOR(ch) \
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */
#ifndef PATH_SEPARATOR_2
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
#else /* PATH_SEPARATOR_2 */
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
#endif /* PATH_SEPARATOR_2 */
#ifndef FOPEN_WB
# define FOPEN_WB "w"
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
#define XFREE(stale) do { \
if (stale) { free ((void *) stale); stale = 0; } \
} while (0)
#if defined(LT_DEBUGWRAPPER)
static int lt_debug = 1;
#else
static int lt_debug = 0;
#endif
const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
void *xmalloc (size_t num);
char *xstrdup (const char *string);
const char *base_name (const char *name);
char *find_executable (const char *wrapper);
char *chase_symlinks (const char *pathspec);
int make_executable (const char *path);
int check_executable (const char *path);
char *strendzap (char *str, const char *pat);
void lt_debugprintf (const char *file, int line, const char *fmt, ...);
void lt_fatal (const char *file, int line, const char *message, ...);
static const char *nonnull (const char *s);
static const char *nonempty (const char *s);
void lt_setenv (const char *name, const char *value);
char *lt_extend_str (const char *orig_value, const char *add, int to_end);
void lt_update_exe_path (const char *name, const char *value);
void lt_update_lib_path (const char *name, const char *value);
char **prepare_spawn (char **argv);
void lt_dump_script (FILE *f);
EOF
cat <<EOF
volatile const char * MAGIC_EXE = "$magic_exe";
const char * LIB_PATH_VARNAME = "$shlibpath_var";
EOF
if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
func_to_host_path "$temp_rpath"
cat <<EOF
const char * LIB_PATH_VALUE = "$func_to_host_path_result";
EOF
else
cat <<"EOF"
const char * LIB_PATH_VALUE = "";
EOF
fi
if test -n "$dllsearchpath"; then
func_to_host_path "$dllsearchpath:"
cat <<EOF
const char * EXE_PATH_VARNAME = "PATH";
const char * EXE_PATH_VALUE = "$func_to_host_path_result";
EOF
else
cat <<"EOF"
const char * EXE_PATH_VARNAME = "";
const char * EXE_PATH_VALUE = "";
EOF
fi
if test "$fast_install" = yes; then
cat <<EOF
const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
EOF
else
cat <<EOF
const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
EOF
fi
cat <<"EOF"
#define LTWRAPPER_OPTION_PREFIX "--lt-"
static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug";
int
main (int argc, char *argv[])
{
char **newargz;
int newargc;
char *tmp_pathspec;
char *actual_cwrapper_path;
char *actual_cwrapper_name;
char *target_name;
char *lt_argv_zero;
intptr_t rval = 127;
int i;
program_name = (char *) xstrdup (base_name (argv[0]));
newargz = XMALLOC (char *, argc + 1);
/* very simple arg parsing; don't want to rely on getopt
* also, copy all non cwrapper options to newargz, except
* argz[0], which is handled differently
*/
newargc=0;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], dumpscript_opt) == 0)
{
EOF
case "$host" in
*mingw* | *cygwin* )
# make stdout use "unix" line endings
echo " setmode(1,_O_BINARY);"
;;
esac
cat <<"EOF"
lt_dump_script (stdout);
return 0;
}
if (strcmp (argv[i], debug_opt) == 0)
{
lt_debug = 1;
continue;
}
if (strcmp (argv[i], ltwrapper_option_prefix) == 0)
{
/* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
namespace, but it is not one of the ones we know about and
have already dealt with, above (inluding dump-script), then
report an error. Otherwise, targets might begin to believe
they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
namespace. The first time any user complains about this, we'll
need to make LTWRAPPER_OPTION_PREFIX a configure-time option
or a configure.ac-settable value.
*/
lt_fatal (__FILE__, __LINE__,
"unrecognized %s option: '%s'",
ltwrapper_option_prefix, argv[i]);
}
/* otherwise ... */
newargz[++newargc] = xstrdup (argv[i]);
}
newargz[++newargc] = NULL;
EOF
cat <<EOF
/* The GNU banner must be the first non-error debug message */
lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n");
EOF
cat <<"EOF"
lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
tmp_pathspec = find_executable (argv[0]);
if (tmp_pathspec == NULL)
lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
lt_debugprintf (__FILE__, __LINE__,
"(main) found exe (before symlink chase) at: %s\n",
tmp_pathspec);
actual_cwrapper_path = chase_symlinks (tmp_pathspec);
lt_debugprintf (__FILE__, __LINE__,
"(main) found exe (after symlink chase) at: %s\n",
actual_cwrapper_path);
XFREE (tmp_pathspec);
actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
strendzap (actual_cwrapper_path, actual_cwrapper_name);
/* wrapper name transforms */
strendzap (actual_cwrapper_name, ".exe");
tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
XFREE (actual_cwrapper_name);
actual_cwrapper_name = tmp_pathspec;
tmp_pathspec = 0;
/* target_name transforms -- use actual target program name; might have lt- prefix */
target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
strendzap (target_name, ".exe");
tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
XFREE (target_name);
target_name = tmp_pathspec;
tmp_pathspec = 0;
lt_debugprintf (__FILE__, __LINE__,
"(main) libtool target name: %s\n",
target_name);
EOF
cat <<EOF
newargz[0] =
XMALLOC (char, (strlen (actual_cwrapper_path) +
strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
strcpy (newargz[0], actual_cwrapper_path);
strcat (newargz[0], "$objdir");
strcat (newargz[0], "/");
EOF
cat <<"EOF"
/* stop here, and copy so we don't have to do this twice */
tmp_pathspec = xstrdup (newargz[0]);
/* do NOT want the lt- prefix here, so use actual_cwrapper_name */
strcat (newargz[0], actual_cwrapper_name);
/* DO want the lt- prefix here if it exists, so use target_name */
lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
XFREE (tmp_pathspec);
tmp_pathspec = NULL;
EOF
case $host_os in
mingw*)
cat <<"EOF"
{
char* p;
while ((p = strchr (newargz[0], '\\')) != NULL)
{
*p = '/';
}
while ((p = strchr (lt_argv_zero, '\\')) != NULL)
{
*p = '/';
}
}
EOF
;;
esac
cat <<"EOF"
XFREE (target_name);
XFREE (actual_cwrapper_path);
XFREE (actual_cwrapper_name);
lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
lt_setenv ("DUALCASE", "1"); /* for MSK sh */
/* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must
be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
because on Windows, both *_VARNAMEs are PATH but uninstalled
libraries must come first. */
lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
nonnull (lt_argv_zero));
for (i = 0; i < newargc; i++)
{
lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
i, nonnull (newargz[i]));
}
EOF
case $host_os in
mingw*)
cat <<"EOF"
/* execv doesn't actually work on mingw as expected on unix */
newargz = prepare_spawn (newargz);
rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
if (rval == -1)
{
/* failed to start process */
lt_debugprintf (__FILE__, __LINE__,
"(main) failed to launch target \"%s\": %s\n",
lt_argv_zero, nonnull (strerror (errno)));
return 127;
}
return rval;
EOF
;;
*)
cat <<"EOF"
execv (lt_argv_zero, newargz);
return rval; /* =127, but avoids unused variable warning */
EOF
;;
esac
cat <<"EOF"
}
void *
xmalloc (size_t num)
{
void *p = (void *) malloc (num);
if (!p)
lt_fatal (__FILE__, __LINE__, "memory exhausted");
return p;
}
char *
xstrdup (const char *string)
{
return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
string) : NULL;
}
const char *
base_name (const char *name)
{
const char *base;
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
/* Skip over the disk name in MSDOS pathnames. */
if (isalpha ((unsigned char) name[0]) && name[1] == ':')
name += 2;
#endif
for (base = name; *name; name++)
if (IS_DIR_SEPARATOR (*name))
base = name + 1;
return base;
}
int
check_executable (const char *path)
{
struct stat st;
lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
nonempty (path));
if ((!path) || (!*path))
return 0;
if ((stat (path, &st) >= 0)
&& (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
return 1;
else
return 0;
}
int
make_executable (const char *path)
{
int rval = 0;
struct stat st;
lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
nonempty (path));
if ((!path) || (!*path))
return 0;
if (stat (path, &st) >= 0)
{
rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
}
return rval;
}
/* Searches for the full path of the wrapper. Returns
newly allocated full path name if found, NULL otherwise
Does not chase symlinks, even on platforms that support them.
*/
char *
find_executable (const char *wrapper)
{
int has_slash = 0;
const char *p;
const char *p_next;
/* static buffer for getcwd */
char tmp[LT_PATHMAX + 1];
int tmp_len;
char *concat_name;
lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
nonempty (wrapper));
if ((wrapper == NULL) || (*wrapper == '\0'))
return NULL;
/* Absolute path? */
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
else
{
#endif
if (IS_DIR_SEPARATOR (wrapper[0]))
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
}
#endif
for (p = wrapper; *p; p++)
if (*p == '/')
{
has_slash = 1;
break;
}
if (!has_slash)
{
/* no slashes; search PATH */
const char *path = getenv ("PATH");
if (path != NULL)
{
for (p = path; *p; p = p_next)
{
const char *q;
size_t p_len;
for (q = p; *q; q++)
if (IS_PATH_SEPARATOR (*q))
break;
p_len = q - p;
p_next = (*q == '\0' ? q : q + 1);
if (p_len == 0)
{
/* empty path: current directory */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name =
XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
}
else
{
concat_name =
XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, p, p_len);
concat_name[p_len] = '/';
strcpy (concat_name + p_len + 1, wrapper);
}
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
}
/* not found in PATH; assume curdir */
}
/* Relative path | not found in path: prepend cwd */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
return NULL;
}
char *
chase_symlinks (const char *pathspec)
{
#ifndef S_ISLNK
return xstrdup (pathspec);
#else
char buf[LT_PATHMAX];
struct stat s;
char *tmp_pathspec = xstrdup (pathspec);
char *p;
int has_symlinks = 0;
while (strlen (tmp_pathspec) && !has_symlinks)
{
lt_debugprintf (__FILE__, __LINE__,
"checking path component for symlinks: %s\n",
tmp_pathspec);
if (lstat (tmp_pathspec, &s) == 0)
{
if (S_ISLNK (s.st_mode) != 0)
{
has_symlinks = 1;
break;
}
/* search backwards for last DIR_SEPARATOR */
p = tmp_pathspec + strlen (tmp_pathspec) - 1;
while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
p--;
if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
{
/* no more DIR_SEPARATORS left */
break;
}
*p = '\0';
}
else
{
lt_fatal (__FILE__, __LINE__,
"error accessing file \"%s\": %s",
tmp_pathspec, nonnull (strerror (errno)));
}
}
XFREE (tmp_pathspec);
if (!has_symlinks)
{
return xstrdup (pathspec);
}
tmp_pathspec = realpath (pathspec, buf);
if (tmp_pathspec == 0)
{
lt_fatal (__FILE__, __LINE__,
"could not follow symlinks for %s", pathspec);
}
return xstrdup (tmp_pathspec);
#endif
}
char *
strendzap (char *str, const char *pat)
{
size_t len, patlen;
assert (str != NULL);
assert (pat != NULL);
len = strlen (str);
patlen = strlen (pat);
if (patlen <= len)
{
str += len - patlen;
if (strcmp (str, pat) == 0)
*str = '\0';
}
return str;
}
void
lt_debugprintf (const char *file, int line, const char *fmt, ...)
{
va_list args;
if (lt_debug)
{
(void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
va_start (args, fmt);
(void) vfprintf (stderr, fmt, args);
va_end (args);
}
}
static void
lt_error_core (int exit_status, const char *file,
int line, const char *mode,
const char *message, va_list ap)
{
fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
vfprintf (stderr, message, ap);
fprintf (stderr, ".\n");
if (exit_status >= 0)
exit (exit_status);
}
void
lt_fatal (const char *file, int line, const char *message, ...)
{
va_list ap;
va_start (ap, message);
lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
va_end (ap);
}
static const char *
nonnull (const char *s)
{
return s ? s : "(null)";
}
static const char *
nonempty (const char *s)
{
return (s && !*s) ? "(empty)" : nonnull (s);
}
void
lt_setenv (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_setenv) setting '%s' to '%s'\n",
nonnull (name), nonnull (value));
{
#ifdef HAVE_SETENV
/* always make a copy, for consistency with !HAVE_SETENV */
char *str = xstrdup (value);
setenv (name, str, 1);
#else
int len = strlen (name) + 1 + strlen (value) + 1;
char *str = XMALLOC (char, len);
sprintf (str, "%s=%s", name, value);
if (putenv (str) != EXIT_SUCCESS)
{
XFREE (str);
}
#endif
}
}
char *
lt_extend_str (const char *orig_value, const char *add, int to_end)
{
char *new_value;
if (orig_value && *orig_value)
{
int orig_value_len = strlen (orig_value);
int add_len = strlen (add);
new_value = XMALLOC (char, add_len + orig_value_len + 1);
if (to_end)
{
strcpy (new_value, orig_value);
strcpy (new_value + orig_value_len, add);
}
else
{
strcpy (new_value, add);
strcpy (new_value + add_len, orig_value);
}
}
else
{
new_value = xstrdup (add);
}
return new_value;
}
void
lt_update_exe_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
/* some systems can't cope with a ':'-terminated path #' */
int len = strlen (new_value);
while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
{
new_value[len-1] = '\0';
}
lt_setenv (name, new_value);
XFREE (new_value);
}
}
void
lt_update_lib_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
lt_setenv (name, new_value);
XFREE (new_value);
}
}
EOF
case $host_os in
mingw*)
cat <<"EOF"
/* Prepares an argument vector before calling spawn().
Note that spawn() does not by itself call the command interpreter
(getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&v);
v.dwPlatformId == VER_PLATFORM_WIN32_NT;
}) ? "cmd.exe" : "command.com").
Instead it simply concatenates the arguments, separated by ' ', and calls
CreateProcess(). We must quote the arguments since Win32 CreateProcess()
interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
special way:
- Space and tab are interpreted as delimiters. They are not treated as
delimiters if they are surrounded by double quotes: "...".
- Unescaped double quotes are removed from the input. Their only effect is
that within double quotes, space and tab are treated like normal
characters.
- Backslashes not followed by double quotes are not special.
- But 2*n+1 backslashes followed by a double quote become
n backslashes followed by a double quote (n >= 0):
\" -> "
\\\" -> \"
\\\\\" -> \\"
*/
#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
char **
prepare_spawn (char **argv)
{
size_t argc;
char **new_argv;
size_t i;
/* Count number of arguments. */
for (argc = 0; argv[argc] != NULL; argc++)
;
/* Allocate new argument vector. */
new_argv = XMALLOC (char *, argc + 1);
/* Put quoted arguments into the new argument vector. */
for (i = 0; i < argc; i++)
{
const char *string = argv[i];
if (string[0] == '\0')
new_argv[i] = xstrdup ("\"\"");
else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
{
int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
size_t length;
unsigned int backslashes;
const char *s;
char *quoted_string;
char *p;
length = 0;
backslashes = 0;
if (quote_around)
length++;
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
length += backslashes + 1;
length++;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
length += backslashes + 1;
quoted_string = XMALLOC (char, length + 1);
p = quoted_string;
backslashes = 0;
if (quote_around)
*p++ = '"';
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
{
unsigned int j;
for (j = backslashes + 1; j > 0; j--)
*p++ = '\\';
}
*p++ = c;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
{
unsigned int j;
for (j = backslashes; j > 0; j--)
*p++ = '\\';
*p++ = '"';
}
*p = '\0';
new_argv[i] = quoted_string;
}
else
new_argv[i] = (char *) string;
}
new_argv[argc] = NULL;
return new_argv;
}
EOF
;;
esac
cat <<"EOF"
void lt_dump_script (FILE* f)
{
EOF
func_emit_wrapper yes |
$SED -n -e '
s/^\(.\{79\}\)\(..*\)/\1\
\2/
h
s/\([\\"]\)/\\\1/g
s/$/\\n/
s/\([^\n]*\).*/ fputs ("\1", f);/p
g
D'
cat <<"EOF"
}
EOF
}
# end: func_emit_cwrapperexe_src
# func_win32_import_lib_p ARG
# True if ARG is an import lib, as indicated by $file_magic_cmd
func_win32_import_lib_p ()
{
$opt_debug
case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
*import*) : ;;
*) false ;;
esac
}
# func_mode_link arg...
func_mode_link ()
{
$opt_debug
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
# It is impossible to link a dll without this setting, and
# we shouldn't force the makefile maintainer to figure out
# which system we are compiling for in order to pass an extra
# flag for every libtool invocation.
# allow_undefined=no
# FIXME: Unfortunately, there are problems with the above when trying
# to make a dll which has undefined symbols, in which case not
# even a static library is built. For now, we need to specify
# -no-undefined on the libtool link line when we can be certain
# that all symbols are satisfied, otherwise we get a static library.
allow_undefined=yes
;;
*)
allow_undefined=yes
;;
esac
libtool_args=$nonopt
base_compile="$nonopt $@"
compile_command=$nonopt
finalize_command=$nonopt
compile_rpath=
finalize_rpath=
compile_shlibpath=
finalize_shlibpath=
convenience=
old_convenience=
deplibs=
old_deplibs=
compiler_flags=
linker_flags=
dllsearchpath=
lib_search_path=`pwd`
inst_prefix_dir=
new_inherited_linker_flags=
avoid_version=no
bindir=
dlfiles=
dlprefiles=
dlself=no
export_dynamic=no
export_symbols=
export_symbols_regex=
generated=
libobjs=
ltlibs=
module=no
no_install=no
objs=
non_pic_objects=
precious_files_regex=
prefer_static_libs=no
preload=no
prev=
prevarg=
release=
rpath=
xrpath=
perm_rpath=
temp_rpath=
thread_safe=no
vinfo=
vinfo_number=no
weak_libs=
single_module="${wl}-single_module"
func_infer_tag $base_compile
# We need to know -static, to get the right output filenames.
for arg
do
case $arg in
-shared)
test "$build_libtool_libs" != yes && \
func_fatal_configuration "can not build a shared library"
build_old_libs=no
break
;;
-all-static | -static | -static-libtool-libs)
case $arg in
-all-static)
if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
func_warning "complete static linking is impossible in this configuration"
fi
if test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
-static)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=built
;;
-static-libtool-libs)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
esac
build_libtool_libs=no
build_old_libs=yes
break
;;
esac
done
# See if our shared archives depend on static archives.
test -n "$old_archive_from_new_cmds" && build_old_libs=yes
# Go through the arguments, transforming them on the way.
while test "$#" -gt 0; do
arg="$1"
shift
func_quote_for_eval "$arg"
qarg=$func_quote_for_eval_unquoted_result
func_append libtool_args " $func_quote_for_eval_result"
# If the previous option needs an argument, assign it.
if test -n "$prev"; then
case $prev in
output)
func_append compile_command " @OUTPUT@"
func_append finalize_command " @OUTPUT@"
;;
esac
case $prev in
bindir)
bindir="$arg"
prev=
continue
;;
dlfiles|dlprefiles)
if test "$preload" = no; then
# Add the symbol object into the linking commands.
func_append compile_command " @SYMFILE@"
func_append finalize_command " @SYMFILE@"
preload=yes
fi
case $arg in
*.la | *.lo) ;; # We handle these cases below.
force)
if test "$dlself" = no; then
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
self)
if test "$prev" = dlprefiles; then
dlself=yes
elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
dlself=yes
else
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
*)
if test "$prev" = dlfiles; then
func_append dlfiles " $arg"
else
func_append dlprefiles " $arg"
fi
prev=
continue
;;
esac
;;
expsyms)
export_symbols="$arg"
test -f "$arg" \
|| func_fatal_error "symbol file \`$arg' does not exist"
prev=
continue
;;
expsyms_regex)
export_symbols_regex="$arg"
prev=
continue
;;
framework)
case $host in
*-*-darwin*)
case "$deplibs " in
*" $qarg.ltframework "*) ;;
*) func_append deplibs " $qarg.ltframework" # this is fixed later
;;
esac
;;
esac
prev=
continue
;;
inst_prefix)
inst_prefix_dir="$arg"
prev=
continue
;;
objectlist)
if test -f "$arg"; then
save_arg=$arg
moreargs=
for fil in `cat "$save_arg"`
do
# func_append moreargs " $fil"
arg=$fil
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test "$pic_object" = none &&
test "$non_pic_object" = none; then
func_fatal_error "cannot find name of object for \`$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
if test "$pic_object" != none; then
# Prepend the subdirectory the object is found in.
pic_object="$xdir$pic_object"
if test "$prev" = dlfiles; then
if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test "$prev" = dlprefiles; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg="$pic_object"
fi
# Non-PIC object.
if test "$non_pic_object" != none; then
# Prepend the subdirectory the object is found in.
non_pic_object="$xdir$non_pic_object"
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object="$pic_object"
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "\`$arg' is not a valid libtool object"
fi
fi
done
else
func_fatal_error "link input file \`$arg' does not exist"
fi
arg=$save_arg
prev=
continue
;;
precious_regex)
precious_files_regex="$arg"
prev=
continue
;;
release)
release="-$arg"
prev=
continue
;;
rpath | xrpath)
# We need an absolute path.
case $arg in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
func_fatal_error "only absolute run-paths are allowed"
;;
esac
if test "$prev" = rpath; then
case "$rpath " in
*" $arg "*) ;;
*) func_append rpath " $arg" ;;
esac
else
case "$xrpath " in
*" $arg "*) ;;
*) func_append xrpath " $arg" ;;
esac
fi
prev=
continue
;;
shrext)
shrext_cmds="$arg"
prev=
continue
;;
weak)
func_append weak_libs " $arg"
prev=
continue
;;
xcclinker)
func_append linker_flags " $qarg"
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xcompiler)
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xlinker)
func_append linker_flags " $qarg"
func_append compiler_flags " $wl$qarg"
prev=
func_append compile_command " $wl$qarg"
func_append finalize_command " $wl$qarg"
continue
;;
*)
eval "$prev=\"\$arg\""
prev=
continue
;;
esac
fi # test -n "$prev"
prevarg="$arg"
case $arg in
-all-static)
if test -n "$link_static_flag"; then
# See comment for -static flag below, for more details.
func_append compile_command " $link_static_flag"
func_append finalize_command " $link_static_flag"
fi
continue
;;
-allow-undefined)
# FIXME: remove this flag sometime in the future.
func_fatal_error "\`-allow-undefined' must not be used because it is the default"
;;
-avoid-version)
avoid_version=yes
continue
;;
-bindir)
prev=bindir
continue
;;
-dlopen)
prev=dlfiles
continue
;;
-dlpreopen)
prev=dlprefiles
continue
;;
-export-dynamic)
export_dynamic=yes
continue
;;
-export-symbols | -export-symbols-regex)
if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
func_fatal_error "more than one -exported-symbols argument is not allowed"
fi
if test "X$arg" = "X-export-symbols"; then
prev=expsyms
else
prev=expsyms_regex
fi
continue
;;
-framework)
prev=framework
continue
;;
-inst-prefix-dir)
prev=inst_prefix
continue
;;
# The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
# so, if we see these flags be careful not to treat them like -L
-L[A-Z][A-Z]*:*)
case $with_gcc/$host in
no/*-*-irix* | /*-*-irix*)
func_append compile_command " $arg"
func_append finalize_command " $arg"
;;
esac
continue
;;
-L*)
func_stripname "-L" '' "$arg"
if test -z "$func_stripname_result"; then
if test "$#" -gt 0; then
func_fatal_error "require no space between \`-L' and \`$1'"
else
func_fatal_error "need path for \`-L' option"
fi
fi
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
absdir=`cd "$dir" && pwd`
test -z "$absdir" && \
func_fatal_error "cannot determine absolute directory name of \`$dir'"
dir="$absdir"
;;
esac
case "$deplibs " in
*" -L$dir "* | *" $arg "*)
# Will only happen for absolute or sysroot arguments
;;
*)
# Preserve sysroot, but never include relative directories
case $dir in
[\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
*) func_append deplibs " -L$dir" ;;
esac
func_append lib_search_path " $dir"
;;
esac
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$dir:"*) ;;
::) dllsearchpath=$dir;;
*) func_append dllsearchpath ":$dir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
continue
;;
-l*)
if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
# These systems don't actually have a C or math library (as such)
continue
;;
*-*-os2*)
# These systems don't actually have a C library (as such)
test "X$arg" = "X-lc" && continue
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
test "X$arg" = "X-lc" && continue
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C and math libraries are in the System framework
func_append deplibs " System.ltframework"
continue
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
test "X$arg" = "X-lc" && continue
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
test "X$arg" = "X-lc" && continue
;;
esac
elif test "X$arg" = "X-lc_r"; then
case $host in
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc_r directly, use -pthread flag.
continue
;;
esac
fi
func_append deplibs " $arg"
continue
;;
-module)
module=yes
continue
;;
# Tru64 UNIX uses -model [arg] to determine the layout of C++
# classes, name mangling, and exception handling.
# Darwin uses the -arch flag to determine output architecture.
-model|-arch|-isysroot|--sysroot)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
prev=xcompiler
continue
;;
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
case "$new_inherited_linker_flags " in
*" $arg "*) ;;
* ) func_append new_inherited_linker_flags " $arg" ;;
esac
continue
;;
-multi_module)
single_module="${wl}-multi_module"
continue
;;
-no-fast-install)
fast_install=no
continue
;;
-no-install)
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
# The PATH hackery in wrapper scripts is required on Windows
# and Darwin in order for the loader to find any dlls it needs.
func_warning "\`-no-install' is ignored for $host"
func_warning "assuming \`-no-fast-install' instead"
fast_install=no
;;
*) no_install=yes ;;
esac
continue
;;
-no-undefined)
allow_undefined=no
continue
;;
-objectlist)
prev=objectlist
continue
;;
-o) prev=output ;;
-precious-files-regex)
prev=precious_regex
continue
;;
-release)
prev=release
continue
;;
-rpath)
prev=rpath
continue
;;
-R)
prev=xrpath
continue
;;
-R*)
func_stripname '-R' '' "$arg"
dir=$func_stripname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
=*)
func_stripname '=' '' "$dir"
dir=$lt_sysroot$func_stripname_result
;;
*)
func_fatal_error "only absolute run-paths are allowed"
;;
esac
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
continue
;;
-shared)
# The effects of -shared are defined in a previous loop.
continue
;;
-shrext)
prev=shrext
continue
;;
-static | -static-libtool-libs)
# The effects of -static are defined in a previous loop.
# We used to do the same as -all-static on platforms that
# didn't have a PIC flag, but the assumption that the effects
# would be equivalent was wrong. It would break on at least
# Digital Unix and AIX.
continue
;;
-thread-safe)
thread_safe=yes
continue
;;
-version-info)
prev=vinfo
continue
;;
-version-number)
prev=vinfo
vinfo_number=yes
continue
;;
-weak)
prev=weak
continue
;;
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs="$IFS"; IFS=','
for flag in $args; do
IFS="$save_ifs"
func_quote_for_eval "$flag"
func_append arg " $func_quote_for_eval_result"
func_append compiler_flags " $func_quote_for_eval_result"
done
IFS="$save_ifs"
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Wl,*)
func_stripname '-Wl,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs="$IFS"; IFS=','
for flag in $args; do
IFS="$save_ifs"
func_quote_for_eval "$flag"
func_append arg " $wl$func_quote_for_eval_result"
func_append compiler_flags " $wl$func_quote_for_eval_result"
func_append linker_flags " $func_quote_for_eval_result"
done
IFS="$save_ifs"
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Xcompiler)
prev=xcompiler
continue
;;
-Xlinker)
prev=xlinker
continue
;;
-XCClinker)
prev=xcclinker
continue
;;
# -msg_* for osf cc
-msg_*)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
# Flags to be passed through unchanged, with rationale:
# -64, -mips[0-9] enable 64-bit mode for the SGI compiler
# -r[0-9][0-9]* specify processor for the SGI compiler
# -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
# +DA*, +DD* enable 64-bit mode for the HP compiler
# -q* compiler args for the IBM compiler
# -m*, -t[45]*, -txscale* architecture-specific flags for GCC
# -F/path path to uninstalled frameworks, gcc on darwin
# -p, -pg, --coverage, -fprofile-* profiling flags for GCC
# @file GCC response files
# -tp=* Portland pgcc target processor selection
# --sysroot=* for sysroot support
# -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
-O*|-flto*|-fwhopr*|-fuse-linker-plugin)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
func_append compile_command " $arg"
func_append finalize_command " $arg"
func_append compiler_flags " $arg"
continue
;;
# Some other compiler flag.
-* | +*)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
*.$objext)
# A standard object.
func_append objs " $arg"
;;
*.lo)
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test "$pic_object" = none &&
test "$non_pic_object" = none; then
func_fatal_error "cannot find name of object for \`$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
if test "$pic_object" != none; then
# Prepend the subdirectory the object is found in.
pic_object="$xdir$pic_object"
if test "$prev" = dlfiles; then
if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test "$prev" = dlprefiles; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg="$pic_object"
fi
# Non-PIC object.
if test "$non_pic_object" != none; then
# Prepend the subdirectory the object is found in.
non_pic_object="$xdir$non_pic_object"
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object="$pic_object"
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "\`$arg' is not a valid libtool object"
fi
fi
;;
*.$libext)
# An archive.
func_append deplibs " $arg"
func_append old_deplibs " $arg"
continue
;;
*.la)
# A libtool-controlled library.
func_resolve_sysroot "$arg"
if test "$prev" = dlfiles; then
# This library was specified with -dlopen.
func_append dlfiles " $func_resolve_sysroot_result"
prev=
elif test "$prev" = dlprefiles; then
# The library was specified with -dlpreopen.
func_append dlprefiles " $func_resolve_sysroot_result"
prev=
else
func_append deplibs " $func_resolve_sysroot_result"
fi
continue
;;
# Some other compiler argument.
*)
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
esac # arg
# Now actually substitute the argument into the commands.
if test -n "$arg"; then
func_append compile_command " $arg"
func_append finalize_command " $arg"
fi
done # argument parsing loop
test -n "$prev" && \
func_fatal_help "the \`$prevarg' option requires an argument"
if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
eval arg=\"$export_dynamic_flag_spec\"
func_append compile_command " $arg"
func_append finalize_command " $arg"
fi
oldlibs=
# calculate the name of the file, without its directory
func_basename "$output"
outputname="$func_basename_result"
libobjs_save="$libobjs"
if test -n "$shlibpath_var"; then
# get the directories listed in $shlibpath_var
eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
else
shlib_search_path=
fi
eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
func_dirname "$output" "/" ""
output_objdir="$func_dirname_result$objdir"
func_to_tool_file "$output_objdir/"
tool_output_objdir=$func_to_tool_file_result
# Create the object directory.
func_mkdir_p "$output_objdir"
# Determine the type of output
case $output in
"")
func_fatal_help "you must specify an output file"
;;
*.$libext) linkmode=oldlib ;;
*.lo | *.$objext) linkmode=obj ;;
*.la) linkmode=lib ;;
*) linkmode=prog ;; # Anything else should be a program.
esac
specialdeplibs=
libs=
# Find all interdependent deplibs by searching for libraries
# that are linked more than once (e.g. -la -lb -la)
for deplib in $deplibs; do
if $opt_preserve_dup_deps ; then
case "$libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append libs " $deplib"
done
if test "$linkmode" = lib; then
libs="$predeps $libs $compiler_lib_search_path $postdeps"
# Compute libraries that are listed more than once in $predeps
# $postdeps and mark them as special (i.e., whose duplicates are
# not to be eliminated).
pre_post_deps=
if $opt_duplicate_compiler_generated_deps; then
for pre_post_dep in $predeps $postdeps; do
case "$pre_post_deps " in
*" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
esac
func_append pre_post_deps " $pre_post_dep"
done
fi
pre_post_deps=
fi
deplibs=
newdependency_libs=
newlib_search_path=
need_relink=no # whether we're linking any uninstalled libtool libraries
notinst_deplibs= # not-installed libtool libraries
notinst_path= # paths that contain not-installed libtool libraries
case $linkmode in
lib)
passes="conv dlpreopen link"
for file in $dlfiles $dlprefiles; do
case $file in
*.la) ;;
*)
func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
;;
esac
done
;;
prog)
compile_deplibs=
finalize_deplibs=
alldeplibs=no
newdlfiles=
newdlprefiles=
passes="conv scan dlopen dlpreopen link"
;;
*) passes="conv"
;;
esac
for pass in $passes; do
# The preopen pass in lib mode reverses $deplibs; put it back here
# so that -L comes before libs that need it for instance...
if test "$linkmode,$pass" = "lib,link"; then
## FIXME: Find the place where the list is rebuilt in the wrong
## order, and fix it there properly
tmp_deplibs=
for deplib in $deplibs; do
tmp_deplibs="$deplib $tmp_deplibs"
done
deplibs="$tmp_deplibs"
fi
if test "$linkmode,$pass" = "lib,link" ||
test "$linkmode,$pass" = "prog,scan"; then
libs="$deplibs"
deplibs=
fi
if test "$linkmode" = prog; then
case $pass in
dlopen) libs="$dlfiles" ;;
dlpreopen) libs="$dlprefiles" ;;
link)
libs="$deplibs %DEPLIBS%"
test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
;;
esac
fi
if test "$linkmode,$pass" = "lib,dlpreopen"; then
# Collect and forward deplibs of preopened libtool libs
for lib in $dlprefiles; do
# Ignore non-libtool-libs
dependency_libs=
func_resolve_sysroot "$lib"
case $lib in
*.la) func_source "$func_resolve_sysroot_result" ;;
esac
# Collect preopened libtool deplibs, except any this library
# has declared as weak libs
for deplib in $dependency_libs; do
func_basename "$deplib"
deplib_base=$func_basename_result
case " $weak_libs " in
*" $deplib_base "*) ;;
*) func_append deplibs " $deplib" ;;
esac
done
done
libs="$dlprefiles"
fi
if test "$pass" = dlopen; then
# Collect dlpreopened libraries
save_deplibs="$deplibs"
deplibs=
fi
for deplib in $libs; do
lib=
found=no
case $deplib in
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append compiler_flags " $deplib"
if test "$linkmode" = lib ; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-l*)
if test "$linkmode" != lib && test "$linkmode" != prog; then
func_warning "\`-l' is ignored for archives/objects"
continue
fi
func_stripname '-l' '' "$deplib"
name=$func_stripname_result
if test "$linkmode" = lib; then
searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
else
searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
fi
for searchdir in $searchdirs; do
for search_ext in .la $std_shrext .so .a; do
# Search the libtool library
lib="$searchdir/lib${name}${search_ext}"
if test -f "$lib"; then
if test "$search_ext" = ".la"; then
found=yes
else
found=no
fi
break 2
fi
done
done
if test "$found" != yes; then
# deplib doesn't seem to be a libtool library
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
fi
continue
else # deplib is a libtool library
# If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
# We need to do some special things here, and not later.
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $deplib "*)
if func_lalib_p "$lib"; then
library_names=
old_library=
func_source "$lib"
for l in $old_library $library_names; do
ll="$l"
done
if test "X$ll" = "X$old_library" ; then # only static version available
found=no
func_dirname "$lib" "" "."
ladir="$func_dirname_result"
lib=$ladir/$old_library
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
fi
continue
fi
fi
;;
*) ;;
esac
fi
fi
;; # -l
*.ltframework)
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
if test "$linkmode" = lib ; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-L*)
case $linkmode in
lib)
deplibs="$deplib $deplibs"
test "$pass" = conv && continue
newdependency_libs="$deplib $newdependency_libs"
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
prog)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
continue
fi
if test "$pass" = scan; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
*)
func_warning "\`-L' is ignored for archives/objects"
;;
esac # linkmode
continue
;; # -L
-R*)
if test "$pass" = link; then
func_stripname '-R' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# Make sure the xrpath contains only unique directories.
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
fi
deplibs="$deplib $deplibs"
continue
;;
*.la)
func_resolve_sysroot "$deplib"
lib=$func_resolve_sysroot_result
;;
*.$libext)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
continue
fi
case $linkmode in
lib)
# Linking convenience modules into shared libraries is allowed,
# but linking other static libraries is non-portable.
case " $dlpreconveniencelibs " in
*" $deplib "*) ;;
*)
valid_a_lib=no
case $deplibs_check_method in
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
| $EGREP "$match_pattern_regex" > /dev/null; then
valid_a_lib=yes
fi
;;
pass_all)
valid_a_lib=yes
;;
esac
if test "$valid_a_lib" != yes; then
echo
$ECHO "*** Warning: Trying to link with static lib archive $deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because the file extensions .$libext of this argument makes me believe"
echo "*** that it is just a static archive that I should not use here."
else
echo
$ECHO "*** Warning: Linking the shared library $output against the"
$ECHO "*** static library $deplib is not portable!"
deplibs="$deplib $deplibs"
fi
;;
esac
continue
;;
prog)
if test "$pass" != link; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
continue
;;
esac # linkmode
;; # *.$libext
*.lo | *.$objext)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
elif test "$linkmode" = prog; then
if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
# If there is no dlopen support or we're linking statically,
# we need to preload.
func_append newdlprefiles " $deplib"
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append newdlfiles " $deplib"
fi
fi
continue
;;
%DEPLIBS%)
alldeplibs=yes
continue
;;
esac # case $deplib
if test "$found" = yes || test -f "$lib"; then :
else
func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
fi
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$lib" \
|| func_fatal_error "\`$lib' is not a valid libtool archive"
func_dirname "$lib" "" "."
ladir="$func_dirname_result"
dlname=
dlopen=
dlpreopen=
libdir=
library_names=
old_library=
inherited_linker_flags=
# If the library was installed with an old release of libtool,
# it will not redefine variables installed, or shouldnotlink
installed=yes
shouldnotlink=no
avoidtemprpath=
# Read the .la file
func_source "$lib"
# Convert "-framework foo" to "foo.ltframework"
if test -n "$inherited_linker_flags"; then
tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
case " $new_inherited_linker_flags " in
*" $tmp_inherited_linker_flag "*) ;;
*) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
esac
done
fi
dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
if test "$linkmode,$pass" = "lib,link" ||
test "$linkmode,$pass" = "prog,scan" ||
{ test "$linkmode" != prog && test "$linkmode" != lib; }; then
test -n "$dlopen" && func_append dlfiles " $dlopen"
test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
fi
if test "$pass" = conv; then
# Only check for convenience libraries
deplibs="$lib $deplibs"
if test -z "$libdir"; then
if test -z "$old_library"; then
func_fatal_error "cannot find name of link library for \`$lib'"
fi
# It is a libtool convenience library, so add in its objects.
func_append convenience " $ladir/$objdir/$old_library"
func_append old_convenience " $ladir/$objdir/$old_library"
tmp_libs=
for deplib in $dependency_libs; do
deplibs="$deplib $deplibs"
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done
elif test "$linkmode" != prog && test "$linkmode" != lib; then
func_fatal_error "\`$lib' is not a convenience library"
fi
continue
fi # $pass = conv
# Get the name of the library we link against.
linklib=
if test -n "$old_library" &&
{ test "$prefer_static_libs" = yes ||
test "$prefer_static_libs,$installed" = "built,no"; }; then
linklib=$old_library
else
for l in $old_library $library_names; do
linklib="$l"
done
fi
if test -z "$linklib"; then
func_fatal_error "cannot find name of link library for \`$lib'"
fi
# This library was specified with -dlopen.
if test "$pass" = dlopen; then
if test -z "$libdir"; then
func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
fi
if test -z "$dlname" ||
test "$dlopen_support" != yes ||
test "$build_libtool_libs" = no; then
# If there is no dlname, no dlopen support or we're linking
# statically, we need to preload. We also need to preload any
# dependent libraries so libltdl's deplib preloader doesn't
# bomb out in the load deplibs phase.
func_append dlprefiles " $lib $dependency_libs"
else
func_append newdlfiles " $lib"
fi
continue
fi # $pass = dlopen
# We need an absolute path.
case $ladir in
[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
*)
abs_ladir=`cd "$ladir" && pwd`
if test -z "$abs_ladir"; then
func_warning "cannot determine absolute directory name of \`$ladir'"
func_warning "passing it literally to the linker, although it might fail"
abs_ladir="$ladir"
fi
;;
esac
func_basename "$lib"
laname="$func_basename_result"
# Find the relevant object directory and library name.
if test "X$installed" = Xyes; then
if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
func_warning "library \`$lib' was moved."
dir="$ladir"
absdir="$abs_ladir"
libdir="$abs_ladir"
else
dir="$lt_sysroot$libdir"
absdir="$lt_sysroot$libdir"
fi
test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
else
if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
dir="$ladir"
absdir="$abs_ladir"
# Remove this search path later
func_append notinst_path " $abs_ladir"
else
dir="$ladir/$objdir"
absdir="$abs_ladir/$objdir"
# Remove this search path later
func_append notinst_path " $abs_ladir"
fi
fi # $installed = yes
func_stripname 'lib' '.la' "$laname"
name=$func_stripname_result
# This library was specified with -dlpreopen.
if test "$pass" = dlpreopen; then
if test -z "$libdir" && test "$linkmode" = prog; then
func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
fi
case "$host" in
# special handling for platforms with PE-DLLs.
*cygwin* | *mingw* | *cegcc* )
# Linker will automatically link against shared library if both
# static and shared are present. Therefore, ensure we extract
# symbols from the import library if a shared library is present
# (otherwise, the dlopen module name will be incorrect). We do
# this by putting the import library name into $newdlprefiles.
# We recover the dlopen module name by 'saving' the la file
# name in a special purpose variable, and (later) extracting the
# dlname from the la file.
if test -n "$dlname"; then
func_tr_sh "$dir/$linklib"
eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
func_append newdlprefiles " $dir/$linklib"
else
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
fi
;;
* )
# Prefer using a static library (so that no silly _DYNAMIC symbols
# are required to link).
if test -n "$old_library"; then
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
# Otherwise, use the dlname, so that lt_dlopen finds it.
elif test -n "$dlname"; then
func_append newdlprefiles " $dir/$dlname"
else
func_append newdlprefiles " $dir/$linklib"
fi
;;
esac
fi # $pass = dlpreopen
if test -z "$libdir"; then
# Link the convenience library
if test "$linkmode" = lib; then
deplibs="$dir/$old_library $deplibs"
elif test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$dir/$old_library $compile_deplibs"
finalize_deplibs="$dir/$old_library $finalize_deplibs"
else
deplibs="$lib $deplibs" # used for prog,scan pass
fi
continue
fi
if test "$linkmode" = prog && test "$pass" != link; then
func_append newlib_search_path " $ladir"
deplibs="$lib $deplibs"
linkalldeplibs=no
if test "$link_all_deplibs" != no || test -z "$library_names" ||
test "$build_libtool_libs" = no; then
linkalldeplibs=yes
fi
tmp_libs=
for deplib in $dependency_libs; do
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
esac
# Need to link against all dependency_libs?
if test "$linkalldeplibs" = yes; then
deplibs="$deplib $deplibs"
else
# Need to hardcode shared library paths
# or/and link against static libraries
newdependency_libs="$deplib $newdependency_libs"
fi
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done # for deplib
continue
fi # $linkmode = prog...
if test "$linkmode,$pass" = "prog,link"; then
if test -n "$library_names" &&
{ { test "$prefer_static_libs" = no ||
test "$prefer_static_libs,$installed" = "built,yes"; } ||
test -z "$old_library"; }; then
# We need to hardcode the library path
if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
# Make sure the rpath contains only unique directories.
case "$temp_rpath:" in
*"$absdir:"*) ;;
*) func_append temp_rpath "$absdir:" ;;
esac
fi
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
*" $absdir "*) ;;
*) func_append compile_rpath " $absdir" ;;
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi # $linkmode,$pass = prog,link...
if test "$alldeplibs" = yes &&
{ test "$deplibs_check_method" = pass_all ||
{ test "$build_libtool_libs" = yes &&
test -n "$library_names"; }; }; then
# We only need to search for static libraries
continue
fi
fi
link_static=no # Whether the deplib will be linked statically
use_static_libs=$prefer_static_libs
if test "$use_static_libs" = built && test "$installed" = yes; then
use_static_libs=no
fi
if test -n "$library_names" &&
{ test "$use_static_libs" = no || test -z "$old_library"; }; then
case $host in
*cygwin* | *mingw* | *cegcc*)
# No point in relinking DLLs because paths are not encoded
func_append notinst_deplibs " $lib"
need_relink=no
;;
*)
if test "$installed" = no; then
func_append notinst_deplibs " $lib"
need_relink=yes
fi
;;
esac
# This is a shared library
# Warn about portability, can't link against -module's on some
# systems (darwin). Don't bleat about dlopened modules though!
dlopenmodule=""
for dlpremoduletest in $dlprefiles; do
if test "X$dlpremoduletest" = "X$lib"; then
dlopenmodule="$dlpremoduletest"
break
fi
done
if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
echo
if test "$linkmode" = prog; then
$ECHO "*** Warning: Linking the executable $output against the loadable module"
else
$ECHO "*** Warning: Linking the shared library $output against the loadable module"
fi
$ECHO "*** $linklib is not portable!"
fi
if test "$linkmode" = lib &&
test "$hardcode_into_libs" = yes; then
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
*" $absdir "*) ;;
*) func_append compile_rpath " $absdir" ;;
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi
if test -n "$old_archive_from_expsyms_cmds"; then
# figure out the soname
set dummy $library_names
shift
realname="$1"
shift
libname=`eval "\\$ECHO \"$libname_spec\""`
# use dlname if we got it. it's perfectly good, no?
if test -n "$dlname"; then
soname="$dlname"
elif test -n "$soname_spec"; then
# bleh windows
case $host in
*cygwin* | mingw* | *cegcc*)
func_arith $current - $age
major=$func_arith_result
versuffix="-$major"
;;
esac
eval soname=\"$soname_spec\"
else
soname="$realname"
fi
# Make a new name for the extract_expsyms_cmds to use
soroot="$soname"
func_basename "$soroot"
soname="$func_basename_result"
func_stripname 'lib' '.dll' "$soname"
newlib=libimp-$func_stripname_result.a
# If the library has no export list, then create one now
if test -f "$output_objdir/$soname-def"; then :
else
func_verbose "extracting exported symbol list from \`$soname'"
func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
fi
# Create $newlib
if test -f "$output_objdir/$newlib"; then :; else
func_verbose "generating import library for \`$soname'"
func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
fi
# make sure the library variables are pointing to the new library
dir=$output_objdir
linklib=$newlib
fi # test -n "$old_archive_from_expsyms_cmds"
if test "$linkmode" = prog || test "$opt_mode" != relink; then
add_shlibpath=
add_dir=
add=
lib_linked=yes
case $hardcode_action in
immediate | unsupported)
if test "$hardcode_direct" = no; then
add="$dir/$linklib"
case $host in
*-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
*-*-sysv4*uw2*) add_dir="-L$dir" ;;
*-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
*-*-unixware7*) add_dir="-L$dir" ;;
*-*-darwin* )
# if the lib is a (non-dlopened) module then we can not
# link against it, someone is ignoring the earlier warnings
if /usr/bin/file -L $add 2> /dev/null |
$GREP ": [^:]* bundle" >/dev/null ; then
if test "X$dlopenmodule" != "X$lib"; then
$ECHO "*** Warning: lib $linklib is a module, not a shared library"
if test -z "$old_library" ; then
echo
echo "*** And there doesn't seem to be a static archive available"
echo "*** The link will probably fail, sorry"
else
add="$dir/$old_library"
fi
elif test -n "$old_library"; then
add="$dir/$old_library"
fi
fi
esac
elif test "$hardcode_minus_L" = no; then
case $host in
*-*-sunos*) add_shlibpath="$dir" ;;
esac
add_dir="-L$dir"
add="-l$name"
elif test "$hardcode_shlibpath_var" = no; then
add_shlibpath="$dir"
add="-l$name"
else
lib_linked=no
fi
;;
relink)
if test "$hardcode_direct" = yes &&
test "$hardcode_direct_absolute" = no; then
add="$dir/$linklib"
elif test "$hardcode_minus_L" = yes; then
add_dir="-L$absdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add="-l$name"
elif test "$hardcode_shlibpath_var" = yes; then
add_shlibpath="$dir"
add="-l$name"
else
lib_linked=no
fi
;;
*) lib_linked=no ;;
esac
if test "$lib_linked" != yes; then
func_fatal_configuration "unsupported hardcode properties"
fi
if test -n "$add_shlibpath"; then
case :$compile_shlibpath: in
*":$add_shlibpath:"*) ;;
*) func_append compile_shlibpath "$add_shlibpath:" ;;
esac
fi
if test "$linkmode" = prog; then
test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
test -n "$add" && compile_deplibs="$add $compile_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
if test "$hardcode_direct" != yes &&
test "$hardcode_minus_L" != yes &&
test "$hardcode_shlibpath_var" = yes; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
fi
fi
fi
if test "$linkmode" = prog || test "$opt_mode" = relink; then
add_shlibpath=
add_dir=
add=
# Finalize command for both is simple: just hardcode it.
if test "$hardcode_direct" = yes &&
test "$hardcode_direct_absolute" = no; then
add="$libdir/$linklib"
elif test "$hardcode_minus_L" = yes; then
add_dir="-L$libdir"
add="-l$name"
elif test "$hardcode_shlibpath_var" = yes; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
add="-l$name"
elif test "$hardcode_automatic" = yes; then
if test -n "$inst_prefix_dir" &&
test -f "$inst_prefix_dir$libdir/$linklib" ; then
add="$inst_prefix_dir$libdir/$linklib"
else
add="$libdir/$linklib"
fi
else
# We cannot seem to hardcode it, guess we'll fake it.
add_dir="-L$libdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add="-l$name"
fi
if test "$linkmode" = prog; then
test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
fi
fi
elif test "$linkmode" = prog; then
# Here we assume that one of hardcode_direct or hardcode_minus_L
# is not unsupported. This is valid on all known static and
# shared platforms.
if test "$hardcode_direct" != unsupported; then
test -n "$old_library" && linklib="$old_library"
compile_deplibs="$dir/$linklib $compile_deplibs"
finalize_deplibs="$dir/$linklib $finalize_deplibs"
else
compile_deplibs="-l$name -L$dir $compile_deplibs"
finalize_deplibs="-l$name -L$dir $finalize_deplibs"
fi
elif test "$build_libtool_libs" = yes; then
# Not a shared library
if test "$deplibs_check_method" != pass_all; then
# We're trying link a shared library against a static one
# but the system doesn't support it.
# Just print a warning and add the library to dependency_libs so
# that the program can be linked against the static library.
echo
$ECHO "*** Warning: This system can not link to static lib archive $lib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have."
if test "$module" = yes; then
echo "*** But as you try to build a module library, libtool will still create "
echo "*** a static module, that should work as long as the dlopening application"
echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
if test -z "$global_symbol_pipe"; then
echo
echo "*** However, this would only work if libtool was able to extract symbol"
echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
echo "*** not find such a program. So, this module is probably useless."
echo "*** \`nm' from GNU binutils and a full rebuild may help."
fi
if test "$build_old_libs" = no; then
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
else
deplibs="$dir/$old_library $deplibs"
link_static=yes
fi
fi # link shared/static library?
if test "$linkmode" = lib; then
if test -n "$dependency_libs" &&
{ test "$hardcode_into_libs" != yes ||
test "$build_old_libs" = yes ||
test "$link_static" = yes; }; then
# Extract -R from dependency_libs
temp_deplibs=
for libdir in $dependency_libs; do
case $libdir in
-R*) func_stripname '-R' '' "$libdir"
temp_xrpath=$func_stripname_result
case " $xrpath " in
*" $temp_xrpath "*) ;;
*) func_append xrpath " $temp_xrpath";;
esac;;
*) func_append temp_deplibs " $libdir";;
esac
done
dependency_libs="$temp_deplibs"
fi
func_append newlib_search_path " $absdir"
# Link against this library
test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
# ... and its dependency_libs
tmp_libs=
for deplib in $dependency_libs; do
newdependency_libs="$deplib $newdependency_libs"
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result";;
*) func_resolve_sysroot "$deplib" ;;
esac
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $func_resolve_sysroot_result "*)
func_append specialdeplibs " $func_resolve_sysroot_result" ;;
esac
fi
func_append tmp_libs " $func_resolve_sysroot_result"
done
if test "$link_all_deplibs" != no; then
# Add the search paths of all dependency libraries
for deplib in $dependency_libs; do
path=
case $deplib in
-L*) path="$deplib" ;;
*.la)
func_resolve_sysroot "$deplib"
deplib=$func_resolve_sysroot_result
func_dirname "$deplib" "" "."
dir=$func_dirname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
*)
absdir=`cd "$dir" && pwd`
if test -z "$absdir"; then
func_warning "cannot determine absolute directory name of \`$dir'"
absdir="$dir"
fi
;;
esac
if $GREP "^installed=no" $deplib > /dev/null; then
case $host in
*-*-darwin*)
depdepl=
eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
if test -n "$deplibrary_names" ; then
for tmp in $deplibrary_names ; do
depdepl=$tmp
done
if test -f "$absdir/$objdir/$depdepl" ; then
depdepl="$absdir/$objdir/$depdepl"
darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
if test -z "$darwin_install_name"; then
darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
fi
func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}"
path=
fi
fi
;;
*)
path="-L$absdir/$objdir"
;;
esac
else
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
test -z "$libdir" && \
func_fatal_error "\`$deplib' is not a valid libtool archive"
test "$absdir" != "$libdir" && \
func_warning "\`$deplib' seems to be moved"
path="-L$absdir"
fi
;;
esac
case " $deplibs " in
*" $path "*) ;;
*) deplibs="$path $deplibs" ;;
esac
done
fi # link_all_deplibs != no
fi # linkmode = lib
done # for deplib in $libs
if test "$pass" = link; then
if test "$linkmode" = "prog"; then
compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
else
compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
fi
fi
dependency_libs="$newdependency_libs"
if test "$pass" = dlpreopen; then
# Link the dlpreopened libraries before other libraries
for deplib in $save_deplibs; do
deplibs="$deplib $deplibs"
done
fi
if test "$pass" != dlopen; then
if test "$pass" != conv; then
# Make sure lib_search_path contains only unique directories.
lib_search_path=
for dir in $newlib_search_path; do
case "$lib_search_path " in
*" $dir "*) ;;
*) func_append lib_search_path " $dir" ;;
esac
done
newlib_search_path=
fi
if test "$linkmode,$pass" != "prog,link"; then
vars="deplibs"
else
vars="compile_deplibs finalize_deplibs"
fi
for var in $vars dependency_libs; do
# Add libraries to $var in reverse order
eval tmp_libs=\"\$$var\"
new_libs=
for deplib in $tmp_libs; do
# FIXME: Pedantically, this is the right thing to do, so
# that some nasty dependency loop isn't accidentally
# broken:
#new_libs="$deplib $new_libs"
# Pragmatically, this seems to cause very few problems in
# practice:
case $deplib in
-L*) new_libs="$deplib $new_libs" ;;
-R*) ;;
*)
# And here is the reason: when a library appears more
# than once as an explicit dependence of a library, or
# is implicitly linked in more than once by the
# compiler, it is considered special, and multiple
# occurrences thereof are not removed. Compare this
# with having the same library being listed as a
# dependency of multiple other libraries: in this case,
# we know (pedantically, we assume) the library does not
# need to be listed more than once, so we keep only the
# last copy. This is not always right, but it is rare
# enough that we require users that really mean to play
# such unportable linking tricks to link the library
# using -Wl,-lname, so that libtool does not consider it
# for duplicate removal.
case " $specialdeplibs " in
*" $deplib "*) new_libs="$deplib $new_libs" ;;
*)
case " $new_libs " in
*" $deplib "*) ;;
*) new_libs="$deplib $new_libs" ;;
esac
;;
esac
;;
esac
done
tmp_libs=
for deplib in $new_libs; do
case $deplib in
-L*)
case " $tmp_libs " in
*" $deplib "*) ;;
*) func_append tmp_libs " $deplib" ;;
esac
;;
*) func_append tmp_libs " $deplib" ;;
esac
done
eval $var=\"$tmp_libs\"
done # for var
fi
# Last step: remove runtime libs from dependency_libs
# (they stay in deplibs)
tmp_libs=
for i in $dependency_libs ; do
case " $predeps $postdeps $compiler_lib_search_path " in
*" $i "*)
i=""
;;
esac
if test -n "$i" ; then
func_append tmp_libs " $i"
fi
done
dependency_libs=$tmp_libs
done # for pass
if test "$linkmode" = prog; then
dlfiles="$newdlfiles"
fi
if test "$linkmode" = prog || test "$linkmode" = lib; then
dlprefiles="$newdlprefiles"
fi
case $linkmode in
oldlib)
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
func_warning "\`-dlopen' is ignored for archives"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "\`-l' and \`-L' are ignored for archives" ;;
esac
test -n "$rpath" && \
func_warning "\`-rpath' is ignored for archives"
test -n "$xrpath" && \
func_warning "\`-R' is ignored for archives"
test -n "$vinfo" && \
func_warning "\`-version-info/-version-number' is ignored for archives"
test -n "$release" && \
func_warning "\`-release' is ignored for archives"
test -n "$export_symbols$export_symbols_regex" && \
func_warning "\`-export-symbols' is ignored for archives"
# Now set the variables for building old libraries.
build_libtool_libs=no
oldlibs="$output"
func_append objs "$old_deplibs"
;;
lib)
# Make sure we only generate libraries of the form `libNAME.la'.
case $outputname in
lib*)
func_stripname 'lib' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
;;
*)
test "$module" = no && \
func_fatal_help "libtool library \`$output' must begin with \`lib'"
if test "$need_lib_prefix" != no; then
# Add the "lib" prefix for modules if required
func_stripname '' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
else
func_stripname '' '.la' "$outputname"
libname=$func_stripname_result
fi
;;
esac
if test -n "$objs"; then
if test "$deplibs_check_method" != pass_all; then
func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
else
echo
$ECHO "*** Warning: Linking the shared library $output against the non-libtool"
$ECHO "*** objects $objs is not portable!"
func_append libobjs " $objs"
fi
fi
test "$dlself" != no && \
func_warning "\`-dlopen self' is ignored for libtool libraries"
set dummy $rpath
shift
test "$#" -gt 1 && \
func_warning "ignoring multiple \`-rpath's for a libtool library"
install_libdir="$1"
oldlibs=
if test -z "$rpath"; then
if test "$build_libtool_libs" = yes; then
# Building a libtool convenience library.
# Some compilers have problems with a `.al' extension so
# convenience libraries should have the same extension an
# archive normally would.
oldlibs="$output_objdir/$libname.$libext $oldlibs"
build_libtool_libs=convenience
build_old_libs=yes
fi
test -n "$vinfo" && \
func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
test -n "$release" && \
func_warning "\`-release' is ignored for convenience libraries"
else
# Parse the version information argument.
save_ifs="$IFS"; IFS=':'
set dummy $vinfo 0 0 0
shift
IFS="$save_ifs"
test -n "$7" && \
func_fatal_help "too many parameters to \`-version-info'"
# convert absolute version numbers to libtool ages
# this retains compatibility with .la files and attempts
# to make the code below a bit more comprehensible
case $vinfo_number in
yes)
number_major="$1"
number_minor="$2"
number_revision="$3"
#
# There are really only two kinds -- those that
# use the current revision as the major version
# and those that subtract age and use age as
# a minor version. But, then there is irix
# which has an extra 1 added just for fun
#
case $version_type in
# correct linux to gnu/linux during the next big refactor
darwin|linux|osf|windows|none)
func_arith $number_major + $number_minor
current=$func_arith_result
age="$number_minor"
revision="$number_revision"
;;
freebsd-aout|freebsd-elf|qnx|sunos)
current="$number_major"
revision="$number_minor"
age="0"
;;
irix|nonstopux)
func_arith $number_major + $number_minor
current=$func_arith_result
age="$number_minor"
revision="$number_minor"
lt_irix_increment=no
;;
*)
func_fatal_configuration "$modename: unknown library version type \`$version_type'"
;;
esac
;;
no)
current="$1"
revision="$2"
age="$3"
;;
esac
# Check that each of the things are valid numbers.
case $current in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "CURRENT \`$current' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
case $revision in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "REVISION \`$revision' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
case $age in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "AGE \`$age' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
if test "$age" -gt "$current"; then
func_error "AGE \`$age' is greater than the current interface number \`$current'"
func_fatal_error "\`$vinfo' is not valid version information"
fi
# Calculate the version variables.
major=
versuffix=
verstring=
case $version_type in
none) ;;
darwin)
# Like Linux, but with the current version available in
# verstring for coding it into the library header
func_arith $current - $age
major=.$func_arith_result
versuffix="$major.$age.$revision"
# Darwin ld doesn't like 0 for these options...
func_arith $current + 1
minor_current=$func_arith_result
xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
;;
freebsd-aout)
major=".$current"
versuffix=".$current.$revision";
;;
freebsd-elf)
major=".$current"
versuffix=".$current"
;;
irix | nonstopux)
if test "X$lt_irix_increment" = "Xno"; then
func_arith $current - $age
else
func_arith $current - $age + 1
fi
major=$func_arith_result
case $version_type in
nonstopux) verstring_prefix=nonstopux ;;
*) verstring_prefix=sgi ;;
esac
verstring="$verstring_prefix$major.$revision"
# Add in all the interfaces that we are compatible with.
loop=$revision
while test "$loop" -ne 0; do
func_arith $revision - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring="$verstring_prefix$major.$iface:$verstring"
done
# Before this point, $major must not contain `.'.
major=.$major
versuffix="$major.$revision"
;;
linux) # correct to gnu/linux during the next big refactor
func_arith $current - $age
major=.$func_arith_result
versuffix="$major.$age.$revision"
;;
osf)
func_arith $current - $age
major=.$func_arith_result
versuffix=".$current.$age.$revision"
verstring="$current.$age.$revision"
# Add in all the interfaces that we are compatible with.
loop=$age
while test "$loop" -ne 0; do
func_arith $current - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring="$verstring:${iface}.0"
done
# Make executables depend on our current version.
func_append verstring ":${current}.0"
;;
qnx)
major=".$current"
versuffix=".$current"
;;
sunos)
major=".$current"
versuffix=".$current.$revision"
;;
windows)
# Use '-' rather than '.', since we only want one
# extension on DOS 8.3 filesystems.
func_arith $current - $age
major=$func_arith_result
versuffix="-$major"
;;
*)
func_fatal_configuration "unknown library version type \`$version_type'"
;;
esac
# Clear the version info if we defaulted, and they specified a release.
if test -z "$vinfo" && test -n "$release"; then
major=
case $version_type in
darwin)
# we can't check for "0.0" in archive_cmds due to quoting
# problems, so we reset it completely
verstring=
;;
*)
verstring="0.0"
;;
esac
if test "$need_version" = no; then
versuffix=
else
versuffix=".0.0"
fi
fi
# Remove version info from name if versioning should be avoided
if test "$avoid_version" = yes && test "$need_version" = no; then
major=
versuffix=
verstring=""
fi
# Check to see if the archive will have undefined symbols.
if test "$allow_undefined" = yes; then
if test "$allow_undefined_flag" = unsupported; then
func_warning "undefined symbols not allowed in $host shared libraries"
build_libtool_libs=no
build_old_libs=yes
fi
else
# Don't allow undefined symbols.
allow_undefined_flag="$no_undefined_flag"
fi
fi
func_generate_dlsyms "$libname" "$libname" "yes"
func_append libobjs " $symfileobj"
test "X$libobjs" = "X " && libobjs=
if test "$opt_mode" != relink; then
# Remove our outputs, but don't remove object files since they
# may have been created when compiling PIC objects.
removelist=
tempremovelist=`$ECHO "$output_objdir/*"`
for p in $tempremovelist; do
case $p in
*.$objext | *.gcno)
;;
$output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
if test "X$precious_files_regex" != "X"; then
if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
then
continue
fi
fi
func_append removelist " $p"
;;
*) ;;
esac
done
test -n "$removelist" && \
func_show_eval "${RM}r \$removelist"
fi
# Now set the variables for building old libraries.
if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
func_append oldlibs " $output_objdir/$libname.$libext"
# Transform .lo files to .o files.
oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
fi
# Eliminate all temporary directories.
#for path in $notinst_path; do
# lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
# deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
# dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
#done
if test -n "$xrpath"; then
# If the user specified any rpath flags, then add them.
temp_xrpath=
for libdir in $xrpath; do
func_replace_sysroot "$libdir"
func_append temp_xrpath " -R$func_replace_sysroot_result"
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
dependency_libs="$temp_xrpath $dependency_libs"
fi
fi
# Make sure dlfiles contains only unique files that won't be dlpreopened
old_dlfiles="$dlfiles"
dlfiles=
for lib in $old_dlfiles; do
case " $dlprefiles $dlfiles " in
*" $lib "*) ;;
*) func_append dlfiles " $lib" ;;
esac
done
# Make sure dlprefiles contains only unique files
old_dlprefiles="$dlprefiles"
dlprefiles=
for lib in $old_dlprefiles; do
case "$dlprefiles " in
*" $lib "*) ;;
*) func_append dlprefiles " $lib" ;;
esac
done
if test "$build_libtool_libs" = yes; then
if test -n "$rpath"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
# these systems don't actually have a c library (as such)!
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C library is in the System framework
func_append deplibs " System.ltframework"
;;
*-*-netbsd*)
# Don't link with libc until the a.out ld.so is fixed.
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
;;
*)
# Add libc to deplibs on all other systems if necessary.
if test "$build_libtool_need_lc" = "yes"; then
func_append deplibs " -lc"
fi
;;
esac
fi
# Transform deplibs into only deplibs that can be linked in shared.
name_save=$name
libname_save=$libname
release_save=$release
versuffix_save=$versuffix
major_save=$major
# I'm not sure if I'm treating the release correctly. I think
# release should show up in the -l (ie -lgmp5) so we don't want to
# add it in twice. Is that correct?
release=""
versuffix=""
major=""
newdeplibs=
droppeddeps=no
case $deplibs_check_method in
pass_all)
# Don't check for shared/static. Everything works.
# This might be a little naive. We might want to check
# whether the library exists or not. But this is on
# osf3 & osf4 and I'm not really sure... Just
# implementing what was already the behavior.
newdeplibs=$deplibs
;;
test_compile)
# This code stresses the "libraries are programs" paradigm to its
# limits. Maybe even breaks it. We compile a program, linking it
# against the deplibs as a proxy for the library. Then we can check
# whether they linked in statically or dynamically with ldd.
$opt_dry_run || $RM conftest.c
cat > conftest.c <<EOF
int main() { return 0; }
EOF
$opt_dry_run || $RM conftest
if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
ldd_output=`ldd conftest`
for i in $deplibs; do
case $i in
-l*)
func_stripname -l '' "$i"
name=$func_stripname_result
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $i "*)
func_append newdeplibs " $i"
i=""
;;
esac
fi
if test -n "$i" ; then
libname=`eval "\\$ECHO \"$libname_spec\""`
deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
set dummy $deplib_matches; shift
deplib_match=$1
if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
func_append newdeplibs " $i"
else
droppeddeps=yes
echo
$ECHO "*** Warning: dynamic linker does not accept needed library $i."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which I believe you do not have"
echo "*** because a test_compile did reveal that the linker did not use it for"
echo "*** its dynamic dependency list that programs get resolved with at runtime."
fi
fi
;;
*)
func_append newdeplibs " $i"
;;
esac
done
else
# Error occurred in the first compile. Let's try to salvage
# the situation: Compile a separate program for each library.
for i in $deplibs; do
case $i in
-l*)
func_stripname -l '' "$i"
name=$func_stripname_result
$opt_dry_run || $RM conftest
if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
ldd_output=`ldd conftest`
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $i "*)
func_append newdeplibs " $i"
i=""
;;
esac
fi
if test -n "$i" ; then
libname=`eval "\\$ECHO \"$libname_spec\""`
deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
set dummy $deplib_matches; shift
deplib_match=$1
if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
func_append newdeplibs " $i"
else
droppeddeps=yes
echo
$ECHO "*** Warning: dynamic linker does not accept needed library $i."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because a test_compile did reveal that the linker did not use this one"
echo "*** as a dynamic dependency that programs can get resolved with at runtime."
fi
fi
else
droppeddeps=yes
echo
$ECHO "*** Warning! Library $i is needed by this library but I was not able to"
echo "*** make it link in! You will probably need to install it or some"
echo "*** library that it depends on before this library will be fully"
echo "*** functional. Installing it before continuing would be even better."
fi
;;
*)
func_append newdeplibs " $i"
;;
esac
done
fi
;;
file_magic*)
set dummy $deplibs_check_method; shift
file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
for a_deplib in $deplibs; do
case $a_deplib in
-l*)
func_stripname -l '' "$a_deplib"
name=$func_stripname_result
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $a_deplib "*)
func_append newdeplibs " $a_deplib"
a_deplib=""
;;
esac
fi
if test -n "$a_deplib" ; then
libname=`eval "\\$ECHO \"$libname_spec\""`
if test -n "$file_magic_glob"; then
libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
else
libnameglob=$libname
fi
test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob`
for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
if test "$want_nocaseglob" = yes; then
shopt -s nocaseglob
potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
$nocaseglob
else
potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
fi
for potent_lib in $potential_libs; do
# Follow soft links.
if ls -lLd "$potent_lib" 2>/dev/null |
$GREP " -> " >/dev/null; then
continue
fi
# The statement above tries to avoid entering an
# endless loop below, in case of cyclic links.
# We might still enter an endless loop, since a link
# loop can be closed while we follow links,
# but so what?
potlib="$potent_lib"
while test -h "$potlib" 2>/dev/null; do
potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
case $potliblink in
[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
esac
done
if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
$SED -e 10q |
$EGREP "$file_magic_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=""
break 2
fi
done
done
fi
if test -n "$a_deplib" ; then
droppeddeps=yes
echo
$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because I did check the linker path looking for a file starting"
if test -z "$potlib" ; then
$ECHO "*** with $libname but no candidates were found. (...for file magic test)"
else
$ECHO "*** with $libname and none of the candidates passed a file format test"
$ECHO "*** using a file magic. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
for a_deplib in $deplibs; do
case $a_deplib in
-l*)
func_stripname -l '' "$a_deplib"
name=$func_stripname_result
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $a_deplib "*)
func_append newdeplibs " $a_deplib"
a_deplib=""
;;
esac
fi
if test -n "$a_deplib" ; then
libname=`eval "\\$ECHO \"$libname_spec\""`
for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
for potent_lib in $potential_libs; do
potlib="$potent_lib" # see symlink-check above in file_magic test
if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
$EGREP "$match_pattern_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=""
break 2
fi
done
done
fi
if test -n "$a_deplib" ; then
droppeddeps=yes
echo
$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because I did check the linker path looking for a file starting"
if test -z "$potlib" ; then
$ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
else
$ECHO "*** with $libname and none of the candidates passed a file format test"
$ECHO "*** using a regex pattern. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
none | unknown | *)
newdeplibs=""
tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
for i in $predeps $postdeps ; do
# can't use Xsed below, because $i might contain '/'
tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
done
fi
case $tmp_deplibs in
*[!\ \ ]*)
echo
if test "X$deplibs_check_method" = "Xnone"; then
echo "*** Warning: inter-library dependencies are not supported in this platform."
else
echo "*** Warning: inter-library dependencies are not known to be supported."
fi
echo "*** All declared inter-library dependencies are being dropped."
droppeddeps=yes
;;
esac
;;
esac
versuffix=$versuffix_save
major=$major_save
release=$release_save
libname=$libname_save
name=$name_save
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library with the System framework
newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
if test "$droppeddeps" = yes; then
if test "$module" = yes; then
echo
echo "*** Warning: libtool could not satisfy all declared inter-library"
$ECHO "*** dependencies of module $libname. Therefore, libtool will create"
echo "*** a static module, that should work as long as the dlopening"
echo "*** application is linked with the -dlopen flag."
if test -z "$global_symbol_pipe"; then
echo
echo "*** However, this would only work if libtool was able to extract symbol"
echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
echo "*** not find such a program. So, this module is probably useless."
echo "*** \`nm' from GNU binutils and a full rebuild may help."
fi
if test "$build_old_libs" = no; then
oldlibs="$output_objdir/$libname.$libext"
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
else
echo "*** The inter-library dependencies that have been dropped here will be"
echo "*** automatically added whenever a program is linked with this library"
echo "*** or is declared to -dlopen it."
if test "$allow_undefined" = no; then
echo
echo "*** Since this library must not contain undefined symbols,"
echo "*** because either the platform does not support them or"
echo "*** it was explicitly requested with -no-undefined,"
echo "*** libtool will only create a static version of it."
if test "$build_old_libs" = no; then
oldlibs="$output_objdir/$libname.$libext"
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
fi
fi
# Done checking deplibs!
deplibs=$newdeplibs
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
case $host in
*-*-darwin*)
newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
deplibs="$new_libs"
# All the library-specific variables (install_libdir is set above).
library_names=
old_library=
dlname=
# Test again, we may have decided not to build it any more
if test "$build_libtool_libs" = yes; then
# Remove ${wl} instances when linking with ld.
# FIXME: should test the right _cmds variable.
case $archive_cmds in
*\$LD\ *) wl= ;;
esac
if test "$hardcode_into_libs" = yes; then
# Hardcode the library paths
hardcode_libdirs=
dep_rpath=
rpath="$finalize_rpath"
test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
for libdir in $rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
func_replace_sysroot "$libdir"
libdir=$func_replace_sysroot_result
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append dep_rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
fi
if test -n "$runpath_var" && test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
fi
test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
fi
shlibpath="$finalize_shlibpath"
test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
if test -n "$shlibpath"; then
eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
fi
# Get the real and link names of the library.
eval shared_ext=\"$shrext_cmds\"
eval library_names=\"$library_names_spec\"
set dummy $library_names
shift
realname="$1"
shift
if test -n "$soname_spec"; then
eval soname=\"$soname_spec\"
else
soname="$realname"
fi
if test -z "$dlname"; then
dlname=$soname
fi
lib="$output_objdir/$realname"
linknames=
for link
do
func_append linknames " $link"
done
# Use standard objects if they are pic
test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
test "X$libobjs" = "X " && libobjs=
delfiles=
if test -n "$export_symbols" && test -n "$include_expsyms"; then
$opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
export_symbols="$output_objdir/$libname.uexp"
func_append delfiles " $export_symbols"
fi
orig_export_symbols=
case $host_os in
cygwin* | mingw* | cegcc*)
if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
# exporting using user supplied symfile
if test "x`$SED "$sed_uncomment_deffile" $export_symbols | $SED 1q`" != xEXPORTS; then
# and it's NOT already a .def file. Must figure out
# which of the given symbols are data symbols and tag
# them as such. So, trigger use of export_symbols_cmds.
# export_symbols gets reassigned inside the "prepare
# the list of exported symbols" if statement, so the
# include_expsyms logic still works.
orig_export_symbols="$export_symbols"
export_symbols=
always_export_symbols=yes
fi
fi
;;
esac
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
func_verbose "generating symbol list for \`$libname.la'"
export_symbols="$output_objdir/$libname.exp"
$opt_dry_run || $RM $export_symbols
cmds=$export_symbols_cmds
save_ifs="$IFS"; IFS='~'
for cmd1 in $cmds; do
IFS="$save_ifs"
# Take the normal branch if the nm_file_list_spec branch
# doesn't work or if tool conversion is not needed.
case $nm_file_list_spec~$to_tool_file_cmd in
*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
try_normal_branch=yes
eval cmd=\"$cmd1\"
func_len " $cmd"
len=$func_len_result
;;
*)
try_normal_branch=no
;;
esac
if test "$try_normal_branch" = yes \
&& { test "$len" -lt "$max_cmd_len" \
|| test "$max_cmd_len" -le -1; }
then
func_show_eval "$cmd" 'exit $?'
skipped_export=false
elif test -n "$nm_file_list_spec"; then
func_basename "$output"
output_la=$func_basename_result
save_libobjs=$libobjs
save_output=$output
output=${output_objdir}/${output_la}.nm
func_to_tool_file "$output"
libobjs=$nm_file_list_spec$func_to_tool_file_result
func_append delfiles " $output"
func_verbose "creating $NM input file list: $output"
for obj in $save_libobjs; do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > "$output"
eval cmd=\"$cmd1\"
func_show_eval "$cmd" 'exit $?'
output=$save_output
libobjs=$save_libobjs
skipped_export=false
else
# The command line is too long to execute in one step.
func_verbose "using reloadable object file for export list..."
skipped_export=:
# Break out early, otherwise skipped_export may be
# set to false by a later but shorter cmd.
break
fi
done
IFS="$save_ifs"
if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
fi
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols="$export_symbols"
test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
tmp_deplibs=
for test_deplib in $deplibs; do
case " $convenience " in
*" $test_deplib "*) ;;
*)
func_append tmp_deplibs " $test_deplib"
;;
esac
done
deplibs="$tmp_deplibs"
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec" &&
test "$compiler_needs_object" = yes &&
test -z "$libobjs"; then
# extract the archives, so we have objects to list.
# TODO: could optimize this to just extract one archive.
whole_archive_flag_spec=
fi
if test -n "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
else
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $convenience
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
fi
if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
func_append linker_flags " $flag"
fi
# Make a backup of the uninstalled library when relinking
if test "$opt_mode" = relink; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
fi
# Do each of the archive commands.
if test "$module" = yes && test -n "$module_cmds" ; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
eval test_cmds=\"$module_expsym_cmds\"
cmds=$module_expsym_cmds
else
eval test_cmds=\"$module_cmds\"
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
eval test_cmds=\"$archive_expsym_cmds\"
cmds=$archive_expsym_cmds
else
eval test_cmds=\"$archive_cmds\"
cmds=$archive_cmds
fi
fi
if test "X$skipped_export" != "X:" &&
func_len " $test_cmds" &&
len=$func_len_result &&
test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
:
else
# The command line is too long to link in one step, link piecewise
# or, if using GNU ld and skipped_export is not :, use a linker
# script.
# Save the value of $output and $libobjs because we want to
# use them later. If we have whole_archive_flag_spec, we
# want to use save_libobjs as it was before
# whole_archive_flag_spec was expanded, because we can't
# assume the linker understands whole_archive_flag_spec.
# This may have to be revisited, in case too many
# convenience libraries get linked in and end up exceeding
# the spec.
if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
fi
save_output=$output
func_basename "$output"
output_la=$func_basename_result
# Clear the reloadable object creation command queue and
# initialize k to one.
test_cmds=
concat_cmds=
objlist=
last_robj=
k=1
if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
output=${output_objdir}/${output_la}.lnkscript
func_verbose "creating GNU ld script: $output"
echo 'INPUT (' > $output
for obj in $save_libobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
echo ')' >> $output
func_append delfiles " $output"
func_to_tool_file "$output"
output=$func_to_tool_file_result
elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
output=${output_objdir}/${output_la}.lnk
func_verbose "creating linker input file list: $output"
: > $output
set x $save_libobjs
shift
firstobj=
if test "$compiler_needs_object" = yes; then
firstobj="$1 "
shift
fi
for obj
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
func_append delfiles " $output"
func_to_tool_file "$output"
output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
else
if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..."
output=$output_objdir/$output_la-${k}.$objext
eval test_cmds=\"$reload_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
# Loop over the list of objects to be linked.
for obj in $save_libobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
if test "X$objlist" = X ||
test "$len" -lt "$max_cmd_len"; then
func_append objlist " $obj"
else
# The command $test_cmds is almost too long, add a
# command to the queue.
if test "$k" -eq 1 ; then
# The first file doesn't have a previous command to add.
reload_objs=$objlist
eval concat_cmds=\"$reload_cmds\"
else
# All subsequent reloadable object files will link in
# the last one created.
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
fi
last_robj=$output_objdir/$output_la-${k}.$objext
func_arith $k + 1
k=$func_arith_result
output=$output_objdir/$output_la-${k}.$objext
objlist=" $obj"
func_len " $last_robj"
func_arith $len0 + $func_len_result
len=$func_arith_result
fi
done
# Handle the remaining objects by creating one last
# reloadable object file. All subsequent reloadable object
# files will link in the last one created.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
fi
func_append delfiles " $output"
else
output=
fi
if ${skipped_export-false}; then
func_verbose "generating symbol list for \`$libname.la'"
export_symbols="$output_objdir/$libname.exp"
$opt_dry_run || $RM $export_symbols
libobjs=$output
# Append the command to create the export file.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
fi
fi
test -n "$save_libobjs" &&
func_verbose "creating a temporary reloadable object file: $output"
# Loop through the commands generated above and execute them.
save_ifs="$IFS"; IFS='~'
for cmd in $concat_cmds; do
IFS="$save_ifs"
$opt_silent || {
func_quote_for_expand "$cmd"
eval "func_echo $func_quote_for_expand_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS="$save_ifs"
if test -n "$export_symbols_regex" && ${skipped_export-false}; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
if ${skipped_export-false}; then
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols="$export_symbols"
test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
fi
libobjs=$output
# Restore the value of output.
output=$save_output
if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
fi
# Expand the library linking commands again to reset the
# value of $libobjs for piecewise linking.
# Do each of the archive commands.
if test "$module" = yes && test -n "$module_cmds" ; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
cmds=$module_expsym_cmds
else
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
cmds=$archive_expsym_cmds
else
cmds=$archive_cmds
fi
fi
fi
if test -n "$delfiles"; then
# Append the command to remove temporary files to $cmds.
eval cmds=\"\$cmds~\$RM $delfiles\"
fi
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
eval cmd=\"$cmd\"
$opt_silent || {
func_quote_for_expand "$cmd"
eval "func_echo $func_quote_for_expand_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS="$save_ifs"
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
if test -n "$convenience"; then
if test -z "$whole_archive_flag_spec"; then
func_show_eval '${RM}r "$gentop"'
fi
fi
exit $EXIT_SUCCESS
fi
# Create links to the real library.
for linkname in $linknames; do
if test "$realname" != "$linkname"; then
func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
fi
done
# If -module or -export-dynamic was specified, set the dlname.
if test "$module" = yes || test "$export_dynamic" = yes; then
# On all known operating systems, these are identical.
dlname="$soname"
fi
fi
;;
obj)
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
func_warning "\`-dlopen' is ignored for objects"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "\`-l' and \`-L' are ignored for objects" ;;
esac
test -n "$rpath" && \
func_warning "\`-rpath' is ignored for objects"
test -n "$xrpath" && \
func_warning "\`-R' is ignored for objects"
test -n "$vinfo" && \
func_warning "\`-version-info' is ignored for objects"
test -n "$release" && \
func_warning "\`-release' is ignored for objects"
case $output in
*.lo)
test -n "$objs$old_deplibs" && \
func_fatal_error "cannot build library object \`$output' from non-libtool objects"
libobj=$output
func_lo2o "$libobj"
obj=$func_lo2o_result
;;
*)
libobj=
obj="$output"
;;
esac
# Delete the old objects.
$opt_dry_run || $RM $obj $libobj
# Objects from convenience libraries. This assumes
# single-version convenience libraries. Whenever we create
# different ones for PIC/non-PIC, this we'll have to duplicate
# the extraction.
reload_conv_objs=
gentop=
# reload_cmds runs $LD directly, so let us get rid of
# -Wl from whole_archive_flag_spec and hope we can get by with
# turning comma into space..
wl=
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
else
gentop="$output_objdir/${obj}x"
func_append generated " $gentop"
func_extract_archives $gentop $convenience
reload_conv_objs="$reload_objs $func_extract_archives_result"
fi
fi
# If we're not building shared, we need to use non_pic_objs
test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
# Create the old-style object.
reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
output="$obj"
func_execute_cmds "$reload_cmds" 'exit $?'
# Exit if we aren't doing a library object file.
if test -z "$libobj"; then
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
fi
if test "$build_libtool_libs" != yes; then
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
# Create an invalid libtool object if no PIC, so that we don't
# accidentally link it into a program.
# $show "echo timestamp > $libobj"
# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
exit $EXIT_SUCCESS
fi
if test -n "$pic_flag" || test "$pic_mode" != default; then
# Only do commands if we really have different PIC objects.
reload_objs="$libobjs $reload_conv_objs"
output="$libobj"
func_execute_cmds "$reload_cmds" 'exit $?'
fi
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
;;
prog)
case $host in
*cygwin*) func_stripname '' '.exe' "$output"
output=$func_stripname_result.exe;;
esac
test -n "$vinfo" && \
func_warning "\`-version-info' is ignored for programs"
test -n "$release" && \
func_warning "\`-release' is ignored for programs"
test "$preload" = yes \
&& test "$dlopen_support" = unknown \
&& test "$dlopen_self" = unknown \
&& test "$dlopen_self_static" = unknown && \
func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library is the System framework
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
case $host in
*-*-darwin*)
# Don't allow lazy linking, it breaks C++ global constructors
# But is supposedly fixed on 10.4 or later (yay!).
if test "$tagname" = CXX ; then
case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
10.[0123])
func_append compile_command " ${wl}-bind_at_load"
func_append finalize_command " ${wl}-bind_at_load"
;;
esac
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $compile_deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $compile_deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
compile_deplibs="$new_libs"
func_append compile_command " $compile_deplibs"
func_append finalize_command " $finalize_deplibs"
if test -n "$rpath$xrpath"; then
# If the user specified any rpath flags, then add them.
for libdir in $rpath $xrpath; do
# This is the magic to use -rpath.
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
fi
# Now hardcode the library paths
rpath=
hardcode_libdirs=
for libdir in $compile_rpath $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$libdir:"*) ;;
::) dllsearchpath=$libdir;;
*) func_append dllsearchpath ":$libdir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
compile_rpath="$rpath"
rpath=
hardcode_libdirs=
for libdir in $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$finalize_perm_rpath " in
*" $libdir "*) ;;
*) func_append finalize_perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
finalize_rpath="$rpath"
if test -n "$libobjs" && test "$build_old_libs" = yes; then
# Transform all the library objects into standard objects.
compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
fi
func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
# template prelinking step
if test -n "$prelink_cmds"; then
func_execute_cmds "$prelink_cmds" 'exit $?'
fi
wrappers_required=yes
case $host in
*cegcc* | *mingw32ce*)
# Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
wrappers_required=no
;;
*cygwin* | *mingw* )
if test "$build_libtool_libs" != yes; then
wrappers_required=no
fi
;;
*)
if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
wrappers_required=no
fi
;;
esac
if test "$wrappers_required" = no; then
# Replace the output file specification.
compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
link_command="$compile_command$compile_rpath"
# We have no uninstalled library dependencies, so finalize right now.
exit_status=0
func_show_eval "$link_command" 'exit_status=$?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Delete the generated files.
if test -f "$output_objdir/${outputname}S.${objext}"; then
func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
fi
exit $exit_status
fi
if test -n "$compile_shlibpath$finalize_shlibpath"; then
compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
fi
if test -n "$finalize_shlibpath"; then
finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
fi
compile_var=
finalize_var=
if test -n "$runpath_var"; then
if test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
if test -n "$finalize_perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $finalize_perm_rpath; do
func_append rpath "$dir:"
done
finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
fi
if test "$no_install" = yes; then
# We don't need to create a wrapper script.
link_command="$compile_var$compile_command$compile_rpath"
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
# Delete the old output file.
$opt_dry_run || $RM $output
# Link the executable and exit
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
exit $EXIT_SUCCESS
fi
if test "$hardcode_action" = relink; then
# Fast installation is not supported
link_command="$compile_var$compile_command$compile_rpath"
relink_command="$finalize_var$finalize_command$finalize_rpath"
func_warning "this platform does not like uninstalled shared libraries"
func_warning "\`$output' will be relinked during installation"
else
if test "$fast_install" != no; then
link_command="$finalize_var$compile_command$finalize_rpath"
if test "$fast_install" = yes; then
relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
else
# fast_install is set to needless
relink_command=
fi
else
link_command="$compile_var$compile_command$compile_rpath"
relink_command="$finalize_var$finalize_command$finalize_rpath"
fi
fi
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
# Delete the old output files.
$opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output_objdir/$outputname"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Now create the wrapper script.
func_verbose "creating $output"
# Quote the relink command for shipping.
if test -n "$relink_command"; then
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_for_eval "$var_value"
relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
fi
done
relink_command="(cd `pwd`; $relink_command)"
relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
fi
# Only actually do things if not in dry run mode.
$opt_dry_run || {
# win32 will think the script is a binary if it has
# a .exe suffix, so we strip it off here.
case $output in
*.exe) func_stripname '' '.exe' "$output"
output=$func_stripname_result ;;
esac
# test for cygwin because mv fails w/o .exe extensions
case $host in
*cygwin*)
exeext=.exe
func_stripname '' '.exe' "$outputname"
outputname=$func_stripname_result ;;
*) exeext= ;;
esac
case $host in
*cygwin* | *mingw* )
func_dirname_and_basename "$output" "" "."
output_name=$func_basename_result
output_path=$func_dirname_result
cwrappersource="$output_path/$objdir/lt-$output_name.c"
cwrapper="$output_path/$output_name.exe"
$RM $cwrappersource $cwrapper
trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
func_emit_cwrapperexe_src > $cwrappersource
# The wrapper executable is built using the $host compiler,
# because it contains $host paths and files. If cross-
# compiling, it, like the target executable, must be
# executed on the $host or under an emulation environment.
$opt_dry_run || {
$LTCC $LTCFLAGS -o $cwrapper $cwrappersource
$STRIP $cwrapper
}
# Now, create the wrapper script for func_source use:
func_ltwrapper_scriptname $cwrapper
$RM $func_ltwrapper_scriptname_result
trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
$opt_dry_run || {
# note: this script will not be executed, so do not chmod.
if test "x$build" = "x$host" ; then
$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
else
func_emit_wrapper no > $func_ltwrapper_scriptname_result
fi
}
;;
* )
$RM $output
trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
func_emit_wrapper no > $output
chmod +x $output
;;
esac
}
exit $EXIT_SUCCESS
;;
esac
# See if we need to build an old-fashioned archive.
for oldlib in $oldlibs; do
if test "$build_libtool_libs" = convenience; then
oldobjs="$libobjs_save $symfileobj"
addlibs="$convenience"
build_libtool_libs=no
else
if test "$build_libtool_libs" = module; then
oldobjs="$libobjs_save"
build_libtool_libs=no
else
oldobjs="$old_deplibs $non_pic_objects"
if test "$preload" = yes && test -f "$symfileobj"; then
func_append oldobjs " $symfileobj"
fi
fi
addlibs="$old_convenience"
fi
if test -n "$addlibs"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $addlibs
func_append oldobjs " $func_extract_archives_result"
fi
# Do each command in the archive commands.
if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
cmds=$old_archive_from_new_cmds
else
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append oldobjs " $func_extract_archives_result"
fi
# POSIX demands no paths to be encoded in archives. We have
# to avoid creating archives with duplicate basenames if we
# might have to extract them afterwards, e.g., when creating a
# static archive out of a convenience library, or when linking
# the entirety of a libtool archive into another (currently
# not supported by libtool).
if (for obj in $oldobjs
do
func_basename "$obj"
$ECHO "$func_basename_result"
done | sort | sort -uc >/dev/null 2>&1); then
:
else
echo "copying selected object files to avoid basename conflicts..."
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_mkdir_p "$gentop"
save_oldobjs=$oldobjs
oldobjs=
counter=1
for obj in $save_oldobjs
do
func_basename "$obj"
objbase="$func_basename_result"
case " $oldobjs " in
" ") oldobjs=$obj ;;
*[\ /]"$objbase "*)
while :; do
# Make sure we don't pick an alternate name that also
# overlaps.
newobj=lt$counter-$objbase
func_arith $counter + 1
counter=$func_arith_result
case " $oldobjs " in
*[\ /]"$newobj "*) ;;
*) if test ! -f "$gentop/$newobj"; then break; fi ;;
esac
done
func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
func_append oldobjs " $gentop/$newobj"
;;
*) func_append oldobjs " $obj" ;;
esac
done
fi
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
eval cmds=\"$old_archive_cmds\"
func_len " $cmds"
len=$func_len_result
if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
cmds=$old_archive_cmds
elif test -n "$archiver_list_spec"; then
func_verbose "using command file archive linking..."
for obj in $oldobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > $output_objdir/$libname.libcmd
func_to_tool_file "$output_objdir/$libname.libcmd"
oldobjs=" $archiver_list_spec$func_to_tool_file_result"
cmds=$old_archive_cmds
else
# the command line is too long to link in one step, link in parts
func_verbose "using piecewise archive linking..."
save_RANLIB=$RANLIB
RANLIB=:
objlist=
concat_cmds=
save_oldobjs=$oldobjs
oldobjs=
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
last_oldobj=$obj
done
eval test_cmds=\"$old_archive_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
for obj in $save_oldobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
func_append objlist " $obj"
if test "$len" -lt "$max_cmd_len"; then
:
else
# the above command should be used before it gets too long
oldobjs=$objlist
if test "$obj" = "$last_oldobj" ; then
RANLIB=$save_RANLIB
fi
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
objlist=
len=$len0
fi
done
RANLIB=$save_RANLIB
oldobjs=$objlist
if test "X$oldobjs" = "X" ; then
eval cmds=\"\$concat_cmds\"
else
eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
fi
fi
fi
func_execute_cmds "$cmds" 'exit $?'
done
test -n "$generated" && \
func_show_eval "${RM}r$generated"
# Now create the libtool archive.
case $output in
*.la)
old_library=
test "$build_old_libs" = yes && old_library="$libname.$libext"
func_verbose "creating $output"
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_for_eval "$var_value"
relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
fi
done
# Quote the link command for shipping.
relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
if test "$hardcode_automatic" = yes ; then
relink_command=
fi
# Only create the output if not a dry run.
$opt_dry_run || {
for installed in no yes; do
if test "$installed" = yes; then
if test -z "$install_libdir"; then
break
fi
output="$output_objdir/$outputname"i
# Replace all uninstalled libtool libraries with the installed ones
newdependency_libs=
for deplib in $dependency_libs; do
case $deplib in
*.la)
func_basename "$deplib"
name="$func_basename_result"
func_resolve_sysroot "$deplib"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
test -z "$libdir" && \
func_fatal_error "\`$deplib' is not a valid libtool archive"
func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
;;
-L*)
func_stripname -L '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -L$func_replace_sysroot_result"
;;
-R*)
func_stripname -R '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -R$func_replace_sysroot_result"
;;
*) func_append newdependency_libs " $deplib" ;;
esac
done
dependency_libs="$newdependency_libs"
newdlfiles=
for lib in $dlfiles; do
case $lib in
*.la)
func_basename "$lib"
name="$func_basename_result"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "\`$lib' is not a valid libtool archive"
func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
;;
*) func_append newdlfiles " $lib" ;;
esac
done
dlfiles="$newdlfiles"
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
*.la)
# Only pass preopened files to the pseudo-archive (for
# eventual linking with the app. that links it) if we
# didn't already link the preopened objects directly into
# the library:
func_basename "$lib"
name="$func_basename_result"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "\`$lib' is not a valid libtool archive"
func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
;;
esac
done
dlprefiles="$newdlprefiles"
else
newdlfiles=
for lib in $dlfiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlfiles " $abs"
done
dlfiles="$newdlfiles"
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlprefiles " $abs"
done
dlprefiles="$newdlprefiles"
fi
$RM $output
# place dlname in correct position for cygwin
# In fact, it would be nice if we could use this code for all target
# systems that can't hard-code library paths into their executables
# and that have no shared library path variable independent of PATH,
# but it turns out we can't easily determine that from inspecting
# libtool variables, so we have to hard-code the OSs to which it
# applies here; at the moment, that means platforms that use the PE
# object format with DLL files. See the long comment at the top of
# tests/bindir.at for full details.
tdlname=$dlname
case $host,$output,$installed,$module,$dlname in
*cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
# If a -bindir argument was supplied, place the dll there.
if test "x$bindir" != x ;
then
func_relative_path "$install_libdir" "$bindir"
tdlname=$func_relative_path_result$dlname
else
# Otherwise fall back on heuristic.
tdlname=../bin/$dlname
fi
;;
esac
$ECHO > $output "\
# $outputname - a libtool library file
# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='$tdlname'
# Names of this library.
library_names='$library_names'
# The name of the static archive.
old_library='$old_library'
# Linker flags that can not go in dependency_libs.
inherited_linker_flags='$new_inherited_linker_flags'
# Libraries that this one depends upon.
dependency_libs='$dependency_libs'
# Names of additional weak libraries provided by this library
weak_library_names='$weak_libs'
# Version information for $libname.
current=$current
age=$age
revision=$revision
# Is this an already installed library?
installed=$installed
# Should we warn about portability when linking against -modules?
shouldnotlink=$module
# Files to dlopen/dlpreopen
dlopen='$dlfiles'
dlpreopen='$dlprefiles'
# Directory that this library needs to be installed in:
libdir='$install_libdir'"
if test "$installed" = no && test "$need_relink" = yes; then
$ECHO >> $output "\
relink_command=\"$relink_command\""
fi
done
}
# Do a symbolic link so that the libtool archive can be found in
# LD_LIBRARY_PATH before the program is installed.
func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
;;
esac
exit $EXIT_SUCCESS
}
{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
func_mode_link ${1+"$@"}
# func_mode_uninstall arg...
func_mode_uninstall ()
{
$opt_debug
RM="$nonopt"
files=
rmforce=
exit_status=0
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic="$magic"
for arg
do
case $arg in
-f) func_append RM " $arg"; rmforce=yes ;;
-*) func_append RM " $arg" ;;
*) func_append files " $arg" ;;
esac
done
test -z "$RM" && \
func_fatal_help "you must specify an RM program"
rmdirs=
for file in $files; do
func_dirname "$file" "" "."
dir="$func_dirname_result"
if test "X$dir" = X.; then
odir="$objdir"
else
odir="$dir/$objdir"
fi
func_basename "$file"
name="$func_basename_result"
test "$opt_mode" = uninstall && odir="$dir"
# Remember odir for removal later, being careful to avoid duplicates
if test "$opt_mode" = clean; then
case " $rmdirs " in
*" $odir "*) ;;
*) func_append rmdirs " $odir" ;;
esac
fi
# Don't error if the file doesn't exist and rm -f was used.
if { test -L "$file"; } >/dev/null 2>&1 ||
{ test -h "$file"; } >/dev/null 2>&1 ||
test -f "$file"; then
:
elif test -d "$file"; then
exit_status=1
continue
elif test "$rmforce" = yes; then
continue
fi
rmfiles="$file"
case $name in
*.la)
# Possibly a libtool archive, so verify it.
if func_lalib_p "$file"; then
func_source $dir/$name
# Delete the libtool libraries and symlinks.
for n in $library_names; do
func_append rmfiles " $odir/$n"
done
test -n "$old_library" && func_append rmfiles " $odir/$old_library"
case "$opt_mode" in
clean)
case " $library_names " in
*" $dlname "*) ;;
*) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
esac
test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
;;
uninstall)
if test -n "$library_names"; then
# Do each command in the postuninstall commands.
func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
fi
if test -n "$old_library"; then
# Do each command in the old_postuninstall commands.
func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
fi
# FIXME: should reinstall the best remaining shared library.
;;
esac
fi
;;
*.lo)
# Possibly a libtool object, so verify it.
if func_lalib_p "$file"; then
# Read the .lo file
func_source $dir/$name
# Add PIC object to the list of files to remove.
if test -n "$pic_object" &&
test "$pic_object" != none; then
func_append rmfiles " $dir/$pic_object"
fi
# Add non-PIC object to the list of files to remove.
if test -n "$non_pic_object" &&
test "$non_pic_object" != none; then
func_append rmfiles " $dir/$non_pic_object"
fi
fi
;;
*)
if test "$opt_mode" = clean ; then
noexename=$name
case $file in
*.exe)
func_stripname '' '.exe' "$file"
file=$func_stripname_result
func_stripname '' '.exe' "$name"
noexename=$func_stripname_result
# $file with .exe has already been added to rmfiles,
# add $file without .exe
func_append rmfiles " $file"
;;
esac
# Do a test to see if this is a libtool program.
if func_ltwrapper_p "$file"; then
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
relink_command=
func_source $func_ltwrapper_scriptname_result
func_append rmfiles " $func_ltwrapper_scriptname_result"
else
relink_command=
func_source $dir/$noexename
fi
# note $name still contains .exe if it was in $file originally
# as does the version of $file that was added into $rmfiles
func_append rmfiles " $odir/$name $odir/${name}S.${objext}"
if test "$fast_install" = yes && test -n "$relink_command"; then
func_append rmfiles " $odir/lt-$name"
fi
if test "X$noexename" != "X$name" ; then
func_append rmfiles " $odir/lt-${noexename}.c"
fi
fi
fi
;;
esac
func_show_eval "$RM $rmfiles" 'exit_status=1'
done
# Try to remove the ${objdir}s in the directories where we deleted files
for dir in $rmdirs; do
if test -d "$dir"; then
func_show_eval "rmdir $dir >/dev/null 2>&1"
fi
done
exit $exit_status
}
{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
func_mode_uninstall ${1+"$@"}
test -z "$opt_mode" && {
help="$generic_help"
func_fatal_help "you must specify a MODE"
}
test -z "$exec_cmd" && \
func_fatal_help "invalid operation mode \`$opt_mode'"
if test -n "$exec_cmd"; then
eval exec "$exec_cmd"
exit $EXIT_FAILURE
fi
exit $exit_status
# The TAGs below are defined such that we never get into a situation
# in which we disable both kinds of libraries. Given conflicting
# choices, we go for a static library, that is the most portable,
# since we can't tell whether shared libraries were disabled because
# the user asked for that or because the platform doesn't support
# them. This is particularly important on AIX, because we don't
# support having both static and shared libraries enabled at the same
# time on that platform, so we default to a shared-only configuration.
# If a disable-shared tag is given, we'll fallback to a static-only
# configuration. But we'll never go from static-only to shared-only.
# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
build_libtool_libs=no
build_old_libs=yes
# ### END LIBTOOL TAG CONFIG: disable-shared
# ### BEGIN LIBTOOL TAG CONFIG: disable-static
build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
# ### END LIBTOOL TAG CONFIG: disable-static
# Local Variables:
# mode:shell-script
# sh-indentation:2
# End:
# vi:sw=2
diff --git a/build-aux/mdate-sh b/build-aux/mdate-sh
index b3719cf7..39f48bb1 100755
--- a/build-aux/mdate-sh
+++ b/build-aux/mdate-sh
@@ -1,224 +1,224 @@
#!/bin/sh
# Get modification time of a file or directory and pretty-print it.
scriptversion=2010-08-21.06; # UTC
# Copyright (C) 1995-2013 Free Software Foundation, Inc.
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
#
# 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, 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 <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
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
fi
case $1 in
'')
echo "$0: No file. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: mdate-sh [--help] [--version] FILE
Pretty-print the modification day of FILE, in the format:
1 January 1970
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "mdate-sh $scriptversion"
exit $?
;;
esac
error ()
{
echo "$0: $1" >&2
exit 1
}
# Prevent date giving response in another language.
LANG=C
export LANG
LC_ALL=C
export LC_ALL
LC_TIME=C
export LC_TIME
# GNU ls changes its time format in response to the TIME_STYLE
# variable. Since we cannot assume 'unset' works, revert this
# variable to its documented default.
if test "${TIME_STYLE+set}" = set; then
TIME_STYLE=posix-long-iso
export TIME_STYLE
fi
save_arg1=$1
# Find out how to get the extended ls output of a file or directory.
if ls -L /dev/null 1>/dev/null 2>&1; then
ls_command='ls -L -l -d'
else
ls_command='ls -l -d'
fi
# Avoid user/group names that might have spaces, when possible.
if ls -n /dev/null 1>/dev/null 2>&1; then
ls_command="$ls_command -n"
fi
# A 'ls -l' line looks as follows on OS/2.
# drwxrwx--- 0 Aug 11 2001 foo
# This differs from Unix, which adds ownership information.
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
#
# To find the date, we split the line on spaces and iterate on words
# until we find a month. This cannot work with files whose owner is a
# user named "Jan", or "Feb", etc. However, it's unlikely that '/'
# will be owned by a user whose name is a month. So we first look at
# the extended ls output of the root directory to decide how many
# words should be skipped to get the date.
# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
set x`$ls_command /`
# Find which argument is the month.
month=
command=
until test $month
do
test $# -gt 0 || error "failed parsing '$ls_command /' output"
shift
# Add another shift to the command.
command="$command shift;"
case $1 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
done
test -n "$month" || error "failed parsing '$ls_command /' output"
# Get the extended ls output of the file or directory.
set dummy x`eval "$ls_command \"\\\$save_arg1\""`
# Remove all preceding arguments
eval $command
# Because of the dummy argument above, month is in $2.
#
# On a POSIX system, we should have
#
# $# = 5
# $1 = file size
# $2 = month
# $3 = day
# $4 = year or time
# $5 = filename
#
# On Darwin 7.7.0 and 7.6.0, we have
#
# $# = 4
# $1 = day
# $2 = month
# $3 = year or time
# $4 = filename
# Get the month.
case $2 in
Jan) month=January; nummonth=1;;
Feb) month=February; nummonth=2;;
Mar) month=March; nummonth=3;;
Apr) month=April; nummonth=4;;
May) month=May; nummonth=5;;
Jun) month=June; nummonth=6;;
Jul) month=July; nummonth=7;;
Aug) month=August; nummonth=8;;
Sep) month=September; nummonth=9;;
Oct) month=October; nummonth=10;;
Nov) month=November; nummonth=11;;
Dec) month=December; nummonth=12;;
esac
case $3 in
???*) day=$1;;
*) day=$3; shift;;
esac
# Here we have to deal with the problem that the ls output gives either
# the time of day or the year.
case $3 in
*:*) set `date`; eval year=\$$#
case $2 in
Jan) nummonthtod=1;;
Feb) nummonthtod=2;;
Mar) nummonthtod=3;;
Apr) nummonthtod=4;;
May) nummonthtod=5;;
Jun) nummonthtod=6;;
Jul) nummonthtod=7;;
Aug) nummonthtod=8;;
Sep) nummonthtod=9;;
Oct) nummonthtod=10;;
Nov) nummonthtod=11;;
Dec) nummonthtod=12;;
esac
# For the first six month of the year the time notation can also
# be used for files modified in the last year.
if (expr $nummonth \> $nummonthtod) > /dev/null;
then
year=`expr $year - 1`
fi;;
*) year=$3;;
esac
# The result.
echo $day $month $year
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
diff --git a/build-aux/missing b/build-aux/missing
index db98974f..43e37bd5 100755
--- a/build-aux/missing
+++ b/build-aux/missing
@@ -1,215 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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, 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 <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
-gnu_software_URL=http://www.gnu.org/software
+gnu_software_URL=https://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
diff --git a/build-aux/texinfo.tex b/build-aux/texinfo.tex
index 5a17f979..abcbe140 100644
--- a/build-aux/texinfo.tex
+++ b/build-aux/texinfo.tex
@@ -1,8638 +1,8638 @@
% texinfo.tex -- TeX macros to handle Texinfo files.
%
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
\def\texinfoversion{2007-05-03.09}
%
% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
% 2007 Free Software Foundation, Inc.
%
% This texinfo.tex file 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, or (at
% your option) any later version.
%
% This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not,
-% see <http://www.gnu.org/licenses/>.
+% see <https://www.gnu.org/licenses/>.
%
% As a special exception, when this file is read by TeX when processing
% a Texinfo source document, you may use the result without
% restriction. (This has been our intent since Texinfo was invented.)
%
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
-% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+% https://www.gnu.org/software/texinfo/ (the Texinfo home page), or
% ftp://tug.org/tex/texinfo.tex
% (and all CTAN mirrors, see http://www.ctan.org).
% The texinfo.tex in any given distribution could well be out
% of date, so if that's what you're using, please check.
%
% Send bug reports to bug-texinfo@gnu.org. Please include including a
% complete document in each bug report with which we can reproduce the
% problem. Patches are, of course, greatly appreciated.
%
% To process a Texinfo manual with TeX, it's most reliable to use the
% texi2dvi shell script that comes with the distribution. For a simple
% manual foo.texi, however, you can get away with this:
% tex foo.texi
% texindex foo.??
% tex foo.texi
% tex foo.texi
% dvips foo.dvi -o # or whatever; this makes foo.ps.
% The extra TeX runs get the cross-reference information correct.
% Sometimes one run after texindex suffices, and sometimes you need more
% than two; texi2dvi does it as many times as necessary.
%
% It is possible to adapt texinfo.tex for other languages, to some
% extent. You can get the existing language-specific files from the
% full Texinfo distribution.
%
-% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+% The GNU Texinfo home page is https://www.gnu.org/software/texinfo.
\message{Loading texinfo [version \texinfoversion]:}
% If in a .fmt file, print the version number
% and turn on active characters that we couldn't do earlier because
% they might have appeared in the input file name.
\everyjob{\message{[Texinfo version \texinfoversion]}%
\catcode`+=\active \catcode`\_=\active}
\chardef\other=12
% We never want plain's \outer definition of \+ in Texinfo.
% For @tex, we can use \tabalign.
\let\+ = \relax
% Save some plain tex macros whose names we will redefine.
\let\ptexb=\b
\let\ptexbullet=\bullet
\let\ptexc=\c
\let\ptexcomma=\,
\let\ptexdot=\.
\let\ptexdots=\dots
\let\ptexend=\end
\let\ptexequiv=\equiv
\let\ptexexclam=\!
\let\ptexfootnote=\footnote
\let\ptexgtr=>
\let\ptexhat=^
\let\ptexi=\i
\let\ptexindent=\indent
\let\ptexinsert=\insert
\let\ptexlbrace=\{
\let\ptexless=<
\let\ptexnewwrite\newwrite
\let\ptexnoindent=\noindent
\let\ptexplus=+
\let\ptexrbrace=\}
\let\ptexslash=\/
\let\ptexstar=\*
\let\ptext=\t
% If this character appears in an error message or help string, it
% starts a new line in the output.
\newlinechar = `^^J
% Use TeX 3.0's \inputlineno to get the line number, for better error
% messages, but if we're using an old version of TeX, don't do anything.
%
\ifx\inputlineno\thisisundefined
\let\linenumber = \empty % Pre-3.0.
\else
\def\linenumber{l.\the\inputlineno:\space}
\fi
% Set up fixed words for English if not already set.
\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
\ifx\putwordin\undefined \gdef\putwordin{in}\fi
\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi
\ifx\putwordof\undefined \gdef\putwordof{of}\fi
\ifx\putwordon\undefined \gdef\putwordon{on}\fi
\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi
\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi
\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi
\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi
\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi
\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi
\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi
%
\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
%
\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi
\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi
\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi
\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi
\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi
% Since the category of space is not known, we have to be careful.
\chardef\spacecat = 10
\def\spaceisspace{\catcode`\ =\spacecat}
% sometimes characters are active, so we need control sequences.
\chardef\colonChar = `\:
\chardef\commaChar = `\,
\chardef\dashChar = `\-
\chardef\dotChar = `\.
\chardef\exclamChar= `\!
\chardef\lquoteChar= `\`
\chardef\questChar = `\?
\chardef\rquoteChar= `\'
\chardef\semiChar = `\;
\chardef\underChar = `\_
% Ignore a token.
%
\def\gobble#1{}
% The following is used inside several \edef's.
\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
% Hyphenation fixes.
\hyphenation{
Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
ap-pen-dix bit-map bit-maps
data-base data-bases eshell fall-ing half-way long-est man-u-script
man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
spell-ing spell-ings
stand-alone strong-est time-stamp time-stamps which-ever white-space
wide-spread wrap-around
}
% Margin to add to right of even pages, to left of odd pages.
\newdimen\bindingoffset
\newdimen\normaloffset
\newdimen\pagewidth \newdimen\pageheight
% For a final copy, take out the rectangles
% that mark overfull boxes (in case you have decided
% that the text looks ok even though it passes the margin).
%
\def\finalout{\overfullrule=0pt}
% @| inserts a changebar to the left of the current line. It should
% surround any changed text. This approach does *not* work if the
% change spans more than two lines of output. To handle that, we would
% have adopt a much more difficult approach (putting marks into the main
% vertical list for the beginning and end of each change).
%
\def\|{%
% \vadjust can only be used in horizontal mode.
\leavevmode
%
% Append this vertical mode material after the current line in the output.
\vadjust{%
% We want to insert a rule with the height and depth of the current
% leading; that is exactly what \strutbox is supposed to record.
\vskip-\baselineskip
%
% \vadjust-items are inserted at the left edge of the type. So
% the \llap here moves out into the left-hand margin.
\llap{%
%
% For a thicker or thinner bar, change the `1pt'.
\vrule height\baselineskip width1pt
%
% This is the space between the bar and the text.
\hskip 12pt
}%
}%
}
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
% since that produces some useless output on the terminal. We also make
% some effort to order the tracing commands to reduce output in the log
% file; cf. trace.sty in LaTeX.
%
\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
\def\loggingall{%
\tracingstats2
\tracingpages1
\tracinglostchars2 % 2 gives us more in etex
\tracingparagraphs1
\tracingoutput1
\tracingmacros2
\tracingrestores1
\showboxbreadth\maxdimen \showboxdepth\maxdimen
\ifx\eTeXversion\undefined\else % etex gives us more logging
\tracingscantokens1
\tracingifs1
\tracinggroups1
\tracingnesting2
\tracingassigns1
\fi
\tracingcommands3 % 3 gives us more in etex
\errorcontextlines16
}%
% add check for \lastpenalty to plain's definitions. If the last thing
% we did was a \nobreak, we don't want to insert more space.
%
\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
\removelastskip\penalty-50\smallskip\fi\fi}
\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
\removelastskip\penalty-100\medskip\fi\fi}
\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
\removelastskip\penalty-200\bigskip\fi\fi}
% For @cropmarks command.
% Do @cropmarks to get crop marks.
%
\newif\ifcropmarks
\let\cropmarks = \cropmarkstrue
%
% Dimensions to add cropmarks at corners.
% Added by P. A. MacKay, 12 Nov. 1986
%
\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
\newdimen\cornerlong \cornerlong=1pc
\newdimen\cornerthick \cornerthick=.3pt
\newdimen\topandbottommargin \topandbottommargin=.75in
% Main output routine.
\chardef\PAGE = 255
\output = {\onepageout{\pagecontents\PAGE}}
\newbox\headlinebox
\newbox\footlinebox
% \onepageout takes a vbox as an argument. Note that \pagecontents
% does insertions, but you have to call it yourself.
\def\onepageout#1{%
\ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
%
\ifodd\pageno \advance\hoffset by \bindingoffset
\else \advance\hoffset by -\bindingoffset\fi
%
% Do this outside of the \shipout so @code etc. will be expanded in
% the headline as they should be, not taken literally (outputting ''code).
\setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
\setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
%
{%
% Have to do this stuff outside the \shipout because we want it to
% take effect in \write's, yet the group defined by the \vbox ends
% before the \shipout runs.
%
\indexdummies % don't expand commands in the output.
\normalturnoffactive % \ in index entries must not stay \, e.g., if
% the page break happens to be in the middle of an example.
% We don't want .vr (or whatever) entries like this:
% \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}}
% "\acronym" won't work when it's read back in;
% it needs to be
% {\code {{\tt \backslashcurfont }acronym}
\shipout\vbox{%
% Do this early so pdf references go to the beginning of the page.
\ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
%
\ifcropmarks \vbox to \outervsize\bgroup
\hsize = \outerhsize
\vskip-\topandbottommargin
\vtop to0pt{%
\line{\ewtop\hfil\ewtop}%
\nointerlineskip
\line{%
\vbox{\moveleft\cornerthick\nstop}%
\hfill
\vbox{\moveright\cornerthick\nstop}%
}%
\vss}%
\vskip\topandbottommargin
\line\bgroup
\hfil % center the page within the outer (page) hsize.
\ifodd\pageno\hskip\bindingoffset\fi
\vbox\bgroup
\fi
%
\unvbox\headlinebox
\pagebody{#1}%
\ifdim\ht\footlinebox > 0pt
% Only leave this space if the footline is nonempty.
% (We lessened \vsize for it in \oddfootingyyy.)
% The \baselineskip=24pt in plain's \makefootline has no effect.
\vskip 24pt
\unvbox\footlinebox
\fi
%
\ifcropmarks
\egroup % end of \vbox\bgroup
\hfil\egroup % end of (centering) \line\bgroup
\vskip\topandbottommargin plus1fill minus1fill
\boxmaxdepth = \cornerthick
\vbox to0pt{\vss
\line{%
\vbox{\moveleft\cornerthick\nsbot}%
\hfill
\vbox{\moveright\cornerthick\nsbot}%
}%
\nointerlineskip
\line{\ewbot\hfil\ewbot}%
}%
\egroup % \vbox from first cropmarks clause
\fi
}% end of \shipout\vbox
}% end of group with \indexdummies
\advancepageno
\ifnum\outputpenalty>-20000 \else\dosupereject\fi
}
\newinsert\margin \dimen\margin=\maxdimen
\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
{\catcode`\@ =11
\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
% marginal hacks, juha@viisa.uucp (Juha Takala)
\ifvoid\margin\else % marginal info is present
\rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
\dimen@=\dp#1 \unvbox#1
\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
}
% Here are the rules for the cropmarks. Note that they are
% offset so that the space between them is truly \outerhsize or \outervsize
% (P. A. MacKay, 12 November, 1986)
%
\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
\def\nstop{\vbox
{\hrule height\cornerthick depth\cornerlong width\cornerthick}}
\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
\def\nsbot{\vbox
{\hrule height\cornerlong depth\cornerthick width\cornerthick}}
% Parse an argument, then pass it to #1. The argument is the rest of
% the input line (except we remove a trailing comment). #1 should be a
% macro which expects an ordinary undelimited TeX argument.
%
\def\parsearg{\parseargusing{}}
\def\parseargusing#1#2{%
\def\argtorun{#2}%
\begingroup
\obeylines
\spaceisspace
#1%
\parseargline\empty% Insert the \empty token, see \finishparsearg below.
}
{\obeylines %
\gdef\parseargline#1^^M{%
\endgroup % End of the group started in \parsearg.
\argremovecomment #1\comment\ArgTerm%
}%
}
% First remove any @comment, then any @c comment.
\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
% Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space.
%
% \argremovec might leave us with trailing space, e.g.,
% @end itemize @c foo
% This space token undergoes the same procedure and is eventually removed
% by \finishparsearg.
%
\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
\def\temp{#3}%
\ifx\temp\empty
% Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp:
\let\temp\finishparsearg
\else
\let\temp\argcheckspaces
\fi
% Put the space token in:
\temp#1 #3\ArgTerm
}
% If a _delimited_ argument is enclosed in braces, they get stripped; so
% to get _exactly_ the rest of the line, we had to prevent such situation.
% We prepended an \empty token at the very beginning and we expand it now,
% just before passing the control to \argtorun.
% (Similarly, we have to think about #3 of \argcheckspacesY above: it is
% either the null string, or it ends with \^^M---thus there is no danger
% that a pair of braces would be stripped.
%
% But first, we have to remove the trailing space token.
%
\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}}
% \parseargdef\foo{...}
% is roughly equivalent to
% \def\foo{\parsearg\Xfoo}
% \def\Xfoo#1{...}
%
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
% favourite TeX trick. --kasal, 16nov03
\def\parseargdef#1{%
\expandafter \doparseargdef \csname\string#1\endcsname #1%
}
\def\doparseargdef#1#2{%
\def#2{\parsearg#1}%
\def#1##1%
}
% Several utility definitions with active space:
{
\obeyspaces
\gdef\obeyedspace{ }
% Make each space character in the input produce a normal interword
% space in the output. Don't allow a line break at this space, as this
% is used only in environments like @example, where each line of input
% should produce a line of output anyway.
%
\gdef\sepspaces{\obeyspaces\let =\tie}
% If an index command is used in an @example environment, any spaces
% therein should become regular spaces in the raw index file, not the
% expansion of \tie (\leavevmode \penalty \@M \ ).
\gdef\unsepspaces{\let =\space}
}
\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
% Define the framework for environments in texinfo.tex. It's used like this:
%
% \envdef\foo{...}
% \def\Efoo{...}
%
% It's the responsibility of \envdef to insert \begingroup before the
% actual body; @end closes the group after calling \Efoo. \envdef also
% defines \thisenv, so the current environment is known; @end checks
% whether the environment name matches. The \checkenv macro can also be
% used to check whether the current environment is the one expected.
%
% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
% are not treated as environments; they don't open a group. (The
% implementation of @end takes care not to call \endgroup in this
% special case.)
% At runtime, environments start with this:
\def\startenvironment#1{\begingroup\def\thisenv{#1}}
% initialize
\let\thisenv\empty
% ... but they get defined via ``\envdef\foo{...}'':
\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
% Check whether we're in the right environment:
\def\checkenv#1{%
\def\temp{#1}%
\ifx\thisenv\temp
\else
\badenverr
\fi
}
% Environment mismatch, #1 expected:
\def\badenverr{%
\errhelp = \EMsimple
\errmessage{This command can appear only \inenvironment\temp,
not \inenvironment\thisenv}%
}
\def\inenvironment#1{%
\ifx#1\empty
out of any environment%
\else
in environment \expandafter\string#1%
\fi
}
% @end foo executes the definition of \Efoo.
% But first, it executes a specialized version of \checkenv
%
\parseargdef\end{%
\if 1\csname iscond.#1\endcsname
\else
% The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
\expandafter\checkenv\csname#1\endcsname
\csname E#1\endcsname
\endgroup
\fi
}
\newhelp\EMsimple{Press RETURN to continue.}
%% Simple single-character @ commands
% @@ prints an @
% Kludge this until the fonts are right (grr).
\def\@{{\tt\char64}}
% This is turned off because it was never documented
% and you can use @w{...} around a quote to suppress ligatures.
%% Define @` and @' to be the same as ` and '
%% but suppressing ligatures.
%\def\`{{`}}
%\def\'{{'}}
% Used to generate quoted braces.
\def\mylbrace {{\tt\char123}}
\def\myrbrace {{\tt\char125}}
\let\{=\mylbrace
\let\}=\myrbrace
\begingroup
% Definitions to produce \{ and \} commands for indices,
% and @{ and @} for the aux/toc files.
\catcode`\{ = \other \catcode`\} = \other
\catcode`\[ = 1 \catcode`\] = 2
\catcode`\! = 0 \catcode`\\ = \other
!gdef!lbracecmd[\{]%
!gdef!rbracecmd[\}]%
!gdef!lbraceatcmd[@{]%
!gdef!rbraceatcmd[@}]%
!endgroup
% @comma{} to avoid , parsing problems.
\let\comma = ,
% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
\let\, = \c
\let\dotaccent = \.
\def\ringaccent#1{{\accent23 #1}}
\let\tieaccent = \t
\let\ubaraccent = \b
\let\udotaccent = \d
% Other special characters: @questiondown @exclamdown @ordf @ordm
% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
\def\questiondown{?`}
\def\exclamdown{!`}
\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
% Dotless i and dotless j, used for accents.
\def\imacro{i}
\def\jmacro{j}
\def\dotless#1{%
\def\temp{#1}%
\ifx\temp\imacro \ptexi
\else\ifx\temp\jmacro \j
\else \errmessage{@dotless can be used only with i or j}%
\fi\fi
}
% The \TeX{} logo, as in plain, but resetting the spacing so that a
% period following counts as ending a sentence. (Idea found in latex.)
%
\edef\TeX{\TeX \spacefactor=1000 }
% @LaTeX{} logo. Not quite the same results as the definition in
% latex.ltx, since we use a different font for the raised A; it's most
% convenient for us to use an explicitly smaller font, rather than using
% the \scriptstyle font (since we don't reset \scriptstyle and
% \scriptscriptstyle).
%
\def\LaTeX{%
L\kern-.36em
{\setbox0=\hbox{T}%
\vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
\kern-.15em
\TeX
}
% Be sure we're in horizontal mode when doing a tie, since we make space
% equivalent to this in @example-like environments. Otherwise, a space
% at the beginning of a line will start with \penalty -- and
% since \penalty is valid in vertical mode, we'd end up putting the
% penalty on the vertical list instead of in the new paragraph.
{\catcode`@ = 11
% Avoid using \@M directly, because that causes trouble
% if the definition is written into an index file.
\global\let\tiepenalty = \@M
\gdef\tie{\leavevmode\penalty\tiepenalty\ }
}
% @: forces normal size whitespace following.
\def\:{\spacefactor=1000 }
% @* forces a line break.
\def\*{\hfil\break\hbox{}\ignorespaces}
% @/ allows a line break.
\let\/=\allowbreak
% @. is an end-of-sentence period.
\def\.{.\spacefactor=\endofsentencespacefactor\space}
% @! is an end-of-sentence bang.
\def\!{!\spacefactor=\endofsentencespacefactor\space}
% @? is an end-of-sentence query.
\def\?{?\spacefactor=\endofsentencespacefactor\space}
% @frenchspacing on|off says whether to put extra space after punctuation.
%
\def\onword{on}
\def\offword{off}
%
\parseargdef\frenchspacing{%
\def\temp{#1}%
\ifx\temp\onword \plainfrenchspacing
\else\ifx\temp\offword \plainnonfrenchspacing
\else
\errhelp = \EMsimple
\errmessage{Unknown @frenchspacing option `\temp', must be on/off}%
\fi\fi
}
% @w prevents a word break. Without the \leavevmode, @w at the
% beginning of a paragraph, when TeX is still in vertical mode, would
% produce a whole line of output instead of starting the paragraph.
\def\w#1{\leavevmode\hbox{#1}}
% @group ... @end group forces ... to be all on one page, by enclosing
% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
% to keep its height that of a normal line. According to the rules for
% \topskip (p.114 of the TeXbook), the glue inserted is
% max (\topskip - \ht (first item), 0). If that height is large,
% therefore, no glue is inserted, and the space between the headline and
% the text is small, which looks bad.
%
% Another complication is that the group might be very large. This can
% cause the glue on the previous page to be unduly stretched, because it
% does not have much material. In this case, it's better to add an
% explicit \vfill so that the extra space is at the bottom. The
% threshold for doing this is if the group is more than \vfilllimit
% percent of a page (\vfilllimit can be changed inside of @tex).
%
\newbox\groupbox
\def\vfilllimit{0.7}
%
\envdef\group{%
\ifnum\catcode`\^^M=\active \else
\errhelp = \groupinvalidhelp
\errmessage{@group invalid in context where filling is enabled}%
\fi
\startsavinginserts
%
\setbox\groupbox = \vtop\bgroup
% Do @comment since we are called inside an environment such as
% @example, where each end-of-line in the input causes an
% end-of-line in the output. We don't want the end-of-line after
% the `@group' to put extra space in the output. Since @group
% should appear on a line by itself (according to the Texinfo
% manual), we don't worry about eating any user text.
\comment
}
%
% The \vtop produces a box with normal height and large depth; thus, TeX puts
% \baselineskip glue before it, and (when the next line of text is done)
% \lineskip glue after it. Thus, space below is not quite equal to space
% above. But it's pretty close.
\def\Egroup{%
% To get correct interline space between the last line of the group
% and the first line afterwards, we have to propagate \prevdepth.
\endgraf % Not \par, as it may have been set to \lisppar.
\global\dimen1 = \prevdepth
\egroup % End the \vtop.
% \dimen0 is the vertical size of the group's box.
\dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox
% \dimen2 is how much space is left on the page (more or less).
\dimen2 = \pageheight \advance\dimen2 by -\pagetotal
% if the group doesn't fit on the current page, and it's a big big
% group, force a page break.
\ifdim \dimen0 > \dimen2
\ifdim \pagetotal < \vfilllimit\pageheight
\page
\fi
\fi
\box\groupbox
\prevdepth = \dimen1
\checkinserts
}
%
% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
% message, so this ends up printing `@group can only ...'.
%
\newhelp\groupinvalidhelp{%
group can only be used in environments such as @example,^^J%
where each line of input produces a line of output.}
% @need space-in-mils
% forces a page break if there is not space-in-mils remaining.
\newdimen\mil \mil=0.001in
% Old definition--didn't work.
%\parseargdef\need{\par %
%% This method tries to make TeX break the page naturally
%% if the depth of the box does not fit.
%{\baselineskip=0pt%
%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
%\prevdepth=-1000pt
%}}
\parseargdef\need{%
% Ensure vertical mode, so we don't make a big box in the middle of a
% paragraph.
\par
%
% If the @need value is less than one line space, it's useless.
\dimen0 = #1\mil
\dimen2 = \ht\strutbox
\advance\dimen2 by \dp\strutbox
\ifdim\dimen0 > \dimen2
%
% Do a \strut just to make the height of this box be normal, so the
% normal leading is inserted relative to the preceding line.
% And a page break here is fine.
\vtop to #1\mil{\strut\vfil}%
%
% TeX does not even consider page breaks if a penalty added to the
% main vertical list is 10000 or more. But in order to see if the
% empty box we just added fits on the page, we must make it consider
% page breaks. On the other hand, we don't want to actually break the
% page after the empty box. So we use a penalty of 9999.
%
% There is an extremely small chance that TeX will actually break the
% page at this \penalty, if there are no other feasible breakpoints in
% sight. (If the user is using lots of big @group commands, which
% almost-but-not-quite fill up a page, TeX will have a hard time doing
% good page breaking, for example.) However, I could not construct an
% example where a page broke at this \penalty; if it happens in a real
% document, then we can reconsider our strategy.
\penalty9999
%
% Back up by the size of the box, whether we did a page break or not.
\kern -#1\mil
%
% Do not allow a page break right after this kern.
\nobreak
\fi
}
% @br forces paragraph break (and is undocumented).
\let\br = \par
% @page forces the start of a new page.
%
\def\page{\par\vfill\supereject}
% @exdent text....
% outputs text on separate line in roman font, starting at standard page margin
% This records the amount of indent in the innermost environment.
% That's how much \exdent should take out.
\newskip\exdentamount
% This defn is used inside fill environments such as @defun.
\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
% This defn is used inside nofill environments such as @example.
\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
\leftline{\hskip\leftskip{\rm#1}}}}
% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
% paragraph. For more general purposes, use the \margin insertion
% class. WHICH is `l' or `r'.
%
\newskip\inmarginspacing \inmarginspacing=1cm
\def\strutdepth{\dp\strutbox}
%
\def\doinmargin#1#2{\strut\vadjust{%
\nobreak
\kern-\strutdepth
\vtop to \strutdepth{%
\baselineskip=\strutdepth
\vss
% if you have multiple lines of stuff to put here, you'll need to
% make the vbox yourself of the appropriate size.
\ifx#1l%
\llap{\ignorespaces #2\hskip\inmarginspacing}%
\else
\rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
\fi
\null
}%
}}
\def\inleftmargin{\doinmargin l}
\def\inrightmargin{\doinmargin r}
%
% @inmargin{TEXT [, RIGHT-TEXT]}
% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
% else use TEXT for both).
%
\def\inmargin#1{\parseinmargin #1,,\finish}
\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0 > 0pt
\def\lefttext{#1}% have both texts
\def\righttext{#2}%
\else
\def\lefttext{#1}% have only one text
\def\righttext{#1}%
\fi
%
\ifodd\pageno
\def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
\else
\def\temp{\inleftmargin\lefttext}%
\fi
\temp
}
% @include file insert text of that file as input.
%
\def\include{\parseargusing\filenamecatcodes\includezzz}
\def\includezzz#1{%
\pushthisfilestack
\def\thisfile{#1}%
{%
\makevalueexpandable
\def\temp{\input #1 }%
\expandafter
}\temp
\popthisfilestack
}
\def\filenamecatcodes{%
\catcode`\\=\other
\catcode`~=\other
\catcode`^=\other
\catcode`_=\other
\catcode`|=\other
\catcode`<=\other
\catcode`>=\other
\catcode`+=\other
\catcode`-=\other
}
\def\pushthisfilestack{%
\expandafter\pushthisfilestackX\popthisfilestack\StackTerm
}
\def\pushthisfilestackX{%
\expandafter\pushthisfilestackY\thisfile\StackTerm
}
\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
\gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
}
\def\popthisfilestack{\errthisfilestackempty}
\def\errthisfilestackempty{\errmessage{Internal error:
the stack of filenames is empty.}}
\def\thisfile{}
% @center line
% outputs that line, centered.
%
\parseargdef\center{%
\ifhmode
\let\next\centerH
\else
\let\next\centerV
\fi
\next{\hfil \ignorespaces#1\unskip \hfil}%
}
\def\centerH#1{%
{%
\hfil\break
\advance\hsize by -\leftskip
\advance\hsize by -\rightskip
\line{#1}%
\break
}%
}
\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
% @sp n outputs n lines of vertical space
\parseargdef\sp{\vskip #1\baselineskip}
% @comment ...line which is ignored...
% @c is the same as @comment
% @ignore ... @end ignore is another way to write a comment
\def\comment{\begingroup \catcode`\^^M=\other%
\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
\commentxxx}
{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
\let\c=\comment
% @paragraphindent NCHARS
% We'll use ems for NCHARS, close enough.
% NCHARS can also be the word `asis' or `none'.
% We cannot feasibly implement @paragraphindent asis, though.
%
\def\asisword{asis} % no translation, these are keywords
\def\noneword{none}
%
\parseargdef\paragraphindent{%
\def\temp{#1}%
\ifx\temp\asisword
\else
\ifx\temp\noneword
\defaultparindent = 0pt
\else
\defaultparindent = #1em
\fi
\fi
\parindent = \defaultparindent
}
% @exampleindent NCHARS
% We'll use ems for NCHARS like @paragraphindent.
% It seems @exampleindent asis isn't necessary, but
% I preserve it to make it similar to @paragraphindent.
\parseargdef\exampleindent{%
\def\temp{#1}%
\ifx\temp\asisword
\else
\ifx\temp\noneword
\lispnarrowing = 0pt
\else
\lispnarrowing = #1em
\fi
\fi
}
% @firstparagraphindent WORD
% If WORD is `none', then suppress indentation of the first paragraph
% after a section heading. If WORD is `insert', then do indent at such
% paragraphs.
%
% The paragraph indentation is suppressed or not by calling
% \suppressfirstparagraphindent, which the sectioning commands do.
% We switch the definition of this back and forth according to WORD.
% By default, we suppress indentation.
%
\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
\def\insertword{insert}
%
\parseargdef\firstparagraphindent{%
\def\temp{#1}%
\ifx\temp\noneword
\let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
\else\ifx\temp\insertword
\let\suppressfirstparagraphindent = \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @firstparagraphindent option `\temp'}%
\fi\fi
}
% Here is how we actually suppress indentation. Redefine \everypar to
% \kern backwards by \parindent, and then reset itself to empty.
%
% We also make \indent itself not actually do anything until the next
% paragraph.
%
\gdef\dosuppressfirstparagraphindent{%
\gdef\indent{%
\restorefirstparagraphindent
\indent
}%
\gdef\noindent{%
\restorefirstparagraphindent
\noindent
}%
\global\everypar = {%
\kern -\parindent
\restorefirstparagraphindent
}%
}
\gdef\restorefirstparagraphindent{%
\global \let \indent = \ptexindent
\global \let \noindent = \ptexnoindent
\global \everypar = {}%
}
% @asis just yields its argument. Used with @table, for example.
%
\def\asis#1{#1}
% @math outputs its argument in math mode.
%
% One complication: _ usually means subscripts, but it could also mean
% an actual _ character, as in @math{@var{some_variable} + 1}. So make
% _ active, and distinguish by seeing if the current family is \slfam,
% which is what @var uses.
{
\catcode`\_ = \active
\gdef\mathunderscore{%
\catcode`\_=\active
\def_{\ifnum\fam=\slfam \_\else\sb\fi}%
}
}
% Another complication: we want \\ (and @\) to output a \ character.
% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
% this is not advertised and we don't care. Texinfo does not
% otherwise define @\.
%
% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
%
\def\math{%
\tex
\mathunderscore
\let\\ = \mathbackslash
\mathactive
$\finishmath
}
\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex.
% Some active characters (such as <) are spaced differently in math.
% We have to reset their definitions in case the @math was an argument
% to a command which sets the catcodes (such as @item or @section).
%
{
\catcode`^ = \active
\catcode`< = \active
\catcode`> = \active
\catcode`+ = \active
\gdef\mathactive{%
\let^ = \ptexhat
\let< = \ptexless
\let> = \ptexgtr
\let+ = \ptexplus
}
}
% @bullet and @minus need the same treatment as @math, just above.
\def\bullet{$\ptexbullet$}
\def\minus{$-$}
% @dots{} outputs an ellipsis using the current font.
% We do .5em per period so that it has the same spacing in the cm
% typewriter fonts as three actual period characters; on the other hand,
% in other typewriter fonts three periods are wider than 1.5em. So do
% whichever is larger.
%
\def\dots{%
\leavevmode
\setbox0=\hbox{...}% get width of three periods
\ifdim\wd0 > 1.5em
\dimen0 = \wd0
\else
\dimen0 = 1.5em
\fi
\hbox to \dimen0{%
\hskip 0pt plus.25fil
.\hskip 0pt plus1fil
.\hskip 0pt plus1fil
.\hskip 0pt plus.5fil
}%
}
% @enddots{} is an end-of-sentence ellipsis.
%
\def\enddots{%
\dots
\spacefactor=\endofsentencespacefactor
}
% @comma{} is so commas can be inserted into text without messing up
% Texinfo's parsing.
%
\let\comma = ,
% @refill is a no-op.
\let\refill=\relax
% If working on a large document in chapters, it is convenient to
% be able to disable indexing, cross-referencing, and contents, for test runs.
% This is done with @novalidate (before @setfilename).
%
\newif\iflinks \linkstrue % by default we want the aux files.
\let\novalidate = \linksfalse
% @setfilename is done at the beginning of every texinfo file.
% So open here the files we need to have open while reading the input.
% This makes it possible to make a .fmt file for texinfo.
\def\setfilename{%
\fixbackslash % Turn off hack to swallow `\input texinfo'.
\iflinks
\tryauxfile
% Open the new aux file. TeX will close it automatically at exit.
\immediate\openout\auxfile=\jobname.aux
\fi % \openindices needs to do some work in any case.
\openindices
\let\setfilename=\comment % Ignore extra @setfilename cmds.
%
% If texinfo.cnf is present on the system, read it.
% Useful for site-wide @afourpaper, etc.
\openin 1 texinfo.cnf
\ifeof 1 \else \input texinfo.cnf \fi
\closein 1
%
\comment % Ignore the actual filename.
}
% Called from \setfilename.
%
\def\openindices{%
\newindex{cp}%
\newcodeindex{fn}%
\newcodeindex{vr}%
\newcodeindex{tp}%
\newcodeindex{ky}%
\newcodeindex{pg}%
}
% @bye.
\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
\message{pdf,}
% adobe `portable' document format
\newcount\tempnum
\newcount\lnkcount
\newtoks\filename
\newcount\filenamelength
\newcount\pgn
\newtoks\toksA
\newtoks\toksB
\newtoks\toksC
\newtoks\toksD
\newbox\boxA
\newcount\countA
\newif\ifpdf
\newif\ifpdfmakepagedest
% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
% can be set). So we test for \relax and 0 as well as \undefined,
% borrowed from ifpdf.sty.
\ifx\pdfoutput\undefined
\else
\ifx\pdfoutput\relax
\else
\ifcase\pdfoutput
\else
\pdftrue
\fi
\fi
\fi
% PDF uses PostScript string constants for the names of xref targets,
% for display in the outlines, and in other places. Thus, we have to
% double any backslashes. Otherwise, a name like "\node" will be
% interpreted as a newline (\n), followed by o, d, e. Not good.
% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html
% (and related messages, the final outcome is that it is up to the TeX
% user to double the backslashes and otherwise make the string valid, so
% that's what we do).
% double active backslashes.
%
{\catcode`\@=0 \catcode`\\=\active
@gdef@activebackslashdouble{%
@catcode`@\=@active
@let\=@doublebackslash}
}
% To handle parens, we must adopt a different approach, since parens are
% not active characters. hyperref.dtx (which has the same problem as
% us) handles it with this amazing macro to replace tokens, with minor
% changes for Texinfo. It is included here under the GPL by permission
% from the author, Heiko Oberdiek.
%
% #1 is the tokens to replace.
% #2 is the replacement.
% #3 is the control sequence with the string.
%
\def\HyPsdSubst#1#2#3{%
\def\HyPsdReplace##1#1##2\END{%
##1%
\ifx\\##2\\%
\else
#2%
\HyReturnAfterFi{%
\HyPsdReplace##2\END
}%
\fi
}%
\xdef#3{\expandafter\HyPsdReplace#3#1\END}%
}
\long\def\HyReturnAfterFi#1\fi{\fi#1}
% #1 is a control sequence in which to do the replacements.
\def\backslashparens#1{%
\xdef#1{#1}% redefine it as its expansion; the definition is simply
% \lastnode when called from \setref -> \pdfmkdest.
\HyPsdSubst{(}{\realbackslash(}{#1}%
\HyPsdSubst{)}{\realbackslash)}{#1}%
}
\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
with PDF output, and none of those formats could be found. (.eps cannot
be supported due to the design of the PDF format; use regular TeX (DVI
output) for that.)}
\ifpdf
\input pdfcolor
\pdfcatalog{/PageMode /UseOutlines}
%
% #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
\def\dopdfimage#1#2#3{%
\def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
\def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
%
% pdftex (and the PDF format) support .png, .jpg, .pdf (among
% others). Let's try in that order.
\let\pdfimgext=\empty
\begingroup
\openin 1 #1.png \ifeof 1
\openin 1 #1.jpg \ifeof 1
\openin 1 #1.jpeg \ifeof 1
\openin 1 #1.JPG \ifeof 1
\openin 1 #1.pdf \ifeof 1
\errhelp = \nopdfimagehelp
\errmessage{Could not find image file #1 for pdf}%
\else \gdef\pdfimgext{pdf}%
\fi
\else \gdef\pdfimgext{JPG}%
\fi
\else \gdef\pdfimgext{jpeg}%
\fi
\else \gdef\pdfimgext{jpg}%
\fi
\else \gdef\pdfimgext{png}%
\fi
\closein 1
\endgroup
%
% without \immediate, pdftex seg faults when the same image is
% included twice. (Version 3.14159-pre-1.0-unofficial-20010704.)
\ifnum\pdftexversion < 14
\immediate\pdfimage
\else
\immediate\pdfximage
\fi
\ifdim \wd0 >0pt width \imagewidth \fi
\ifdim \wd2 >0pt height \imageheight \fi
\ifnum\pdftexversion<13
#1.\pdfimgext
\else
{#1.\pdfimgext}%
\fi
\ifnum\pdftexversion < 14 \else
\pdfrefximage \pdflastximage
\fi}
%
\def\pdfmkdest#1{{%
% We have to set dummies so commands such as @code, and characters
% such as \, aren't expanded when present in a section title.
\indexnofonts
\turnoffactive
\activebackslashdouble
\makevalueexpandable
\def\pdfdestname{#1}%
\backslashparens\pdfdestname
\safewhatsit{\pdfdest name{\pdfdestname} xyz}%
}}
%
% used to mark target names; must be expandable.
\def\pdfmkpgn#1{#1}
%
% by default, use a color that is dark enough to print on paper as
% nearly black, but still distinguishable for online viewing.
% (Defined in pdfcolor.tex.)
\let\urlcolor = \BrickRed
\let\linkcolor = \BrickRed
\def\endlink{\Black\pdfendlink}
%
% Adding outlines to PDF; macros for calculating structure of outlines
% come from Petr Olsak
\def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
\else \csname#1\endcsname \fi}
\def\advancenumber#1{\tempnum=\expnumber{#1}\relax
\advance\tempnum by 1
\expandafter\xdef\csname#1\endcsname{\the\tempnum}}
%
% #1 is the section text, which is what will be displayed in the
% outline by the pdf viewer. #2 is the pdf expression for the number
% of subentries (or empty, for subsubsections). #3 is the node text,
% which might be empty if this toc entry had no corresponding node.
% #4 is the page number
%
\def\dopdfoutline#1#2#3#4{%
% Generate a link to the node text if that exists; else, use the
% page number. We could generate a destination for the section
% text in the case where a section has no node, but it doesn't
% seem worth the trouble, since most documents are normally structured.
\def\pdfoutlinedest{#3}%
\ifx\pdfoutlinedest\empty
\def\pdfoutlinedest{#4}%
\else
% Doubled backslashes in the name.
{\activebackslashdouble \xdef\pdfoutlinedest{#3}%
\backslashparens\pdfoutlinedest}%
\fi
%
% Also double the backslashes in the display string.
{\activebackslashdouble \xdef\pdfoutlinetext{#1}%
\backslashparens\pdfoutlinetext}%
%
\pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}%
}
%
\def\pdfmakeoutlines{%
\begingroup
% Thanh's hack / proper braces in bookmarks
\edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
\edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
%
% Read toc silently, to get counts of subentries for \pdfoutline.
\def\numchapentry##1##2##3##4{%
\def\thischapnum{##2}%
\def\thissecnum{0}%
\def\thissubsecnum{0}%
}%
\def\numsecentry##1##2##3##4{%
\advancenumber{chap\thischapnum}%
\def\thissecnum{##2}%
\def\thissubsecnum{0}%
}%
\def\numsubsecentry##1##2##3##4{%
\advancenumber{sec\thissecnum}%
\def\thissubsecnum{##2}%
}%
\def\numsubsubsecentry##1##2##3##4{%
\advancenumber{subsec\thissubsecnum}%
}%
\def\thischapnum{0}%
\def\thissecnum{0}%
\def\thissubsecnum{0}%
%
% use \def rather than \let here because we redefine \chapentry et
% al. a second time, below.
\def\appentry{\numchapentry}%
\def\appsecentry{\numsecentry}%
\def\appsubsecentry{\numsubsecentry}%
\def\appsubsubsecentry{\numsubsubsecentry}%
\def\unnchapentry{\numchapentry}%
\def\unnsecentry{\numsecentry}%
\def\unnsubsecentry{\numsubsecentry}%
\def\unnsubsubsecentry{\numsubsubsecentry}%
\readdatafile{toc}%
%
% Read toc second time, this time actually producing the outlines.
% The `-' means take the \expnumber as the absolute number of
% subentries, which we calculated on our first read of the .toc above.
%
% We use the node names as the destinations.
\def\numchapentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
\def\numsecentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
\def\numsubsecentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
\def\numsubsubsecentry##1##2##3##4{% count is always zero
\dopdfoutline{##1}{}{##3}{##4}}%
%
% PDF outlines are displayed using system fonts, instead of
% document fonts. Therefore we cannot use special characters,
% since the encoding is unknown. For example, the eogonek from
% Latin 2 (0xea) gets translated to a | character. Info from
% Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
%
% xx to do this right, we have to translate 8-bit characters to
% their "best" equivalent, based on the @documentencoding. Right
% now, I guess we'll just let the pdf reader have its way.
\indexnofonts
\setupdatafile
\catcode`\\=\active \otherbackslash
\input \jobname.toc
\endgroup
}
%
\def\skipspaces#1{\def\PP{#1}\def\D{|}%
\ifx\PP\D\let\nextsp\relax
\else\let\nextsp\skipspaces
\ifx\p\space\else\addtokens{\filename}{\PP}%
\advance\filenamelength by 1
\fi
\fi
\nextsp}
\def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
\ifnum\pdftexversion < 14
\let \startlink \pdfannotlink
\else
\let \startlink \pdfstartlink
\fi
% make a live url in pdf output.
\def\pdfurl#1{%
\begingroup
% it seems we really need yet another set of dummies; have not
% tried to figure out what each command should do in the context
% of @url. for now, just make @/ a no-op, that's the only one
% people have actually reported a problem with.
%
\normalturnoffactive
\def\@{@}%
\let\/=\empty
\makevalueexpandable
\leavevmode\urlcolor
\startlink attr{/Border [0 0 0]}%
user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
\endgroup}
\def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
\def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
\def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
\def\maketoks{%
\expandafter\poptoks\the\toksA|ENDTOKS|\relax
\ifx\first0\adn0
\else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
\else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
\else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
\else
\ifnum0=\countA\else\makelink\fi
\ifx\first.\let\next=\done\else
\let\next=\maketoks
\addtokens{\toksB}{\the\toksD}
\ifx\first,\addtokens{\toksB}{\space}\fi
\fi
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
\next}
\def\makelink{\addtokens{\toksB}%
{\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
\def\pdflink#1{%
\startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
\linkcolor #1\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
\else
\let\pdfmkdest = \gobble
\let\pdfurl = \gobble
\let\endlink = \relax
\let\linkcolor = \relax
\let\pdfmakeoutlines = \relax
\fi % \ifx\pdfoutput
\message{fonts,}
% Change the current font style to #1, remembering it in \curfontstyle.
% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
% italics, not bold italics.
%
\def\setfontstyle#1{%
\def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
\csname ten#1\endcsname % change the current font
}
% Select #1 fonts with the current style.
%
\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname}
\def\rm{\fam=0 \setfontstyle{rm}}
\def\it{\fam=\itfam \setfontstyle{it}}
\def\sl{\fam=\slfam \setfontstyle{sl}}
\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
\def\tt{\fam=\ttfam \setfontstyle{tt}}
% Texinfo sort of supports the sans serif font style, which plain TeX does not.
% So we set up a \sf.
\newfam\sffam
\def\sf{\fam=\sffam \setfontstyle{sf}}
\let\li = \sf % Sometimes we call it \li, not \sf.
% We don't need math for this font style.
\def\ttsl{\setfontstyle{ttsl}}
% Default leading.
\newdimen\textleading \textleading = 13.2pt
% Set the baselineskip to #1, and the lineskip and strut size
% correspondingly. There is no deep meaning behind these magic numbers
% used as factors; they just match (closely enough) what Knuth defined.
%
\def\lineskipfactor{.08333}
\def\strutheightpercent{.70833}
\def\strutdepthpercent {.29167}
%
\def\setleading#1{%
\normalbaselineskip = #1\relax
\normallineskip = \lineskipfactor\normalbaselineskip
\normalbaselines
\setbox\strutbox =\hbox{%
\vrule width0pt height\strutheightpercent\baselineskip
depth \strutdepthpercent \baselineskip
}%
}
%
% PDF CMaps. See also LaTeX's t1.cmap.
%
% \cmapOT1
\ifpdf
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1-0)
%%Title: (TeX-OT1-0 TeX OT1 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1)
/Supplement 0
>> def
/CMapName /TeX-OT1-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
8 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<23> <26> <0023>
<28> <3B> <0028>
<3F> <5B> <003F>
<5D> <5E> <005D>
<61> <7A> <0061>
<7B> <7C> <2013>
endbfrange
40 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <00660066>
<0C> <00660069>
<0D> <0066006C>
<0E> <006600660069>
<0F> <00660066006C>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<21> <0021>
<22> <201D>
<27> <2019>
<3C> <00A1>
<3D> <003D>
<3E> <00BF>
<5C> <201C>
<5F> <02D9>
<60> <2018>
<7D> <02DD>
<7E> <007E>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
%
% \cmapOT1IT
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1IT-0)
%%Title: (TeX-OT1IT-0 TeX OT1IT 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1IT)
/Supplement 0
>> def
/CMapName /TeX-OT1IT-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
8 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<25> <26> <0025>
<28> <3B> <0028>
<3F> <5B> <003F>
<5D> <5E> <005D>
<61> <7A> <0061>
<7B> <7C> <2013>
endbfrange
42 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <00660066>
<0C> <00660069>
<0D> <0066006C>
<0E> <006600660069>
<0F> <00660066006C>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<21> <0021>
<22> <201D>
<23> <0023>
<24> <00A3>
<27> <2019>
<3C> <00A1>
<3D> <003D>
<3E> <00BF>
<5C> <201C>
<5F> <02D9>
<60> <2018>
<7D> <02DD>
<7E> <007E>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1IT\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
%
% \cmapOT1TT
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1TT-0)
%%Title: (TeX-OT1TT-0 TeX OT1TT 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1TT)
/Supplement 0
>> def
/CMapName /TeX-OT1TT-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
5 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<21> <26> <0021>
<28> <5F> <0028>
<61> <7E> <0061>
endbfrange
32 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <2191>
<0C> <2193>
<0D> <0027>
<0E> <00A1>
<0F> <00BF>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<20> <2423>
<27> <2019>
<60> <2018>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1TT\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
\else
\expandafter\let\csname cmapOT1\endcsname\gobble
\expandafter\let\csname cmapOT1IT\endcsname\gobble
\expandafter\let\csname cmapOT1TT\endcsname\gobble
\fi
% Set the font macro #1 to the font named #2, adding on the
% specified font prefix (normally `cm').
% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass
% empty to omit).
\def\setfont#1#2#3#4#5{%
\font#1=\fontprefix#2#3 scaled #4
\csname cmap#5\endcsname#1%
}
% This is what gets called when #5 of \setfont is empty.
\let\cmap\gobble
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
% before you read in texinfo.tex.
\ifx\fontprefix\undefined
\def\fontprefix{cm}
\fi
% Support font families that don't use the same naming scheme as CM.
\def\rmshape{r}
\def\rmbshape{bx} %where the normal face is bold
\def\bfshape{b}
\def\bxshape{bx}
\def\ttshape{tt}
\def\ttbshape{tt}
\def\ttslshape{sltt}
\def\itshape{ti}
\def\itbshape{bxti}
\def\slshape{sl}
\def\slbshape{bxsl}
\def\sfshape{ss}
\def\sfbshape{ss}
\def\scshape{csc}
\def\scbshape{csc}
% Definitions for a main text size of 11pt. This is the default in
% Texinfo.
%
\def\definetextfontsizexi{%
% Text fonts (11.2pt, magstep1).
\def\textnominalsize{11pt}
\edef\mainmagstep{\magstephalf}
\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
\font\texti=cmmi10 scaled \mainmagstep
\font\textsy=cmsy10 scaled \mainmagstep
% A few fonts for @defun names and args.
\setfont\defbf\bfshape{10}{\magstep1}{OT1}
\setfont\deftt\ttshape{10}{\magstep1}{OT1TT}
\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT}
\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
% Fonts for indices, footnotes, small examples (9pt).
\def\smallnominalsize{9pt}
\setfont\smallrm\rmshape{9}{1000}{OT1}
\setfont\smalltt\ttshape{9}{1000}{OT1TT}
\setfont\smallbf\bfshape{10}{900}{OT1}
\setfont\smallit\itshape{9}{1000}{OT1IT}
\setfont\smallsl\slshape{9}{1000}{OT1}
\setfont\smallsf\sfshape{9}{1000}{OT1}
\setfont\smallsc\scshape{10}{900}{OT1}
\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
\font\smalli=cmmi9
\font\smallsy=cmsy9
% Fonts for small examples (8pt).
\def\smallernominalsize{8pt}
\setfont\smallerrm\rmshape{8}{1000}{OT1}
\setfont\smallertt\ttshape{8}{1000}{OT1TT}
\setfont\smallerbf\bfshape{10}{800}{OT1}
\setfont\smallerit\itshape{8}{1000}{OT1IT}
\setfont\smallersl\slshape{8}{1000}{OT1}
\setfont\smallersf\sfshape{8}{1000}{OT1}
\setfont\smallersc\scshape{10}{800}{OT1}
\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
\font\smalleri=cmmi8
\font\smallersy=cmsy8
% Fonts for title page (20.4pt):
\def\titlenominalsize{20pt}
\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
\let\titlebf=\titlerm
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
\def\authorrm{\secrm}
\def\authortt{\sectt}
% Chapter (and unnumbered) fonts (17.28pt).
\def\chapnominalsize{17pt}
\setfont\chaprm\rmbshape{12}{\magstep2}{OT1}
\setfont\chapit\itbshape{10}{\magstep3}{OT1IT}
\setfont\chapsl\slbshape{10}{\magstep3}{OT1}
\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT}
\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT}
\setfont\chapsf\sfbshape{17}{1000}{OT1}
\let\chapbf=\chaprm
\setfont\chapsc\scbshape{10}{\magstep3}{OT1}
\font\chapi=cmmi12 scaled \magstep2
\font\chapsy=cmsy10 scaled \magstep3
% Section fonts (14.4pt).
\def\secnominalsize{14pt}
\setfont\secrm\rmbshape{12}{\magstep1}{OT1}
\setfont\secit\itbshape{10}{\magstep2}{OT1IT}
\setfont\secsl\slbshape{10}{\magstep2}{OT1}
\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT}
\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT}
\setfont\secsf\sfbshape{12}{\magstep1}{OT1}
\let\secbf\secrm
\setfont\secsc\scbshape{10}{\magstep2}{OT1}
\font\seci=cmmi12 scaled \magstep1
\font\secsy=cmsy10 scaled \magstep2
% Subsection fonts (13.15pt).
\def\ssecnominalsize{13pt}
\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1}
\setfont\ssecit\itbshape{10}{1315}{OT1IT}
\setfont\ssecsl\slbshape{10}{1315}{OT1}
\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT}
\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT}
\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1}
\let\ssecbf\ssecrm
\setfont\ssecsc\scbshape{10}{1315}{OT1}
\font\sseci=cmmi12 scaled \magstephalf
\font\ssecsy=cmsy10 scaled 1315
% Reduced fonts for @acro in text (10pt).
\def\reducednominalsize{10pt}
\setfont\reducedrm\rmshape{10}{1000}{OT1}
\setfont\reducedtt\ttshape{10}{1000}{OT1TT}
\setfont\reducedbf\bfshape{10}{1000}{OT1}
\setfont\reducedit\itshape{10}{1000}{OT1IT}
\setfont\reducedsl\slshape{10}{1000}{OT1}
\setfont\reducedsf\sfshape{10}{1000}{OT1}
\setfont\reducedsc\scshape{10}{1000}{OT1}
\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT}
\font\reducedi=cmmi10
\font\reducedsy=cmsy10
% reset the current fonts
\textfonts
\rm
} % end of 11pt text font size definitions
% Definitions to make the main text be 10pt Computer Modern, with
% section, chapter, etc., sizes following suit. This is for the GNU
% Press printing of the Emacs 22 manual. Maybe other manuals in the
% future. Used with @smallbook, which sets the leading to 12pt.
%
\def\definetextfontsizex{%
% Text fonts (10pt).
\def\textnominalsize{10pt}
\edef\mainmagstep{1000}
\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
\font\texti=cmmi10 scaled \mainmagstep
\font\textsy=cmsy10 scaled \mainmagstep
% A few fonts for @defun names and args.
\setfont\defbf\bfshape{10}{\magstephalf}{OT1}
\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT}
\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT}
\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
% Fonts for indices, footnotes, small examples (9pt).
\def\smallnominalsize{9pt}
\setfont\smallrm\rmshape{9}{1000}{OT1}
\setfont\smalltt\ttshape{9}{1000}{OT1TT}
\setfont\smallbf\bfshape{10}{900}{OT1}
\setfont\smallit\itshape{9}{1000}{OT1IT}
\setfont\smallsl\slshape{9}{1000}{OT1}
\setfont\smallsf\sfshape{9}{1000}{OT1}
\setfont\smallsc\scshape{10}{900}{OT1}
\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
\font\smalli=cmmi9
\font\smallsy=cmsy9
% Fonts for small examples (8pt).
\def\smallernominalsize{8pt}
\setfont\smallerrm\rmshape{8}{1000}{OT1}
\setfont\smallertt\ttshape{8}{1000}{OT1TT}
\setfont\smallerbf\bfshape{10}{800}{OT1}
\setfont\smallerit\itshape{8}{1000}{OT1IT}
\setfont\smallersl\slshape{8}{1000}{OT1}
\setfont\smallersf\sfshape{8}{1000}{OT1}
\setfont\smallersc\scshape{10}{800}{OT1}
\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
\font\smalleri=cmmi8
\font\smallersy=cmsy8
% Fonts for title page (20.4pt):
\def\titlenominalsize{20pt}
\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
\let\titlebf=\titlerm
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
\def\authorrm{\secrm}
\def\authortt{\sectt}
% Chapter fonts (14.4pt).
\def\chapnominalsize{14pt}
\setfont\chaprm\rmbshape{12}{\magstep1}{OT1}
\setfont\chapit\itbshape{10}{\magstep2}{OT1IT}
\setfont\chapsl\slbshape{10}{\magstep2}{OT1}
\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT}
\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT}
\setfont\chapsf\sfbshape{12}{\magstep1}{OT1}
\let\chapbf\chaprm
\setfont\chapsc\scbshape{10}{\magstep2}{OT1}
\font\chapi=cmmi12 scaled \magstep1
\font\chapsy=cmsy10 scaled \magstep2
% Section fonts (12pt).
\def\secnominalsize{12pt}
\setfont\secrm\rmbshape{12}{1000}{OT1}
\setfont\secit\itbshape{10}{\magstep1}{OT1IT}
\setfont\secsl\slbshape{10}{\magstep1}{OT1}
\setfont\sectt\ttbshape{12}{1000}{OT1TT}
\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT}
\setfont\secsf\sfbshape{12}{1000}{OT1}
\let\secbf\secrm
\setfont\secsc\scbshape{10}{\magstep1}{OT1}
\font\seci=cmmi12
\font\secsy=cmsy10 scaled \magstep1
% Subsection fonts (10pt).
\def\ssecnominalsize{10pt}
\setfont\ssecrm\rmbshape{10}{1000}{OT1}
\setfont\ssecit\itbshape{10}{1000}{OT1IT}
\setfont\ssecsl\slbshape{10}{1000}{OT1}
\setfont\ssectt\ttbshape{10}{1000}{OT1TT}
\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT}
\setfont\ssecsf\sfbshape{10}{1000}{OT1}
\let\ssecbf\ssecrm
\setfont\ssecsc\scbshape{10}{1000}{OT1}
\font\sseci=cmmi10
\font\ssecsy=cmsy10
% Reduced fonts for @acro in text (9pt).
\def\reducednominalsize{9pt}
\setfont\reducedrm\rmshape{9}{1000}{OT1}
\setfont\reducedtt\ttshape{9}{1000}{OT1TT}
\setfont\reducedbf\bfshape{10}{900}{OT1}
\setfont\reducedit\itshape{9}{1000}{OT1IT}
\setfont\reducedsl\slshape{9}{1000}{OT1}
\setfont\reducedsf\sfshape{9}{1000}{OT1}
\setfont\reducedsc\scshape{10}{900}{OT1}
\setfont\reducedttsl\ttslshape{10}{900}{OT1TT}
\font\reducedi=cmmi9
\font\reducedsy=cmsy9
% reduce space between paragraphs
\divide\parskip by 2
% reset the current fonts
\textfonts
\rm
} % end of 10pt text font size definitions
% We provide the user-level command
% @fonttextsize 10
% (or 11) to redefine the text font size. pt is assumed.
%
\def\xword{10}
\def\xiword{11}
%
\parseargdef\fonttextsize{%
\def\textsizearg{#1}%
\wlog{doing @fonttextsize \textsizearg}%
%
% Set \globaldefs so that documents can use this inside @tex, since
% makeinfo 4.8 does not support it, but we need it nonetheless.
%
\begingroup \globaldefs=1
\ifx\textsizearg\xword \definetextfontsizex
\else \ifx\textsizearg\xiword \definetextfontsizexi
\else
\errhelp=\EMsimple
\errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'}
\fi\fi
\endgroup
}
% In order for the font changes to affect most math symbols and letters,
% we have to define the \textfont of the standard families. Since
% texinfo doesn't allow for producing subscripts and superscripts except
% in the main text, we don't bother to reset \scriptfont and
% \scriptscriptfont (which would also require loading a lot more fonts).
%
\def\resetmathfonts{%
\textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
\textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
\textfont\ttfam=\tentt \textfont\sffam=\tensf
}
% The font-changing commands redefine the meanings of \tenSTYLE, instead
% of just \STYLE. We do this because \STYLE needs to also set the
% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire
% \tenSTYLE to set the current font.
%
% Each font-changing command also sets the names \lsize (one size lower)
% and \lllsize (three sizes lower). These relative commands are used in
% the LaTeX logo and acronyms.
%
% This all needs generalizing, badly.
%
\def\textfonts{%
\let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
\let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
\let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
\let\tenttsl=\textttsl
\def\curfontsize{text}%
\def\lsize{reduced}\def\lllsize{smaller}%
\resetmathfonts \setleading{\textleading}}
\def\titlefonts{%
\let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
\let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
\let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
\let\tenttsl=\titlettsl
\def\curfontsize{title}%
\def\lsize{chap}\def\lllsize{subsec}%
\resetmathfonts \setleading{25pt}}
\def\titlefont#1{{\titlefonts\rm #1}}
\def\chapfonts{%
\let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
\let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
\let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
\let\tenttsl=\chapttsl
\def\curfontsize{chap}%
\def\lsize{sec}\def\lllsize{text}%
\resetmathfonts \setleading{19pt}}
\def\secfonts{%
\let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
\let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
\let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
\let\tenttsl=\secttsl
\def\curfontsize{sec}%
\def\lsize{subsec}\def\lllsize{reduced}%
\resetmathfonts \setleading{16pt}}
\def\subsecfonts{%
\let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
\let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
\let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
\let\tenttsl=\ssecttsl
\def\curfontsize{ssec}%
\def\lsize{text}\def\lllsize{small}%
\resetmathfonts \setleading{15pt}}
\let\subsubsecfonts = \subsecfonts
\def\reducedfonts{%
\let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl
\let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
\let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
\let\tenttsl=\reducedttsl
\def\curfontsize{reduced}%
\def\lsize{small}\def\lllsize{smaller}%
\resetmathfonts \setleading{10.5pt}}
\def\smallfonts{%
\let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
\let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
\let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
\let\tenttsl=\smallttsl
\def\curfontsize{small}%
\def\lsize{smaller}\def\lllsize{smaller}%
\resetmathfonts \setleading{10.5pt}}
\def\smallerfonts{%
\let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
\let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
\let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
\let\tenttsl=\smallerttsl
\def\curfontsize{smaller}%
\def\lsize{smaller}\def\lllsize{smaller}%
\resetmathfonts \setleading{9.5pt}}
% Set the fonts to use with the @small... environments.
\let\smallexamplefonts = \smallfonts
% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample
% can fit this many characters:
% 8.5x11=86 smallbook=72 a4=90 a5=69
% If we use \scriptfonts (8pt), then we can fit this many characters:
% 8.5x11=90+ smallbook=80 a4=90+ a5=77
% For me, subjectively, the few extra characters that fit aren't worth
% the additional smallness of 8pt. So I'm making the default 9pt.
%
% By the way, for comparison, here's what fits with @example (10pt):
% 8.5x11=71 smallbook=60 a4=75 a5=58
%
% I wish the USA used A4 paper.
% --karl, 24jan03.
% Set up the default fonts, so we can use them for creating boxes.
%
\definetextfontsizexi
% Define these so they can be easily changed for other fonts.
\def\angleleft{$\langle$}
\def\angleright{$\rangle$}
% Count depth in font-changes, for error checks
\newcount\fontdepth \fontdepth=0
% Fonts for short table of contents.
\setfont\shortcontrm\rmshape{12}{1000}{OT1}
\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12
\setfont\shortcontsl\slshape{12}{1000}{OT1}
\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
%% Add scribe-like font environments, plus @l for inline lisp (usually sans
%% serif) and @ii for TeX italic
% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
% unless the following character is such as not to need one.
\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
\ptexslash\fi\fi\fi}
\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
% like \smartslanted except unconditionally uses \ttsl.
% @var is set to this for defun arguments.
\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
% like \smartslanted except unconditionally use \sl. We never want
% ttsl for book titles, do we?
\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
\let\i=\smartitalic
\let\slanted=\smartslanted
\let\var=\smartslanted
\let\dfn=\smartslanted
\let\emph=\smartitalic
% @b, explicit bold.
\def\b#1{{\bf #1}}
\let\strong=\b
% @sansserif, explicit sans.
\def\sansserif#1{{\sf #1}}
% We can't just use \exhyphenpenalty, because that only has effect at
% the end of a paragraph. Restore normal hyphenation at the end of the
% group within which \nohyphenation is presumably called.
%
\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
\def\restorehyphenation{\hyphenchar\font = `- }
% Set sfcode to normal for the chars that usually have another value.
% Can't use plain's \frenchspacing because it uses the `\x notation, and
% sometimes \x has an active definition that messes things up.
%
\catcode`@=11
\def\plainfrenchspacing{%
\sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
\sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
\def\endofsentencespacefactor{1000}% for @. and friends
}
\def\plainnonfrenchspacing{%
\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000
\sfcode`\:2000\sfcode`\;1500\sfcode`\,1250
\def\endofsentencespacefactor{3000}% for @. and friends
}
\catcode`@=\other
\def\endofsentencespacefactor{3000}% default
\def\t#1{%
{\tt \rawbackslash \plainfrenchspacing #1}%
\null
}
\def\samp#1{`\tclose{#1}'\null}
\setfont\keyrm\rmshape{8}{1000}{OT1}
\font\keysy=cmsy9
\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
\raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
\vbox{\hrule\kern-0.4pt
\hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
\kern-0.4pt\hrule}%
\kern-.06em\raise0.4pt\hbox{\angleright}}}}
\def\key #1{{\nohyphenation \uppercase{#1}}\null}
% The old definition, with no lozenge:
%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
\def\ctrl #1{{\tt \rawbackslash \hat}#1}
% @file, @option are the same as @samp.
\let\file=\samp
\let\option=\samp
% @code is a modification of @t,
% which makes spaces the same size as normal in the surrounding text.
\def\tclose#1{%
{%
% Change normal interword space to be same as for the current font.
\spaceskip = \fontdimen2\font
%
% Switch to typewriter.
\tt
%
% But `\ ' produces the large typewriter interword space.
\def\ {{\spaceskip = 0pt{} }}%
%
% Turn off hyphenation.
\nohyphenation
%
\rawbackslash
\plainfrenchspacing
#1%
}%
\null
}
% We *must* turn on hyphenation at `-' and `_' in @code.
% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
% Unfortunately, TeX uses one parameter (\hyphenchar) to control
% both hyphenation at - and hyphenation within words.
% We must therefore turn them both off (\tclose does that)
% and arrange explicitly to hyphenate at a dash.
% -- rms.
{
\catcode`\-=\active \catcode`\_=\active
\catcode`\'=\active \catcode`\`=\active
%
\global\def\code{\begingroup
\catcode\rquoteChar=\active \catcode\lquoteChar=\active
\let'\codequoteright \let`\codequoteleft
%
\catcode\dashChar=\active \catcode\underChar=\active
\ifallowcodebreaks
\let-\codedash
\let_\codeunder
\else
\let-\realdash
\let_\realunder
\fi
\codex
}
}
\def\realdash{-}
\def\codedash{-\discretionary{}{}{}}
\def\codeunder{%
% this is all so @math{@code{var_name}+1} can work. In math mode, _
% is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
% will therefore expand the active definition of _, which is us
% (inside @code that is), therefore an endless loop.
\ifusingtt{\ifmmode
\mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
\else\normalunderscore \fi
\discretionary{}{}{}}%
{\_}%
}
\def\codex #1{\tclose{#1}\endgroup}
% An additional complication: the above will allow breaks after, e.g.,
% each of the four underscores in __typeof__. This is undesirable in
% some manuals, especially if they don't have long identifiers in
% general. @allowcodebreaks provides a way to control this.
%
\newif\ifallowcodebreaks \allowcodebreakstrue
\def\keywordtrue{true}
\def\keywordfalse{false}
\parseargdef\allowcodebreaks{%
\def\txiarg{#1}%
\ifx\txiarg\keywordtrue
\allowcodebreakstrue
\else\ifx\txiarg\keywordfalse
\allowcodebreaksfalse
\else
\errhelp = \EMsimple
\errmessage{Unknown @allowcodebreaks option `\txiarg'}%
\fi\fi
}
% @kbd is like @code, except that if the argument is just one @key command,
% then @kbd has no effect.
% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
% `example' (@kbd uses ttsl only inside of @example and friends),
% or `code' (@kbd uses normal tty font always).
\parseargdef\kbdinputstyle{%
\def\txiarg{#1}%
\ifx\txiarg\worddistinct
\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
\else\ifx\txiarg\wordexample
\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
\else\ifx\txiarg\wordcode
\gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
\else
\errhelp = \EMsimple
\errmessage{Unknown @kbdinputstyle option `\txiarg'}%
\fi\fi\fi
}
\def\worddistinct{distinct}
\def\wordexample{example}
\def\wordcode{code}
% Default is `distinct.'
\kbdinputstyle distinct
\def\xkey{\key}
\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
\ifx\one\xkey\ifx\threex\three \key{#2}%
\else{\tclose{\kbdfont\look}}\fi
\else{\tclose{\kbdfont\look}}\fi}
% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
\let\indicateurl=\code
\let\env=\code
\let\command=\code
% @uref (abbreviation for `urlref') takes an optional (comma-separated)
% second argument specifying the text to display and an optional third
% arg as text to display instead of (rather than in addition to) the url
% itself. First (mandatory) arg is the url. Perhaps eventually put in
% a hypertex \special here.
%
\def\uref#1{\douref #1,,,\finish}
\def\douref#1,#2,#3,#4\finish{\begingroup
\unsepspaces
\pdfurl{#1}%
\setbox0 = \hbox{\ignorespaces #3}%
\ifdim\wd0 > 0pt
\unhbox0 % third arg given, show only that
\else
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0 > 0pt
\ifpdf
\unhbox0 % PDF: 2nd arg given, show only it
\else
\unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
\fi
\else
\code{#1}% only url given, so show it
\fi
\fi
\endlink
\endgroup}
% @url synonym for @uref, since that's how everyone uses it.
%
\let\url=\uref
% rms does not like angle brackets --karl, 17may97.
% So now @email is just like @uref, unless we are pdf.
%
%\def\email#1{\angleleft{\tt #1}\angleright}
\ifpdf
\def\email#1{\doemail#1,,\finish}
\def\doemail#1,#2,#3\finish{\begingroup
\unsepspaces
\pdfurl{mailto:#1}%
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
\endlink
\endgroup}
\else
\let\email=\uref
\fi
% Check if we are currently using a typewriter font. Since all the
% Computer Modern typewriter fonts have zero interword stretch (and
% shrink), and it is reasonable to expect all typewriter fonts to have
% this property, we can check that font parameter.
%
\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
%
\def\dmn#1{\thinspace #1}
\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
% @l was never documented to mean ``switch to the Lisp font'',
% and it is not used as such in any manual I can find. We need it for
% Polish suppressed-l. --karl, 22sep96.
%\def\l#1{{\li #1}\null}
% Explicit font changes: @r, @sc, undocumented @ii.
\def\r#1{{\rm #1}} % roman font
\def\sc#1{{\smallcaps#1}} % smallcaps font
\def\ii#1{{\it #1}} % italic font
% @acronym for "FBI", "NATO", and the like.
% We print this one point size smaller, since it's intended for
% all-uppercase.
%
\def\acronym#1{\doacronym #1,,\finish}
\def\doacronym#1,#2,#3\finish{%
{\selectfonts\lsize #1}%
\def\temp{#2}%
\ifx\temp\empty \else
\space ({\unsepspaces \ignorespaces \temp \unskip})%
\fi
}
% @abbr for "Comput. J." and the like.
% No font change, but don't do end-of-sentence spacing.
%
\def\abbr#1{\doabbr #1,,\finish}
\def\doabbr#1,#2,#3\finish{%
{\plainfrenchspacing #1}%
\def\temp{#2}%
\ifx\temp\empty \else
\space ({\unsepspaces \ignorespaces \temp \unskip})%
\fi
}
% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
%
\def\pounds{{\it\$}}
% @euro{} comes from a separate font, depending on the current style.
% We use the free feym* fonts from the eurosym package by Henrik
% Theiling, which support regular, slanted, bold and bold slanted (and
% "outlined" (blackboard board, sort of) versions, which we don't need).
% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
%
% Although only regular is the truly official Euro symbol, we ignore
% that. The Euro is designed to be slightly taller than the regular
% font height.
%
% feymr - regular
% feymo - slanted
% feybr - bold
% feybo - bold slanted
%
% There is no good (free) typewriter version, to my knowledge.
% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide.
% Hmm.
%
% Also doesn't work in math. Do we need to do math with euro symbols?
% Hope not.
%
%
\def\euro{{\eurofont e}}
\def\eurofont{%
% We set the font at each command, rather than predefining it in
% \textfonts and the other font-switching commands, so that
% installations which never need the symbol don't have to have the
% font installed.
%
% There is only one designed size (nominal 10pt), so we always scale
% that to the current nominal size.
%
% By the way, simply using "at 1em" works for cmr10 and the like, but
% does not work for cmbx10 and other extended/shrunken fonts.
%
\def\eurosize{\csname\curfontsize nominalsize\endcsname}%
%
\ifx\curfontstyle\bfstylename
% bold:
\font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize
\else
% regular:
\font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize
\fi
\thiseurofont
}
% @registeredsymbol - R in a circle. The font for the R should really
% be smaller yet, but lllsize is the best we can do for now.
% Adapted from the plain.tex definition of \copyright.
%
\def\registeredsymbol{%
$^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}%
\hfil\crcr\Orb}}%
}$%
}
% @textdegree - the normal degrees sign.
%
\def\textdegree{$^\circ$}
% Laurent Siebenmann reports \Orb undefined with:
% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38
% so we'll define it if necessary.
%
\ifx\Orb\undefined
\def\Orb{\mathhexbox20D}
\fi
\message{page headings,}
\newskip\titlepagetopglue \titlepagetopglue = 1.5in
\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
% First the title page. Must do @settitle before @titlepage.
\newif\ifseenauthor
\newif\iffinishedtitlepage
% Do an implicit @contents or @shortcontents after @end titlepage if the
% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
%
\newif\ifsetcontentsaftertitlepage
\let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
\newif\ifsetshortcontentsaftertitlepage
\let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
\endgroup\page\hbox{}\page}
\envdef\titlepage{%
% Open one extra group, as we want to close it in the middle of \Etitlepage.
\begingroup
\parindent=0pt \textfonts
% Leave some space at the very top of the page.
\vglue\titlepagetopglue
% No rule at page bottom unless we print one at the top with @title.
\finishedtitlepagetrue
%
% Most title ``pages'' are actually two pages long, with space
% at the top of the second. We don't want the ragged left on the second.
\let\oldpage = \page
\def\page{%
\iffinishedtitlepage\else
\finishtitlepage
\fi
\let\page = \oldpage
\page
\null
}%
}
\def\Etitlepage{%
\iffinishedtitlepage\else
\finishtitlepage
\fi
% It is important to do the page break before ending the group,
% because the headline and footline are only empty inside the group.
% If we use the new definition of \page, we always get a blank page
% after the title page, which we certainly don't want.
\oldpage
\endgroup
%
% Need this before the \...aftertitlepage checks so that if they are
% in effect the toc pages will come out with page numbers.
\HEADINGSon
%
% If they want short, they certainly want long too.
\ifsetshortcontentsaftertitlepage
\shortcontents
\contents
\global\let\shortcontents = \relax
\global\let\contents = \relax
\fi
%
\ifsetcontentsaftertitlepage
\contents
\global\let\contents = \relax
\global\let\shortcontents = \relax
\fi
}
\def\finishtitlepage{%
\vskip4pt \hrule height 2pt width \hsize
\vskip\titlepagebottomglue
\finishedtitlepagetrue
}
%%% Macros to be used within @titlepage:
\let\subtitlerm=\tenrm
\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
\let\tt=\authortt}
\parseargdef\title{%
\checkenv\titlepage
\leftline{\titlefonts\rm #1}
% print a rule at the page bottom also.
\finishedtitlepagefalse
\vskip4pt \hrule height 4pt width \hsize \vskip4pt
}
\parseargdef\subtitle{%
\checkenv\titlepage
{\subtitlefont \rightline{#1}}%
}
% @author should come last, but may come many times.
% It can also be used inside @quotation.
%
\parseargdef\author{%
\def\temp{\quotation}%
\ifx\thisenv\temp
\def\quotationauthor{#1}% printed in \Equotation.
\else
\checkenv\titlepage
\ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
{\authorfont \leftline{#1}}%
\fi
}
%%% Set up page headings and footings.
\let\thispage=\folio
\newtoks\evenheadline % headline on even pages
\newtoks\oddheadline % headline on odd pages
\newtoks\evenfootline % footline on even pages
\newtoks\oddfootline % footline on odd pages
% Now make TeX use those variables
\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
\else \the\evenheadline \fi}}
\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
\else \the\evenfootline \fi}\HEADINGShook}
\let\HEADINGShook=\relax
% Commands to set those variables.
% For example, this is what @headings on does
% @evenheading @thistitle|@thispage|@thischapter
% @oddheading @thischapter|@thispage|@thistitle
% @evenfooting @thisfile||
% @oddfooting ||@thisfile
\def\evenheading{\parsearg\evenheadingxxx}
\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
\def\oddheading{\parsearg\oddheadingxxx}
\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
\def\evenfooting{\parsearg\evenfootingxxx}
\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
\def\oddfooting{\parsearg\oddfootingxxx}
\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
\global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
%
% Leave some space for the footline. Hopefully ok to assume
% @evenfooting will not be used by itself.
\global\advance\pageheight by -12pt
\global\advance\vsize by -12pt
}
\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
% @headings double turns headings on for double-sided printing.
% @headings single turns headings on for single-sided printing.
% @headings off turns them off.
% @headings on same as @headings double, retained for compatibility.
% @headings after turns on double-sided headings after this page.
% @headings doubleafter turns on double-sided headings after this page.
% @headings singleafter turns on single-sided headings after this page.
% By default, they are off at the start of a document,
% and turned `on' after @end titlepage.
\def\headings #1 {\csname HEADINGS#1\endcsname}
\def\HEADINGSoff{%
\global\evenheadline={\hfil} \global\evenfootline={\hfil}
\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
\HEADINGSoff
% When we turn headings on, set the page number to 1.
% For double-sided printing, put current file name in lower left corner,
% chapter name on inside top of right hand pages, document
% title on inside top of left hand pages, and page numbers on outside top
% edge of all pages.
\def\HEADINGSdouble{%
\global\pageno=1
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\let\contentsalignmacro = \chapoddpage
}
\let\contentsalignmacro = \chappager
% For single-sided printing, chapter title goes across top left of page,
% page number on top right.
\def\HEADINGSsingle{%
\global\pageno=1
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\let\contentsalignmacro = \chappager
}
\def\HEADINGSon{\HEADINGSdouble}
\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
\let\HEADINGSdoubleafter=\HEADINGSafter
\def\HEADINGSdoublex{%
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\let\contentsalignmacro = \chapoddpage
}
\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
\def\HEADINGSsinglex{%
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\let\contentsalignmacro = \chappager
}
% Subroutines used in generating headings
% This produces Day Month Year style of output.
% Only define if not already defined, in case a txi-??.tex file has set
% up a different format (e.g., txi-cs.tex does this).
\ifx\today\undefined
\def\today{%
\number\day\space
\ifcase\month
\or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
\or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
\or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
\fi
\space\number\year}
\fi
% @settitle line... specifies the title of the document, for headings.
% It generates no output of its own.
\def\thistitle{\putwordNoTitle}
\def\settitle{\parsearg{\gdef\thistitle}}
\message{tables,}
% Tables -- @table, @ftable, @vtable, @item(x).
% default indentation of table text
\newdimen\tableindent \tableindent=.8in
% default indentation of @itemize and @enumerate text
\newdimen\itemindent \itemindent=.3in
% margin between end of table item and start of table text.
\newdimen\itemmargin \itemmargin=.1in
% used internally for \itemindent minus \itemmargin
\newdimen\itemmax
% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
% these defs.
% They also define \itemindex
% to index the item name in whatever manner is desired (perhaps none).
\newif\ifitemxneedsnegativevskip
\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
\def\internalBitem{\smallbreak \parsearg\itemzzz}
\def\internalBitemx{\itemxpar \parsearg\itemzzz}
\def\itemzzz #1{\begingroup %
\advance\hsize by -\rightskip
\advance\hsize by -\tableindent
\setbox0=\hbox{\itemindicate{#1}}%
\itemindex{#1}%
\nobreak % This prevents a break before @itemx.
%
% If the item text does not fit in the space we have, put it on a line
% by itself, and do not allow a page break either before or after that
% line. We do not start a paragraph here because then if the next
% command is, e.g., @kindex, the whatsit would get put into the
% horizontal list on a line by itself, resulting in extra blank space.
\ifdim \wd0>\itemmax
%
% Make this a paragraph so we get the \parskip glue and wrapping,
% but leave it ragged-right.
\begingroup
\advance\leftskip by-\tableindent
\advance\hsize by\tableindent
\advance\rightskip by0pt plus1fil
\leavevmode\unhbox0\par
\endgroup
%
% We're going to be starting a paragraph, but we don't want the
% \parskip glue -- logically it's part of the @item we just started.
\nobreak \vskip-\parskip
%
% Stop a page break at the \parskip glue coming up. However, if
% what follows is an environment such as @example, there will be no
% \parskip glue; then the negative vskip we just inserted would
% cause the example and the item to crash together. So we use this
% bizarre value of 10001 as a signal to \aboveenvbreak to insert
% \parskip glue after all. Section titles are handled this way also.
%
\penalty 10001
\endgroup
\itemxneedsnegativevskipfalse
\else
% The item text fits into the space. Start a paragraph, so that the
% following text (if any) will end up on the same line.
\noindent
% Do this with kerns and \unhbox so that if there is a footnote in
% the item text, it can migrate to the main vertical list and
% eventually be printed.
\nobreak\kern-\tableindent
\dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
\unhbox0
\nobreak\kern\dimen0
\endgroup
\itemxneedsnegativevskiptrue
\fi
}
\def\item{\errmessage{@item while not in a list environment}}
\def\itemx{\errmessage{@itemx while not in a list environment}}
% @table, @ftable, @vtable.
\envdef\table{%
\let\itemindex\gobble
\tablecheck{table}%
}
\envdef\ftable{%
\def\itemindex ##1{\doind {fn}{\code{##1}}}%
\tablecheck{ftable}%
}
\envdef\vtable{%
\def\itemindex ##1{\doind {vr}{\code{##1}}}%
\tablecheck{vtable}%
}
\def\tablecheck#1{%
\ifnum \the\catcode`\^^M=\active
\endgroup
\errmessage{This command won't work in this context; perhaps the problem is
that we are \inenvironment\thisenv}%
\def\next{\doignore{#1}}%
\else
\let\next\tablex
\fi
\next
}
\def\tablex#1{%
\def\itemindicate{#1}%
\parsearg\tabley
}
\def\tabley#1{%
{%
\makevalueexpandable
\edef\temp{\noexpand\tablez #1\space\space\space}%
\expandafter
}\temp \endtablez
}
\def\tablez #1 #2 #3 #4\endtablez{%
\aboveenvbreak
\ifnum 0#1>0 \advance \leftskip by #1\mil \fi
\ifnum 0#2>0 \tableindent=#2\mil \fi
\ifnum 0#3>0 \advance \rightskip by #3\mil \fi
\itemmax=\tableindent
\advance \itemmax by -\itemmargin
\advance \leftskip by \tableindent
\exdentamount=\tableindent
\parindent = 0pt
\parskip = \smallskipamount
\ifdim \parskip=0pt \parskip=2pt \fi
\let\item = \internalBitem
\let\itemx = \internalBitemx
}
\def\Etable{\endgraf\afterenvbreak}
\let\Eftable\Etable
\let\Evtable\Etable
\let\Eitemize\Etable
\let\Eenumerate\Etable
% This is the counter used by @enumerate, which is really @itemize
\newcount \itemno
\envdef\itemize{\parsearg\doitemize}
\def\doitemize#1{%
\aboveenvbreak
\itemmax=\itemindent
\advance\itemmax by -\itemmargin
\advance\leftskip by \itemindent
\exdentamount=\itemindent
\parindent=0pt
\parskip=\smallskipamount
\ifdim\parskip=0pt \parskip=2pt \fi
\def\itemcontents{#1}%
% @itemize with no arg is equivalent to @itemize @bullet.
\ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
\let\item=\itemizeitem
}
% Definition of @item while inside @itemize and @enumerate.
%
\def\itemizeitem{%
\advance\itemno by 1 % for enumerations
{\let\par=\endgraf \smallbreak}% reasonable place to break
{%
% If the document has an @itemize directly after a section title, a
% \nobreak will be last on the list, and \sectionheading will have
% done a \vskip-\parskip. In that case, we don't want to zero
% parskip, or the item text will crash with the heading. On the
% other hand, when there is normal text preceding the item (as there
% usually is), we do want to zero parskip, or there would be too much
% space. In that case, we won't have a \nobreak before. At least
% that's the theory.
\ifnum\lastpenalty<10000 \parskip=0in \fi
\noindent
\hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
\vadjust{\penalty 1200}}% not good to break after first line of item.
\flushcr
}
% \splitoff TOKENS\endmark defines \first to be the first token in
% TOKENS, and \rest to be the remainder.
%
\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
% Allow an optional argument of an uppercase letter, lowercase letter,
% or number, to specify the first label in the enumerated list. No
% argument is the same as `1'.
%
\envparseargdef\enumerate{\enumeratey #1 \endenumeratey}
\def\enumeratey #1 #2\endenumeratey{%
% If we were given no argument, pretend we were given `1'.
\def\thearg{#1}%
\ifx\thearg\empty \def\thearg{1}\fi
%
% Detect if the argument is a single token. If so, it might be a
% letter. Otherwise, the only valid thing it can be is a number.
% (We will always have one token, because of the test we just made.
% This is a good thing, since \splitoff doesn't work given nothing at
% all -- the first parameter is undelimited.)
\expandafter\splitoff\thearg\endmark
\ifx\rest\empty
% Only one token in the argument. It could still be anything.
% A ``lowercase letter'' is one whose \lccode is nonzero.
% An ``uppercase letter'' is one whose \lccode is both nonzero, and
% not equal to itself.
% Otherwise, we assume it's a number.
%
% We need the \relax at the end of the \ifnum lines to stop TeX from
% continuing to look for a <number>.
%
\ifnum\lccode\expandafter`\thearg=0\relax
\numericenumerate % a number (we hope)
\else
% It's a letter.
\ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
\lowercaseenumerate % lowercase letter
\else
\uppercaseenumerate % uppercase letter
\fi
\fi
\else
% Multiple tokens in the argument. We hope it's a number.
\numericenumerate
\fi
}
% An @enumerate whose labels are integers. The starting integer is
% given in \thearg.
%
\def\numericenumerate{%
\itemno = \thearg
\startenumeration{\the\itemno}%
}
% The starting (lowercase) letter is in \thearg.
\def\lowercaseenumerate{%
\itemno = \expandafter`\thearg
\startenumeration{%
% Be sure we're not beyond the end of the alphabet.
\ifnum\itemno=0
\errmessage{No more lowercase letters in @enumerate; get a bigger
alphabet}%
\fi
\char\lccode\itemno
}%
}
% The starting (uppercase) letter is in \thearg.
\def\uppercaseenumerate{%
\itemno = \expandafter`\thearg
\startenumeration{%
% Be sure we're not beyond the end of the alphabet.
\ifnum\itemno=0
\errmessage{No more uppercase letters in @enumerate; get a bigger
alphabet}
\fi
\char\uccode\itemno
}%
}
% Call \doitemize, adding a period to the first argument and supplying the
% common last two arguments. Also subtract one from the initial value in
% \itemno, since @item increments \itemno.
%
\def\startenumeration#1{%
\advance\itemno by -1
\doitemize{#1.}\flushcr
}
% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
% to @enumerate.
%
\def\alphaenumerate{\enumerate{a}}
\def\capsenumerate{\enumerate{A}}
\def\Ealphaenumerate{\Eenumerate}
\def\Ecapsenumerate{\Eenumerate}
% @multitable macros
% Amy Hendrickson, 8/18/94, 3/6/96
%
% @multitable ... @end multitable will make as many columns as desired.
% Contents of each column will wrap at width given in preamble. Width
% can be specified either with sample text given in a template line,
% or in percent of \hsize, the current width of text on page.
% Table can continue over pages but will only break between lines.
% To make preamble:
%
% Either define widths of columns in terms of percent of \hsize:
% @multitable @columnfractions .25 .3 .45
% @item ...
%
% Numbers following @columnfractions are the percent of the total
% current hsize to be used for each column. You may use as many
% columns as desired.
% Or use a template:
% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
% @item ...
% using the widest term desired in each column.
% Each new table line starts with @item, each subsequent new column
% starts with @tab. Empty columns may be produced by supplying @tab's
% with nothing between them for as many times as empty columns are needed,
% ie, @tab@tab@tab will produce two empty columns.
% @item, @tab do not need to be on their own lines, but it will not hurt
% if they are.
% Sample multitable:
% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
% @item first col stuff @tab second col stuff @tab third col
% @item
% first col stuff
% @tab
% second col stuff
% @tab
% third col
% @item first col stuff @tab second col stuff
% @tab Many paragraphs of text may be used in any column.
%
% They will wrap at the width determined by the template.
% @item@tab@tab This will be in third column.
% @end multitable
% Default dimensions may be reset by user.
% @multitableparskip is vertical space between paragraphs in table.
% @multitableparindent is paragraph indent in table.
% @multitablecolmargin is horizontal space to be left between columns.
% @multitablelinespace is space to leave between table items, baseline
% to baseline.
% 0pt means it depends on current normal line spacing.
%
\newskip\multitableparskip
\newskip\multitableparindent
\newdimen\multitablecolspace
\newskip\multitablelinespace
\multitableparskip=0pt
\multitableparindent=6pt
\multitablecolspace=12pt
\multitablelinespace=0pt
% Macros used to set up halign preamble:
%
\let\endsetuptable\relax
\def\xendsetuptable{\endsetuptable}
\let\columnfractions\relax
\def\xcolumnfractions{\columnfractions}
\newif\ifsetpercent
% #1 is the @columnfraction, usually a decimal number like .5, but might
% be just 1. We just use it, whatever it is.
%
\def\pickupwholefraction#1 {%
\global\advance\colcount by 1
\expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
\setuptable
}
\newcount\colcount
\def\setuptable#1{%
\def\firstarg{#1}%
\ifx\firstarg\xendsetuptable
\let\go = \relax
\else
\ifx\firstarg\xcolumnfractions
\global\setpercenttrue
\else
\ifsetpercent
\let\go\pickupwholefraction
\else
\global\advance\colcount by 1
\setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
% separator; typically that is always in the input, anyway.
\expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
\fi
\fi
\ifx\go\pickupwholefraction
% Put the argument back for the \pickupwholefraction call, so
% we'll always have a period there to be parsed.
\def\go{\pickupwholefraction#1}%
\else
\let\go = \setuptable
\fi%
\fi
\go
}
% multitable-only commands.
%
% @headitem starts a heading row, which we typeset in bold.
% Assignments have to be global since we are inside the implicit group
% of an alignment entry. Note that \everycr resets \everytab.
\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}%
%
% A \tab used to include \hskip1sp. But then the space in a template
% line is not enough. That is bad. So let's go back to just `&' until
% we encounter the problem it was intended to solve again.
% --karl, nathan@acm.org, 20apr99.
\def\tab{\checkenv\multitable &\the\everytab}%
% @multitable ... @end multitable definitions:
%
\newtoks\everytab % insert after every tab.
%
\envdef\multitable{%
\vskip\parskip
\startsavinginserts
%
% @item within a multitable starts a normal row.
% We use \def instead of \let so that if one of the multitable entries
% contains an @itemize, we don't choke on the \item (seen as \crcr aka
% \endtemplate) expanding \doitemize.
\def\item{\crcr}%
%
\tolerance=9500
\hbadness=9500
\setmultitablespacing
\parskip=\multitableparskip
\parindent=\multitableparindent
\overfullrule=0pt
\global\colcount=0
%
\everycr = {%
\noalign{%
\global\everytab={}%
\global\colcount=0 % Reset the column counter.
% Check for saved footnotes, etc.
\checkinserts
% Keeps underfull box messages off when table breaks over pages.
%\filbreak
% Maybe so, but it also creates really weird page breaks when the
% table breaks over pages. Wouldn't \vfil be better? Wait until the
% problem manifests itself, so it can be fixed for real --karl.
}%
}%
%
\parsearg\domultitable
}
\def\domultitable#1{%
% To parse everything between @multitable and @item:
\setuptable#1 \endsetuptable
%
% This preamble sets up a generic column definition, which will
% be used as many times as user calls for columns.
% \vtop will set a single line and will also let text wrap and
% continue for many paragraphs if desired.
\halign\bgroup &%
\global\advance\colcount by 1
\multistrut
\vtop{%
% Use the current \colcount to find the correct column width:
\hsize=\expandafter\csname col\the\colcount\endcsname
%
% In order to keep entries from bumping into each other
% we will add a \leftskip of \multitablecolspace to all columns after
% the first one.
%
% If a template has been used, we will add \multitablecolspace
% to the width of each template entry.
%
% If the user has set preamble in terms of percent of \hsize we will
% use that dimension as the width of the column, and the \leftskip
% will keep entries from bumping into each other. Table will start at
% left margin and final column will justify at right margin.
%
% Make sure we don't inherit \rightskip from the outer environment.
\rightskip=0pt
\ifnum\colcount=1
% The first column will be indented with the surrounding text.
\advance\hsize by\leftskip
\else
\ifsetpercent \else
% If user has not set preamble in terms of percent of \hsize
% we will advance \hsize by \multitablecolspace.
\advance\hsize by \multitablecolspace
\fi
% In either case we will make \leftskip=\multitablecolspace:
\leftskip=\multitablecolspace
\fi
% Ignoring space at the beginning and end avoids an occasional spurious
% blank line, when TeX decides to break the line at the space before the
% box from the multistrut, so the strut ends up on a line by itself.
% For example:
% @multitable @columnfractions .11 .89
% @item @code{#}
% @tab Legal holiday which is valid in major parts of the whole country.
% Is automatically provided with highlighting sequences respectively
% marking characters.
\noindent\ignorespaces##\unskip\multistrut
}\cr
}
\def\Emultitable{%
\crcr
\egroup % end the \halign
\global\setpercentfalse
}
\def\setmultitablespacing{%
\def\multistrut{\strut}% just use the standard line spacing
%
% Compute \multitablelinespace (if not defined by user) for use in
% \multitableparskip calculation. We used define \multistrut based on
% this, but (ironically) that caused the spacing to be off.
% See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100.
\ifdim\multitablelinespace=0pt
\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
\global\advance\multitablelinespace by-\ht0
\fi
%% Test to see if parskip is larger than space between lines of
%% table. If not, do nothing.
%% If so, set to same dimension as multitablelinespace.
\ifdim\multitableparskip>\multitablelinespace
\global\multitableparskip=\multitablelinespace
\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
%% than skip between lines in the table.
\fi%
\ifdim\multitableparskip=0pt
\global\multitableparskip=\multitablelinespace
\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
%% than skip between lines in the table.
\fi}
\message{conditionals,}
% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext,
% @ifnotxml always succeed. They currently do nothing; we don't
% attempt to check whether the conditionals are properly nested. But we
% have to remember that they are conditionals, so that @end doesn't
% attempt to close an environment group.
%
\def\makecond#1{%
\expandafter\let\csname #1\endcsname = \relax
\expandafter\let\csname iscond.#1\endcsname = 1
}
\makecond{iftex}
\makecond{ifnotdocbook}
\makecond{ifnothtml}
\makecond{ifnotinfo}
\makecond{ifnotplaintext}
\makecond{ifnotxml}
% Ignore @ignore, @ifhtml, @ifinfo, and the like.
%
\def\direntry{\doignore{direntry}}
\def\documentdescription{\doignore{documentdescription}}
\def\docbook{\doignore{docbook}}
\def\html{\doignore{html}}
\def\ifdocbook{\doignore{ifdocbook}}
\def\ifhtml{\doignore{ifhtml}}
\def\ifinfo{\doignore{ifinfo}}
\def\ifnottex{\doignore{ifnottex}}
\def\ifplaintext{\doignore{ifplaintext}}
\def\ifxml{\doignore{ifxml}}
\def\ignore{\doignore{ignore}}
\def\menu{\doignore{menu}}
\def\xml{\doignore{xml}}
% Ignore text until a line `@end #1', keeping track of nested conditionals.
%
% A count to remember the depth of nesting.
\newcount\doignorecount
\def\doignore#1{\begingroup
% Scan in ``verbatim'' mode:
\obeylines
\catcode`\@ = \other
\catcode`\{ = \other
\catcode`\} = \other
%
% Make sure that spaces turn into tokens that match what \doignoretext wants.
\spaceisspace
%
% Count number of #1's that we've seen.
\doignorecount = 0
%
% Swallow text until we reach the matching `@end #1'.
\dodoignore{#1}%
}
{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
\obeylines %
%
\gdef\dodoignore#1{%
% #1 contains the command name as a string, e.g., `ifinfo'.
%
% Define a command to find the next `@end #1'.
\long\def\doignoretext##1^^M@end #1{%
\doignoretextyyy##1^^M@#1\_STOP_}%
%
% And this command to find another #1 command, at the beginning of a
% line. (Otherwise, we would consider a line `@c @ifset', for
% example, to count as an @ifset for nesting.)
\long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
%
% And now expand that command.
\doignoretext ^^M%
}%
}
\def\doignoreyyy#1{%
\def\temp{#1}%
\ifx\temp\empty % Nothing found.
\let\next\doignoretextzzz
\else % Found a nested condition, ...
\advance\doignorecount by 1
\let\next\doignoretextyyy % ..., look for another.
% If we're here, #1 ends with ^^M\ifinfo (for example).
\fi
\next #1% the token \_STOP_ is present just after this macro.
}
% We have to swallow the remaining "\_STOP_".
%
\def\doignoretextzzz#1{%
\ifnum\doignorecount = 0 % We have just found the outermost @end.
\let\next\enddoignore
\else % Still inside a nested condition.
\advance\doignorecount by -1
\let\next\doignoretext % Look for the next @end.
\fi
\next
}
% Finish off ignored text.
{ \obeylines%
% Ignore anything after the last `@end #1'; this matters in verbatim
% environments, where otherwise the newline after an ignored conditional
% would result in a blank line in the output.
\gdef\enddoignore#1^^M{\endgroup\ignorespaces}%
}
% @set VAR sets the variable VAR to an empty value.
% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
%
% Since we want to separate VAR from REST-OF-LINE (which might be
% empty), we can't just use \parsearg; we have to insert a space of our
% own to delimit the rest of the line, and then take it out again if we
% didn't need it.
% We rely on the fact that \parsearg sets \catcode`\ =10.
%
\parseargdef\set{\setyyy#1 \endsetyyy}
\def\setyyy#1 #2\endsetyyy{%
{%
\makevalueexpandable
\def\temp{#2}%
\edef\next{\gdef\makecsname{SET#1}}%
\ifx\temp\empty
\next{}%
\else
\setzzz#2\endsetzzz
\fi
}%
}
% Remove the trailing space \setxxx inserted.
\def\setzzz#1 \endsetzzz{\next{#1}}
% @clear VAR clears (i.e., unsets) the variable VAR.
%
\parseargdef\clear{%
{%
\makevalueexpandable
\global\expandafter\let\csname SET#1\endcsname=\relax
}%
}
% @value{foo} gets the text saved in variable foo.
\def\value{\begingroup\makevalueexpandable\valuexxx}
\def\valuexxx#1{\expandablevalue{#1}\endgroup}
{
\catcode`\- = \active \catcode`\_ = \active
%
\gdef\makevalueexpandable{%
\let\value = \expandablevalue
% We don't want these characters active, ...
\catcode`\-=\other \catcode`\_=\other
% ..., but we might end up with active ones in the argument if
% we're called from @code, as @code{@value{foo-bar_}}, though.
% So \let them to their normal equivalents.
\let-\realdash \let_\normalunderscore
}
}
% We have this subroutine so that we can handle at least some @value's
% properly in indexes (we call \makevalueexpandable in \indexdummies).
% The command has to be fully expandable (if the variable is set), since
% the result winds up in the index file. This means that if the
% variable's value contains other Texinfo commands, it's almost certain
% it will fail (although perhaps we could fix that with sufficient work
% to do a one-level expansion on the result, instead of complete).
%
\def\expandablevalue#1{%
\expandafter\ifx\csname SET#1\endcsname\relax
{[No value for ``#1'']}%
\message{Variable `#1', used in @value, is not set.}%
\else
\csname SET#1\endcsname
\fi
}
% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
% with @set.
%
% To get special treatment of `@end ifset,' call \makeond and the redefine.
%
\makecond{ifset}
\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
\def\doifset#1#2{%
{%
\makevalueexpandable
\let\next=\empty
\expandafter\ifx\csname SET#2\endcsname\relax
#1% If not set, redefine \next.
\fi
\expandafter
}\next
}
\def\ifsetfail{\doignore{ifset}}
% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
% defined with @set, or has been undefined with @clear.
%
% The `\else' inside the `\doifset' parameter is a trick to reuse the
% above code: if the variable is not set, do nothing, if it is set,
% then redefine \next to \ifclearfail.
%
\makecond{ifclear}
\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
\def\ifclearfail{\doignore{ifclear}}
% @dircategory CATEGORY -- specify a category of the dir file
% which this file should belong to. Ignore this in TeX.
\let\dircategory=\comment
% @defininfoenclose.
\let\definfoenclose=\comment
\message{indexing,}
% Index generation facilities
% Define \newwrite to be identical to plain tex's \newwrite
% except not \outer, so it can be used within macros and \if's.
\edef\newwrite{\makecsname{ptexnewwrite}}
% \newindex {foo} defines an index named foo.
% It automatically defines \fooindex such that
% \fooindex ...rest of line... puts an entry in the index foo.
% It also defines \fooindfile to be the number of the output channel for
% the file that accumulates this index. The file's extension is foo.
% The name of an index should be no more than 2 characters long
% for the sake of vms.
%
\def\newindex#1{%
\iflinks
\expandafter\newwrite \csname#1indfile\endcsname
\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
\fi
\expandafter\xdef\csname#1index\endcsname{% % Define @#1index
\noexpand\doindex{#1}}
}
% @defindex foo == \newindex{foo}
%
\def\defindex{\parsearg\newindex}
% Define @defcodeindex, like @defindex except put all entries in @code.
%
\def\defcodeindex{\parsearg\newcodeindex}
%
\def\newcodeindex#1{%
\iflinks
\expandafter\newwrite \csname#1indfile\endcsname
\openout \csname#1indfile\endcsname \jobname.#1
\fi
\expandafter\xdef\csname#1index\endcsname{%
\noexpand\docodeindex{#1}}%
}
% @synindex foo bar makes index foo feed into index bar.
% Do this instead of @defindex foo if you don't want it as a separate index.
%
% @syncodeindex foo bar similar, but put all entries made for index foo
% inside @code.
%
\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
% #3 the target index (bar).
\def\dosynindex#1#2#3{%
% Only do \closeout if we haven't already done it, else we'll end up
% closing the target index.
\expandafter \ifx\csname donesynindex#2\endcsname \undefined
% The \closeout helps reduce unnecessary open files; the limit on the
% Acorn RISC OS is a mere 16 files.
\expandafter\closeout\csname#2indfile\endcsname
\expandafter\let\csname\donesynindex#2\endcsname = 1
\fi
% redefine \fooindfile:
\expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
\expandafter\let\csname#2indfile\endcsname=\temp
% redefine \fooindex:
\expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
}
% Define \doindex, the driver for all \fooindex macros.
% Argument #1 is generated by the calling \fooindex macro,
% and it is "foo", the name of the index.
% \doindex just uses \parsearg; it calls \doind for the actual work.
% This is because \doind is more useful to call from other macros.
% There is also \dosubind {index}{topic}{subtopic}
% which makes an entry in a two-level index such as the operation index.
\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
\def\singleindexer #1{\doind{\indexname}{#1}}
% like the previous two, but they put @code around the argument.
\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
% Take care of Texinfo commands that can appear in an index entry.
% Since there are some commands we want to expand, and others we don't,
% we have to laboriously prevent expansion for those that we don't.
%
\def\indexdummies{%
\escapechar = `\\ % use backslash in output files.
\def\@{@}% change to @@ when we switch to @ as escape char in index files.
\def\ {\realbackslash\space }%
%
% Need these in case \tex is in effect and \{ is a \delimiter again.
% But can't use \lbracecmd and \rbracecmd because texindex assumes
% braces and backslashes are used only as delimiters.
\let\{ = \mylbrace
\let\} = \myrbrace
%
% I don't entirely understand this, but when an index entry is
% generated from a macro call, the \endinput which \scanmacro inserts
% causes processing to be prematurely terminated. This is,
% apparently, because \indexsorttmp is fully expanded, and \endinput
% is an expandable command. The redefinition below makes \endinput
% disappear altogether for that purpose -- although logging shows that
% processing continues to some further point. On the other hand, it
% seems \endinput does not hurt in the printed index arg, since that
% is still getting written without apparent harm.
%
% Sample source (mac-idx3.tex, reported by Graham Percival to
% help-texinfo, 22may06):
% @macro funindex {WORD}
% @findex xyz
% @end macro
% ...
% @funindex commtest
%
% The above is not enough to reproduce the bug, but it gives the flavor.
%
% Sample whatsit resulting:
% .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}}
%
% So:
\let\endinput = \empty
%
% Do the redefinitions.
\commondummies
}
% For the aux and toc files, @ is the escape character. So we want to
% redefine everything using @ as the escape character (instead of
% \realbackslash, still used for index files). When everything uses @,
% this will be simpler.
%
\def\atdummies{%
\def\@{@@}%
\def\ {@ }%
\let\{ = \lbraceatcmd
\let\} = \rbraceatcmd
%
% Do the redefinitions.
\commondummies
\otherbackslash
}
% Called from \indexdummies and \atdummies.
%
\def\commondummies{%
%
% \definedummyword defines \#1 as \string\#1\space, thus effectively
% preventing its expansion. This is used only for control% words,
% not control letters, because the \space would be incorrect for
% control characters, but is needed to separate the control word
% from whatever follows.
%
% For control letters, we have \definedummyletter, which omits the
% space.
%
% These can be used both for control words that take an argument and
% those that do not. If it is followed by {arg} in the input, then
% that will dutifully get written to the index (or wherever).
%
\def\definedummyword ##1{\def##1{\string##1\space}}%
\def\definedummyletter##1{\def##1{\string##1}}%
\let\definedummyaccent\definedummyletter
%
\commondummiesnofonts
%
\definedummyletter\_%
%
% Non-English letters.
\definedummyword\AA
\definedummyword\AE
\definedummyword\L
\definedummyword\OE
\definedummyword\O
\definedummyword\aa
\definedummyword\ae
\definedummyword\l
\definedummyword\oe
\definedummyword\o
\definedummyword\ss
\definedummyword\exclamdown
\definedummyword\questiondown
\definedummyword\ordf
\definedummyword\ordm
%
% Although these internal commands shouldn't show up, sometimes they do.
\definedummyword\bf
\definedummyword\gtr
\definedummyword\hat
\definedummyword\less
\definedummyword\sf
\definedummyword\sl
\definedummyword\tclose
\definedummyword\tt
%
\definedummyword\LaTeX
\definedummyword\TeX
%
% Assorted special characters.
\definedummyword\bullet
\definedummyword\comma
\definedummyword\copyright
\definedummyword\registeredsymbol
\definedummyword\dots
\definedummyword\enddots
\definedummyword\equiv
\definedummyword\error
\definedummyword\euro
\definedummyword\expansion
\definedummyword\minus
\definedummyword\pounds
\definedummyword\point
\definedummyword\print
\definedummyword\result
\definedummyword\textdegree
%
% We want to disable all macros so that they are not expanded by \write.
\macrolist
%
\normalturnoffactive
%
% Handle some cases of @value -- where it does not contain any
% (non-fully-expandable) commands.
\makevalueexpandable
}
% \commondummiesnofonts: common to \commondummies and \indexnofonts.
%
\def\commondummiesnofonts{%
% Control letters and accents.
\definedummyletter\!%
\definedummyaccent\"%
\definedummyaccent\'%
\definedummyletter\*%
\definedummyaccent\,%
\definedummyletter\.%
\definedummyletter\/%
\definedummyletter\:%
\definedummyaccent\=%
\definedummyletter\?%
\definedummyaccent\^%
\definedummyaccent\`%
\definedummyaccent\~%
\definedummyword\u
\definedummyword\v
\definedummyword\H
\definedummyword\dotaccent
\definedummyword\ringaccent
\definedummyword\tieaccent
\definedummyword\ubaraccent
\definedummyword\udotaccent
\definedummyword\dotless
%
% Texinfo font commands.
\definedummyword\b
\definedummyword\i
\definedummyword\r
\definedummyword\sc
\definedummyword\t
%
% Commands that take arguments.
\definedummyword\acronym
\definedummyword\cite
\definedummyword\code
\definedummyword\command
\definedummyword\dfn
\definedummyword\emph
\definedummyword\env
\definedummyword\file
\definedummyword\kbd
\definedummyword\key
\definedummyword\math
\definedummyword\option
\definedummyword\pxref
\definedummyword\ref
\definedummyword\samp
\definedummyword\strong
\definedummyword\tie
\definedummyword\uref
\definedummyword\url
\definedummyword\var
\definedummyword\verb
\definedummyword\w
\definedummyword\xref
}
% \indexnofonts is used when outputting the strings to sort the index
% by, and when constructing control sequence names. It eliminates all
% control sequences and just writes whatever the best ASCII sort string
% would be for a given command (usually its argument).
%
\def\indexnofonts{%
% Accent commands should become @asis.
\def\definedummyaccent##1{\let##1\asis}%
% We can just ignore other control letters.
\def\definedummyletter##1{\let##1\empty}%
% Hopefully, all control words can become @asis.
\let\definedummyword\definedummyaccent
%
\commondummiesnofonts
%
% Don't no-op \tt, since it isn't a user-level command
% and is used in the definitions of the active chars like <, >, |, etc.
% Likewise with the other plain tex font commands.
%\let\tt=\asis
%
\def\ { }%
\def\@{@}%
% how to handle braces?
\def\_{\normalunderscore}%
%
% Non-English letters.
\def\AA{AA}%
\def\AE{AE}%
\def\L{L}%
\def\OE{OE}%
\def\O{O}%
\def\aa{aa}%
\def\ae{ae}%
\def\l{l}%
\def\oe{oe}%
\def\o{o}%
\def\ss{ss}%
\def\exclamdown{!}%
\def\questiondown{?}%
\def\ordf{a}%
\def\ordm{o}%
%
\def\LaTeX{LaTeX}%
\def\TeX{TeX}%
%
% Assorted special characters.
% (The following {} will end up in the sort string, but that's ok.)
\def\bullet{bullet}%
\def\comma{,}%
\def\copyright{copyright}%
\def\registeredsymbol{R}%
\def\dots{...}%
\def\enddots{...}%
\def\equiv{==}%
\def\error{error}%
\def\euro{euro}%
\def\expansion{==>}%
\def\minus{-}%
\def\pounds{pounds}%
\def\point{.}%
\def\print{-|}%
\def\result{=>}%
\def\textdegree{degrees}%
%
% We need to get rid of all macros, leaving only the arguments (if present).
% Of course this is not nearly correct, but it is the best we can do for now.
% makeinfo does not expand macros in the argument to @deffn, which ends up
% writing an index entry, and texindex isn't prepared for an index sort entry
% that starts with \.
%
% Since macro invocations are followed by braces, we can just redefine them
% to take a single TeX argument. The case of a macro invocation that
% goes to end-of-line is not handled.
%
\macrolist
}
\let\indexbackslash=0 %overridden during \printindex.
\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
% Most index entries go through here, but \dosubind is the general case.
% #1 is the index name, #2 is the entry text.
\def\doind#1#2{\dosubind{#1}{#2}{}}
% Workhorse for all \fooindexes.
% #1 is name of index, #2 is stuff to put there, #3 is subentry --
% empty if called from \doind, as we usually are (the main exception
% is with most defuns, which call us directly).
%
\def\dosubind#1#2#3{%
\iflinks
{%
% Store the main index entry text (including the third arg).
\toks0 = {#2}%
% If third arg is present, precede it with a space.
\def\thirdarg{#3}%
\ifx\thirdarg\empty \else
\toks0 = \expandafter{\the\toks0 \space #3}%
\fi
%
\edef\writeto{\csname#1indfile\endcsname}%
%
\safewhatsit\dosubindwrite
}%
\fi
}
% Write the entry in \toks0 to the index file:
%
\def\dosubindwrite{%
% Put the index entry in the margin if desired.
\ifx\SETmarginindex\relax\else
\insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
\fi
%
% Remember, we are within a group.
\indexdummies % Must do this here, since \bf, etc expand at this stage
\def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now
% so it will be output as is; and it will print as backslash.
%
% Process the index entry with all font commands turned off, to
% get the string to sort by.
{\indexnofonts
\edef\temp{\the\toks0}% need full expansion
\xdef\indexsorttmp{\temp}%
}%
%
% Set up the complete index entry, with both the sort key and
% the original text, including any font commands. We write
% three arguments to \entry to the .?? file (four in the
% subentry case), texindex reduces to two when writing the .??s
% sorted result.
\edef\temp{%
\write\writeto{%
\string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
}%
\temp
}
% Take care of unwanted page breaks/skips around a whatsit:
%
% If a skip is the last thing on the list now, preserve it
% by backing up by \lastskip, doing the \write, then inserting
% the skip again. Otherwise, the whatsit generated by the
% \write or \pdfdest will make \lastskip zero. The result is that
% sequences like this:
% @end defun
% @tindex whatever
% @defun ...
% will have extra space inserted, because the \medbreak in the
% start of the @defun won't see the skip inserted by the @end of
% the previous defun.
%
% But don't do any of this if we're not in vertical mode. We
% don't want to do a \vskip and prematurely end a paragraph.
%
% Avoid page breaks due to these extra skips, too.
%
% But wait, there is a catch there:
% We'll have to check whether \lastskip is zero skip. \ifdim is not
% sufficient for this purpose, as it ignores stretch and shrink parts
% of the skip. The only way seems to be to check the textual
% representation of the skip.
%
% The following is almost like \def\zeroskipmacro{0.0pt} except that
% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
%
\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
%
\newskip\whatsitskip
\newcount\whatsitpenalty
%
% ..., ready, GO:
%
\def\safewhatsit#1{%
\ifhmode
#1%
\else
% \lastskip and \lastpenalty cannot both be nonzero simultaneously.
\whatsitskip = \lastskip
\edef\lastskipmacro{\the\lastskip}%
\whatsitpenalty = \lastpenalty
%
% If \lastskip is nonzero, that means the last item was a
% skip. And since a skip is discardable, that means this
% -\skip0 glue we're inserting is preceded by a
% non-discardable item, therefore it is not a potential
% breakpoint, therefore no \nobreak needed.
\ifx\lastskipmacro\zeroskipmacro
\else
\vskip-\whatsitskip
\fi
%
#1%
%
\ifx\lastskipmacro\zeroskipmacro
% If \lastskip was zero, perhaps the last item was a penalty, and
% perhaps it was >=10000, e.g., a \nobreak. In that case, we want
% to re-insert the same penalty (values >10000 are used for various
% signals); since we just inserted a non-discardable item, any
% following glue (such as a \parskip) would be a breakpoint. For example:
%
% @deffn deffn-whatever
% @vindex index-whatever
% Description.
% would allow a break between the index-whatever whatsit
% and the "Description." paragraph.
\ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi
\else
% On the other hand, if we had a nonzero \lastskip,
% this make-up glue would be preceded by a non-discardable item
% (the whatsit from the \write), so we must insert a \nobreak.
\nobreak\vskip\whatsitskip
\fi
\fi
}
% The index entry written in the file actually looks like
% \entry {sortstring}{page}{topic}
% or
% \entry {sortstring}{page}{topic}{subtopic}
% The texindex program reads in these files and writes files
% containing these kinds of lines:
% \initial {c}
% before the first topic whose initial is c
% \entry {topic}{pagelist}
% for a topic that is used without subtopics
% \primary {topic}
% for the beginning of a topic that is used with subtopics
% \secondary {subtopic}{pagelist}
% for each subtopic.
% Define the user-accessible indexing commands
% @findex, @vindex, @kindex, @cindex.
\def\findex {\fnindex}
\def\kindex {\kyindex}
\def\cindex {\cpindex}
\def\vindex {\vrindex}
\def\tindex {\tpindex}
\def\pindex {\pgindex}
\def\cindexsub {\begingroup\obeylines\cindexsub}
{\obeylines %
\gdef\cindexsub "#1" #2^^M{\endgroup %
\dosubind{cp}{#2}{#1}}}
% Define the macros used in formatting output of the sorted index material.
% @printindex causes a particular index (the ??s file) to get printed.
% It does not print any chapter heading (usually an @unnumbered).
%
\parseargdef\printindex{\begingroup
\dobreak \chapheadingskip{10000}%
%
\smallfonts \rm
\tolerance = 9500
\plainfrenchspacing
\everypar = {}% don't want the \kern\-parindent from indentation suppression.
%
% See if the index file exists and is nonempty.
% Change catcode of @ here so that if the index file contains
% \initial {@}
% as its first line, TeX doesn't complain about mismatched braces
% (because it thinks @} is a control sequence).
\catcode`\@ = 11
\openin 1 \jobname.#1s
\ifeof 1
% \enddoublecolumns gets confused if there is no text in the index,
% and it loses the chapter title and the aux file entries for the
% index. The easiest way to prevent this problem is to make sure
% there is some text.
\putwordIndexNonexistent
\else
%
% If the index file exists but is empty, then \openin leaves \ifeof
% false. We have to make TeX try to read something from the file, so
% it can discover if there is anything in it.
\read 1 to \temp
\ifeof 1
\putwordIndexIsEmpty
\else
% Index files are almost Texinfo source, but we use \ as the escape
% character. It would be better to use @, but that's too big a change
% to make right now.
\def\indexbackslash{\backslashcurfont}%
\catcode`\\ = 0
\escapechar = `\\
\begindoublecolumns
\input \jobname.#1s
\enddoublecolumns
\fi
\fi
\closein 1
\endgroup}
% These macros are used by the sorted index file itself.
% Change them to control the appearance of the index.
\def\initial#1{{%
% Some minor font changes for the special characters.
\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
%
% Remove any glue we may have, we'll be inserting our own.
\removelastskip
%
% We like breaks before the index initials, so insert a bonus.
\nobreak
\vskip 0pt plus 3\baselineskip
\penalty 0
\vskip 0pt plus -3\baselineskip
%
% Typeset the initial. Making this add up to a whole number of
% baselineskips increases the chance of the dots lining up from column
% to column. It still won't often be perfect, because of the stretch
% we need before each entry, but it's better.
%
% No shrink because it confuses \balancecolumns.
\vskip 1.67\baselineskip plus .5\baselineskip
\leftline{\secbf #1}%
% Do our best not to break after the initial.
\nobreak
\vskip .33\baselineskip plus .1\baselineskip
}}
% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
% then page number (#2) flushed to the right margin. It is used for index
% and table of contents entries. The paragraph is indented by \leftskip.
%
% A straightforward implementation would start like this:
% \def\entry#1#2{...
% But this frozes the catcodes in the argument, and can cause problems to
% @code, which sets - active. This problem was fixed by a kludge---
% ``-'' was active throughout whole index, but this isn't really right.
%
% The right solution is to prevent \entry from swallowing the whole text.
% --kasal, 21nov03
\def\entry{%
\begingroup
%
% Start a new paragraph if necessary, so our assignments below can't
% affect previous text.
\par
%
% Do not fill out the last line with white space.
\parfillskip = 0in
%
% No extra space above this paragraph.
\parskip = 0in
%
% Do not prefer a separate line ending with a hyphen to fewer lines.
\finalhyphendemerits = 0
%
% \hangindent is only relevant when the entry text and page number
% don't both fit on one line. In that case, bob suggests starting the
% dots pretty far over on the line. Unfortunately, a large
% indentation looks wrong when the entry text itself is broken across
% lines. So we use a small indentation and put up with long leaders.
%
% \hangafter is reset to 1 (which is the value we want) at the start
% of each paragraph, so we need not do anything with that.
\hangindent = 2em
%
% When the entry text needs to be broken, just fill out the first line
% with blank space.
\rightskip = 0pt plus1fil
%
% A bit of stretch before each entry for the benefit of balancing
% columns.
\vskip 0pt plus1pt
%
% Swallow the left brace of the text (first parameter):
\afterassignment\doentry
\let\temp =
}
\def\doentry{%
\bgroup % Instead of the swallowed brace.
\noindent
\aftergroup\finishentry
% And now comes the text of the entry.
}
\def\finishentry#1{%
% #1 is the page number.
%
% The following is kludged to not output a line of dots in the index if
% there are no page numbers. The next person who breaks this will be
% cursed by a Unix daemon.
\def\tempa{{\rm }}%
\def\tempb{#1}%
\edef\tempc{\tempa}%
\edef\tempd{\tempb}%
\ifx\tempc\tempd
\ %
\else
%
% If we must, put the page number on a line of its own, and fill out
% this line with blank space. (The \hfil is overwhelmed with the
% fill leaders glue in \indexdotfill if the page number does fit.)
\hfil\penalty50
\null\nobreak\indexdotfill % Have leaders before the page number.
%
% The `\ ' here is removed by the implicit \unskip that TeX does as
% part of (the primitive) \par. Without it, a spurious underfull
% \hbox ensues.
\ifpdf
\pdfgettoks#1.%
\ \the\toksA
\else
\ #1%
\fi
\fi
\par
\endgroup
}
% Like plain.tex's \dotfill, except uses up at least 1 em.
\def\indexdotfill{\cleaders
\hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill}
\def\primary #1{\line{#1\hfil}}
\newskip\secondaryindent \secondaryindent=0.5cm
\def\secondary#1#2{{%
\parfillskip=0in
\parskip=0in
\hangindent=1in
\hangafter=1
\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
\ifpdf
\pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
\else
#2
\fi
\par
}}
% Define two-column mode, which we use to typeset indexes.
% Adapted from the TeXbook, page 416, which is to say,
% the manmac.tex format used to print the TeXbook itself.
\catcode`\@=11
\newbox\partialpage
\newdimen\doublecolumnhsize
\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
% Grab any single-column material above us.
\output = {%
%
% Here is a possibility not foreseen in manmac: if we accumulate a
% whole lot of material, we might end up calling this \output
% routine twice in a row (see the doublecol-lose test, which is
% essentially a couple of indexes with @setchapternewpage off). In
% that case we just ship out what is in \partialpage with the normal
% output routine. Generally, \partialpage will be empty when this
% runs and this will be a no-op. See the indexspread.tex test case.
\ifvoid\partialpage \else
\onepageout{\pagecontents\partialpage}%
\fi
%
\global\setbox\partialpage = \vbox{%
% Unvbox the main output page.
\unvbox\PAGE
\kern-\topskip \kern\baselineskip
}%
}%
\eject % run that output routine to set \partialpage
%
% Use the double-column output routine for subsequent pages.
\output = {\doublecolumnout}%
%
% Change the page size parameters. We could do this once outside this
% routine, in each of @smallbook, @afourpaper, and the default 8.5x11
% format, but then we repeat the same computation. Repeating a couple
% of assignments once per index is clearly meaningless for the
% execution time, so we may as well do it in one place.
%
% First we halve the line length, less a little for the gutter between
% the columns. We compute the gutter based on the line length, so it
% changes automatically with the paper format. The magic constant
% below is chosen so that the gutter has the same value (well, +-<1pt)
% as it did when we hard-coded it.
%
% We put the result in a separate register, \doublecolumhsize, so we
% can restore it in \pagesofar, after \hsize itself has (potentially)
% been clobbered.
%
\doublecolumnhsize = \hsize
\advance\doublecolumnhsize by -.04154\hsize
\divide\doublecolumnhsize by 2
\hsize = \doublecolumnhsize
%
% Double the \vsize as well. (We don't need a separate register here,
% since nobody clobbers \vsize.)
\vsize = 2\vsize
}
% The double-column output routine for all double-column pages except
% the last.
%
\def\doublecolumnout{%
\splittopskip=\topskip \splitmaxdepth=\maxdepth
% Get the available space for the double columns -- the normal
% (undoubled) page height minus any material left over from the
% previous page.
\dimen@ = \vsize
\divide\dimen@ by 2
\advance\dimen@ by -\ht\partialpage
%
% box0 will be the left-hand column, box2 the right.
\setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
\onepageout\pagesofar
\unvbox255
\penalty\outputpenalty
}
%
% Re-output the contents of the output page -- any previous material,
% followed by the two boxes we just split, in box0 and box2.
\def\pagesofar{%
\unvbox\partialpage
%
\hsize = \doublecolumnhsize
\wd0=\hsize \wd2=\hsize
\hbox to\pagewidth{\box0\hfil\box2}%
}
%
% All done with double columns.
\def\enddoublecolumns{%
% The following penalty ensures that the page builder is exercised
% _before_ we change the output routine. This is necessary in the
% following situation:
%
% The last section of the index consists only of a single entry.
% Before this section, \pagetotal is less than \pagegoal, so no
% break occurs before the last section starts. However, the last
% section, consisting of \initial and the single \entry, does not
% fit on the page and has to be broken off. Without the following
% penalty the page builder will not be exercised until \eject
% below, and by that time we'll already have changed the output
% routine to the \balancecolumns version, so the next-to-last
% double-column page will be processed with \balancecolumns, which
% is wrong: The two columns will go to the main vertical list, with
% the broken-off section in the recent contributions. As soon as
% the output routine finishes, TeX starts reconsidering the page
% break. The two columns and the broken-off section both fit on the
% page, because the two columns now take up only half of the page
% goal. When TeX sees \eject from below which follows the final
% section, it invokes the new output routine that we've set after
% \balancecolumns below; \onepageout will try to fit the two columns
% and the final section into the vbox of \pageheight (see
% \pagebody), causing an overfull box.
%
% Note that glue won't work here, because glue does not exercise the
% page builder, unlike penalties (see The TeXbook, pp. 280-281).
\penalty0
%
\output = {%
% Split the last of the double-column material. Leave it on the
% current page, no automatic page break.
\balancecolumns
%
% If we end up splitting too much material for the current page,
% though, there will be another page break right after this \output
% invocation ends. Having called \balancecolumns once, we do not
% want to call it again. Therefore, reset \output to its normal
% definition right away. (We hope \balancecolumns will never be
% called on to balance too much material, but if it is, this makes
% the output somewhat more palatable.)
\global\output = {\onepageout{\pagecontents\PAGE}}%
}%
\eject
\endgroup % started in \begindoublecolumns
%
% \pagegoal was set to the doubled \vsize above, since we restarted
% the current page. We're now back to normal single-column
% typesetting, so reset \pagegoal to the normal \vsize (after the
% \endgroup where \vsize got restored).
\pagegoal = \vsize
}
%
% Called at the end of the double column material.
\def\balancecolumns{%
\setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
\dimen@ = \ht0
\advance\dimen@ by \topskip
\advance\dimen@ by-\baselineskip
\divide\dimen@ by 2 % target to split to
%debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
\splittopskip = \topskip
% Loop until we get a decent breakpoint.
{%
\vbadness = 10000
\loop
\global\setbox3 = \copy0
\global\setbox1 = \vsplit3 to \dimen@
\ifdim\ht3>\dimen@
\global\advance\dimen@ by 1pt
\repeat
}%
%debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
\setbox0=\vbox to\dimen@{\unvbox1}%
\setbox2=\vbox to\dimen@{\unvbox3}%
%
\pagesofar
}
\catcode`\@ = \other
\message{sectioning,}
% Chapters, sections, etc.
% \unnumberedno is an oxymoron, of course. But we count the unnumbered
% sections so that we can refer to them unambiguously in the pdf
% outlines by their "section number". We avoid collisions with chapter
% numbers by starting them at 10000. (If a document ever has 10000
% chapters, we're in trouble anyway, I'm sure.)
\newcount\unnumberedno \unnumberedno = 10000
\newcount\chapno
\newcount\secno \secno=0
\newcount\subsecno \subsecno=0
\newcount\subsubsecno \subsubsecno=0
% This counter is funny since it counts through charcodes of letters A, B, ...
\newcount\appendixno \appendixno = `\@
%
% \def\appendixletter{\char\the\appendixno}
% We do the following ugly conditional instead of the above simple
% construct for the sake of pdftex, which needs the actual
% letter in the expansion, not just typeset.
%
\def\appendixletter{%
\ifnum\appendixno=`A A%
\else\ifnum\appendixno=`B B%
\else\ifnum\appendixno=`C C%
\else\ifnum\appendixno=`D D%
\else\ifnum\appendixno=`E E%
\else\ifnum\appendixno=`F F%
\else\ifnum\appendixno=`G G%
\else\ifnum\appendixno=`H H%
\else\ifnum\appendixno=`I I%
\else\ifnum\appendixno=`J J%
\else\ifnum\appendixno=`K K%
\else\ifnum\appendixno=`L L%
\else\ifnum\appendixno=`M M%
\else\ifnum\appendixno=`N N%
\else\ifnum\appendixno=`O O%
\else\ifnum\appendixno=`P P%
\else\ifnum\appendixno=`Q Q%
\else\ifnum\appendixno=`R R%
\else\ifnum\appendixno=`S S%
\else\ifnum\appendixno=`T T%
\else\ifnum\appendixno=`U U%
\else\ifnum\appendixno=`V V%
\else\ifnum\appendixno=`W W%
\else\ifnum\appendixno=`X X%
\else\ifnum\appendixno=`Y Y%
\else\ifnum\appendixno=`Z Z%
% The \the is necessary, despite appearances, because \appendixletter is
% expanded while writing the .toc file. \char\appendixno is not
% expandable, thus it is written literally, thus all appendixes come out
% with the same letter (or @) in the toc without it.
\else\char\the\appendixno
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
% Each @chapter defines this as the name of the chapter.
% page headings and footings can use it. @section does likewise.
% However, they are not reliable, because we don't use marks.
\def\thischapter{}
\def\thissection{}
\newcount\absseclevel % used to calculate proper heading level
\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
% @raisesections: treat @section as chapter, @subsection as section, etc.
\def\raisesections{\global\advance\secbase by -1}
\let\up=\raisesections % original BFox name
% @lowersections: treat @chapter as section, @section as subsection, etc.
\def\lowersections{\global\advance\secbase by 1}
\let\down=\lowersections % original BFox name
% we only have subsub.
\chardef\maxseclevel = 3
%
% A numbered section within an unnumbered changes to unnumbered too.
% To achive this, remember the "biggest" unnum. sec. we are currently in:
\chardef\unmlevel = \maxseclevel
%
% Trace whether the current chapter is an appendix or not:
% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
\def\chapheadtype{N}
% Choose a heading macro
% #1 is heading type
% #2 is heading level
% #3 is text for heading
\def\genhead#1#2#3{%
% Compute the abs. sec. level:
\absseclevel=#2
\advance\absseclevel by \secbase
% Make sure \absseclevel doesn't fall outside the range:
\ifnum \absseclevel < 0
\absseclevel = 0
\else
\ifnum \absseclevel > 3
\absseclevel = 3
\fi
\fi
% The heading type:
\def\headtype{#1}%
\if \headtype U%
\ifnum \absseclevel < \unmlevel
\chardef\unmlevel = \absseclevel
\fi
\else
% Check for appendix sections:
\ifnum \absseclevel = 0
\edef\chapheadtype{\headtype}%
\else
\if \headtype A\if \chapheadtype N%
\errmessage{@appendix... within a non-appendix chapter}%
\fi\fi
\fi
% Check for numbered within unnumbered:
\ifnum \absseclevel > \unmlevel
\def\headtype{U}%
\else
\chardef\unmlevel = 3
\fi
\fi
% Now print the heading:
\if \headtype U%
\ifcase\absseclevel
\unnumberedzzz{#3}%
\or \unnumberedseczzz{#3}%
\or \unnumberedsubseczzz{#3}%
\or \unnumberedsubsubseczzz{#3}%
\fi
\else
\if \headtype A%
\ifcase\absseclevel
\appendixzzz{#3}%
\or \appendixsectionzzz{#3}%
\or \appendixsubseczzz{#3}%
\or \appendixsubsubseczzz{#3}%
\fi
\else
\ifcase\absseclevel
\chapterzzz{#3}%
\or \seczzz{#3}%
\or \numberedsubseczzz{#3}%
\or \numberedsubsubseczzz{#3}%
\fi
\fi
\fi
\suppressfirstparagraphindent
}
% an interface:
\def\numhead{\genhead N}
\def\apphead{\genhead A}
\def\unnmhead{\genhead U}
% @chapter, @appendix, @unnumbered. Increment top-level counter, reset
% all lower-level sectioning counters to zero.
%
% Also set \chaplevelprefix, which we prepend to @float sequence numbers
% (e.g., figures), q.v. By default (before any chapter), that is empty.
\let\chaplevelprefix = \empty
%
\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
\def\chapterzzz#1{%
% section resetting is \global in case the chapter is in a group, such
% as an @include file.
\global\secno=0 \global\subsecno=0 \global\subsubsecno=0
\global\advance\chapno by 1
%
% Used for \float.
\gdef\chaplevelprefix{\the\chapno.}%
\resetallfloatnos
%
\message{\putwordChapter\space \the\chapno}%
%
% Write the actual heading.
\chapmacro{#1}{Ynumbered}{\the\chapno}%
%
% So @section and the like are numbered underneath this chapter.
\global\let\section = \numberedsec
\global\let\subsection = \numberedsubsec
\global\let\subsubsection = \numberedsubsubsec
}
\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
\def\appendixzzz#1{%
\global\secno=0 \global\subsecno=0 \global\subsubsecno=0
\global\advance\appendixno by 1
\gdef\chaplevelprefix{\appendixletter.}%
\resetallfloatnos
%
\def\appendixnum{\putwordAppendix\space \appendixletter}%
\message{\appendixnum}%
%
\chapmacro{#1}{Yappendix}{\appendixletter}%
%
\global\let\section = \appendixsec
\global\let\subsection = \appendixsubsec
\global\let\subsubsection = \appendixsubsubsec
}
\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
\def\unnumberedzzz#1{%
\global\secno=0 \global\subsecno=0 \global\subsubsecno=0
\global\advance\unnumberedno by 1
%
% Since an unnumbered has no number, no prefix for figures.
\global\let\chaplevelprefix = \empty
\resetallfloatnos
%
% This used to be simply \message{#1}, but TeX fully expands the
% argument to \message. Therefore, if #1 contained @-commands, TeX
% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
% expanded @cite (which turns out to cause errors because \cite is meant
% to be executed, not expanded).
%
% Anyway, we don't want the fully-expanded definition of @cite to appear
% as a result of the \message, we just want `@cite' itself. We use
% \the<toks register> to achieve this: TeX expands \the<toks> only once,
% simply yielding the contents of <toks register>. (We also do this for
% the toc entries.)
\toks0 = {#1}%
\message{(\the\toks0)}%
%
\chapmacro{#1}{Ynothing}{\the\unnumberedno}%
%
\global\let\section = \unnumberedsec
\global\let\subsection = \unnumberedsubsec
\global\let\subsubsection = \unnumberedsubsubsec
}
% @centerchap is like @unnumbered, but the heading is centered.
\outer\parseargdef\centerchap{%
% Well, we could do the following in a group, but that would break
% an assumption that \chapmacro is called at the outermost level.
% Thus we are safer this way: --kasal, 24feb04
\let\centerparametersmaybe = \centerparameters
\unnmhead0{#1}%
\let\centerparametersmaybe = \relax
}
% @top is like @unnumbered.
\let\top\unnumbered
% Sections.
\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
\def\seczzz#1{%
\global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
\sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
}
\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
\def\appendixsectionzzz#1{%
\global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
\sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
}
\let\appendixsec\appendixsection
\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
\def\unnumberedseczzz#1{%
\global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
\sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
}
% Subsections.
\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
\def\numberedsubseczzz#1{%
\global\subsubsecno=0 \global\advance\subsecno by 1
\sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
}
\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz
\def\appendixsubseczzz#1{%
\global\subsubsecno=0 \global\advance\subsecno by 1
\sectionheading{#1}{subsec}{Yappendix}%
{\appendixletter.\the\secno.\the\subsecno}%
}
\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
\def\unnumberedsubseczzz#1{%
\global\subsubsecno=0 \global\advance\subsecno by 1
\sectionheading{#1}{subsec}{Ynothing}%
{\the\unnumberedno.\the\secno.\the\subsecno}%
}
% Subsubsections.
\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
\def\numberedsubsubseczzz#1{%
\global\advance\subsubsecno by 1
\sectionheading{#1}{subsubsec}{Ynumbered}%
{\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
}
\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
\def\appendixsubsubseczzz#1{%
\global\advance\subsubsecno by 1
\sectionheading{#1}{subsubsec}{Yappendix}%
{\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
}
\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
\def\unnumberedsubsubseczzz#1{%
\global\advance\subsubsecno by 1
\sectionheading{#1}{subsubsec}{Ynothing}%
{\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
}
% These macros control what the section commands do, according
% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
% Define them by default for a numbered chapter.
\let\section = \numberedsec
\let\subsection = \numberedsubsec
\let\subsubsection = \numberedsubsubsec
% Define @majorheading, @heading and @subheading
% NOTE on use of \vbox for chapter headings, section headings, and such:
% 1) We use \vbox rather than the earlier \line to permit
% overlong headings to fold.
% 2) \hyphenpenalty is set to 10000 because hyphenation in a
% heading is obnoxious; this forbids it.
% 3) Likewise, headings look best if no \parindent is used, and
% if justification is not attempted. Hence \raggedright.
\def\majorheading{%
{\advance\chapheadingskip by 10pt \chapbreak }%
\parsearg\chapheadingzzz
}
\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
\def\chapheadingzzz#1{%
{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
\parindent=0pt\raggedright
\rm #1\hfill}}%
\bigskip \par\penalty 200\relax
\suppressfirstparagraphindent
}
% @heading, @subheading, @subsubheading.
\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
% These macros generate a chapter, section, etc. heading only
% (including whitespace, linebreaking, etc. around it),
% given all the information in convenient, parsed form.
%%% Args are the skip and penalty (usually negative)
\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
%%% Define plain chapter starts, and page on/off switching for it
% Parameter controlling skip before chapter headings (if needed)
\newskip\chapheadingskip
\def\chapbreak{\dobreak \chapheadingskip {-4000}}
\def\chappager{\par\vfill\supereject}
\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
\def\CHAPPAGoff{%
\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chapbreak
\global\let\pagealignmacro=\chappager}
\def\CHAPPAGon{%
\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chappager
\global\let\pagealignmacro=\chappager
\global\def\HEADINGSon{\HEADINGSsingle}}
\def\CHAPPAGodd{%
\global\let\contentsalignmacro = \chapoddpage
\global\let\pchapsepmacro=\chapoddpage
\global\let\pagealignmacro=\chapoddpage
\global\def\HEADINGSon{\HEADINGSdouble}}
\CHAPPAGon
% Chapter opening.
%
% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
% Yappendix, Yomitfromtoc), #3 the chapter number.
%
% To test against our argument.
\def\Ynothingkeyword{Ynothing}
\def\Yomitfromtockeyword{Yomitfromtoc}
\def\Yappendixkeyword{Yappendix}
%
\def\chapmacro#1#2#3{%
\pchapsepmacro
{%
\chapfonts \rm
%
% Have to define \thissection before calling \donoderef, because the
% xref code eventually uses it. On the other hand, it has to be called
% after \pchapsepmacro, or the headline will change too soon.
\gdef\thissection{#1}%
\gdef\thischaptername{#1}%
%
% Only insert the separating space if we have a chapter/appendix
% number, and don't print the unnumbered ``number''.
\def\temptype{#2}%
\ifx\temptype\Ynothingkeyword
\setbox0 = \hbox{}%
\def\toctype{unnchap}%
\gdef\thischapternum{}%
\gdef\thischapter{#1}%
\else\ifx\temptype\Yomitfromtockeyword
\setbox0 = \hbox{}% contents like unnumbered, but no toc entry
\def\toctype{omit}%
\gdef\thischapternum{}%
\gdef\thischapter{}%
\else\ifx\temptype\Yappendixkeyword
\setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
\def\toctype{app}%
\xdef\thischapternum{\appendixletter}%
% We don't substitute the actual chapter name into \thischapter
% because we don't want its macros evaluated now. And we don't
% use \thissection because that changes with each section.
%
\xdef\thischapter{\putwordAppendix{} \appendixletter:
\noexpand\thischaptername}%
\else
\setbox0 = \hbox{#3\enspace}%
\def\toctype{numchap}%
\xdef\thischapternum{\the\chapno}%
\xdef\thischapter{\putwordChapter{} \the\chapno:
\noexpand\thischaptername}%
\fi\fi\fi
%
% Write the toc entry for this chapter. Must come before the
% \donoderef, because we include the current node name in the toc
% entry, and \donoderef resets it to empty.
\writetocentry{\toctype}{#1}{#3}%
%
% For pdftex, we have to write out the node definition (aka, make
% the pdfdest) after any page break, but before the actual text has
% been typeset. If the destination for the pdf outline is after the
% text, then jumping from the outline may wind up with the text not
% being visible, for instance under high magnification.
\donoderef{#2}%
%
% Typeset the actual heading.
\vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
\hangindent=\wd0 \centerparametersmaybe
\unhbox0 #1\par}%
}%
\nobreak\bigskip % no page break after a chapter title
\nobreak
}
% @centerchap -- centered and unnumbered.
\let\centerparametersmaybe = \relax
\def\centerparameters{%
\advance\rightskip by 3\rightskip
\leftskip = \rightskip
\parfillskip = 0pt
}
% I don't think this chapter style is supported any more, so I'm not
% updating it with the new noderef stuff. We'll see. --karl, 11aug03.
%
\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
%
\def\unnchfopen #1{%
\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
\parindent=0pt\raggedright
\rm #1\hfill}}\bigskip \par\nobreak
}
\def\chfopen #1#2{\chapoddpage {\chapfonts
\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
\par\penalty 5000 %
}
\def\centerchfopen #1{%
\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
\parindent=0pt
\hfill {\rm #1}\hfill}}\bigskip \par\nobreak
}
\def\CHAPFopen{%
\global\let\chapmacro=\chfopen
\global\let\centerchapmacro=\centerchfopen}
% Section titles. These macros combine the section number parts and
% call the generic \sectionheading to do the printing.
%
\newskip\secheadingskip
\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
% Subsection titles.
\newskip\subsecheadingskip
\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
% Subsubsection titles.
\def\subsubsecheadingskip{\subsecheadingskip}
\def\subsubsecheadingbreak{\subsecheadingbreak}
% Print any size, any type, section title.
%
% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
% section number.
%
\def\sectionheading#1#2#3#4{%
{%
% Switch to the right set of fonts.
\csname #2fonts\endcsname \rm
%
% Insert space above the heading.
\csname #2headingbreak\endcsname
%
% Only insert the space after the number if we have a section number.
\def\sectionlevel{#2}%
\def\temptype{#3}%
%
\ifx\temptype\Ynothingkeyword
\setbox0 = \hbox{}%
\def\toctype{unn}%
\gdef\thissection{#1}%
\else\ifx\temptype\Yomitfromtockeyword
% for @headings -- no section number, don't include in toc,
% and don't redefine \thissection.
\setbox0 = \hbox{}%
\def\toctype{omit}%
\let\sectionlevel=\empty
\else\ifx\temptype\Yappendixkeyword
\setbox0 = \hbox{#4\enspace}%
\def\toctype{app}%
\gdef\thissection{#1}%
\else
\setbox0 = \hbox{#4\enspace}%
\def\toctype{num}%
\gdef\thissection{#1}%
\fi\fi\fi
%
% Write the toc entry (before \donoderef). See comments in \chapmacro.
\writetocentry{\toctype\sectionlevel}{#1}{#4}%
%
% Write the node reference (= pdf destination for pdftex).
% Again, see comments in \chapmacro.
\donoderef{#3}%
%
% Interline glue will be inserted when the vbox is completed.
% That glue will be a valid breakpoint for the page, since it'll be
% preceded by a whatsit (usually from the \donoderef, or from the
% \writetocentry if there was no node). We don't want to allow that
% break, since then the whatsits could end up on page n while the
% section is on page n+1, thus toc/etc. are wrong. Debian bug 276000.
\nobreak
%
% Output the actual section heading.
\vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
\hangindent=\wd0 % zero if no section number
\unhbox0 #1}%
}%
% Add extra space after the heading -- half of whatever came above it.
% Don't allow stretch, though.
\kern .5 \csname #2headingskip\endcsname
%
% Do not let the kern be a potential breakpoint, as it would be if it
% was followed by glue.
\nobreak
%
% We'll almost certainly start a paragraph next, so don't let that
% glue accumulate. (Not a breakpoint because it's preceded by a
% discardable item.)
\vskip-\parskip
%
% This is purely so the last item on the list is a known \penalty >
% 10000. This is so \startdefun can avoid allowing breakpoints after
% section headings. Otherwise, it would insert a valid breakpoint between:
%
% @section sec-whatever
% @deffn def-whatever
\penalty 10001
}
\message{toc,}
% Table of contents.
\newwrite\tocfile
% Write an entry to the toc file, opening it if necessary.
% Called from @chapter, etc.
%
% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
% We append the current node name (if any) and page number as additional
% arguments for the \{chap,sec,...}entry macros which will eventually
% read this. The node name is used in the pdf outlines as the
% destination to jump to.
%
% We open the .toc file for writing here instead of at @setfilename (or
% any other fixed time) so that @contents can be anywhere in the document.
% But if #1 is `omit', then we don't do anything. This is used for the
% table of contents chapter openings themselves.
%
\newif\iftocfileopened
\def\omitkeyword{omit}%
%
\def\writetocentry#1#2#3{%
\edef\writetoctype{#1}%
\ifx\writetoctype\omitkeyword \else
\iftocfileopened\else
\immediate\openout\tocfile = \jobname.toc
\global\tocfileopenedtrue
\fi
%
\iflinks
{\atdummies
\edef\temp{%
\write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}%
\temp
}%
\fi
\fi
%
% Tell \shipout to create a pdf destination on each page, if we're
% writing pdf. These are used in the table of contents. We can't
% just write one on every page because the title pages are numbered
% 1 and 2 (the page numbers aren't printed), and so are the first
% two pages of the document. Thus, we'd have two destinations named
% `1', and two named `2'.
\ifpdf \global\pdfmakepagedesttrue \fi
}
% These characters do not print properly in the Computer Modern roman
% fonts, so we must take special care. This is more or less redundant
% with the Texinfo input format setup at the end of this file.
%
\def\activecatcodes{%
\catcode`\"=\active
\catcode`\$=\active
\catcode`\<=\active
\catcode`\>=\active
\catcode`\\=\active
\catcode`\^=\active
\catcode`\_=\active
\catcode`\|=\active
\catcode`\~=\active
}
% Read the toc file, which is essentially Texinfo input.
\def\readtocfile{%
\setupdatafile
\activecatcodes
\input \jobname.toc
}
\newskip\contentsrightmargin \contentsrightmargin=1in
\newcount\savepageno
\newcount\lastnegativepageno \lastnegativepageno = -1
% Prepare to read what we've written to \tocfile.
%
\def\startcontents#1{%
% If @setchapternewpage on, and @headings double, the contents should
% start on an odd page, unlike chapters. Thus, we maintain
% \contentsalignmacro in parallel with \pagealignmacro.
% From: Torbjorn Granlund <tege@matematik.su.se>
\contentsalignmacro
\immediate\closeout\tocfile
%
% Don't need to put `Contents' or `Short Contents' in the headline.
% It is abundantly clear what they are.
\def\thischapter{}%
\chapmacro{#1}{Yomitfromtoc}{}%
%
\savepageno = \pageno
\begingroup % Set up to handle contents files properly.
\raggedbottom % Worry more about breakpoints than the bottom.
\advance\hsize by -\contentsrightmargin % Don't use the full line length.
%
% Roman numerals for page numbers.
\ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
}
% Normal (long) toc.
\def\contents{%
\startcontents{\putwordTOC}%
\openin 1 \jobname.toc
\ifeof 1 \else
\readtocfile
\fi
\vfill \eject
\contentsalignmacro % in case @setchapternewpage odd is in effect
\ifeof 1 \else
\pdfmakeoutlines
\fi
\closein 1
\endgroup
\lastnegativepageno = \pageno
\global\pageno = \savepageno
}
% And just the chapters.
\def\summarycontents{%
\startcontents{\putwordShortTOC}%
%
\let\numchapentry = \shortchapentry
\let\appentry = \shortchapentry
\let\unnchapentry = \shortunnchapentry
% We want a true roman here for the page numbers.
\secfonts
\let\rm=\shortcontrm \let\bf=\shortcontbf
\let\sl=\shortcontsl \let\tt=\shortconttt
\rm
\hyphenpenalty = 10000
\advance\baselineskip by 1pt % Open it up a little.
\def\numsecentry##1##2##3##4{}
\let\appsecentry = \numsecentry
\let\unnsecentry = \numsecentry
\let\numsubsecentry = \numsecentry
\let\appsubsecentry = \numsecentry
\let\unnsubsecentry = \numsecentry
\let\numsubsubsecentry = \numsecentry
\let\appsubsubsecentry = \numsecentry
\let\unnsubsubsecentry = \numsecentry
\openin 1 \jobname.toc
\ifeof 1 \else
\readtocfile
\fi
\closein 1
\vfill \eject
\contentsalignmacro % in case @setchapternewpage odd is in effect
\endgroup
\lastnegativepageno = \pageno
\global\pageno = \savepageno
}
\let\shortcontents = \summarycontents
% Typeset the label for a chapter or appendix for the short contents.
% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
%
\def\shortchaplabel#1{%
% This space should be enough, since a single number is .5em, and the
% widest letter (M) is 1em, at least in the Computer Modern fonts.
% But use \hss just in case.
% (This space doesn't include the extra space that gets added after
% the label; that gets put in by \shortchapentry above.)
%
% We'd like to right-justify chapter numbers, but that looks strange
% with appendix letters. And right-justifying numbers and
% left-justifying letters looks strange when there is less than 10
% chapters. Have to read the whole toc once to know how many chapters
% there are before deciding ...
\hbox to 1em{#1\hss}%
}
% These macros generate individual entries in the table of contents.
% The first argument is the chapter or section name.
% The last argument is the page number.
% The arguments in between are the chapter number, section number, ...
% Chapters, in the main contents.
\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
%
% Chapters, in the short toc.
% See comments in \dochapentry re vbox and related settings.
\def\shortchapentry#1#2#3#4{%
\tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
}
% Appendices, in the main contents.
% Need the word Appendix, and a fixed-size box.
%
\def\appendixbox#1{%
% We use M since it's probably the widest letter.
\setbox0 = \hbox{\putwordAppendix{} M}%
\hbox to \wd0{\putwordAppendix{} #1\hss}}
%
\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
% Unnumbered chapters.
\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
% Sections.
\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
\let\appsecentry=\numsecentry
\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
% Subsections.
\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
\let\appsubsecentry=\numsubsecentry
\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
% And subsubsections.
\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
\let\appsubsubsecentry=\numsubsubsecentry
\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
% This parameter controls the indentation of the various levels.
% Same as \defaultparindent.
\newdimen\tocindent \tocindent = 15pt
% Now for the actual typesetting. In all these, #1 is the text and #2 is the
% page number.
%
% If the toc has to be broken over pages, we want it to be at chapters
% if at all possible; hence the \penalty.
\def\dochapentry#1#2{%
\penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
\begingroup
\chapentryfonts
\tocentry{#1}{\dopageno\bgroup#2\egroup}%
\endgroup
\nobreak\vskip .25\baselineskip plus.1\baselineskip
}
\def\dosecentry#1#2{\begingroup
\secentryfonts \leftskip=\tocindent
\tocentry{#1}{\dopageno\bgroup#2\egroup}%
\endgroup}
\def\dosubsecentry#1#2{\begingroup
\subsecentryfonts \leftskip=2\tocindent
\tocentry{#1}{\dopageno\bgroup#2\egroup}%
\endgroup}
\def\dosubsubsecentry#1#2{\begingroup
\subsubsecentryfonts \leftskip=3\tocindent
\tocentry{#1}{\dopageno\bgroup#2\egroup}%
\endgroup}
% We use the same \entry macro as for the index entries.
\let\tocentry = \entry
% Space between chapter (or whatever) number and the title.
\def\labelspace{\hskip1em \relax}
\def\dopageno#1{{\rm #1}}
\def\doshortpageno#1{{\rm #1}}
\def\chapentryfonts{\secfonts \rm}
\def\secentryfonts{\textfonts}
\def\subsecentryfonts{\textfonts}
\def\subsubsecentryfonts{\textfonts}
\message{environments,}
% @foo ... @end foo.
% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
%
% Since these characters are used in examples, it should be an even number of
% \tt widths. Each \tt character is 1en, so two makes it 1em.
%
\def\point{$\star$}
\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
% The @error{} command.
% Adapted from the TeXbook's \boxit.
%
\newbox\errorbox
%
{\tentt \global\dimen0 = 3em}% Width of the box.
\dimen2 = .55pt % Thickness of rules
% The text. (`r' is open on the right, `e' somewhat less so on the left.)
\setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt}
%
\setbox\errorbox=\hbox to \dimen0{\hfil
\hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
\advance\hsize by -2\dimen2 % Rules.
\vbox{%
\hrule height\dimen2
\hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
\vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
\kern3pt\vrule width\dimen2}% Space to right.
\hrule height\dimen2}
\hfil}
%
\def\error{\leavevmode\lower.7ex\copy\errorbox}
% @tex ... @end tex escapes into raw Tex temporarily.
% One exception: @ is still an escape character, so that @end tex works.
% But \@ or @@ will get a plain tex @ character.
\envdef\tex{%
\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
\catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
\catcode `\%=14
\catcode `\+=\other
\catcode `\"=\other
\catcode `\|=\other
\catcode `\<=\other
\catcode `\>=\other
\escapechar=`\\
%
\let\b=\ptexb
\let\bullet=\ptexbullet
\let\c=\ptexc
\let\,=\ptexcomma
\let\.=\ptexdot
\let\dots=\ptexdots
\let\equiv=\ptexequiv
\let\!=\ptexexclam
\let\i=\ptexi
\let\indent=\ptexindent
\let\noindent=\ptexnoindent
\let\{=\ptexlbrace
\let\+=\tabalign
\let\}=\ptexrbrace
\let\/=\ptexslash
\let\*=\ptexstar
\let\t=\ptext
\let\frenchspacing=\plainfrenchspacing
%
\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
\def\@{@}%
}
% There is no need to define \Etex.
% Define @lisp ... @end lisp.
% @lisp environment forms a group so it can rebind things,
% including the definition of @end lisp (which normally is erroneous).
% Amount to narrow the margins by for @lisp.
\newskip\lispnarrowing \lispnarrowing=0.4in
% This is the definition that ^^M gets inside @lisp, @example, and other
% such environments. \null is better than a space, since it doesn't
% have any width.
\def\lisppar{\null\endgraf}
% This space is always present above and below environments.
\newskip\envskipamount \envskipamount = 0pt
% Make spacing and below environment symmetrical. We use \parskip here
% to help in doing that, since in @example-like environments \parskip
% is reset to zero; thus the \afterenvbreak inserts no space -- but the
% start of the next paragraph will insert \parskip.
%
\def\aboveenvbreak{{%
% =10000 instead of <10000 because of a special case in \itemzzz and
% \sectionheading, q.v.
\ifnum \lastpenalty=10000 \else
\advance\envskipamount by \parskip
\endgraf
\ifdim\lastskip<\envskipamount
\removelastskip
% it's not a good place to break if the last penalty was \nobreak
% or better ...
\ifnum\lastpenalty<10000 \penalty-50 \fi
\vskip\envskipamount
\fi
\fi
}}
\let\afterenvbreak = \aboveenvbreak
% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will
% also clear it, so that its embedded environments do the narrowing again.
\let\nonarrowing=\relax
% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
% environment contents.
\font\circle=lcircle10
\newdimen\circthick
\newdimen\cartouter\newdimen\cartinner
\newskip\normbskip\newskip\normpskip\newskip\normlskip
\circthick=\fontdimen8\circle
%
\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
\def\ctr{{\hskip 6pt\circle\char'010}}
\def\cbl{{\circle\char'012\hskip -6pt}}
\def\cbr{{\hskip 6pt\circle\char'011}}
\def\carttop{\hbox to \cartouter{\hskip\lskip
\ctl\leaders\hrule height\circthick\hfil\ctr
\hskip\rskip}}
\def\cartbot{\hbox to \cartouter{\hskip\lskip
\cbl\leaders\hrule height\circthick\hfil\cbr
\hskip\rskip}}
%
\newskip\lskip\newskip\rskip
\envdef\cartouche{%
\ifhmode\par\fi % can't be in the midst of a paragraph.
\startsavinginserts
\lskip=\leftskip \rskip=\rightskip
\leftskip=0pt\rightskip=0pt % we want these *outside*.
\cartinner=\hsize \advance\cartinner by-\lskip
\advance\cartinner by-\rskip
\cartouter=\hsize
\advance\cartouter by 18.4pt % allow for 3pt kerns on either
% side, and for 6pt waste from
% each corner char, and rule thickness
\normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
% Flag to tell @lisp, etc., not to narrow margin.
\let\nonarrowing = t%
\vbox\bgroup
\baselineskip=0pt\parskip=0pt\lineskip=0pt
\carttop
\hbox\bgroup
\hskip\lskip
\vrule\kern3pt
\vbox\bgroup
\kern3pt
\hsize=\cartinner
\baselineskip=\normbskip
\lineskip=\normlskip
\parskip=\normpskip
\vskip -\parskip
\comment % For explanation, see the end of \def\group.
}
\def\Ecartouche{%
\ifhmode\par\fi
\kern3pt
\egroup
\kern3pt\vrule
\hskip\rskip
\egroup
\cartbot
\egroup
\checkinserts
}
% This macro is called at the beginning of all the @example variants,
% inside a group.
\def\nonfillstart{%
\aboveenvbreak
\hfuzz = 12pt % Don't be fussy
\sepspaces % Make spaces be word-separators rather than space tokens.
\let\par = \lisppar % don't ignore blank lines
\obeylines % each line of input is a line of output
\parskip = 0pt
\parindent = 0pt
\emergencystretch = 0pt % don't try to avoid overfull boxes
\ifx\nonarrowing\relax
\advance \leftskip by \lispnarrowing
\exdentamount=\lispnarrowing
\else
\let\nonarrowing = \relax
\fi
\let\exdent=\nofillexdent
}
% If you want all examples etc. small: @set dispenvsize small.
% If you want even small examples the full size: @set dispenvsize nosmall.
% This affects the following displayed environments:
% @example, @display, @format, @lisp
%
\def\smallword{small}
\def\nosmallword{nosmall}
\let\SETdispenvsize\relax
\def\setnormaldispenv{%
\ifx\SETdispenvsize\smallword
% end paragraph for sake of leading, in case document has no blank
% line. This is redundant with what happens in \aboveenvbreak, but
% we need to do it before changing the fonts, and it's inconvenient
% to change the fonts afterward.
\ifnum \lastpenalty=10000 \else \endgraf \fi
\smallexamplefonts \rm
\fi
}
\def\setsmalldispenv{%
\ifx\SETdispenvsize\nosmallword
\else
\ifnum \lastpenalty=10000 \else \endgraf \fi
\smallexamplefonts \rm
\fi
}
% We often define two environments, @foo and @smallfoo.
% Let's do it by one command:
\def\makedispenv #1#2{
\expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
\expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
\expandafter\let\csname E#1\endcsname \afterenvbreak
\expandafter\let\csname Esmall#1\endcsname \afterenvbreak
}
% Define two synonyms:
\def\maketwodispenvs #1#2#3{
\makedispenv{#1}{#3}
\makedispenv{#2}{#3}
}
% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
%
% @smallexample and @smalllisp: use smaller fonts.
% Originally contributed by Pavel@xerox.
%
\maketwodispenvs {lisp}{example}{%
\nonfillstart
\tt\quoteexpand
\let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
\gobble % eat return
}
% @display/@smalldisplay: same as @lisp except keep current font.
%
\makedispenv {display}{%
\nonfillstart
\gobble
}
% @format/@smallformat: same as @display except don't narrow margins.
%
\makedispenv{format}{%
\let\nonarrowing = t%
\nonfillstart
\gobble
}
% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
\envdef\flushleft{%
\let\nonarrowing = t%
\nonfillstart
\gobble
}
\let\Eflushleft = \afterenvbreak
% @flushright.
%
\envdef\flushright{%
\let\nonarrowing = t%
\nonfillstart
\advance\leftskip by 0pt plus 1fill
\gobble
}
\let\Eflushright = \afterenvbreak
% @quotation does normal linebreaking (hence we can't use \nonfillstart)
% and narrows the margins. We keep \parskip nonzero in general, since
% we're doing normal filling. So, when using \aboveenvbreak and
% \afterenvbreak, temporarily make \parskip 0.
%
\envdef\quotation{%
{\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
\parindent=0pt
%
% @cartouche defines \nonarrowing to inhibit narrowing at next level down.
\ifx\nonarrowing\relax
\advance\leftskip by \lispnarrowing
\advance\rightskip by \lispnarrowing
\exdentamount = \lispnarrowing
\else
\let\nonarrowing = \relax
\fi
\parsearg\quotationlabel
}
% We have retained a nonzero parskip for the environment, since we're
% doing normal filling.
%
\def\Equotation{%
\par
\ifx\quotationauthor\undefined\else
% indent a bit.
\leftline{\kern 2\leftskip \sl ---\quotationauthor}%
\fi
{\parskip=0pt \afterenvbreak}%
}
% If we're given an argument, typeset it in bold with a colon after.
\def\quotationlabel#1{%
\def\temp{#1}%
\ifx\temp\empty \else
{\bf #1: }%
\fi
}
% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
% If we want to allow any <char> as delimiter,
% we need the curly braces so that makeinfo sees the @verb command, eg:
% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org
%
% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook.
%
% [Knuth] p.344; only we need to do the other characters Texinfo sets
% active too. Otherwise, they get lost as the first character on a
% verbatim line.
\def\dospecials{%
\do\ \do\\\do\{\do\}\do\$\do\&%
\do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
\do\<\do\>\do\|\do\@\do+\do\"%
}
%
% [Knuth] p. 380
\def\uncatcodespecials{%
\def\do##1{\catcode`##1=\other}\dospecials}
%
% [Knuth] pp. 380,381,391
% Disable Spanish ligatures ?` and !` of \tt font
\begingroup
\catcode`\`=\active\gdef`{\relax\lq}
\endgroup
%
% Setup for the @verb command.
%
% Eight spaces for a tab
\begingroup
\catcode`\^^I=\active
\gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
\endgroup
%
\def\setupverb{%
\tt % easiest (and conventionally used) font for verbatim
\def\par{\leavevmode\endgraf}%
\catcode`\`=\active
\tabeightspaces
% Respect line breaks,
% print special symbols as themselves, and
% make each space count
% must do in this order:
\obeylines \uncatcodespecials \sepspaces
}
% Setup for the @verbatim environment
%
% Real tab expansion
\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
%
\def\starttabbox{\setbox0=\hbox\bgroup}
% Allow an option to not replace quotes with a regular directed right
% quote/apostrophe (char 0x27), but instead use the undirected quote
% from cmtt (char 0x0d). The undirected quote is ugly, so don't make it
% the default, but it works for pasting with more pdf viewers (at least
% evince), the lilypond developers report. xpdf does work with the
% regular 0x27.
%
\def\codequoteright{%
\expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
'%
\else
\char'15
\fi
}
%
% and a similar option for the left quote char vs. a grave accent.
% Modern fonts display ASCII 0x60 as a grave accent, so some people like
% the code environments to do likewise.
%
\def\codequoteleft{%
\expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
`%
\else
\char'22
\fi
}
%
\begingroup
\catcode`\^^I=\active
\gdef\tabexpand{%
\catcode`\^^I=\active
\def^^I{\leavevmode\egroup
\dimen0=\wd0 % the width so far, or since the previous tab
\divide\dimen0 by\tabw
\multiply\dimen0 by\tabw % compute previous multiple of \tabw
\advance\dimen0 by\tabw % advance to next multiple of \tabw
\wd0=\dimen0 \box0 \starttabbox
}%
}
\catcode`\'=\active
\gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}%
%
\catcode`\`=\active
\gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}%
%
\gdef\quoteexpand{\rquoteexpand \lquoteexpand}%
\endgroup
% start the verbatim environment.
\def\setupverbatim{%
\let\nonarrowing = t%
\nonfillstart
% Easiest (and conventionally used) font for verbatim
\tt
\def\par{\leavevmode\egroup\box0\endgraf}%
\catcode`\`=\active
\tabexpand
\quoteexpand
% Respect line breaks,
% print special symbols as themselves, and
% make each space count
% must do in this order:
\obeylines \uncatcodespecials \sepspaces
\everypar{\starttabbox}%
}
% Do the @verb magic: verbatim text is quoted by unique
% delimiter characters. Before first delimiter expect a
% right brace, after last delimiter expect closing brace:
%
% \def\doverb'{'<char>#1<char>'}'{#1}
%
% [Knuth] p. 382; only eat outer {}
\begingroup
\catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
\gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
\endgroup
%
\def\verb{\begingroup\setupverb\doverb}
%
%
% Do the @verbatim magic: define the macro \doverbatim so that
% the (first) argument ends when '@end verbatim' is reached, ie:
%
% \def\doverbatim#1@end verbatim{#1}
%
% For Texinfo it's a lot easier than for LaTeX,
% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
% we need not redefine '\', '{' and '}'.
%
% Inspired by LaTeX's verbatim command set [latex.ltx]
%
\begingroup
\catcode`\ =\active
\obeylines %
% ignore everything up to the first ^^M, that's the newline at the end
% of the @verbatim input line itself. Otherwise we get an extra blank
% line in the output.
\xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}%
% We really want {...\end verbatim} in the body of the macro, but
% without the active space; thus we have to use \xdef and \gobble.
\endgroup
%
\envdef\verbatim{%
\setupverbatim\doverbatim
}
\let\Everbatim = \afterenvbreak
% @verbatiminclude FILE - insert text of file in verbatim environment.
%
\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
%
\def\doverbatiminclude#1{%
{%
\makevalueexpandable
\setupverbatim
\input #1
\afterenvbreak
}%
}
% @copying ... @end copying.
% Save the text away for @insertcopying later.
%
% We save the uninterpreted tokens, rather than creating a box.
% Saving the text in a box would be much easier, but then all the
% typesetting commands (@smallbook, font changes, etc.) have to be done
% beforehand -- and a) we want @copying to be done first in the source
% file; b) letting users define the frontmatter in as flexible order as
% possible is very desirable.
%
\def\copying{\checkenv{}\begingroup\scanargctxt\docopying}
\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
%
\def\insertcopying{%
\begingroup
\parindent = 0pt % paragraph indentation looks wrong on title page
\scanexp\copyingtext
\endgroup
}
\message{defuns,}
% @defun etc.
\newskip\defbodyindent \defbodyindent=.4in
\newskip\defargsindent \defargsindent=50pt
\newskip\deflastargmargin \deflastargmargin=18pt
\newcount\defunpenalty
% Start the processing of @deffn:
\def\startdefun{%
\ifnum\lastpenalty<10000
\medbreak
\defunpenalty=10003 % Will keep this @deffn together with the
% following @def command, see below.
\else
% If there are two @def commands in a row, we'll have a \nobreak,
% which is there to keep the function description together with its
% header. But if there's nothing but headers, we need to allow a
% break somewhere. Check specifically for penalty 10002, inserted
% by \printdefunline, instead of 10000, since the sectioning
% commands also insert a nobreak penalty, and we don't want to allow
% a break between a section heading and a defun.
%
% As a minor refinement, we avoid "club" headers by signalling
% with penalty of 10003 after the very first @deffn in the
% sequence (see above), and penalty of 10002 after any following
% @def command.
\ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi
%
% Similarly, after a section heading, do not allow a break.
% But do insert the glue.
\medskip % preceded by discardable penalty, so not a breakpoint
\fi
%
\parindent=0in
\advance\leftskip by \defbodyindent
\exdentamount=\defbodyindent
}
\def\dodefunx#1{%
% First, check whether we are in the right environment:
\checkenv#1%
%
% As above, allow line break if we have multiple x headers in a row.
% It's not a great place, though.
\ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
%
% And now, it's time to reuse the body of the original defun:
\expandafter\gobbledefun#1%
}
\def\gobbledefun#1\startdefun{}
% \printdefunline \deffnheader{text}
%
\def\printdefunline#1#2{%
\begingroup
% call \deffnheader:
#1#2 \endheader
% common ending:
\interlinepenalty = 10000
\advance\rightskip by 0pt plus 1fil
\endgraf
\nobreak\vskip -\parskip
\penalty\defunpenalty % signal to \startdefun and \dodefunx
% Some of the @defun-type tags do not enable magic parentheses,
% rendering the following check redundant. But we don't optimize.
\checkparencounts
\endgroup
}
\def\Edefun{\endgraf\medbreak}
% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
% the only thing remainnig is to define \deffnheader.
%
\def\makedefun#1{%
\expandafter\let\csname E#1\endcsname = \Edefun
\edef\temp{\noexpand\domakedefun
\makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
\temp
}
% \domakedefun \deffn \deffnx \deffnheader
%
% Define \deffn and \deffnx, without parameters.
% \deffnheader has to be defined explicitly.
%
\def\domakedefun#1#2#3{%
\envdef#1{%
\startdefun
\parseargusing\activeparens{\printdefunline#3}%
}%
\def#2{\dodefunx#1}%
\def#3%
}
%%% Untyped functions:
% @deffn category name args
\makedefun{deffn}{\deffngeneral{}}
% @deffn category class name args
\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
% \defopon {category on}class name args
\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
% \deffngeneral {subind}category name args
%
\def\deffngeneral#1#2 #3 #4\endheader{%
% Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}.
\dosubind{fn}{\code{#3}}{#1}%
\defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
}
%%% Typed functions:
% @deftypefn category type name args
\makedefun{deftypefn}{\deftypefngeneral{}}
% @deftypeop category class type name args
\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
% \deftypeopon {category on}class type name args
\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
% \deftypefngeneral {subind}category type name args
%
\def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
\dosubind{fn}{\code{#4}}{#1}%
\defname{#2}{#3}{#4}\defunargs{#5\unskip}%
}
%%% Typed variables:
% @deftypevr category type var args
\makedefun{deftypevr}{\deftypecvgeneral{}}
% @deftypecv category class type var args
\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
% \deftypecvof {category of}class type var args
\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
% \deftypecvgeneral {subind}category type var args
%
\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{%
\dosubind{vr}{\code{#4}}{#1}%
\defname{#2}{#3}{#4}\defunargs{#5\unskip}%
}
%%% Untyped variables:
% @defvr category var args
\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
% @defcv category class var args
\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}}
% \defcvof {category of}class var args
\def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
%%% Type:
% @deftp category name args
\makedefun{deftp}#1 #2 #3\endheader{%
\doind{tp}{\code{#2}}%
\defname{#1}{}{#2}\defunargs{#3\unskip}%
}
% Remaining @defun-like shortcuts:
\makedefun{defun}{\deffnheader{\putwordDeffunc} }
\makedefun{defmac}{\deffnheader{\putwordDefmac} }
\makedefun{defspec}{\deffnheader{\putwordDefspec} }
\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
\makedefun{defvar}{\defvrheader{\putwordDefvar} }
\makedefun{defopt}{\defvrheader{\putwordDefopt} }
\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
\makedefun{defmethod}{\defopon\putwordMethodon}
\makedefun{deftypemethod}{\deftypeopon\putwordMethodon}
\makedefun{defivar}{\defcvof\putwordInstanceVariableof}
\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof}
% \defname, which formats the name of the @def (not the args).
% #1 is the category, such as "Function".
% #2 is the return type, if any.
% #3 is the function name.
%
% We are followed by (but not passed) the arguments, if any.
%
\def\defname#1#2#3{%
% Get the values of \leftskip and \rightskip as they were outside the @def...
\advance\leftskip by -\defbodyindent
%
% How we'll format the type name. Putting it in brackets helps
% distinguish it from the body text that may end up on the next line
% just below it.
\def\temp{#1}%
\setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
%
% Figure out line sizes for the paragraph shape.
% The first line needs space for \box0; but if \rightskip is nonzero,
% we need only space for the part of \box0 which exceeds it:
\dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip
% The continuations:
\dimen2=\hsize \advance\dimen2 by -\defargsindent
% (plain.tex says that \dimen1 should be used only as global.)
\parshape 2 0in \dimen0 \defargsindent \dimen2
%
% Put the type name to the right margin.
\noindent
\hbox to 0pt{%
\hfil\box0 \kern-\hsize
% \hsize has to be shortened this way:
\kern\leftskip
% Intentionally do not respect \rightskip, since we need the space.
}%
%
% Allow all lines to be underfull without complaint:
\tolerance=10000 \hbadness=10000
\exdentamount=\defbodyindent
{%
% defun fonts. We use typewriter by default (used to be bold) because:
% . we're printing identifiers, they should be in tt in principle.
% . in languages with many accents, such as Czech or French, it's
% common to leave accents off identifiers. The result looks ok in
% tt, but exceedingly strange in rm.
% . we don't want -- and --- to be treated as ligatures.
% . this still does not fix the ?` and !` ligatures, but so far no
% one has made identifiers using them :).
\df \tt
\def\temp{#2}% return value type
\ifx\temp\empty\else \tclose{\temp} \fi
#3% output function name
}%
{\rm\enskip}% hskip 0.5 em of \tenrm
%
\boldbrax
% arguments will be output next, if any.
}
% Print arguments in slanted roman (not ttsl), inconsistently with using
% tt for the name. This is because literal text is sometimes needed in
% the argument list (groff manual), and ttsl and tt are not very
% distinguishable. Prevent hyphenation at `-' chars.
%
\def\defunargs#1{%
% use sl by default (not ttsl),
% tt for the names.
\df \sl \hyphenchar\font=0
%
% On the other hand, if an argument has two dashes (for instance), we
% want a way to get ttsl. Let's try @var for that.
\let\var=\ttslanted
#1%
\sl\hyphenchar\font=45
}
% We want ()&[] to print specially on the defun line.
%
\def\activeparens{%
\catcode`\(=\active \catcode`\)=\active
\catcode`\[=\active \catcode`\]=\active
\catcode`\&=\active
}
% Make control sequences which act like normal parenthesis chars.
\let\lparen = ( \let\rparen = )
% Be sure that we always have a definition for `(', etc. For example,
% if the fn name has parens in it, \boldbrax will not be in effect yet,
% so TeX would otherwise complain about undefined control sequence.
{
\activeparens
\global\let(=\lparen \global\let)=\rparen
\global\let[=\lbrack \global\let]=\rbrack
\global\let& = \&
\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
\gdef\magicamp{\let&=\amprm}
}
\newcount\parencount
% If we encounter &foo, then turn on ()-hacking afterwards
\newif\ifampseen
\def\amprm#1 {\ampseentrue{\bf\&#1 }}
\def\parenfont{%
\ifampseen
% At the first level, print parens in roman,
% otherwise use the default font.
\ifnum \parencount=1 \rm \fi
\else
% The \sf parens (in \boldbrax) actually are a little bolder than
% the contained text. This is especially needed for [ and ] .
\sf
\fi
}
\def\infirstlevel#1{%
\ifampseen
\ifnum\parencount=1
#1%
\fi
\fi
}
\def\bfafterword#1 {#1 \bf}
\def\opnr{%
\global\advance\parencount by 1
{\parenfont(}%
\infirstlevel \bfafterword
}
\def\clnr{%
{\parenfont)}%
\infirstlevel \sl
\global\advance\parencount by -1
}
\newcount\brackcount
\def\lbrb{%
\global\advance\brackcount by 1
{\bf[}%
}
\def\rbrb{%
{\bf]}%
\global\advance\brackcount by -1
}
\def\checkparencounts{%
\ifnum\parencount=0 \else \badparencount \fi
\ifnum\brackcount=0 \else \badbrackcount \fi
}
\def\badparencount{%
\errmessage{Unbalanced parentheses in @def}%
\global\parencount=0
}
\def\badbrackcount{%
\errmessage{Unbalanced square braces in @def}%
\global\brackcount=0
}
\message{macros,}
% @macro.
% To do this right we need a feature of e-TeX, \scantokens,
% which we arrange to emulate with a temporary file in ordinary TeX.
\ifx\eTeXversion\undefined
\newwrite\macscribble
\def\scantokens#1{%
\toks0={#1}%
\immediate\openout\macscribble=\jobname.tmp
\immediate\write\macscribble{\the\toks0}%
\immediate\closeout\macscribble
\input \jobname.tmp
}
\fi
\def\scanmacro#1{%
\begingroup
\newlinechar`\^^M
\let\xeatspaces\eatspaces
% Undo catcode changes of \startcontents and \doprintindex
% When called from @insertcopying or (short)caption, we need active
% backslash to get it printed correctly. Previously, we had
% \catcode`\\=\other instead. We'll see whether a problem appears
% with macro expansion. --kasal, 19aug04
\catcode`\@=0 \catcode`\\=\active \escapechar=`\@
% ... and \example
\spaceisspace
%
% Append \endinput to make sure that TeX does not see the ending newline.
% I've verified that it is necessary both for e-TeX and for ordinary TeX
% --kasal, 29nov03
\scantokens{#1\endinput}%
\endgroup
}
\def\scanexp#1{%
\edef\temp{\noexpand\scanmacro{#1}}%
\temp
}
\newcount\paramno % Count of parameters
\newtoks\macname % Macro name
\newif\ifrecursive % Is it recursive?
% List of all defined macros in the form
% \definedummyword\macro1\definedummyword\macro2...
% Currently is also contains all @aliases; the list can be split
% if there is a need.
\def\macrolist{}
% Add the macro to \macrolist
\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname}
\def\addtomacrolistxxx#1{%
\toks0 = \expandafter{\macrolist\definedummyword#1}%
\xdef\macrolist{\the\toks0}%
}
% Utility routines.
% This does \let #1 = #2, with \csnames; that is,
% \let \csname#1\endcsname = \csname#2\endcsname
% (except of course we have to play expansion games).
%
\def\cslet#1#2{%
\expandafter\let
\csname#1\expandafter\endcsname
\csname#2\endcsname
}
% Trim leading and trailing spaces off a string.
% Concepts from aro-bend problem 15 (see CTAN).
{\catcode`\@=11
\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
\def\unbrace#1{#1}
\unbrace{\gdef\trim@@@ #1 } #2@{#1}
}
% Trim a single trailing ^^M off a string.
{\catcode`\^^M=\other \catcode`\Q=3%
\gdef\eatcr #1{\eatcra #1Q^^MQ}%
\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
\gdef\eatcrb#1Q#2Q{#1}%
}
% Macro bodies are absorbed as an argument in a context where
% all characters are catcode 10, 11 or 12, except \ which is active
% (as in normal texinfo). It is necessary to change the definition of \.
% It's necessary to have hard CRs when the macro is executed. This is
% done by making ^^M (\endlinechar) catcode 12 when reading the macro
% body, and then making it the \newlinechar in \scanmacro.
\def\scanctxt{%
\catcode`\"=\other
\catcode`\+=\other
\catcode`\<=\other
\catcode`\>=\other
\catcode`\@=\other
\catcode`\^=\other
\catcode`\_=\other
\catcode`\|=\other
\catcode`\~=\other
}
\def\scanargctxt{%
\scanctxt
\catcode`\\=\other
\catcode`\^^M=\other
}
\def\macrobodyctxt{%
\scanctxt
\catcode`\{=\other
\catcode`\}=\other
\catcode`\^^M=\other
\usembodybackslash
}
\def\macroargctxt{%
\scanctxt
\catcode`\\=\other
}
% \mbodybackslash is the definition of \ in @macro bodies.
% It maps \foo\ => \csname macarg.foo\endcsname => #N
% where N is the macro parameter number.
% We define \csname macarg.\endcsname to be \realbackslash, so
% \\ in macro replacement text gets you a backslash.
{\catcode`@=0 @catcode`@\=@active
@gdef@usembodybackslash{@let\=@mbodybackslash}
@gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
}
\expandafter\def\csname macarg.\endcsname{\realbackslash}
\def\macro{\recursivefalse\parsearg\macroxxx}
\def\rmacro{\recursivetrue\parsearg\macroxxx}
\def\macroxxx#1{%
\getargs{#1}% now \macname is the macname and \argl the arglist
\ifx\argl\empty % no arguments
\paramno=0%
\else
\expandafter\parsemargdef \argl;%
\fi
\if1\csname ismacro.\the\macname\endcsname
\message{Warning: redefining \the\macname}%
\else
\expandafter\ifx\csname \the\macname\endcsname \relax
\else \errmessage{Macro name \the\macname\space already defined}\fi
\global\cslet{macsave.\the\macname}{\the\macname}%
\global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
\addtomacrolist{\the\macname}%
\fi
\begingroup \macrobodyctxt
\ifrecursive \expandafter\parsermacbody
\else \expandafter\parsemacbody
\fi}
\parseargdef\unmacro{%
\if1\csname ismacro.#1\endcsname
\global\cslet{#1}{macsave.#1}%
\global\expandafter\let \csname ismacro.#1\endcsname=0%
% Remove the macro name from \macrolist:
\begingroup
\expandafter\let\csname#1\endcsname \relax
\let\definedummyword\unmacrodo
\xdef\macrolist{\macrolist}%
\endgroup
\else
\errmessage{Macro #1 not defined}%
\fi
}
% Called by \do from \dounmacro on each macro. The idea is to omit any
% macro definitions that have been changed to \relax.
%
\def\unmacrodo#1{%
\ifx #1\relax
% remove this
\else
\noexpand\definedummyword \noexpand#1%
\fi
}
% This makes use of the obscure feature that if the last token of a
% <parameter list> is #, then the preceding argument is delimited by
% an opening brace, and that opening brace is not consumed.
\def\getargs#1{\getargsxxx#1{}}
\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
\def\getmacname #1 #2\relax{\macname={#1}}
\def\getmacargs#1{\def\argl{#1}}
% Parse the optional {params} list. Set up \paramno and \paramlist
% so \defmacro knows what to do. Define \macarg.blah for each blah
% in the params list, to be ##N where N is the position in that list.
% That gets used by \mbodybackslash (above).
% We need to get `macro parameter char #' into several definitions.
% The technique used is stolen from LaTeX: let \hash be something
% unexpandable, insert that wherever you need a #, and then redefine
% it to # just before using the token list produced.
%
% The same technique is used to protect \eatspaces till just before
% the macro is used.
\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
\let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
\def\parsemargdefxxx#1,{%
\if#1;\let\next=\relax
\else \let\next=\parsemargdefxxx
\advance\paramno by 1%
\expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
{\xeatspaces{\hash\the\paramno}}%
\edef\paramlist{\paramlist\hash\the\paramno,}%
\fi\next}
% These two commands read recursive and nonrecursive macro bodies.
% (They're different since rec and nonrec macros end differently.)
\long\def\parsemacbody#1@end macro%
{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
\long\def\parsermacbody#1@end rmacro%
{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
% This defines the macro itself. There are six cases: recursive and
% nonrecursive macros of zero, one, and many arguments.
% Much magic with \expandafter here.
% \xdef is used so that macro definitions will survive the file
% they're defined in; @include reads the file inside a group.
\def\defmacro{%
\let\hash=##% convert placeholders to macro parameter chars
\ifrecursive
\ifcase\paramno
% 0
\expandafter\xdef\csname\the\macname\endcsname{%
\noexpand\scanmacro{\temp}}%
\or % 1
\expandafter\xdef\csname\the\macname\endcsname{%
\bgroup\noexpand\macroargctxt
\noexpand\braceorline
\expandafter\noexpand\csname\the\macname xxx\endcsname}%
\expandafter\xdef\csname\the\macname xxx\endcsname##1{%
\egroup\noexpand\scanmacro{\temp}}%
\else % many
\expandafter\xdef\csname\the\macname\endcsname{%
\bgroup\noexpand\macroargctxt
\noexpand\csname\the\macname xx\endcsname}%
\expandafter\xdef\csname\the\macname xx\endcsname##1{%
\expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
\expandafter\expandafter
\expandafter\xdef
\expandafter\expandafter
\csname\the\macname xxx\endcsname
\paramlist{\egroup\noexpand\scanmacro{\temp}}%
\fi
\else
\ifcase\paramno
% 0
\expandafter\xdef\csname\the\macname\endcsname{%
\noexpand\norecurse{\the\macname}%
\noexpand\scanmacro{\temp}\egroup}%
\or % 1
\expandafter\xdef\csname\the\macname\endcsname{%
\bgroup\noexpand\macroargctxt
\noexpand\braceorline
\expandafter\noexpand\csname\the\macname xxx\endcsname}%
\expandafter\xdef\csname\the\macname xxx\endcsname##1{%
\egroup
\noexpand\norecurse{\the\macname}%
\noexpand\scanmacro{\temp}\egroup}%
\else % many
\expandafter\xdef\csname\the\macname\endcsname{%
\bgroup\noexpand\macroargctxt
\expandafter\noexpand\csname\the\macname xx\endcsname}%
\expandafter\xdef\csname\the\macname xx\endcsname##1{%
\expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
\expandafter\expandafter
\expandafter\xdef
\expandafter\expandafter
\csname\the\macname xxx\endcsname
\paramlist{%
\egroup
\noexpand\norecurse{\the\macname}%
\noexpand\scanmacro{\temp}\egroup}%
\fi
\fi}
\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
% \braceorline decides whether the next nonwhitespace character is a
% {. If so it reads up to the closing }, if not, it reads the whole
% line. Whatever was read is then fed to the next control sequence
% as an argument (by \parsebrace or \parsearg)
\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx}
\def\braceorlinexxx{%
\ifx\nchar\bgroup\else
\expandafter\parsearg
\fi \macnamexxx}
% @alias.
% We need some trickery to remove the optional spaces around the equal
% sign. Just make them active and then expand them all to nothing.
\def\alias{\parseargusing\obeyspaces\aliasxxx}
\def\aliasxxx #1{\aliasyyy#1\relax}
\def\aliasyyy #1=#2\relax{%
{%
\expandafter\let\obeyedspace=\empty
\addtomacrolist{#1}%
\xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
}%
\next
}
\message{cross references,}
\newwrite\auxfile
\newif\ifhavexrefs % True if xref values are known.
\newif\ifwarnedxrefs % True if we warned once that they aren't known.
% @inforef is relatively simple.
\def\inforef #1{\inforefzzz #1,,,,**}
\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
node \samp{\ignorespaces#1{}}}
% @node's only job in TeX is to define \lastnode, which is used in
% cross-references. The @node line might or might not have commas, and
% might or might not have spaces before the first comma, like:
% @node foo , bar , ...
% We don't want such trailing spaces in the node name.
%
\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
%
% also remove a trailing comma, in case of something like this:
% @node Help-Cross, , , Cross-refs
\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
\let\nwnode=\node
\let\lastnode=\empty
% Write a cross-reference definition for the current node. #1 is the
% type (Ynumbered, Yappendix, Ynothing).
%
\def\donoderef#1{%
\ifx\lastnode\empty\else
\setref{\lastnode}{#1}%
\global\let\lastnode=\empty
\fi
}
% @anchor{NAME} -- define xref target at arbitrary point.
%
\newcount\savesfregister
%
\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
% anchor), which consists of three parts:
% 1) NAME-title - the current sectioning name taken from \thissection,
% or the anchor name.
% 2) NAME-snt - section number and type, passed as the SNT arg, or
% empty for anchors.
% 3) NAME-pg - the page number.
%
% This is called from \donoderef, \anchor, and \dofloat. In the case of
% floats, there is an additional part, which is not written here:
% 4) NAME-lof - the text as it should appear in a @listoffloats.
%
\def\setref#1#2{%
\pdfmkdest{#1}%
\iflinks
{%
\atdummies % preserve commands, but don't expand them
\edef\writexrdef##1##2{%
\write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
##1}{##2}}% these are parameters of \writexrdef
}%
\toks0 = \expandafter{\thissection}%
\immediate \writexrdef{title}{\the\toks0 }%
\immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
\safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during \shipout
}%
\fi
}
% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
% the node name, #2 the name of the Info cross-reference, #3 the printed
% node name, #4 the name of the Info file, #5 the name of the printed
% manual. All but the node name can be omitted.
%
\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
\def\ref#1{\xrefX[#1,,,,,,,]}
\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
\unsepspaces
\def\printedmanual{\ignorespaces #5}%
\def\printedrefname{\ignorespaces #3}%
\setbox1=\hbox{\printedmanual\unskip}%
\setbox0=\hbox{\printedrefname\unskip}%
\ifdim \wd0 = 0pt
% No printed node name was explicitly given.
\expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
% Use the node name inside the square brackets.
\def\printedrefname{\ignorespaces #1}%
\else
% Use the actual chapter/section title appear inside
% the square brackets. Use the real section title if we have it.
\ifdim \wd1 > 0pt
% It is in another manual, so we don't have it.
\def\printedrefname{\ignorespaces #1}%
\else
\ifhavexrefs
% We know the real title if we have the xref values.
\def\printedrefname{\refx{#1-title}{}}%
\else
% Otherwise just copy the Info node name.
\def\printedrefname{\ignorespaces #1}%
\fi%
\fi
\fi
\fi
%
% Make link in pdf output.
\ifpdf
\leavevmode
\getfilename{#4}%
{\indexnofonts
\turnoffactive
% See comments at \activebackslashdouble.
{\activebackslashdouble \xdef\pdfxrefdest{#1}%
\backslashparens\pdfxrefdest}%
%
\ifnum\filenamelength>0
\startlink attr{/Border [0 0 0]}%
goto file{\the\filename.pdf} name{\pdfxrefdest}%
\else
\startlink attr{/Border [0 0 0]}%
goto name{\pdfmkpgn{\pdfxrefdest}}%
\fi
}%
\linkcolor
\fi
%
% Float references are printed completely differently: "Figure 1.2"
% instead of "[somenode], p.3". We distinguish them by the
% LABEL-title being set to a magic string.
{%
% Have to otherify everything special to allow the \csname to
% include an _ in the xref name, etc.
\indexnofonts
\turnoffactive
\expandafter\global\expandafter\let\expandafter\Xthisreftitle
\csname XR#1-title\endcsname
}%
\iffloat\Xthisreftitle
% If the user specified the print name (third arg) to the ref,
% print it instead of our usual "Figure 1.2".
\ifdim\wd0 = 0pt
\refx{#1-snt}{}%
\else
\printedrefname
\fi
%
% if the user also gave the printed manual name (fifth arg), append
% "in MANUALNAME".
\ifdim \wd1 > 0pt
\space \putwordin{} \cite{\printedmanual}%
\fi
\else
% node/anchor (non-float) references.
%
% If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
% insert empty discretionaries after hyphens, which means that it will
% not find a line break at a hyphen in a node names. Since some manuals
% are best written with fairly long node names, containing hyphens, this
% is a loss. Therefore, we give the text of the node name again, so it
% is as if TeX is seeing it for the first time.
\ifdim \wd1 > 0pt
\putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
\else
% _ (for example) has to be the character _ for the purposes of the
% control sequence corresponding to the node, but it has to expand
% into the usual \leavevmode...\vrule stuff for purposes of
% printing. So we \turnoffactive for the \refx-snt, back on for the
% printing, back off for the \refx-pg.
{\turnoffactive
% Only output a following space if the -snt ref is nonempty; for
% @unnumbered and @anchor, it won't be.
\setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
\ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
}%
% output the `[mynode]' via a macro so it can be overridden.
\xrefprintnodename\printedrefname
%
% But we always want a comma and a space:
,\space
%
% output the `page 3'.
\turnoffactive \putwordpage\tie\refx{#1-pg}{}%
\fi
\fi
\endlink
\endgroup}
% This macro is called from \xrefX for the `[nodename]' part of xref
% output. It's a separate macro only so it can be changed more easily,
% since square brackets don't work well in some documents. Particularly
% one that Bob is working on :).
%
\def\xrefprintnodename#1{[#1]}
% Things referred to by \setref.
%
\def\Ynothing{}
\def\Yomitfromtoc{}
\def\Ynumbered{%
\ifnum\secno=0
\putwordChapter@tie \the\chapno
\else \ifnum\subsecno=0
\putwordSection@tie \the\chapno.\the\secno
\else \ifnum\subsubsecno=0
\putwordSection@tie \the\chapno.\the\secno.\the\subsecno
\else
\putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
\fi\fi\fi
}
\def\Yappendix{%
\ifnum\secno=0
\putwordAppendix@tie @char\the\appendixno{}%
\else \ifnum\subsecno=0
\putwordSection@tie @char\the\appendixno.\the\secno
\else \ifnum\subsubsecno=0
\putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
\else
\putwordSection@tie
@char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
\fi\fi\fi
}
% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
% If its value is nonempty, SUFFIX is output afterward.
%
\def\refx#1#2{%
{%
\indexnofonts
\otherbackslash
\expandafter\global\expandafter\let\expandafter\thisrefX
\csname XR#1\endcsname
}%
\ifx\thisrefX\relax
% If not defined, say something at least.
\angleleft un\-de\-fined\angleright
\iflinks
\ifhavexrefs
\message{\linenumber Undefined cross reference `#1'.}%
\else
\ifwarnedxrefs\else
\global\warnedxrefstrue
\message{Cross reference values unknown; you must run TeX again.}%
\fi
\fi
\fi
\else
% It's defined, so just use it.
\thisrefX
\fi
#2% Output the suffix in any case.
}
% This is the macro invoked by entries in the aux file. Usually it's
% just a \def (we prepend XR to the control sequence name to avoid
% collisions). But if this is a float type, we have more work to do.
%
\def\xrdef#1#2{%
{% The node name might contain 8-bit characters, which in our current
% implementation are changed to commands like @'e. Don't let these
% mess up the control sequence name.
\indexnofonts
\turnoffactive
\xdef\safexrefname{#1}%
}%
%
\expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref
%
% Was that xref control sequence that we just defined for a float?
\expandafter\iffloat\csname XR\safexrefname\endcsname
% it was a float, and we have the (safe) float type in \iffloattype.
\expandafter\let\expandafter\floatlist
\csname floatlist\iffloattype\endcsname
%
% Is this the first time we've seen this float type?
\expandafter\ifx\floatlist\relax
\toks0 = {\do}% yes, so just \do
\else
% had it before, so preserve previous elements in list.
\toks0 = \expandafter{\floatlist\do}%
\fi
%
% Remember this xref in the control sequence \floatlistFLOATTYPE,
% for later use in \listoffloats.
\expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0
{\safexrefname}}%
\fi
}
% Read the last existing aux file, if any. No error if none exists.
%
\def\tryauxfile{%
\openin 1 \jobname.aux
\ifeof 1 \else
\readdatafile{aux}%
\global\havexrefstrue
\fi
\closein 1
}
\def\setupdatafile{%
\catcode`\^^@=\other
\catcode`\^^A=\other
\catcode`\^^B=\other
\catcode`\^^C=\other
\catcode`\^^D=\other
\catcode`\^^E=\other
\catcode`\^^F=\other
\catcode`\^^G=\other
\catcode`\^^H=\other
\catcode`\^^K=\other
\catcode`\^^L=\other
\catcode`\^^N=\other
\catcode`\^^P=\other
\catcode`\^^Q=\other
\catcode`\^^R=\other
\catcode`\^^S=\other
\catcode`\^^T=\other
\catcode`\^^U=\other
\catcode`\^^V=\other
\catcode`\^^W=\other
\catcode`\^^X=\other
\catcode`\^^Z=\other
\catcode`\^^[=\other
\catcode`\^^\=\other
\catcode`\^^]=\other
\catcode`\^^^=\other
\catcode`\^^_=\other
% It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
% in xref tags, i.e., node names. But since ^^e4 notation isn't
% supported in the main text, it doesn't seem desirable. Furthermore,
% that is not enough: for node names that actually contain a ^
% character, we would end up writing a line like this: 'xrdef {'hat
% b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
% argument, and \hat is not an expandable control sequence. It could
% all be worked out, but why? Either we support ^^ or we don't.
%
% The other change necessary for this was to define \auxhat:
% \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
% and then to call \auxhat in \setq.
%
\catcode`\^=\other
%
% Special characters. Should be turned off anyway, but...
\catcode`\~=\other
\catcode`\[=\other
\catcode`\]=\other
\catcode`\"=\other
\catcode`\_=\other
\catcode`\|=\other
\catcode`\<=\other
\catcode`\>=\other
\catcode`\$=\other
\catcode`\#=\other
\catcode`\&=\other
\catcode`\%=\other
\catcode`+=\other % avoid \+ for paranoia even though we've turned it off
%
% This is to support \ in node names and titles, since the \
% characters end up in a \csname. It's easier than
% leaving it active and making its active definition an actual \
% character. What I don't understand is why it works in the *value*
% of the xrdef. Seems like it should be a catcode12 \, and that
% should not typeset properly. But it works, so I'm moving on for
% now. --karl, 15jan04.
\catcode`\\=\other
%
% Make the characters 128-255 be printing characters.
{%
\count1=128
\def\loop{%
\catcode\count1=\other
\advance\count1 by 1
\ifnum \count1<256 \loop \fi
}%
}%
%
% @ is our escape character in .aux files, and we need braces.
\catcode`\{=1
\catcode`\}=2
\catcode`\@=0
}
\def\readdatafile#1{%
\begingroup
\setupdatafile
\input\jobname.#1
\endgroup}
\message{insertions,}
% including footnotes.
\newcount \footnoteno
% The trailing space in the following definition for supereject is
% vital for proper filling; pages come out unaligned when you do a
% pagealignmacro call if that space before the closing brace is
% removed. (Generally, numeric constants should always be followed by a
% space to prevent strange expansion errors.)
\def\supereject{\par\penalty -20000\footnoteno =0 }
% @footnotestyle is meaningful for info output only.
\let\footnotestyle=\comment
{\catcode `\@=11
%
% Auto-number footnotes. Otherwise like plain.
\gdef\footnote{%
\let\indent=\ptexindent
\let\noindent=\ptexnoindent
\global\advance\footnoteno by \@ne
\edef\thisfootno{$^{\the\footnoteno}$}%
%
% In case the footnote comes at the end of a sentence, preserve the
% extra spacing after we do the footnote number.
\let\@sf\empty
\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
%
% Remove inadvertent blank space before typesetting the footnote number.
\unskip
\thisfootno\@sf
\dofootnote
}%
% Don't bother with the trickery in plain.tex to not require the
% footnote text as a parameter. Our footnotes don't need to be so general.
%
% Oh yes, they do; otherwise, @ifset (and anything else that uses
% \parseargline) fails inside footnotes because the tokens are fixed when
% the footnote is read. --karl, 16nov96.
%
\gdef\dofootnote{%
\insert\footins\bgroup
% We want to typeset this text as a normal paragraph, even if the
% footnote reference occurs in (for example) a display environment.
% So reset some parameters.
\hsize=\pagewidth
\interlinepenalty\interfootnotelinepenalty
\splittopskip\ht\strutbox % top baseline for broken footnotes
\splitmaxdepth\dp\strutbox
\floatingpenalty\@MM
\leftskip\z@skip
\rightskip\z@skip
\spaceskip\z@skip
\xspaceskip\z@skip
\parindent\defaultparindent
%
\smallfonts \rm
%
% Because we use hanging indentation in footnotes, a @noindent appears
% to exdent this text, so make it be a no-op. makeinfo does not use
% hanging indentation so @noindent can still be needed within footnote
% text after an @example or the like (not that this is good style).
\let\noindent = \relax
%
% Hang the footnote text off the number. Use \everypar in case the
% footnote extends for more than one paragraph.
\everypar = {\hang}%
\textindent{\thisfootno}%
%
% Don't crash into the line above the footnote text. Since this
% expands into a box, it must come within the paragraph, lest it
% provide a place where TeX can split the footnote.
\footstrut
\futurelet\next\fo@t
}
}%end \catcode `\@=11
% In case a @footnote appears in a vbox, save the footnote text and create
% the real \insert just after the vbox finished. Otherwise, the insertion
% would be lost.
% Similarly, if a @footnote appears inside an alignment, save the footnote
% text to a box and make the \insert when a row of the table is finished.
% And the same can be done for other insert classes. --kasal, 16nov03.
% Replace the \insert primitive by a cheating macro.
% Deeper inside, just make sure that the saved insertions are not spilled
% out prematurely.
%
\def\startsavinginserts{%
\ifx \insert\ptexinsert
\let\insert\saveinsert
\else
\let\checkinserts\relax
\fi
}
% This \insert replacement works for both \insert\footins{foo} and
% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
%
\def\saveinsert#1{%
\edef\next{\noexpand\savetobox \makeSAVEname#1}%
\afterassignment\next
% swallow the left brace
\let\temp =
}
\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
\def\placesaveins#1{%
\ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
{\box#1}%
}
% eat @SAVE -- beware, all of them have catcode \other:
{
\def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-)
\gdef\gobblesave @SAVE{}
}
% initialization:
\def\newsaveins #1{%
\edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
\next
}
\def\newsaveinsX #1{%
\csname newbox\endcsname #1%
\expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
\checksaveins #1}%
}
% initialize:
\let\checkinserts\empty
\newsaveins\footins
\newsaveins\margin
% @image. We use the macros from epsf.tex to support this.
% If epsf.tex is not installed and @image is used, we complain.
%
% Check for and read epsf.tex up front. If we read it only at @image
% time, we might be inside a group, and then its definitions would get
% undone and the next image would fail.
\openin 1 = epsf.tex
\ifeof 1 \else
% Do not bother showing banner with epsf.tex v2.7k (available in
% doc/epsf.tex and on ctan).
\def\epsfannounce{\toks0 = }%
\input epsf.tex
\fi
\closein 1
%
% We will only complain once about lack of epsf.tex.
\newif\ifwarnednoepsf
\newhelp\noepsfhelp{epsf.tex must be installed for images to
work. It is also included in the Texinfo distribution, or you can get
it from ftp://tug.org/tex/epsf.tex.}
%
\def\image#1{%
\ifx\epsfbox\undefined
\ifwarnednoepsf \else
\errhelp = \noepsfhelp
\errmessage{epsf.tex not found, images will be ignored}%
\global\warnednoepsftrue
\fi
\else
\imagexxx #1,,,,,\finish
\fi
}
%
% Arguments to @image:
% #1 is (mandatory) image filename; we tack on .eps extension.
% #2 is (optional) width, #3 is (optional) height.
% #4 is (ignored optional) html alt text.
% #5 is (ignored optional) extension.
% #6 is just the usual extra ignored arg for parsing this stuff.
\newif\ifimagevmode
\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
\catcode`\^^M = 5 % in case we're inside an example
\normalturnoffactive % allow _ et al. in names
% If the image is by itself, center it.
\ifvmode
\imagevmodetrue
\nobreak\bigskip
% Usually we'll have text after the image which will insert
% \parskip glue, so insert it here too to equalize the space
% above and below.
\nobreak\vskip\parskip
\nobreak
\line\bgroup
\fi
%
% Output the image.
\ifpdf
\dopdfimage{#1}{#2}{#3}%
\else
% \epsfbox itself resets \epsf?size at each figure.
\setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
\setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
\epsfbox{#1.eps}%
\fi
%
\ifimagevmode \egroup \bigbreak \fi % space after the image
\endgroup}
% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
% etc. We don't actually implement floating yet, we always include the
% float "here". But it seemed the best name for the future.
%
\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
% There may be a space before second and/or third parameter; delete it.
\def\eatcommaspace#1, {#1,}
% #1 is the optional FLOATTYPE, the text label for this float, typically
% "Figure", "Table", "Example", etc. Can't contain commas. If omitted,
% this float will not be numbered and cannot be referred to.
%
% #2 is the optional xref label. Also must be present for the float to
% be referable.
%
% #3 is the optional positioning argument; for now, it is ignored. It
% will somehow specify the positions allowed to float to (here, top, bottom).
%
% We keep a separate counter for each FLOATTYPE, which we reset at each
% chapter-level command.
\let\resetallfloatnos=\empty
%
\def\dofloat#1,#2,#3,#4\finish{%
\let\thiscaption=\empty
\let\thisshortcaption=\empty
%
% don't lose footnotes inside @float.
%
% BEWARE: when the floats start float, we have to issue warning whenever an
% insert appears inside a float which could possibly float. --kasal, 26may04
%
\startsavinginserts
%
% We can't be used inside a paragraph.
\par
%
\vtop\bgroup
\def\floattype{#1}%
\def\floatlabel{#2}%
\def\floatloc{#3}% we do nothing with this yet.
%
\ifx\floattype\empty
\let\safefloattype=\empty
\else
{%
% the floattype might have accents or other special characters,
% but we need to use it in a control sequence name.
\indexnofonts
\turnoffactive
\xdef\safefloattype{\floattype}%
}%
\fi
%
% If label is given but no type, we handle that as the empty type.
\ifx\floatlabel\empty \else
% We want each FLOATTYPE to be numbered separately (Figure 1,
% Table 1, Figure 2, ...). (And if no label, no number.)
%
\expandafter\getfloatno\csname\safefloattype floatno\endcsname
\global\advance\floatno by 1
%
{%
% This magic value for \thissection is output by \setref as the
% XREFLABEL-title value. \xrefX uses it to distinguish float
% labels (which have a completely different output format) from
% node and anchor labels. And \xrdef uses it to construct the
% lists of floats.
%
\edef\thissection{\floatmagic=\safefloattype}%
\setref{\floatlabel}{Yfloat}%
}%
\fi
%
% start with \parskip glue, I guess.
\vskip\parskip
%
% Don't suppress indentation if a float happens to start a section.
\restorefirstparagraphindent
}
% we have these possibilities:
% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
% @float Foo,lbl & no caption: Foo 1.1
% @float Foo & @caption{Cap}: Foo: Cap
% @float Foo & no caption: Foo
% @float ,lbl & Caption{Cap}: 1.1: Cap
% @float ,lbl & no caption: 1.1
% @float & @caption{Cap}: Cap
% @float & no caption:
%
\def\Efloat{%
\let\floatident = \empty
%
% In all cases, if we have a float type, it comes first.
\ifx\floattype\empty \else \def\floatident{\floattype}\fi
%
% If we have an xref label, the number comes next.
\ifx\floatlabel\empty \else
\ifx\floattype\empty \else % if also had float type, need tie first.
\appendtomacro\floatident{\tie}%
\fi
% the number.
\appendtomacro\floatident{\chaplevelprefix\the\floatno}%
\fi
%
% Start the printed caption with what we've constructed in
% \floatident, but keep it separate; we need \floatident again.
\let\captionline = \floatident
%
\ifx\thiscaption\empty \else
\ifx\floatident\empty \else
\appendtomacro\captionline{: }% had ident, so need a colon between
\fi
%
% caption text.
\appendtomacro\captionline{\scanexp\thiscaption}%
\fi
%
% If we have anything to print, print it, with space before.
% Eventually this needs to become an \insert.
\ifx\captionline\empty \else
\vskip.5\parskip
\captionline
%
% Space below caption.
\vskip\parskip
\fi
%
% If have an xref label, write the list of floats info. Do this
% after the caption, to avoid chance of it being a breakpoint.
\ifx\floatlabel\empty \else
% Write the text that goes in the lof to the aux file as
% \floatlabel-lof. Besides \floatident, we include the short
% caption if specified, else the full caption if specified, else nothing.
{%
\atdummies
%
% since we read the caption text in the macro world, where ^^M
% is turned into a normal character, we have to scan it back, so
% we don't write the literal three characters "^^M" into the aux file.
\scanexp{%
\xdef\noexpand\gtemp{%
\ifx\thisshortcaption\empty
\thiscaption
\else
\thisshortcaption
\fi
}%
}%
\immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident
\ifx\gtemp\empty \else : \gtemp \fi}}%
}%
\fi
\egroup % end of \vtop
%
% place the captured inserts
%
% BEWARE: when the floats start floating, we have to issue warning
% whenever an insert appears inside a float which could possibly
% float. --kasal, 26may04
%
\checkinserts
}
% Append the tokens #2 to the definition of macro #1, not expanding either.
%
\def\appendtomacro#1#2{%
\expandafter\def\expandafter#1\expandafter{#1#2}%
}
% @caption, @shortcaption
%
\def\caption{\docaption\thiscaption}
\def\shortcaption{\docaption\thisshortcaption}
\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption}
\def\defcaption#1#2{\egroup \def#1{#2}}
% The parameter is the control sequence identifying the counter we are
% going to use. Create it if it doesn't exist and assign it to \floatno.
\def\getfloatno#1{%
\ifx#1\relax
% Haven't seen this figure type before.
\csname newcount\endcsname #1%
%
% Remember to reset this floatno at the next chap.
\expandafter\gdef\expandafter\resetallfloatnos
\expandafter{\resetallfloatnos #1=0 }%
\fi
\let\floatno#1%
}
% \setref calls this to get the XREFLABEL-snt value. We want an @xref
% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we
% first read the @float command.
%
\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
% Magic string used for the XREFLABEL-title value, so \xrefX can
% distinguish floats from other xref types.
\def\floatmagic{!!float!!}
% #1 is the control sequence we are passed; we expand into a conditional
% which is true if #1 represents a float ref. That is, the magic
% \thissection value which we \setref above.
%
\def\iffloat#1{\expandafter\doiffloat#1==\finish}
%
% #1 is (maybe) the \floatmagic string. If so, #2 will be the
% (safe) float type for this float. We set \iffloattype to #2.
%
\def\doiffloat#1=#2=#3\finish{%
\def\temp{#1}%
\def\iffloattype{#2}%
\ifx\temp\floatmagic
}
% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
%
\parseargdef\listoffloats{%
\def\floattype{#1}% floattype
{%
% the floattype might have accents or other special characters,
% but we need to use it in a control sequence name.
\indexnofonts
\turnoffactive
\xdef\safefloattype{\floattype}%
}%
%
% \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
\expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
\ifhavexrefs
% if the user said @listoffloats foo but never @float foo.
\message{\linenumber No `\safefloattype' floats to list.}%
\fi
\else
\begingroup
\leftskip=\tocindent % indent these entries like a toc
\let\do=\listoffloatsdo
\csname floatlist\safefloattype\endcsname
\endgroup
\fi
}
% This is called on each entry in a list of floats. We're passed the
% xref label, in the form LABEL-title, which is how we save it in the
% aux file. We strip off the -title and look up \XRLABEL-lof, which
% has the text we're supposed to typeset here.
%
% Figures without xref labels will not be included in the list (since
% they won't appear in the aux file).
%
\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
\def\listoffloatsdoentry#1-title\finish{{%
% Can't fully expand XR#1-lof because it can contain anything. Just
% pass the control sequence. On the other hand, XR#1-pg is just the
% page number, and we want to fully expand that so we can get a link
% in pdf output.
\toksA = \expandafter{\csname XR#1-lof\endcsname}%
%
% use the same \entry macro we use to generate the TOC and index.
\edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
\writeentry
}}
\message{localization,}
% @documentlanguage is usually given very early, just after
% @setfilename. If done too late, it may not override everything
% properly. Single argument is the language abbreviation.
% It would be nice if we could set up a hyphenation file here.
%
\parseargdef\documentlanguage{%
\tex % read txi-??.tex file in plain TeX.
% Read the file if it exists.
\openin 1 txi-#1.tex
\ifeof 1
\errhelp = \nolanghelp
\errmessage{Cannot read language file txi-#1.tex}%
\else
\input txi-#1.tex
\fi
\closein 1
\endgroup
}
\newhelp\nolanghelp{The given language definition file cannot be found or
is empty. Maybe you need to install it? In the current directory
should work if nowhere else does.}
% Set the catcode of characters 128 through 255 to the specified number.
%
\def\setnonasciicharscatcode#1{%
\count255=128
\loop\ifnum\count255<256
\global\catcode\count255=#1
\advance\count255 by 1
\repeat
}
% @documentencoding sets the definition of non-ASCII characters
% according to the specified encoding.
%
\parseargdef\documentencoding{%
% Encoding being declared for the document.
\def\declaredencoding{\csname #1.enc\endcsname}%
%
% Supported encodings: names converted to tokens in order to be able
% to compare them with \ifx.
\def\ascii{\csname US-ASCII.enc\endcsname}%
\def\latnine{\csname ISO-8859-15.enc\endcsname}%
\def\latone{\csname ISO-8859-1.enc\endcsname}%
\def\lattwo{\csname ISO-8859-2.enc\endcsname}%
\def\utfeight{\csname UTF-8.enc\endcsname}%
%
\ifx \declaredencoding \ascii
\asciichardefs
%
\else \ifx \declaredencoding \lattwo
\setnonasciicharscatcode\active
\lattwochardefs
%
\else \ifx \declaredencoding \latone
\setnonasciicharscatcode\active
\latonechardefs
%
\else \ifx \declaredencoding \latnine
\setnonasciicharscatcode\active
\latninechardefs
%
\else \ifx \declaredencoding \utfeight
\setnonasciicharscatcode\active
\utfeightchardefs
%
\else
\message{Unknown document encoding #1, ignoring.}%
%
\fi % utfeight
\fi % latnine
\fi % latone
\fi % lattwo
\fi % ascii
}
% A message to be logged when using a character that isn't available
% the default font encoding (OT1).
%
\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}}
% Take account of \c (plain) vs. \, (Texinfo) difference.
\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi}
% First, make active non-ASCII characters in order for them to be
% correctly categorized when TeX reads the replacement text of
% macros containing the character definitions.
\setnonasciicharscatcode\active
%
% Latin1 (ISO-8859-1) character definitions.
\def\latonechardefs{%
\gdef^^a0{~}
\gdef^^a1{\exclamdown}
\gdef^^a2{\missingcharmsg{CENT SIGN}}
\gdef^^a3{{\pounds}}
\gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
\gdef^^a5{\missingcharmsg{YEN SIGN}}
\gdef^^a6{\missingcharmsg{BROKEN BAR}}
\gdef^^a7{\S}
\gdef^^a8{\"{}}
\gdef^^a9{\copyright}
\gdef^^aa{\ordf}
\gdef^^ab{\missingcharmsg{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}}
\gdef^^ac{$\lnot$}
\gdef^^ad{\-}
\gdef^^ae{\registeredsymbol}
\gdef^^af{\={}}
%
\gdef^^b0{\textdegree}
\gdef^^b1{$\pm$}
\gdef^^b2{$^2$}
\gdef^^b3{$^3$}
\gdef^^b4{\'{}}
\gdef^^b5{$\mu$}
\gdef^^b6{\P}
%
\gdef^^b7{$^.$}
\gdef^^b8{\cedilla\ }
\gdef^^b9{$^1$}
\gdef^^ba{\ordm}
%
\gdef^^bb{\missingcharmsg{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}}
\gdef^^bc{$1\over4$}
\gdef^^bd{$1\over2$}
\gdef^^be{$3\over4$}
\gdef^^bf{\questiondown}
%
\gdef^^c0{\`A}
\gdef^^c1{\'A}
\gdef^^c2{\^A}
\gdef^^c3{\~A}
\gdef^^c4{\"A}
\gdef^^c5{\ringaccent A}
\gdef^^c6{\AE}
\gdef^^c7{\cedilla C}
\gdef^^c8{\`E}
\gdef^^c9{\'E}
\gdef^^ca{\^E}
\gdef^^cb{\"E}
\gdef^^cc{\`I}
\gdef^^cd{\'I}
\gdef^^ce{\^I}
\gdef^^cf{\"I}
%
\gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}}
\gdef^^d1{\~N}
\gdef^^d2{\`O}
\gdef^^d3{\'O}
\gdef^^d4{\^O}
\gdef^^d5{\~O}
\gdef^^d6{\"O}
\gdef^^d7{$\times$}
\gdef^^d8{\O}
\gdef^^d9{\`U}
\gdef^^da{\'U}
\gdef^^db{\^U}
\gdef^^dc{\"U}
\gdef^^dd{\'Y}
\gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}}
\gdef^^df{\ss}
%
\gdef^^e0{\`a}
\gdef^^e1{\'a}
\gdef^^e2{\^a}
\gdef^^e3{\~a}
\gdef^^e4{\"a}
\gdef^^e5{\ringaccent a}
\gdef^^e6{\ae}
\gdef^^e7{\cedilla c}
\gdef^^e8{\`e}
\gdef^^e9{\'e}
\gdef^^ea{\^e}
\gdef^^eb{\"e}
\gdef^^ec{\`{\dotless i}}
\gdef^^ed{\'{\dotless i}}
\gdef^^ee{\^{\dotless i}}
\gdef^^ef{\"{\dotless i}}
%
\gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}}
\gdef^^f1{\~n}
\gdef^^f2{\`o}
\gdef^^f3{\'o}
\gdef^^f4{\^o}
\gdef^^f5{\~o}
\gdef^^f6{\"o}
\gdef^^f7{$\div$}
\gdef^^f8{\o}
\gdef^^f9{\`u}
\gdef^^fa{\'u}
\gdef^^fb{\^u}
\gdef^^fc{\"u}
\gdef^^fd{\'y}
\gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}}
\gdef^^ff{\"y}
}
% Latin9 (ISO-8859-15) encoding character definitions.
\def\latninechardefs{%
% Encoding is almost identical to Latin1.
\latonechardefs
%
\gdef^^a4{\euro}
\gdef^^a6{\v S}
\gdef^^a8{\v s}
\gdef^^b4{\v Z}
\gdef^^b8{\v z}
\gdef^^bc{\OE}
\gdef^^bd{\oe}
\gdef^^be{\"Y}
}
% Latin2 (ISO-8859-2) character definitions.
\def\lattwochardefs{%
\gdef^^a0{~}
\gdef^^a1{\missingcharmsg{LATIN CAPITAL LETTER A WITH OGONEK}}
\gdef^^a2{\u{}}
\gdef^^a3{\L}
\gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
\gdef^^a5{\v L}
\gdef^^a6{\'S}
\gdef^^a7{\S}
\gdef^^a8{\"{}}
\gdef^^a9{\v S}
\gdef^^aa{\cedilla S}
\gdef^^ab{\v T}
\gdef^^ac{\'Z}
\gdef^^ad{\-}
\gdef^^ae{\v Z}
\gdef^^af{\dotaccent Z}
%
\gdef^^b0{\textdegree}
\gdef^^b1{\missingcharmsg{LATIN SMALL LETTER A WITH OGONEK}}
\gdef^^b2{\missingcharmsg{OGONEK}}
\gdef^^b3{\l}
\gdef^^b4{\'{}}
\gdef^^b5{\v l}
\gdef^^b6{\'s}
\gdef^^b7{\v{}}
\gdef^^b8{\cedilla\ }
\gdef^^b9{\v s}
\gdef^^ba{\cedilla s}
\gdef^^bb{\v t}
\gdef^^bc{\'z}
\gdef^^bd{\H{}}
\gdef^^be{\v z}
\gdef^^bf{\dotaccent z}
%
\gdef^^c0{\'R}
\gdef^^c1{\'A}
\gdef^^c2{\^A}
\gdef^^c3{\u A}
\gdef^^c4{\"A}
\gdef^^c5{\'L}
\gdef^^c6{\'C}
\gdef^^c7{\cedilla C}
\gdef^^c8{\v C}
\gdef^^c9{\'E}
\gdef^^ca{\missingcharmsg{LATIN CAPITAL LETTER E WITH OGONEK}}
\gdef^^cb{\"E}
\gdef^^cc{\v E}
\gdef^^cd{\'I}
\gdef^^ce{\^I}
\gdef^^cf{\v D}
%
\gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}}
\gdef^^d1{\'N}
\gdef^^d2{\v N}
\gdef^^d3{\'O}
\gdef^^d4{\^O}
\gdef^^d5{\H O}
\gdef^^d6{\"O}
\gdef^^d7{$\times$}
\gdef^^d8{\v R}
\gdef^^d9{\ringaccent U}
\gdef^^da{\'U}
\gdef^^db{\H U}
\gdef^^dc{\"U}
\gdef^^dd{\'Y}
\gdef^^de{\cedilla T}
\gdef^^df{\ss}
%
\gdef^^e0{\'r}
\gdef^^e1{\'a}
\gdef^^e2{\^a}
\gdef^^e3{\u a}
\gdef^^e4{\"a}
\gdef^^e5{\'l}
\gdef^^e6{\'c}
\gdef^^e7{\cedilla c}
\gdef^^e8{\v c}
\gdef^^e9{\'e}
\gdef^^ea{\missingcharmsg{LATIN SMALL LETTER E WITH OGONEK}}
\gdef^^eb{\"e}
\gdef^^ec{\v e}
\gdef^^ed{\'\i}
\gdef^^ee{\^\i}
\gdef^^ef{\v d}
%
\gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}}
\gdef^^f1{\'n}
\gdef^^f2{\v n}
\gdef^^f3{\'o}
\gdef^^f4{\^o}
\gdef^^f5{\H o}
\gdef^^f6{\"o}
\gdef^^f7{$\div$}
\gdef^^f8{\v r}
\gdef^^f9{\ringaccent u}
\gdef^^fa{\'u}
\gdef^^fb{\H u}
\gdef^^fc{\"u}
\gdef^^fd{\'y}
\gdef^^fe{\cedilla t}
\gdef^^ff{\dotaccent{}}
}
% UTF-8 character definitions.
%
% This code to support UTF-8 is based on LaTeX's utf8.def, with some
% changes for Texinfo conventions. It is included here under the GPL by
% permission from Frank Mittelbach and the LaTeX team.
%
\newcount\countUTFx
\newcount\countUTFy
\newcount\countUTFz
\gdef\UTFviiiTwoOctets#1#2{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\endcsname}
%
\gdef\UTFviiiThreeOctets#1#2#3{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname}
%
\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname}
\gdef\UTFviiiDefined#1{%
\ifx #1\relax
\message{\linenumber Unicode char \string #1 not defined for Texinfo}%
\else
\expandafter #1%
\fi
}
\begingroup
\catcode`\~13
\catcode`\"12
\def\UTFviiiLoop{%
\global\catcode\countUTFx\active
\uccode`\~\countUTFx
\uppercase\expandafter{\UTFviiiTmp}%
\advance\countUTFx by 1
\ifnum\countUTFx < \countUTFy
\expandafter\UTFviiiLoop
\fi}
\countUTFx = "C2
\countUTFy = "E0
\def\UTFviiiTmp{%
\xdef~{\noexpand\UTFviiiTwoOctets\string~}}
\UTFviiiLoop
\countUTFx = "E0
\countUTFy = "F0
\def\UTFviiiTmp{%
\xdef~{\noexpand\UTFviiiThreeOctets\string~}}
\UTFviiiLoop
\countUTFx = "F0
\countUTFy = "F4
\def\UTFviiiTmp{%
\xdef~{\noexpand\UTFviiiFourOctets\string~}}
\UTFviiiLoop
\endgroup
\begingroup
\catcode`\"=12
\catcode`\<=12
\catcode`\.=12
\catcode`\,=12
\catcode`\;=12
\catcode`\!=12
\catcode`\~=13
\gdef\DeclareUnicodeCharacter#1#2{%
\countUTFz = "#1\relax
\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}%
\begingroup
\parseXMLCharref
\def\UTFviiiTwoOctets##1##2{%
\csname u8:##1\string ##2\endcsname}%
\def\UTFviiiThreeOctets##1##2##3{%
\csname u8:##1\string ##2\string ##3\endcsname}%
\def\UTFviiiFourOctets##1##2##3##4{%
\csname u8:##1\string ##2\string ##3\string ##4\endcsname}%
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter
\gdef\UTFviiiTmp{#2}%
\endgroup}
\gdef\parseXMLCharref{%
\ifnum\countUTFz < "A0\relax
\errhelp = \EMsimple
\errmessage{Cannot define Unicode char value < 00A0}%
\else\ifnum\countUTFz < "800\relax
\parseUTFviiiA,%
\parseUTFviiiB C\UTFviiiTwoOctets.,%
\else\ifnum\countUTFz < "10000\relax
\parseUTFviiiA;%
\parseUTFviiiA,%
\parseUTFviiiB E\UTFviiiThreeOctets.{,;}%
\else
\parseUTFviiiA;%
\parseUTFviiiA,%
\parseUTFviiiA!%
\parseUTFviiiB F\UTFviiiFourOctets.{!,;}%
\fi\fi\fi
}
\gdef\parseUTFviiiA#1{%
\countUTFx = \countUTFz
\divide\countUTFz by 64
\countUTFy = \countUTFz
\multiply\countUTFz by 64
\advance\countUTFx by -\countUTFz
\advance\countUTFx by 128
\uccode `#1\countUTFx
\countUTFz = \countUTFy}
\gdef\parseUTFviiiB#1#2#3#4{%
\advance\countUTFz by "#10\relax
\uccode `#3\countUTFz
\uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
\endgroup
\def\utfeightchardefs{%
\DeclareUnicodeCharacter{00A0}{\tie}
\DeclareUnicodeCharacter{00A1}{\exclamdown}
\DeclareUnicodeCharacter{00A3}{\pounds}
\DeclareUnicodeCharacter{00A8}{\"{ }}
\DeclareUnicodeCharacter{00A9}{\copyright}
\DeclareUnicodeCharacter{00AA}{\ordf}
\DeclareUnicodeCharacter{00AD}{\-}
\DeclareUnicodeCharacter{00AE}{\registeredsymbol}
\DeclareUnicodeCharacter{00AF}{\={ }}
\DeclareUnicodeCharacter{00B0}{\ringaccent{ }}
\DeclareUnicodeCharacter{00B4}{\'{ }}
\DeclareUnicodeCharacter{00B8}{\cedilla{ }}
\DeclareUnicodeCharacter{00BA}{\ordm}
\DeclareUnicodeCharacter{00BF}{\questiondown}
\DeclareUnicodeCharacter{00C0}{\`A}
\DeclareUnicodeCharacter{00C1}{\'A}
\DeclareUnicodeCharacter{00C2}{\^A}
\DeclareUnicodeCharacter{00C3}{\~A}
\DeclareUnicodeCharacter{00C4}{\"A}
\DeclareUnicodeCharacter{00C5}{\AA}
\DeclareUnicodeCharacter{00C6}{\AE}
\DeclareUnicodeCharacter{00C7}{\cedilla{C}}
\DeclareUnicodeCharacter{00C8}{\`E}
\DeclareUnicodeCharacter{00C9}{\'E}
\DeclareUnicodeCharacter{00CA}{\^E}
\DeclareUnicodeCharacter{00CB}{\"E}
\DeclareUnicodeCharacter{00CC}{\`I}
\DeclareUnicodeCharacter{00CD}{\'I}
\DeclareUnicodeCharacter{00CE}{\^I}
\DeclareUnicodeCharacter{00CF}{\"I}
\DeclareUnicodeCharacter{00D1}{\~N}
\DeclareUnicodeCharacter{00D2}{\`O}
\DeclareUnicodeCharacter{00D3}{\'O}
\DeclareUnicodeCharacter{00D4}{\^O}
\DeclareUnicodeCharacter{00D5}{\~O}
\DeclareUnicodeCharacter{00D6}{\"O}
\DeclareUnicodeCharacter{00D8}{\O}
\DeclareUnicodeCharacter{00D9}{\`U}
\DeclareUnicodeCharacter{00DA}{\'U}
\DeclareUnicodeCharacter{00DB}{\^U}
\DeclareUnicodeCharacter{00DC}{\"U}
\DeclareUnicodeCharacter{00DD}{\'Y}
\DeclareUnicodeCharacter{00DF}{\ss}
\DeclareUnicodeCharacter{00E0}{\`a}
\DeclareUnicodeCharacter{00E1}{\'a}
\DeclareUnicodeCharacter{00E2}{\^a}
\DeclareUnicodeCharacter{00E3}{\~a}
\DeclareUnicodeCharacter{00E4}{\"a}
\DeclareUnicodeCharacter{00E5}{\aa}
\DeclareUnicodeCharacter{00E6}{\ae}
\DeclareUnicodeCharacter{00E7}{\cedilla{c}}
\DeclareUnicodeCharacter{00E8}{\`e}
\DeclareUnicodeCharacter{00E9}{\'e}
\DeclareUnicodeCharacter{00EA}{\^e}
\DeclareUnicodeCharacter{00EB}{\"e}
\DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}
\DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}
\DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}
\DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}
\DeclareUnicodeCharacter{00F1}{\~n}
\DeclareUnicodeCharacter{00F2}{\`o}
\DeclareUnicodeCharacter{00F3}{\'o}
\DeclareUnicodeCharacter{00F4}{\^o}
\DeclareUnicodeCharacter{00F5}{\~o}
\DeclareUnicodeCharacter{00F6}{\"o}
\DeclareUnicodeCharacter{00F8}{\o}
\DeclareUnicodeCharacter{00F9}{\`u}
\DeclareUnicodeCharacter{00FA}{\'u}
\DeclareUnicodeCharacter{00FB}{\^u}
\DeclareUnicodeCharacter{00FC}{\"u}
\DeclareUnicodeCharacter{00FD}{\'y}
\DeclareUnicodeCharacter{00FF}{\"y}
\DeclareUnicodeCharacter{0100}{\=A}
\DeclareUnicodeCharacter{0101}{\=a}
\DeclareUnicodeCharacter{0102}{\u{A}}
\DeclareUnicodeCharacter{0103}{\u{a}}
\DeclareUnicodeCharacter{0106}{\'C}
\DeclareUnicodeCharacter{0107}{\'c}
\DeclareUnicodeCharacter{0108}{\^C}
\DeclareUnicodeCharacter{0109}{\^c}
\DeclareUnicodeCharacter{010A}{\dotaccent{C}}
\DeclareUnicodeCharacter{010B}{\dotaccent{c}}
\DeclareUnicodeCharacter{010C}{\v{C}}
\DeclareUnicodeCharacter{010D}{\v{c}}
\DeclareUnicodeCharacter{010E}{\v{D}}
\DeclareUnicodeCharacter{0112}{\=E}
\DeclareUnicodeCharacter{0113}{\=e}
\DeclareUnicodeCharacter{0114}{\u{E}}
\DeclareUnicodeCharacter{0115}{\u{e}}
\DeclareUnicodeCharacter{0116}{\dotaccent{E}}
\DeclareUnicodeCharacter{0117}{\dotaccent{e}}
\DeclareUnicodeCharacter{011A}{\v{E}}
\DeclareUnicodeCharacter{011B}{\v{e}}
\DeclareUnicodeCharacter{011C}{\^G}
\DeclareUnicodeCharacter{011D}{\^g}
\DeclareUnicodeCharacter{011E}{\u{G}}
\DeclareUnicodeCharacter{011F}{\u{g}}
\DeclareUnicodeCharacter{0120}{\dotaccent{G}}
\DeclareUnicodeCharacter{0121}{\dotaccent{g}}
\DeclareUnicodeCharacter{0124}{\^H}
\DeclareUnicodeCharacter{0125}{\^h}
\DeclareUnicodeCharacter{0128}{\~I}
\DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}
\DeclareUnicodeCharacter{012A}{\=I}
\DeclareUnicodeCharacter{012B}{\={\dotless{i}}}
\DeclareUnicodeCharacter{012C}{\u{I}}
\DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}
\DeclareUnicodeCharacter{0130}{\dotaccent{I}}
\DeclareUnicodeCharacter{0131}{\dotless{i}}
\DeclareUnicodeCharacter{0132}{IJ}
\DeclareUnicodeCharacter{0133}{ij}
\DeclareUnicodeCharacter{0134}{\^J}
\DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}
\DeclareUnicodeCharacter{0139}{\'L}
\DeclareUnicodeCharacter{013A}{\'l}
\DeclareUnicodeCharacter{0141}{\L}
\DeclareUnicodeCharacter{0142}{\l}
\DeclareUnicodeCharacter{0143}{\'N}
\DeclareUnicodeCharacter{0144}{\'n}
\DeclareUnicodeCharacter{0147}{\v{N}}
\DeclareUnicodeCharacter{0148}{\v{n}}
\DeclareUnicodeCharacter{014C}{\=O}
\DeclareUnicodeCharacter{014D}{\=o}
\DeclareUnicodeCharacter{014E}{\u{O}}
\DeclareUnicodeCharacter{014F}{\u{o}}
\DeclareUnicodeCharacter{0150}{\H{O}}
\DeclareUnicodeCharacter{0151}{\H{o}}
\DeclareUnicodeCharacter{0152}{\OE}
\DeclareUnicodeCharacter{0153}{\oe}
\DeclareUnicodeCharacter{0154}{\'R}
\DeclareUnicodeCharacter{0155}{\'r}
\DeclareUnicodeCharacter{0158}{\v{R}}
\DeclareUnicodeCharacter{0159}{\v{r}}
\DeclareUnicodeCharacter{015A}{\'S}
\DeclareUnicodeCharacter{015B}{\'s}
\DeclareUnicodeCharacter{015C}{\^S}
\DeclareUnicodeCharacter{015D}{\^s}
\DeclareUnicodeCharacter{015E}{\cedilla{S}}
\DeclareUnicodeCharacter{015F}{\cedilla{s}}
\DeclareUnicodeCharacter{0160}{\v{S}}
\DeclareUnicodeCharacter{0161}{\v{s}}
\DeclareUnicodeCharacter{0162}{\cedilla{t}}
\DeclareUnicodeCharacter{0163}{\cedilla{T}}
\DeclareUnicodeCharacter{0164}{\v{T}}
\DeclareUnicodeCharacter{0168}{\~U}
\DeclareUnicodeCharacter{0169}{\~u}
\DeclareUnicodeCharacter{016A}{\=U}
\DeclareUnicodeCharacter{016B}{\=u}
\DeclareUnicodeCharacter{016C}{\u{U}}
\DeclareUnicodeCharacter{016D}{\u{u}}
\DeclareUnicodeCharacter{016E}{\ringaccent{U}}
\DeclareUnicodeCharacter{016F}{\ringaccent{u}}
\DeclareUnicodeCharacter{0170}{\H{U}}
\DeclareUnicodeCharacter{0171}{\H{u}}
\DeclareUnicodeCharacter{0174}{\^W}
\DeclareUnicodeCharacter{0175}{\^w}
\DeclareUnicodeCharacter{0176}{\^Y}
\DeclareUnicodeCharacter{0177}{\^y}
\DeclareUnicodeCharacter{0178}{\"Y}
\DeclareUnicodeCharacter{0179}{\'Z}
\DeclareUnicodeCharacter{017A}{\'z}
\DeclareUnicodeCharacter{017B}{\dotaccent{Z}}
\DeclareUnicodeCharacter{017C}{\dotaccent{z}}
\DeclareUnicodeCharacter{017D}{\v{Z}}
\DeclareUnicodeCharacter{017E}{\v{z}}
\DeclareUnicodeCharacter{01C4}{D\v{Z}}
\DeclareUnicodeCharacter{01C5}{D\v{z}}
\DeclareUnicodeCharacter{01C6}{d\v{z}}
\DeclareUnicodeCharacter{01C7}{LJ}
\DeclareUnicodeCharacter{01C8}{Lj}
\DeclareUnicodeCharacter{01C9}{lj}
\DeclareUnicodeCharacter{01CA}{NJ}
\DeclareUnicodeCharacter{01CB}{Nj}
\DeclareUnicodeCharacter{01CC}{nj}
\DeclareUnicodeCharacter{01CD}{\v{A}}
\DeclareUnicodeCharacter{01CE}{\v{a}}
\DeclareUnicodeCharacter{01CF}{\v{I}}
\DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}
\DeclareUnicodeCharacter{01D1}{\v{O}}
\DeclareUnicodeCharacter{01D2}{\v{o}}
\DeclareUnicodeCharacter{01D3}{\v{U}}
\DeclareUnicodeCharacter{01D4}{\v{u}}
\DeclareUnicodeCharacter{01E2}{\={\AE}}
\DeclareUnicodeCharacter{01E3}{\={\ae}}
\DeclareUnicodeCharacter{01E6}{\v{G}}
\DeclareUnicodeCharacter{01E7}{\v{g}}
\DeclareUnicodeCharacter{01E8}{\v{K}}
\DeclareUnicodeCharacter{01E9}{\v{k}}
\DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}
\DeclareUnicodeCharacter{01F1}{DZ}
\DeclareUnicodeCharacter{01F2}{Dz}
\DeclareUnicodeCharacter{01F3}{dz}
\DeclareUnicodeCharacter{01F4}{\'G}
\DeclareUnicodeCharacter{01F5}{\'g}
\DeclareUnicodeCharacter{01F8}{\`N}
\DeclareUnicodeCharacter{01F9}{\`n}
\DeclareUnicodeCharacter{01FC}{\'{\AE}}
\DeclareUnicodeCharacter{01FD}{\'{\ae}}
\DeclareUnicodeCharacter{01FE}{\'{\O}}
\DeclareUnicodeCharacter{01FF}{\'{\o}}
\DeclareUnicodeCharacter{021E}{\v{H}}
\DeclareUnicodeCharacter{021F}{\v{h}}
\DeclareUnicodeCharacter{0226}{\dotaccent{A}}
\DeclareUnicodeCharacter{0227}{\dotaccent{a}}
\DeclareUnicodeCharacter{0228}{\cedilla{E}}
\DeclareUnicodeCharacter{0229}{\cedilla{e}}
\DeclareUnicodeCharacter{022E}{\dotaccent{O}}
\DeclareUnicodeCharacter{022F}{\dotaccent{o}}
\DeclareUnicodeCharacter{0232}{\=Y}
\DeclareUnicodeCharacter{0233}{\=y}
\DeclareUnicodeCharacter{0237}{\dotless{j}}
\DeclareUnicodeCharacter{1E02}{\dotaccent{B}}
\DeclareUnicodeCharacter{1E03}{\dotaccent{b}}
\DeclareUnicodeCharacter{1E04}{\udotaccent{B}}
\DeclareUnicodeCharacter{1E05}{\udotaccent{b}}
\DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}
\DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}
\DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}
\DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}
\DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}
\DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}
\DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}
\DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}
\DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}
\DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}
\DeclareUnicodeCharacter{1E20}{\=G}
\DeclareUnicodeCharacter{1E21}{\=g}
\DeclareUnicodeCharacter{1E22}{\dotaccent{H}}
\DeclareUnicodeCharacter{1E23}{\dotaccent{h}}
\DeclareUnicodeCharacter{1E24}{\udotaccent{H}}
\DeclareUnicodeCharacter{1E25}{\udotaccent{h}}
\DeclareUnicodeCharacter{1E26}{\"H}
\DeclareUnicodeCharacter{1E27}{\"h}
\DeclareUnicodeCharacter{1E30}{\'K}
\DeclareUnicodeCharacter{1E31}{\'k}
\DeclareUnicodeCharacter{1E32}{\udotaccent{K}}
\DeclareUnicodeCharacter{1E33}{\udotaccent{k}}
\DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}
\DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}
\DeclareUnicodeCharacter{1E36}{\udotaccent{L}}
\DeclareUnicodeCharacter{1E37}{\udotaccent{l}}
\DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}
\DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}
\DeclareUnicodeCharacter{1E3E}{\'M}
\DeclareUnicodeCharacter{1E3F}{\'m}
\DeclareUnicodeCharacter{1E40}{\dotaccent{M}}
\DeclareUnicodeCharacter{1E41}{\dotaccent{m}}
\DeclareUnicodeCharacter{1E42}{\udotaccent{M}}
\DeclareUnicodeCharacter{1E43}{\udotaccent{m}}
\DeclareUnicodeCharacter{1E44}{\dotaccent{N}}
\DeclareUnicodeCharacter{1E45}{\dotaccent{n}}
\DeclareUnicodeCharacter{1E46}{\udotaccent{N}}
\DeclareUnicodeCharacter{1E47}{\udotaccent{n}}
\DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}
\DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}
\DeclareUnicodeCharacter{1E54}{\'P}
\DeclareUnicodeCharacter{1E55}{\'p}
\DeclareUnicodeCharacter{1E56}{\dotaccent{P}}
\DeclareUnicodeCharacter{1E57}{\dotaccent{p}}
\DeclareUnicodeCharacter{1E58}{\dotaccent{R}}
\DeclareUnicodeCharacter{1E59}{\dotaccent{r}}
\DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}
\DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}
\DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}
\DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}
\DeclareUnicodeCharacter{1E60}{\dotaccent{S}}
\DeclareUnicodeCharacter{1E61}{\dotaccent{s}}
\DeclareUnicodeCharacter{1E62}{\udotaccent{S}}
\DeclareUnicodeCharacter{1E63}{\udotaccent{s}}
\DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}
\DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}
\DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}
\DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}
\DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}
\DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}
\DeclareUnicodeCharacter{1E7C}{\~V}
\DeclareUnicodeCharacter{1E7D}{\~v}
\DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}
\DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}
\DeclareUnicodeCharacter{1E80}{\`W}
\DeclareUnicodeCharacter{1E81}{\`w}
\DeclareUnicodeCharacter{1E82}{\'W}
\DeclareUnicodeCharacter{1E83}{\'w}
\DeclareUnicodeCharacter{1E84}{\"W}
\DeclareUnicodeCharacter{1E85}{\"w}
\DeclareUnicodeCharacter{1E86}{\dotaccent{W}}
\DeclareUnicodeCharacter{1E87}{\dotaccent{w}}
\DeclareUnicodeCharacter{1E88}{\udotaccent{W}}
\DeclareUnicodeCharacter{1E89}{\udotaccent{w}}
\DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}
\DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}
\DeclareUnicodeCharacter{1E8C}{\"X}
\DeclareUnicodeCharacter{1E8D}{\"x}
\DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}
\DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}
\DeclareUnicodeCharacter{1E90}{\^Z}
\DeclareUnicodeCharacter{1E91}{\^z}
\DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}
\DeclareUnicodeCharacter{1E93}{\udotaccent{z}}
\DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}
\DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}
\DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}
\DeclareUnicodeCharacter{1E97}{\"t}
\DeclareUnicodeCharacter{1E98}{\ringaccent{w}}
\DeclareUnicodeCharacter{1E99}{\ringaccent{y}}
\DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}
\DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}
\DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}
\DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}
\DeclareUnicodeCharacter{1EBC}{\~E}
\DeclareUnicodeCharacter{1EBD}{\~e}
\DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}
\DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}
\DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}
\DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}
\DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}
\DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}
\DeclareUnicodeCharacter{1EF2}{\`Y}
\DeclareUnicodeCharacter{1EF3}{\`y}
\DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}
\DeclareUnicodeCharacter{1EF8}{\~Y}
\DeclareUnicodeCharacter{1EF9}{\~y}
\DeclareUnicodeCharacter{2013}{--}
\DeclareUnicodeCharacter{2014}{---}
\DeclareUnicodeCharacter{2022}{\bullet}
\DeclareUnicodeCharacter{2026}{\dots}
\DeclareUnicodeCharacter{20AC}{\euro}
\DeclareUnicodeCharacter{2192}{\expansion}
\DeclareUnicodeCharacter{21D2}{\result}
\DeclareUnicodeCharacter{2212}{\minus}
\DeclareUnicodeCharacter{2217}{\point}
\DeclareUnicodeCharacter{2261}{\equiv}
}% end of \utfeightchardefs
% US-ASCII character definitions.
\def\asciichardefs{% nothing need be done
\relax
}
% Make non-ASCII characters printable again for compatibility with
% existing Texinfo documents that may use them, even without declaring a
% document encoding.
%
\setnonasciicharscatcode \other
\message{formatting,}
\newdimen\defaultparindent \defaultparindent = 15pt
\chapheadingskip = 15pt plus 4pt minus 2pt
\secheadingskip = 12pt plus 3pt minus 2pt
\subsecheadingskip = 9pt plus 2pt minus 2pt
% Prevent underfull vbox error messages.
\vbadness = 10000
% Don't be so finicky about underfull hboxes, either.
\hbadness = 2000
% Following George Bush, just get rid of widows and orphans.
\widowpenalty=10000
\clubpenalty=10000
% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
% using an old version of TeX, don't do anything. We want the amount of
% stretch added to depend on the line length, hence the dependence on
% \hsize. We call this whenever the paper size is set.
%
\def\setemergencystretch{%
\ifx\emergencystretch\thisisundefined
% Allow us to assign to \emergencystretch anyway.
\def\emergencystretch{\dimen0}%
\else
\emergencystretch = .15\hsize
\fi
}
% Parameters in order: 1) textheight; 2) textwidth;
% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip;
% 7) physical page height; 8) physical page width.
%
% We also call \setleading{\textleading}, so the caller should define
% \textleading. The caller should also set \parskip.
%
\def\internalpagesizes#1#2#3#4#5#6#7#8{%
\voffset = #3\relax
\topskip = #6\relax
\splittopskip = \topskip
%
\vsize = #1\relax
\advance\vsize by \topskip
\outervsize = \vsize
\advance\outervsize by 2\topandbottommargin
\pageheight = \vsize
%
\hsize = #2\relax
\outerhsize = \hsize
\advance\outerhsize by 0.5in
\pagewidth = \hsize
%
\normaloffset = #4\relax
\bindingoffset = #5\relax
%
\ifpdf
\pdfpageheight #7\relax
\pdfpagewidth #8\relax
\fi
%
\setleading{\textleading}
%
\parindent = \defaultparindent
\setemergencystretch
}
% @letterpaper (the default).
\def\letterpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
\textleading = 13.2pt
%
% If page is nothing but text, make it come out even.
\internalpagesizes{46\baselineskip}{6in}%
{\voffset}{.25in}%
{\bindingoffset}{36pt}%
{11in}{8.5in}%
}}
% Use @smallbook to reset parameters for 7x9.25 trim size.
\def\smallbook{{\globaldefs = 1
\parskip = 2pt plus 1pt
\textleading = 12pt
%
\internalpagesizes{7.5in}{5in}%
{\voffset}{.25in}%
{\bindingoffset}{16pt}%
{9.25in}{7in}%
%
\lispnarrowing = 0.3in
\tolerance = 700
\hfuzz = 1pt
\contentsrightmargin = 0pt
\defbodyindent = .5cm
}}
% Use @smallerbook to reset parameters for 6x9 trim size.
% (Just testing, parameters still in flux.)
\def\smallerbook{{\globaldefs = 1
\parskip = 1.5pt plus 1pt
\textleading = 12pt
%
\internalpagesizes{7.4in}{4.8in}%
{-.2in}{-.4in}%
{0pt}{14pt}%
{9in}{6in}%
%
\lispnarrowing = 0.25in
\tolerance = 700
\hfuzz = 1pt
\contentsrightmargin = 0pt
\defbodyindent = .4cm
}}
% Use @afourpaper to print on European A4 paper.
\def\afourpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
\textleading = 13.2pt
%
% Double-side printing via postscript on Laserjet 4050
% prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
% To change the settings for a different printer or situation, adjust
% \normaloffset until the front-side and back-side texts align. Then
% do the same for \bindingoffset. You can set these for testing in
% your texinfo source file like this:
% @tex
% \global\normaloffset = -6mm
% \global\bindingoffset = 10mm
% @end tex
\internalpagesizes{51\baselineskip}{160mm}
{\voffset}{\hoffset}%
{\bindingoffset}{44pt}%
{297mm}{210mm}%
%
\tolerance = 700
\hfuzz = 1pt
\contentsrightmargin = 0pt
\defbodyindent = 5mm
}}
% Use @afivepaper to print on European A5 paper.
% From romildo@urano.iceb.ufop.br, 2 July 2000.
% He also recommends making @example and @lisp be small.
\def\afivepaper{{\globaldefs = 1
\parskip = 2pt plus 1pt minus 0.1pt
\textleading = 12.5pt
%
\internalpagesizes{160mm}{120mm}%
{\voffset}{\hoffset}%
{\bindingoffset}{8pt}%
{210mm}{148mm}%
%
\lispnarrowing = 0.2in
\tolerance = 800
\hfuzz = 1.2pt
\contentsrightmargin = 0pt
\defbodyindent = 2mm
\tableindent = 12mm
}}
% A specific text layout, 24x15cm overall, intended for A4 paper.
\def\afourlatex{{\globaldefs = 1
\afourpaper
\internalpagesizes{237mm}{150mm}%
{\voffset}{4.6mm}%
{\bindingoffset}{7mm}%
{297mm}{210mm}%
%
% Must explicitly reset to 0 because we call \afourpaper.
\globaldefs = 0
}}
% Use @afourwide to print on A4 paper in landscape format.
\def\afourwide{{\globaldefs = 1
\afourpaper
\internalpagesizes{241mm}{165mm}%
{\voffset}{-2.95mm}%
{\bindingoffset}{7mm}%
{297mm}{210mm}%
\globaldefs = 0
}}
% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
% Perhaps we should allow setting the margins, \topskip, \parskip,
% and/or leading, also. Or perhaps we should compute them somehow.
%
\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
\def\pagesizesyyy#1,#2,#3\finish{{%
\setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
\globaldefs = 1
%
\parskip = 3pt plus 2pt minus 1pt
\setleading{\textleading}%
%
\dimen0 = #1
\advance\dimen0 by \voffset
%
\dimen2 = \hsize
\advance\dimen2 by \normaloffset
%
\internalpagesizes{#1}{\hsize}%
{\voffset}{\normaloffset}%
{\bindingoffset}{44pt}%
{\dimen0}{\dimen2}%
}}
% Set default to letter.
%
\letterpaper
\message{and turning on texinfo input format.}
% Define macros to output various characters with catcode for normal text.
\catcode`\"=\other
\catcode`\~=\other
\catcode`\^=\other
\catcode`\_=\other
\catcode`\|=\other
\catcode`\<=\other
\catcode`\>=\other
\catcode`\+=\other
\catcode`\$=\other
\def\normaldoublequote{"}
\def\normaltilde{~}
\def\normalcaret{^}
\def\normalunderscore{_}
\def\normalverticalbar{|}
\def\normalless{<}
\def\normalgreater{>}
\def\normalplus{+}
\def\normaldollar{$}%$ font-lock fix
% This macro is used to make a character print one way in \tt
% (where it can probably be output as-is), and another way in other fonts,
% where something hairier probably needs to be done.
%
% #1 is what to print if we are indeed using \tt; #2 is what to print
% otherwise. Since all the Computer Modern typewriter fonts have zero
% interword stretch (and shrink), and it is reasonable to expect all
% typewriter fonts to have this, we can check that font parameter.
%
\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
% Same as above, but check for italic font. Actually this also catches
% non-italic slanted fonts since it is impossible to distinguish them from
% italic fonts. But since this is only used by $ and it uses \sl anyway
% this is not a problem.
\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
% Turn off all special characters except @
% (and those which the user can use as if they were ordinary).
% Most of these we simply print from the \tt font, but for some, we can
% use math or other variants that look better in normal text.
\catcode`\"=\active
\def\activedoublequote{{\tt\char34}}
\let"=\activedoublequote
\catcode`\~=\active
\def~{{\tt\char126}}
\chardef\hat=`\^
\catcode`\^=\active
\def^{{\tt \hat}}
\catcode`\_=\active
\def_{\ifusingtt\normalunderscore\_}
\let\realunder=_
% Subroutine for the previous macro.
\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
\catcode`\|=\active
\def|{{\tt\char124}}
\chardef \less=`\<
\catcode`\<=\active
\def<{{\tt \less}}
\chardef \gtr=`\>
\catcode`\>=\active
\def>{{\tt \gtr}}
\catcode`\+=\active
\def+{{\tt \char 43}}
\catcode`\$=\active
\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
% If a .fmt file is being used, characters that might appear in a file
% name cannot be active until we have parsed the command line.
% So turn them off again, and have \everyjob (or @setfilename) turn them on.
% \otherifyactive is called near the end of this file.
\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
% Used sometimes to turn off (effectively) the active characters even after
% parsing them.
\def\turnoffactive{%
\normalturnoffactive
\otherbackslash
}
\catcode`\@=0
% \backslashcurfont outputs one backslash character in current font,
% as in \char`\\.
\global\chardef\backslashcurfont=`\\
\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work
% \realbackslash is an actual character `\' with catcode other, and
% \doublebackslash is two of them (for the pdf outlines).
{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}}
% In texinfo, backslash is an active character; it prints the backslash
% in fixed width font.
\catcode`\\=\active
@def@normalbackslash{{@tt@backslashcurfont}}
% On startup, @fixbackslash assigns:
% @let \ = @normalbackslash
% \rawbackslash defines an active \ to do \backslashcurfont.
% \otherbackslash defines an active \ to be a literal `\' character with
% catcode other.
@gdef@rawbackslash{@let\=@backslashcurfont}
@gdef@otherbackslash{@let\=@realbackslash}
% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
% the literal character `\'.
%
@def@normalturnoffactive{%
@let\=@normalbackslash
@let"=@normaldoublequote
@let~=@normaltilde
@let^=@normalcaret
@let_=@normalunderscore
@let|=@normalverticalbar
@let<=@normalless
@let>=@normalgreater
@let+=@normalplus
@let$=@normaldollar %$ font-lock fix
@unsepspaces
}
% Make _ and + \other characters, temporarily.
% This is canceled by @fixbackslash.
@otherifyactive
% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
% That is what \eatinput is for; after that, the `\' should revert to printing
% a backslash.
%
@gdef@eatinput input texinfo{@fixbackslash}
@global@let\ = @eatinput
% On the other hand, perhaps the file did not have a `\input texinfo'. Then
% the first `\' in the file would cause an error. This macro tries to fix
% that, assuming it is called before the first `\' could plausibly occur.
% Also turn back on active characters that might appear in the input
% file name, in case not using a pre-dumped format.
%
@gdef@fixbackslash{%
@ifx\@eatinput @let\ = @normalbackslash @fi
@catcode`+=@active
@catcode`@_=@active
}
% Say @foo, not \foo, in error messages.
@escapechar = `@@
% These look ok in all fonts, so just make them not special.
@catcode`@& = @other
@catcode`@# = @other
@catcode`@% = @other
@c Local variables:
@c eval: (add-hook 'write-file-hooks 'time-stamp)
@c page-delimiter: "^\\\\message"
@c time-stamp-start: "def\\\\texinfoversion{"
@c time-stamp-format: "%:y-%02m-%02d.%02H"
@c time-stamp-end: "}"
@c End:
@c vim:sw=2:
@ignore
arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
@end ignore
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 2acd7cb3..efcf8f90 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -1,149 +1,149 @@
# 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/>.
+# License along with this program; if not, see <https://www.gnu.org/licenses/>.
# Process this file with automake to produce Makefile.in
# Need to include ../src in addition to top_srcdir because gcrypt.h is
# a built header.
AM_CPPFLAGS = -I../src -I$(top_srcdir)/src -I../mpi -I$(top_srcdir)/mpi
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-armv7-neon.S \
cipher-gcm-armv8-aarch32-ce.S cipher-gcm-armv8-aarch64-ce.S \
cipher-poly1305.c \
cipher-ocb.c \
cipher-xts.c \
cipher-eax.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 = \
asm-common-amd64.h \
asm-common-aarch64.h \
asm-poly1305-amd64.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 \
crc.c crc-intel-pclmul.c crc-armv8-ce.c \
crc-armv8-aarch64-ce.S \
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 \
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-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 \
sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S \
sha512-avx2-bmi2-amd64.S \
sha512-armv7-neon.S sha512-arm.S \
sm3.c \
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 \
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
if ENABLE_O_FLAG_MUNGING
o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-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.lo: $(srcdir)/tiger.c
`echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) `
diff --git a/cipher/asm-common-aarch64.h b/cipher/asm-common-aarch64.h
index 4ffc1b71..f712ad15 100644
--- a/cipher/asm-common-aarch64.h
+++ b/cipher/asm-common-aarch64.h
@@ -1,100 +1,100 @@
/* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_ASM_COMMON_AARCH64_H
#define GCRY_ASM_COMMON_AARCH64_H
#include <config.h>
#ifdef __ELF__
# define ELF(...) __VA_ARGS__
#else
# define ELF(...) /*_*/
#endif
#ifdef _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
#endif /* GCRY_ASM_COMMON_AARCH64_H */
diff --git a/cipher/asm-common-amd64.h b/cipher/asm-common-amd64.h
index 9d4a028a..0b130a06 100644
--- a/cipher/asm-common-amd64.h
+++ b/cipher/asm-common-amd64.h
@@ -1,189 +1,189 @@
/* 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/>.
+ * License along with this program; if not, see <https://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
#endif /* GCRY_ASM_COMMON_AMD64_H */
diff --git a/cipher/asm-poly1305-amd64.h b/cipher/asm-poly1305-amd64.h
index 3f99ea3e..e39b56bf 100644
--- a/cipher/asm-poly1305-amd64.h
+++ b/cipher/asm-poly1305-amd64.h
@@ -1,171 +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/>.
+ * License along with this program; if not, see <https://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/bithelp.h b/cipher/bithelp.h
index 26ef7c35..eceeee2d 100644
--- a/cipher/bithelp.h
+++ b/cipher/bithelp.h
@@ -1,121 +1,121 @@
/* bithelp.h - Some bit manipulation helpers
* Copyright (C) 1999, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRYPT_BITHELP_H
#define GCRYPT_BITHELP_H
#include "types.h"
/****************
* Rotate the 32 bit unsigned integer X by N bits left/right
*/
static inline u32 rol(u32 x, int n)
{
return ( (x << (n&(32-1))) | (x >> ((32-n)&(32-1))) );
}
static inline u32 ror(u32 x, int n)
{
return ( (x >> (n&(32-1))) | (x << ((32-n)&(32-1))) );
}
static inline u64 rol64(u64 x, int n)
{
return ( (x << (n&(64-1))) | (x >> ((64-n)&(64-1))) );
}
/* Byte swap for 32-bit and 64-bit integers. If available, use compiler
provided helpers. */
#ifdef HAVE_BUILTIN_BSWAP32
# define _gcry_bswap32 __builtin_bswap32
#else
static inline u32
_gcry_bswap32(u32 x)
{
return ((rol(x, 8) & 0x00ff00ffL) | (ror(x, 8) & 0xff00ff00L));
}
#endif
#ifdef HAVE_BUILTIN_BSWAP64
# define _gcry_bswap64 __builtin_bswap64
#else
static inline u64
_gcry_bswap64(u64 x)
{
return ((u64)_gcry_bswap32(x) << 32) | (_gcry_bswap32(x >> 32));
}
#endif
/* Endian dependent byte swap operations. */
#ifdef WORDS_BIGENDIAN
# define le_bswap32(x) _gcry_bswap32(x)
# define be_bswap32(x) ((u32)(x))
# define le_bswap64(x) _gcry_bswap64(x)
# define be_bswap64(x) ((u64)(x))
#else
# define le_bswap32(x) ((u32)(x))
# define be_bswap32(x) _gcry_bswap32(x)
# define le_bswap64(x) ((u64)(x))
# define be_bswap64(x) _gcry_bswap64(x)
#endif
/* Count trailing zero bits in an unsigend int. We return an int
because that is what gcc's builtin does. Returns the number of
bits in X if X is 0. */
static inline int
_gcry_ctz (unsigned int x)
{
#if defined (HAVE_BUILTIN_CTZ)
return x? __builtin_ctz (x) : 8 * sizeof (x);
#else
/* See
- * http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup
+ * https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup
*/
static const unsigned char mod37[] =
{
sizeof (unsigned int)*8,
0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13,
4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9,
5, 20, 8, 19, 18
};
return (int)mod37[(-x & x) % 37];
#endif
}
/* Count trailing zero bits in an u64. We return an int because that
is what gcc's builtin does. Returns the number of bits in X if X
is 0. */
static inline int
_gcry_ctz64(u64 x)
{
#if defined (HAVE_BUILTIN_CTZ) && SIZEOF_UNSIGNED_INT >= 8
#warning hello
return x? __builtin_ctz (x) : 8 * sizeof (x);
#else
if ((x & 0xffffffff))
return _gcry_ctz (x);
else
return 32 + _gcry_ctz (x >> 32);
#endif
}
#endif /*GCRYPT_BITHELP_H*/
diff --git a/cipher/blake2.c b/cipher/blake2.c
index f2bf49e5..6c1acc23 100644
--- a/cipher/blake2.c
+++ b/cipher/blake2.c
@@ -1,996 +1,996 @@
/* blake2.c - BLAKE2b and BLAKE2s hash functions (RFC 7693)
* Copyright (C) 2017 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/>.
+ * License along with this program; if not, see <https://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/ref
* Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
*/
#include <config.h>
#include <string.h>
#include "g10lib.h"
#include "bithelp.h"
#include "bufhelp.h"
#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
#define BLAKE2S_BLOCKBYTES 64
#define BLAKE2S_OUTBYTES 32
#define BLAKE2S_KEYBYTES 32
typedef struct
{
u64 h[8];
u64 t[2];
u64 f[2];
} BLAKE2B_STATE;
struct blake2b_param_s
{
byte digest_length;
byte key_length;
byte fanout;
byte depth;
byte leaf_length[4];
byte node_offset[4];
byte xof_length[4];
byte node_depth;
byte inner_length;
byte reserved[14];
byte salt[16];
byte personal[16];
};
typedef struct BLAKE2B_CONTEXT_S
{
BLAKE2B_STATE state;
byte buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
#ifdef USE_AVX2
unsigned int use_avx2:1;
#endif
} BLAKE2B_CONTEXT;
typedef struct
{
u32 h[8];
u32 t[2];
u32 f[2];
} BLAKE2S_STATE;
struct blake2s_param_s
{
byte digest_length;
byte key_length;
byte fanout;
byte depth;
byte leaf_length[4];
byte node_offset[4];
byte xof_length[2];
byte node_depth;
byte inner_length;
/* byte reserved[0]; */
byte salt[8];
byte personal[8];
};
typedef struct BLAKE2S_CONTEXT_S
{
BLAKE2S_STATE state;
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,
size_t nblks);
static const u64 blake2b_IV[8] =
{
U64_C(0x6a09e667f3bcc908), U64_C(0xbb67ae8584caa73b),
U64_C(0x3c6ef372fe94f82b), U64_C(0xa54ff53a5f1d36f1),
U64_C(0x510e527fade682d1), U64_C(0x9b05688c2b3e6c1f),
U64_C(0x1f83d9abfb41bd6b), U64_C(0x5be0cd19137e2179)
};
static const u32 blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static byte zero_block[BLAKE2B_BLOCKBYTES] = { 0, };
static void blake2_write(void *S, const void *inbuf, size_t inlen,
byte *tmpbuf, size_t *tmpbuflen, size_t blkbytes,
blake2_transform_t transform_fn)
{
const byte* in = inbuf;
unsigned int burn = 0;
if (inlen > 0)
{
size_t left = *tmpbuflen;
size_t fill = blkbytes - left;
size_t nblks;
if (inlen > fill)
{
if (fill > 0)
buf_cpy (tmpbuf + left, in, fill); /* Fill buffer */
left = 0;
burn = transform_fn (S, tmpbuf, 1); /* Increment counter + Compress */
in += fill;
inlen -= fill;
nblks = inlen / blkbytes - !(inlen % blkbytes);
if (nblks)
{
burn = transform_fn(S, in, nblks);
in += blkbytes * nblks;
inlen -= blkbytes * nblks;
}
}
gcry_assert (inlen > 0);
buf_cpy (tmpbuf + left, in, inlen);
*tmpbuflen = left + inlen;
}
if (burn)
_gcry_burn_stack (burn);
return;
}
static inline void blake2b_set_lastblock(BLAKE2B_STATE *S)
{
S->f[0] = U64_C(0xffffffffffffffff);
}
static inline int blake2b_is_lastblock(const BLAKE2B_STATE *S)
{
return S->f[0] != 0;
}
static inline void blake2b_increment_counter(BLAKE2B_STATE *S, const int inc)
{
S->t[0] += (u64)inc;
S->t[1] += (S->t[0] < (u64)inc) - (inc < 0);
}
static inline u64 rotr64(u64 x, u64 n)
{
return ((x >> (n & 63)) | (x << ((64 - n) & 63)));
}
static unsigned int blake2b_transform_generic(BLAKE2B_STATE *S,
const void *inblks,
size_t nblks)
{
static const byte blake2b_sigma[12][16] =
{
{ 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 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 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 },
{ 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 }
};
const byte* in = inblks;
u64 m[16];
u64 v[16];
while (nblks--)
{
/* Increment counter */
blake2b_increment_counter (S, BLAKE2B_BLOCKBYTES);
/* Compress */
m[0] = buf_get_le64 (in + 0 * sizeof(m[0]));
m[1] = buf_get_le64 (in + 1 * sizeof(m[0]));
m[2] = buf_get_le64 (in + 2 * sizeof(m[0]));
m[3] = buf_get_le64 (in + 3 * sizeof(m[0]));
m[4] = buf_get_le64 (in + 4 * sizeof(m[0]));
m[5] = buf_get_le64 (in + 5 * sizeof(m[0]));
m[6] = buf_get_le64 (in + 6 * sizeof(m[0]));
m[7] = buf_get_le64 (in + 7 * sizeof(m[0]));
m[8] = buf_get_le64 (in + 8 * sizeof(m[0]));
m[9] = buf_get_le64 (in + 9 * sizeof(m[0]));
m[10] = buf_get_le64 (in + 10 * sizeof(m[0]));
m[11] = buf_get_le64 (in + 11 * sizeof(m[0]));
m[12] = buf_get_le64 (in + 12 * sizeof(m[0]));
m[13] = buf_get_le64 (in + 13 * sizeof(m[0]));
m[14] = buf_get_le64 (in + 14 * sizeof(m[0]));
m[15] = buf_get_le64 (in + 15 * sizeof(m[0]));
v[ 0] = S->h[0];
v[ 1] = S->h[1];
v[ 2] = S->h[2];
v[ 3] = S->h[3];
v[ 4] = S->h[4];
v[ 5] = S->h[5];
v[ 6] = S->h[6];
v[ 7] = S->h[7];
v[ 8] = blake2b_IV[0];
v[ 9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
ROUND(10);
ROUND(11);
#undef G
#undef ROUND
S->h[0] = S->h[0] ^ v[0] ^ v[0 + 8];
S->h[1] = S->h[1] ^ v[1] ^ v[1 + 8];
S->h[2] = S->h[2] ^ v[2] ^ v[2 + 8];
S->h[3] = S->h[3] ^ v[3] ^ v[3 + 8];
S->h[4] = S->h[4] ^ v[4] ^ v[4 + 8];
S->h[5] = S->h[5] ^ v[5] ^ v[5 + 8];
S->h[6] = S->h[6] ^ v[6] ^ v[6 + 8];
S->h[7] = S->h[7] ^ v[7] ^ v[7 + 8];
in += BLAKE2B_BLOCKBYTES;
}
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;
BLAKE2B_STATE *S = &c->state;
unsigned int burn;
size_t i;
gcry_assert (sizeof(c->buf) >= c->outlen);
if (blake2b_is_lastblock(S))
return;
if (c->buflen < BLAKE2B_BLOCKBYTES)
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 (ctx, c->buf, 1);
/* Output full hash to buffer */
for (i = 0; i < 8; ++i)
buf_put_le64 (c->buf + sizeof(S->h[i]) * i, S->h[i]);
/* Zero out extra buffer bytes. */
if (c->outlen < sizeof(c->buf))
memset (c->buf + c->outlen, 0, sizeof(c->buf) - c->outlen);
if (burn)
_gcry_burn_stack (burn);
}
static byte *blake2b_read(void *ctx)
{
BLAKE2B_CONTEXT *c = ctx;
return c->buf;
}
static void blake2b_write(void *ctx, const void *inbuf, size_t inlen)
{
BLAKE2B_CONTEXT *c = ctx;
BLAKE2B_STATE *S = &c->state;
blake2_write(S, inbuf, inlen, c->buf, &c->buflen, BLAKE2B_BLOCKBYTES,
blake2b_transform);
}
static inline void blake2b_init_param(BLAKE2B_STATE *S,
const struct blake2b_param_s *P)
{
const byte *p = (const byte *)P;
size_t i;
/* init xors IV with input parameter block */
/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i)
S->h[i] = blake2b_IV[i] ^ buf_get_le64(p + sizeof(S->h[i]) * i);
}
static inline gcry_err_code_t blake2b_init(BLAKE2B_CONTEXT *ctx,
const byte *key, size_t keylen)
{
struct blake2b_param_s P[1] = { { 0, } };
BLAKE2B_STATE *S = &ctx->state;
if (!ctx->outlen || ctx->outlen > BLAKE2B_OUTBYTES)
return GPG_ERR_INV_ARG;
if (sizeof(P[0]) != sizeof(u64) * 8)
return GPG_ERR_INTERNAL;
if (keylen && (!key || keylen > BLAKE2B_KEYBYTES))
return GPG_ERR_INV_KEYLEN;
P->digest_length = ctx->outlen;
P->key_length = keylen;
P->fanout = 1;
P->depth = 1;
blake2b_init_param (S, P);
wipememory (P, sizeof(P));
if (key)
{
blake2b_write (ctx, key, keylen);
blake2b_write (ctx, zero_block, BLAKE2B_BLOCKBYTES - keylen);
}
return 0;
}
static gcry_err_code_t blake2b_init_ctx(void *ctx, unsigned int flags,
const byte *key, size_t keylen,
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);
}
static inline void blake2s_set_lastblock(BLAKE2S_STATE *S)
{
S->f[0] = 0xFFFFFFFFUL;
}
static inline int blake2s_is_lastblock(BLAKE2S_STATE *S)
{
return S->f[0] != 0;
}
static inline void blake2s_increment_counter(BLAKE2S_STATE *S, const int inc)
{
S->t[0] += (u32)inc;
S->t[1] += (S->t[0] < (u32)inc) - (inc < 0);
}
static unsigned int blake2s_transform_generic(BLAKE2S_STATE *S,
const void *inblks,
size_t nblks)
{
static const byte blake2s_sigma[10][16] =
{
{ 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 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 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 },
};
unsigned int burn = 0;
const byte* in = inblks;
u32 m[16];
u32 v[16];
while (nblks--)
{
/* Increment counter */
blake2s_increment_counter (S, BLAKE2S_BLOCKBYTES);
/* Compress */
m[0] = buf_get_le32 (in + 0 * sizeof(m[0]));
m[1] = buf_get_le32 (in + 1 * sizeof(m[0]));
m[2] = buf_get_le32 (in + 2 * sizeof(m[0]));
m[3] = buf_get_le32 (in + 3 * sizeof(m[0]));
m[4] = buf_get_le32 (in + 4 * sizeof(m[0]));
m[5] = buf_get_le32 (in + 5 * sizeof(m[0]));
m[6] = buf_get_le32 (in + 6 * sizeof(m[0]));
m[7] = buf_get_le32 (in + 7 * sizeof(m[0]));
m[8] = buf_get_le32 (in + 8 * sizeof(m[0]));
m[9] = buf_get_le32 (in + 9 * sizeof(m[0]));
m[10] = buf_get_le32 (in + 10 * sizeof(m[0]));
m[11] = buf_get_le32 (in + 11 * sizeof(m[0]));
m[12] = buf_get_le32 (in + 12 * sizeof(m[0]));
m[13] = buf_get_le32 (in + 13 * sizeof(m[0]));
m[14] = buf_get_le32 (in + 14 * sizeof(m[0]));
m[15] = buf_get_le32 (in + 15 * sizeof(m[0]));
v[ 0] = S->h[0];
v[ 1] = S->h[1];
v[ 2] = S->h[2];
v[ 3] = S->h[3];
v[ 4] = S->h[4];
v[ 5] = S->h[5];
v[ 6] = S->h[6];
v[ 7] = S->h[7];
v[ 8] = blake2s_IV[0];
v[ 9] = blake2s_IV[1];
v[10] = blake2s_IV[2];
v[11] = blake2s_IV[3];
v[12] = S->t[0] ^ blake2s_IV[4];
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
d = ror(d ^ a, 16); \
c = c + d; \
b = ror(b ^ c, 12); \
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
d = ror(d ^ a, 8); \
c = c + d; \
b = ror(b ^ c, 7); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
#undef G
#undef ROUND
S->h[0] = S->h[0] ^ v[0] ^ v[0 + 8];
S->h[1] = S->h[1] ^ v[1] ^ v[1 + 8];
S->h[2] = S->h[2] ^ v[2] ^ v[2 + 8];
S->h[3] = S->h[3] ^ v[3] ^ v[3 + 8];
S->h[4] = S->h[4] ^ v[4] ^ v[4 + 8];
S->h[5] = S->h[5] ^ v[5] ^ v[5 + 8];
S->h[6] = S->h[6] ^ v[6] ^ v[6 + 8];
S->h[7] = S->h[7] ^ v[7] ^ v[7 + 8];
in += BLAKE2S_BLOCKBYTES;
}
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;
BLAKE2S_STATE *S = &c->state;
unsigned int burn;
size_t i;
gcry_assert (sizeof(c->buf) >= c->outlen);
if (blake2s_is_lastblock(S))
return;
if (c->buflen < BLAKE2S_BLOCKBYTES)
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 (ctx, c->buf, 1);
/* Output full hash to buffer */
for (i = 0; i < 8; ++i)
buf_put_le32 (c->buf + sizeof(S->h[i]) * i, S->h[i]);
/* Zero out extra buffer bytes. */
if (c->outlen < sizeof(c->buf))
memset (c->buf + c->outlen, 0, sizeof(c->buf) - c->outlen);
if (burn)
_gcry_burn_stack (burn);
}
static byte *blake2s_read(void *ctx)
{
BLAKE2S_CONTEXT *c = ctx;
return c->buf;
}
static void blake2s_write(void *ctx, const void *inbuf, size_t inlen)
{
BLAKE2S_CONTEXT *c = ctx;
BLAKE2S_STATE *S = &c->state;
blake2_write(S, inbuf, inlen, c->buf, &c->buflen, BLAKE2S_BLOCKBYTES,
blake2s_transform);
}
static inline void blake2s_init_param(BLAKE2S_STATE *S,
const struct blake2s_param_s *P)
{
const byte *p = (const byte *)P;
size_t i;
/* init2 xors IV with input parameter block */
/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i)
S->h[i] ^= blake2s_IV[i] ^ buf_get_le32(&p[i * 4]);
}
static inline gcry_err_code_t blake2s_init(BLAKE2S_CONTEXT *ctx,
const byte *key, size_t keylen)
{
struct blake2s_param_s P[1] = { { 0, } };
BLAKE2S_STATE *S = &ctx->state;
if (!ctx->outlen || ctx->outlen > BLAKE2S_OUTBYTES)
return GPG_ERR_INV_ARG;
if (sizeof(P[0]) != sizeof(u32) * 8)
return GPG_ERR_INTERNAL;
if (keylen && (!key || keylen > BLAKE2S_KEYBYTES))
return GPG_ERR_INV_KEYLEN;
P->digest_length = ctx->outlen;
P->key_length = keylen;
P->fanout = 1;
P->depth = 1;
blake2s_init_param (S, P);
wipememory (P, sizeof(P));
if (key)
{
blake2s_write (ctx, key, keylen);
blake2s_write (ctx, zero_block, BLAKE2S_BLOCKBYTES - keylen);
}
return 0;
}
static gcry_err_code_t blake2s_init_ctx(void *ctx, unsigned int flags,
const byte *key, size_t keylen,
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);
}
/* Selftests from "RFC 7693, Appendix E. BLAKE2b and BLAKE2s Self-Test
* Module C Source". */
static void selftest_seq(byte *out, size_t len, u32 seed)
{
size_t i;
u32 t, a, b;
a = 0xDEAD4BAD * seed;
b = 1;
for (i = 0; i < len; i++)
{
t = a + b;
a = b;
b = t;
out[i] = (t >> 24) & 0xFF;
}
}
static gpg_err_code_t
selftests_blake2b (int algo, int extended, selftest_report_func_t report)
{
static const byte blake2b_res[32] =
{
0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD,
0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56,
0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73,
0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75
};
static const size_t b2b_md_len[4] = { 20, 32, 48, 64 };
static const size_t b2b_in_len[6] = { 0, 3, 128, 129, 255, 1024 };
size_t i, j, outlen, inlen;
byte in[1024], key[64];
BLAKE2B_CONTEXT ctx;
BLAKE2B_CONTEXT ctx2;
const char *what;
const char *errtxt;
(void)extended;
what = "rfc7693 BLAKE2b selftest";
/* 256-bit hash for testing */
if (blake2b_init_ctx(&ctx, 0, NULL, 0, 32 * 8))
{
errtxt = "init failed";
goto failed;
}
for (i = 0; i < 4; i++)
{
outlen = b2b_md_len[i];
for (j = 0; j < 6; j++)
{
inlen = b2b_in_len[j];
selftest_seq(in, inlen, inlen); /* unkeyed hash */
blake2b_init_ctx(&ctx2, 0, NULL, 0, outlen * 8);
blake2b_write(&ctx2, in, inlen);
blake2b_final(&ctx2);
blake2b_write(&ctx, ctx2.buf, outlen); /* hash the hash */
selftest_seq(key, outlen, outlen); /* keyed hash */
blake2b_init_ctx(&ctx2, 0, key, outlen, outlen * 8);
blake2b_write(&ctx2, in, inlen);
blake2b_final(&ctx2);
blake2b_write(&ctx, ctx2.buf, outlen); /* hash the hash */
}
}
/* compute and compare the hash of hashes */
blake2b_final(&ctx);
for (i = 0; i < 32; i++)
{
if (ctx.buf[i] != blake2b_res[i])
{
errtxt = "digest mismatch";
goto failed;
}
}
return 0;
failed:
if (report)
report ("digest", algo, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
static gpg_err_code_t
selftests_blake2s (int algo, int extended, selftest_report_func_t report)
{
static const byte blake2s_res[32] =
{
0x6A, 0x41, 0x1F, 0x08, 0xCE, 0x25, 0xAD, 0xCD,
0xFB, 0x02, 0xAB, 0xA6, 0x41, 0x45, 0x1C, 0xEC,
0x53, 0xC5, 0x98, 0xB2, 0x4F, 0x4F, 0xC7, 0x87,
0xFB, 0xDC, 0x88, 0x79, 0x7F, 0x4C, 0x1D, 0xFE
};
static const size_t b2s_md_len[4] = { 16, 20, 28, 32 };
static const size_t b2s_in_len[6] = { 0, 3, 64, 65, 255, 1024 };
size_t i, j, outlen, inlen;
byte in[1024], key[32];
BLAKE2S_CONTEXT ctx;
BLAKE2S_CONTEXT ctx2;
const char *what;
const char *errtxt;
(void)extended;
what = "rfc7693 BLAKE2s selftest";
/* 256-bit hash for testing */
if (blake2s_init_ctx(&ctx, 0, NULL, 0, 32 * 8))
{
errtxt = "init failed";
goto failed;
}
for (i = 0; i < 4; i++)
{
outlen = b2s_md_len[i];
for (j = 0; j < 6; j++)
{
inlen = b2s_in_len[j];
selftest_seq(in, inlen, inlen); /* unkeyed hash */
blake2s_init_ctx(&ctx2, 0, NULL, 0, outlen * 8);
blake2s_write(&ctx2, in, inlen);
blake2s_final(&ctx2);
blake2s_write(&ctx, ctx2.buf, outlen); /* hash the hash */
selftest_seq(key, outlen, outlen); /* keyed hash */
blake2s_init_ctx(&ctx2, 0, key, outlen, outlen * 8);
blake2s_write(&ctx2, in, inlen);
blake2s_final(&ctx2);
blake2s_write(&ctx, ctx2.buf, outlen); /* hash the hash */
}
}
/* compute and compare the hash of hashes */
blake2s_final(&ctx);
for (i = 0; i < 32; i++)
{
if (ctx.buf[i] != blake2s_res[i])
{
errtxt = "digest mismatch";
goto failed;
}
}
return 0;
failed:
if (report)
report ("digest", algo, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags,
const unsigned char *key,
size_t keylen, int algo)
{
gcry_err_code_t rc;
switch (algo)
{
case GCRY_MD_BLAKE2B_512:
rc = blake2b_init_ctx (ctx, flags, key, keylen, 512);
break;
case GCRY_MD_BLAKE2B_384:
rc = blake2b_init_ctx (ctx, flags, key, keylen, 384);
break;
case GCRY_MD_BLAKE2B_256:
rc = blake2b_init_ctx (ctx, flags, key, keylen, 256);
break;
case GCRY_MD_BLAKE2B_160:
rc = blake2b_init_ctx (ctx, flags, key, keylen, 160);
break;
case GCRY_MD_BLAKE2S_256:
rc = blake2s_init_ctx (ctx, flags, key, keylen, 256);
break;
case GCRY_MD_BLAKE2S_224:
rc = blake2s_init_ctx (ctx, flags, key, keylen, 224);
break;
case GCRY_MD_BLAKE2S_160:
rc = blake2s_init_ctx (ctx, flags, key, keylen, 160);
break;
case GCRY_MD_BLAKE2S_128:
rc = blake2s_init_ctx (ctx, flags, key, keylen, 128);
break;
default:
rc = GPG_ERR_DIGEST_ALGO;
break;
}
return rc;
}
#define DEFINE_BLAKE2_VARIANT(bs, BS, dbits, oid_branch) \
static void blake2##bs##_##dbits##_init(void *ctx, unsigned int flags) \
{ \
int err = blake2##bs##_init_ctx (ctx, flags, NULL, 0, dbits); \
gcry_assert (err == 0); \
} \
static void \
_gcry_blake2##bs##_##dbits##_hash_buffer(void *outbuf, \
const void *buffer, size_t length) \
{ \
BLAKE2##BS##_CONTEXT hd; \
blake2##bs##_##dbits##_init (&hd, 0); \
blake2##bs##_write (&hd, buffer, length); \
blake2##bs##_final (&hd); \
memcpy (outbuf, blake2##bs##_read (&hd), dbits / 8); \
} \
static void \
_gcry_blake2##bs##_##dbits##_hash_buffers(void *outbuf, \
const gcry_buffer_t *iov, int iovcnt) \
{ \
BLAKE2##BS##_CONTEXT hd; \
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 byte blake2##bs##_##dbits##_asn[] = { 0x30 }; \
static 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 = \
{ \
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_buffer, \
_gcry_blake2##bs##_##dbits##_hash_buffers, \
sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \
};
DEFINE_BLAKE2_VARIANT(b, B, 512, "1.16")
DEFINE_BLAKE2_VARIANT(b, B, 384, "1.12")
DEFINE_BLAKE2_VARIANT(b, B, 256, "1.8")
DEFINE_BLAKE2_VARIANT(b, B, 160, "1.5")
DEFINE_BLAKE2_VARIANT(s, S, 256, "2.8")
DEFINE_BLAKE2_VARIANT(s, S, 224, "2.7")
DEFINE_BLAKE2_VARIANT(s, S, 160, "2.5")
DEFINE_BLAKE2_VARIANT(s, S, 128, "2.4")
diff --git a/cipher/blake2b-amd64-avx2.S b/cipher/blake2b-amd64-avx2.S
index 08c816cd..1ee416e7 100644
--- a/cipher/blake2b-amd64-avx2.S
+++ b/cipher/blake2b-amd64-avx2.S
@@ -1,300 +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/>.
+ * License along with this program; if not, see <https://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 (RIP), R16;
vbroadcasti128 .Lshuf_ror24 (RIP), R24;
vmovdqa .Liv+(0 * 8) (RIP), ROW3;
vmovdqa .Liv+(4 * 8) (RIP), 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) (RIP), ROW3;
vmovdqa .Liv+(4 * 8) (RIP), 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;
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
index 19837326..b322c518 100644
--- a/cipher/blake2s-amd64-avx.S
+++ b/cipher/blake2s-amd64-avx.S
@@ -1,278 +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/>.
+ * License along with this program; if not, see <https://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 (RIP), R16;
vmovdqa .Lshuf_ror8 (RIP), R8;
vmovdqa .Liv+(0 * 4) (RIP), ROW3;
vmovdqa .Liv+(4 * 4) (RIP), 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) (RIP), ROW3;
vmovdqa .Liv+(4 * 4) (RIP), 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;
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*/
diff --git a/cipher/blowfish-amd64.S b/cipher/blowfish-amd64.S
index bdb361d7..5231d333 100644
--- a/cipher/blowfish-amd64.S
+++ b/cipher/blowfish-amd64.S
@@ -1,601 +1,601 @@
/* blowfish-amd64.S - AMD64 assembly implementation of Blowfish cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef __x86_64
#include <config.h>
#if defined(USE_BLOWFISH) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
#include "asm-common-amd64.h"
.text
/* structure of BLOWFISH_context: */
#define s0 0
#define s1 ((s0) + 256 * 4)
#define s2 ((s1) + 256 * 4)
#define s3 ((s2) + 256 * 4)
#define p ((s3) + 256 * 4)
/* register macros */
#define CTX %rdi
#define RIO %rsi
#define RX0 %rax
#define RX1 %rbx
#define RX2 %rcx
#define RX3 %rdx
#define RX0d %eax
#define RX1d %ebx
#define RX2d %ecx
#define RX3d %edx
#define RX0bl %al
#define RX1bl %bl
#define RX2bl %cl
#define RX3bl %dl
#define RX0bh %ah
#define RX1bh %bh
#define RX2bh %ch
#define RX3bh %dh
#define RT0 %rbp
#define RT1 %rsi
#define RT2 %r8
#define RT3 %r9
#define RT0d %ebp
#define RT1d %esi
#define RT2d %r8d
#define RT3d %r9d
#define RKEY %r10
/***********************************************************************
* 1-way blowfish
***********************************************************************/
#define F() \
movzbl RX0bh, RT1d; \
movzbl RX0bl, RT3d; \
rorq $16, RX0; \
movzbl RX0bh, RT0d; \
movzbl RX0bl, RT2d; \
rorq $16, RX0; \
movl s0(CTX,RT0,4), RT0d; \
addl s1(CTX,RT2,4), RT0d; \
xorl s2(CTX,RT1,4), RT0d; \
addl s3(CTX,RT3,4), RT0d; \
xorq RT0, RX0;
#define load_roundkey_enc(n) \
movq p+4*(n)(CTX), RX3;
#define add_roundkey_enc() \
xorq RX3, RX0;
#define round_enc(n) \
add_roundkey_enc(); \
load_roundkey_enc(n); \
\
F(); \
F();
#define load_roundkey_dec(n) \
movq p+4*(n-1)(CTX), RX3; \
rorq $32, RX3;
#define add_roundkey_dec() \
xorq RX3, RX0;
#define round_dec(n) \
add_roundkey_dec(); \
load_roundkey_dec(n); \
\
F(); \
F();
#define read_block() \
movq (RIO), RX0; \
rorq $32, RX0; \
bswapq RX0;
#define write_block() \
bswapq RX0; \
movq RX0, (RIO);
.align 8
ELF(.type __blowfish_enc_blk1,@function;)
__blowfish_enc_blk1:
/* input:
* %rdi: ctx, CTX
* RX0: input plaintext block
* output:
* RX0: output plaintext block
*/
CFI_STARTPROC();
movq %rbp, %r11;
CFI_REGISTER(%rbp, %r11);
load_roundkey_enc(0);
round_enc(2);
round_enc(4);
round_enc(6);
round_enc(8);
round_enc(10);
round_enc(12);
round_enc(14);
round_enc(16);
add_roundkey_enc();
movq %r11, %rbp;
CFI_RESTORE(%rbp)
ret;
CFI_ENDPROC();
ELF(.size __blowfish_enc_blk1,.-__blowfish_enc_blk1;)
.align 8
.globl _gcry_blowfish_amd64_do_encrypt
ELF(.type _gcry_blowfish_amd64_do_encrypt,@function;)
_gcry_blowfish_amd64_do_encrypt:
/* input:
* %rdi: ctx, CTX
* %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;
movq %rdx, %r10;
orq RT3, RX0;
movq %rsi, RX2;
call __blowfish_enc_blk1;
movl RX0d, (%r10);
shrq $32, RX0;
movl RX0d, (RX2);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_do_encrypt,.-_gcry_blowfish_amd64_do_encrypt;)
.align 8
.globl _gcry_blowfish_amd64_encrypt_block
ELF(.type _gcry_blowfish_amd64_encrypt_block,@function;)
_gcry_blowfish_amd64_encrypt_block:
/* input:
* %rdi: ctx, CTX
* %rsi: dst
* %rdx: src
*/
CFI_STARTPROC();
ENTER_SYSV_FUNC_PARAMS_0_4
movq %rsi, %r10;
movq %rdx, RIO;
read_block();
call __blowfish_enc_blk1;
movq %r10, RIO;
write_block();
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_encrypt_block,.-_gcry_blowfish_amd64_encrypt_block;)
.align 8
.globl _gcry_blowfish_amd64_decrypt_block
ELF(.type _gcry_blowfish_amd64_decrypt_block,@function;)
_gcry_blowfish_amd64_decrypt_block:
/* input:
* %rdi: ctx, CTX
* %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;
read_block();
load_roundkey_dec(17);
round_dec(15);
round_dec(13);
round_dec(11);
round_dec(9);
round_dec(7);
round_dec(5);
round_dec(3);
round_dec(1);
add_roundkey_dec();
movq %r10, RIO;
write_block();
movq %r11, %rbp;
CFI_RESTORE(%rbp);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_decrypt_block,.-_gcry_blowfish_amd64_decrypt_block;)
/**********************************************************************
4-way blowfish, four blocks parallel
**********************************************************************/
#define F4(x) \
movzbl x ## bh, RT1d; \
movzbl x ## bl, RT3d; \
rorq $16, x; \
movzbl x ## bh, RT0d; \
movzbl x ## bl, RT2d; \
rorq $16, x; \
movl s0(CTX,RT0,4), RT0d; \
addl s1(CTX,RT2,4), RT0d; \
xorl s2(CTX,RT1,4), RT0d; \
addl s3(CTX,RT3,4), RT0d; \
xorq RT0, x;
#define add_preloaded_roundkey4() \
xorq RKEY, RX0; \
xorq RKEY, RX1; \
xorq RKEY, RX2; \
xorq RKEY, RX3;
#define preload_roundkey_enc(n) \
movq p+4*(n)(CTX), RKEY;
#define add_roundkey_enc4(n) \
add_preloaded_roundkey4(); \
preload_roundkey_enc(n + 2);
#define round_enc4(n) \
add_roundkey_enc4(n); \
\
F4(RX0); \
F4(RX1); \
F4(RX2); \
F4(RX3); \
\
F4(RX0); \
F4(RX1); \
F4(RX2); \
F4(RX3);
#define preload_roundkey_dec(n) \
movq p+4*((n)-1)(CTX), RKEY; \
rorq $32, RKEY;
#define add_roundkey_dec4(n) \
add_preloaded_roundkey4(); \
preload_roundkey_dec(n - 2);
#define round_dec4(n) \
add_roundkey_dec4(n); \
\
F4(RX0); \
F4(RX1); \
F4(RX2); \
F4(RX3); \
\
F4(RX0); \
F4(RX1); \
F4(RX2); \
F4(RX3);
#define inbswap_block4() \
rorq $32, RX0; \
bswapq RX0; \
rorq $32, RX1; \
bswapq RX1; \
rorq $32, RX2; \
bswapq RX2; \
rorq $32, RX3; \
bswapq RX3;
#define inctrswap_block4() \
rorq $32, RX0; \
rorq $32, RX1; \
rorq $32, RX2; \
rorq $32, RX3;
#define outbswap_block4() \
bswapq RX0; \
bswapq RX1; \
bswapq RX2; \
bswapq RX3;
.align 8
ELF(.type __blowfish_enc_blk4,@function;)
__blowfish_enc_blk4:
/* input:
* %rdi: ctx, CTX
* RX0,RX1,RX2,RX3: four input inbswapped plaintext blocks
* output:
* RX0,RX1,RX2,RX3: four output ciphertext blocks
*/
CFI_STARTPROC();
preload_roundkey_enc(0);
round_enc4(0);
round_enc4(2);
round_enc4(4);
round_enc4(6);
round_enc4(8);
round_enc4(10);
round_enc4(12);
round_enc4(14);
add_preloaded_roundkey4();
outbswap_block4();
ret;
CFI_ENDPROC();
ELF(.size __blowfish_enc_blk4,.-__blowfish_enc_blk4;)
.align 8
ELF(.type __blowfish_dec_blk4,@function;)
__blowfish_dec_blk4:
/* input:
* %rdi: ctx, CTX
* RX0,RX1,RX2,RX3: four input ciphertext blocks
* output:
* RX0,RX1,RX2,RX3: four output plaintext blocks
*/
CFI_STARTPROC();
preload_roundkey_dec(17);
inbswap_block4();
round_dec4(17);
round_dec4(15);
round_dec4(13);
round_dec4(11);
round_dec4(9);
round_dec4(7);
round_dec4(5);
round_dec4(3);
add_preloaded_roundkey4();
outbswap_block4();
ret;
CFI_ENDPROC();
ELF(.size __blowfish_dec_blk4,.-__blowfish_dec_blk4;)
.align 8
.globl _gcry_blowfish_amd64_ctr_enc
ELF(.type _gcry_blowfish_amd64_ctr_enc,@function;)
_gcry_blowfish_amd64_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %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);
/* %r11-%r13 are not used by __blowfish_enc_blk4 */
movq %rcx, %r13; /*iv*/
movq %rdx, %r12; /*src*/
movq %rsi, %r11; /*dst*/
/* load IV and byteswap */
movq (%r13), RT0;
bswapq RT0;
movq RT0, RX0;
/* construct IVs */
leaq 1(RT0), RX1;
leaq 2(RT0), RX2;
leaq 3(RT0), RX3;
leaq 4(RT0), RT0;
bswapq RT0;
inctrswap_block4();
/* store new IV */
movq RT0, (%r13);
call __blowfish_enc_blk4;
/* XOR key-stream with plaintext */
xorq 0 * 8(%r12), RX0;
xorq 1 * 8(%r12), RX1;
xorq 2 * 8(%r12), RX2;
xorq 3 * 8(%r12), RX3;
movq RX0, 0 * 8(%r11);
movq RX1, 1 * 8(%r11);
movq RX2, 2 * 8(%r11);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_ctr_enc,.-_gcry_blowfish_amd64_ctr_enc;)
.align 8
.globl _gcry_blowfish_amd64_cbc_dec
ELF(.type _gcry_blowfish_amd64_cbc_dec,@function;)
_gcry_blowfish_amd64_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %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);
/* %r11-%r13 are not used by __blowfish_dec_blk4 */
movq %rsi, %r11; /*dst*/
movq %rdx, %r12; /*src*/
movq %rcx, %r13; /*iv*/
/* load input */
movq 0 * 8(%r12), RX0;
movq 1 * 8(%r12), RX1;
movq 2 * 8(%r12), RX2;
movq 3 * 8(%r12), RX3;
call __blowfish_dec_blk4;
movq 3 * 8(%r12), RT0;
xorq (%r13), RX0;
xorq 0 * 8(%r12), RX1;
xorq 1 * 8(%r12), RX2;
xorq 2 * 8(%r12), RX3;
movq RT0, (%r13); /* store new IV */
movq RX0, 0 * 8(%r11);
movq RX1, 1 * 8(%r11);
movq RX2, 2 * 8(%r11);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_cbc_dec,.-_gcry_blowfish_amd64_cbc_dec;)
.align 8
.globl _gcry_blowfish_amd64_cfb_dec
ELF(.type _gcry_blowfish_amd64_cfb_dec,@function;)
_gcry_blowfish_amd64_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %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);
/* %r11-%r13 are not used by __blowfish_enc_blk4 */
movq %rcx, %r13; /*iv*/
movq %rdx, %r12; /*src*/
movq %rsi, %r11; /*dst*/
/* Load input */
movq (%r13), RX0;
movq 0 * 8(%r12), RX1;
movq 1 * 8(%r12), RX2;
movq 2 * 8(%r12), RX3;
inbswap_block4();
/* Update IV */
movq 3 * 8(%r12), RT0;
movq RT0, (%r13);
call __blowfish_enc_blk4;
xorq 0 * 8(%r12), RX0;
xorq 1 * 8(%r12), RX1;
xorq 2 * 8(%r12), RX2;
xorq 3 * 8(%r12), RX3;
movq RX0, 0 * 8(%r11);
movq RX1, 1 * 8(%r11);
movq RX2, 2 * 8(%r11);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_blowfish_amd64_cfb_dec,.-_gcry_blowfish_amd64_cfb_dec;)
#endif /*defined(USE_BLOWFISH)*/
#endif /*__x86_64*/
diff --git a/cipher/blowfish-arm.S b/cipher/blowfish-arm.S
index b30aa31f..3a6f28db 100644
--- a/cipher/blowfish-arm.S
+++ b/cipher/blowfish-arm.S
@@ -1,743 +1,743 @@
/* blowfish-arm.S - ARM assembly implementation of Blowfish cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.arm
/* structure of crypto context */
#define s0 0
#define s1 (s0 + (1 * 256) * 4)
#define s2 (s0 + (2 * 256) * 4)
#define s3 (s0 + (3 * 256) * 4)
#define p (s3 + (1 * 256) * 4)
/* register macros */
#define CTXs0 %r0
#define CTXs1 %r9
#define CTXs2 %r8
#define CTXs3 %r10
#define RMASK %lr
#define RKEYL %r2
#define RKEYR %ip
#define RL0 %r3
#define RR0 %r4
#define RL1 %r9
#define RR1 %r10
#define RT0 %r11
#define RT1 %r7
#define RT2 %r5
#define RT3 %r6
/* helper macros */
#define ldr_unaligned_le(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 0)]; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 3)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_le(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 0)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 1)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 2)]; \
strb rtmp0, [rdst, #((offs) + 3)];
#define ldr_unaligned_be(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 3)]; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 0)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_be(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 3)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 2)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 1)]; \
strb rtmp0, [rdst, #((offs) + 0)];
#ifdef __ARMEL__
#define ldr_unaligned_host ldr_unaligned_le
#define str_unaligned_host str_unaligned_le
/* bswap on little-endian */
#ifdef HAVE_ARM_ARCH_V6
#define host_to_be(reg, rtmp) \
rev reg, reg;
#define be_to_host(reg, rtmp) \
rev reg, reg;
#else
#define host_to_be(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#define be_to_host(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#endif
#else
#define ldr_unaligned_host ldr_unaligned_be
#define str_unaligned_host str_unaligned_be
/* nop on big-endian */
#define host_to_be(reg, rtmp) /*_*/
#define be_to_host(reg, rtmp) /*_*/
#endif
#define host_to_host(x, y) /*_*/
/***********************************************************************
* 1-way blowfish
***********************************************************************/
#define F(l, r) \
and RT0, RMASK, l, lsr#(24 - 2); \
and RT1, RMASK, l, lsr#(16 - 2); \
ldr RT0, [CTXs0, RT0]; \
and RT2, RMASK, l, lsr#(8 - 2); \
ldr RT1, [CTXs1, RT1]; \
and RT3, RMASK, l, lsl#2; \
ldr RT2, [CTXs2, RT2]; \
add RT0, RT1; \
ldr RT3, [CTXs3, RT3]; \
eor RT0, RT2; \
add RT0, RT3; \
eor r, RT0;
#define load_roundkey_enc(n) \
ldr RKEYL, [CTXs2, #((p - s2) + (4 * (n) + 0))]; \
ldr RKEYR, [CTXs2, #((p - s2) + (4 * (n) + 4))];
#define add_roundkey_enc() \
eor RL0, RKEYL; \
eor RR0, RKEYR;
#define round_enc(n) \
add_roundkey_enc(); \
load_roundkey_enc(n); \
\
F(RL0, RR0); \
F(RR0, RL0);
#define load_roundkey_dec(n) \
ldr RKEYL, [CTXs2, #((p - s2) + (4 * ((n) - 1) + 4))]; \
ldr RKEYR, [CTXs2, #((p - s2) + (4 * ((n) - 1) + 0))];
#define add_roundkey_dec() \
eor RL0, RKEYL; \
eor RR0, RKEYR;
#define round_dec(n) \
add_roundkey_dec(); \
load_roundkey_dec(n); \
\
F(RL0, RR0); \
F(RR0, RL0);
#define read_block_aligned(rin, offs, l0, r0, convert, rtmp) \
ldr l0, [rin, #((offs) + 0)]; \
ldr r0, [rin, #((offs) + 4)]; \
convert(l0, rtmp); \
convert(r0, rtmp);
#define write_block_aligned(rout, offs, l0, r0, convert, rtmp) \
convert(l0, rtmp); \
convert(r0, rtmp); \
str l0, [rout, #((offs) + 0)]; \
str r0, [rout, #((offs) + 4)];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads allowed */
#define read_block(rin, offs, l0, r0, rtmp0) \
read_block_aligned(rin, offs, l0, r0, host_to_be, rtmp0)
#define write_block(rout, offs, r0, l0, rtmp0, rtmp1) \
write_block_aligned(rout, offs, r0, l0, be_to_host, rtmp0)
#define read_block_host(rin, offs, l0, r0, rtmp0) \
read_block_aligned(rin, offs, l0, r0, host_to_host, rtmp0)
#define write_block_host(rout, offs, r0, l0, rtmp0, rtmp1) \
write_block_aligned(rout, offs, r0, l0, host_to_host, rtmp0)
#else
/* need to handle unaligned reads by byte reads */
#define read_block(rin, offs, l0, r0, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_be(l0, rin, (offs) + 0, rtmp0); \
ldr_unaligned_be(r0, rin, (offs) + 4, rtmp0); \
b 2f; \
1:;\
read_block_aligned(rin, offs, l0, r0, host_to_be, rtmp0); \
2:;
#define write_block(rout, offs, l0, r0, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_be(l0, rout, (offs) + 0, rtmp0, rtmp1); \
str_unaligned_be(r0, rout, (offs) + 4, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block_aligned(rout, offs, l0, r0, be_to_host, rtmp0); \
2:;
#define read_block_host(rin, offs, l0, r0, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_host(l0, rin, (offs) + 0, rtmp0); \
ldr_unaligned_host(r0, rin, (offs) + 4, rtmp0); \
b 2f; \
1:;\
read_block_aligned(rin, offs, l0, r0, host_to_host, rtmp0); \
2:;
#define write_block_host(rout, offs, l0, r0, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_host(l0, rout, (offs) + 0, rtmp0, rtmp1); \
str_unaligned_host(r0, rout, (offs) + 4, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block_aligned(rout, offs, l0, r0, host_to_host); \
2:;
#endif
.align 3
.type __blowfish_enc_blk1,%function;
__blowfish_enc_blk1:
/* input:
* preloaded: CTX
* [RL0, RR0]: src
* output:
* [RR0, RL0]: dst
*/
push {%lr};
add CTXs1, CTXs0, #(s1 - s0);
add CTXs2, CTXs0, #(s2 - s0);
mov RMASK, #(0xff << 2); /* byte mask */
add CTXs3, CTXs1, #(s3 - s1);
load_roundkey_enc(0);
round_enc(2);
round_enc(4);
round_enc(6);
round_enc(8);
round_enc(10);
round_enc(12);
round_enc(14);
round_enc(16);
add_roundkey_enc();
pop {%pc};
.size __blowfish_enc_blk1,.-__blowfish_enc_blk1;
.align 8
.globl _gcry_blowfish_arm_do_encrypt
.type _gcry_blowfish_arm_do_encrypt,%function;
_gcry_blowfish_arm_do_encrypt:
/* input:
* %r0: ctx, CTX
* %r1: u32 *ret_xl
* %r2: u32 *ret_xr
*/
push {%r2, %r4-%r11, %ip, %lr};
ldr RL0, [%r1];
ldr RR0, [%r2];
bl __blowfish_enc_blk1;
pop {%r2};
str RR0, [%r1];
str RL0, [%r2];
pop {%r4-%r11, %ip, %pc};
.size _gcry_blowfish_arm_do_encrypt,.-_gcry_blowfish_arm_do_encrypt;
.align 3
.globl _gcry_blowfish_arm_encrypt_block
.type _gcry_blowfish_arm_encrypt_block,%function;
_gcry_blowfish_arm_encrypt_block:
/* input:
* %r0: ctx, CTX
* %r1: dst
* %r2: src
*/
push {%r4-%r11, %ip, %lr};
read_block(%r2, 0, RL0, RR0, RT0);
bl __blowfish_enc_blk1;
write_block(%r1, 0, RR0, RL0, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.size _gcry_blowfish_arm_encrypt_block,.-_gcry_blowfish_arm_encrypt_block;
.align 3
.globl _gcry_blowfish_arm_decrypt_block
.type _gcry_blowfish_arm_decrypt_block,%function;
_gcry_blowfish_arm_decrypt_block:
/* input:
* %r0: ctx, CTX
* %r1: dst
* %r2: src
*/
push {%r4-%r11, %ip, %lr};
add CTXs1, CTXs0, #(s1 - s0);
add CTXs2, CTXs0, #(s2 - s0);
mov RMASK, #(0xff << 2); /* byte mask */
add CTXs3, CTXs1, #(s3 - s1);
read_block(%r2, 0, RL0, RR0, RT0);
load_roundkey_dec(17);
round_dec(15);
round_dec(13);
round_dec(11);
round_dec(9);
round_dec(7);
round_dec(5);
round_dec(3);
round_dec(1);
add_roundkey_dec();
write_block(%r1, 0, RR0, RL0, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.size _gcry_blowfish_arm_decrypt_block,.-_gcry_blowfish_arm_decrypt_block;
/***********************************************************************
* 2-way blowfish
***********************************************************************/
#define F2(n, l0, r0, l1, r1, set_nextk, dec) \
\
and RT0, RMASK, l0, lsr#(24 - 2); \
and RT1, RMASK, l0, lsr#(16 - 2); \
and RT2, RMASK, l0, lsr#(8 - 2); \
add RT1, #(s1 - s0); \
\
ldr RT0, [CTXs0, RT0]; \
and RT3, RMASK, l0, lsl#2; \
ldr RT1, [CTXs0, RT1]; \
add RT3, #(s3 - s2); \
ldr RT2, [CTXs2, RT2]; \
add RT0, RT1; \
ldr RT3, [CTXs2, RT3]; \
\
and RT1, RMASK, l1, lsr#(24 - 2); \
eor RT0, RT2; \
and RT2, RMASK, l1, lsr#(16 - 2); \
add RT0, RT3; \
add RT2, #(s1 - s0); \
and RT3, RMASK, l1, lsr#(8 - 2); \
eor r0, RT0; \
\
ldr RT1, [CTXs0, RT1]; \
and RT0, RMASK, l1, lsl#2; \
ldr RT2, [CTXs0, RT2]; \
add RT0, #(s3 - s2); \
ldr RT3, [CTXs2, RT3]; \
add RT1, RT2; \
ldr RT0, [CTXs2, RT0]; \
\
and RT2, RMASK, r0, lsr#(24 - 2); \
eor RT1, RT3; \
and RT3, RMASK, r0, lsr#(16 - 2); \
add RT1, RT0; \
add RT3, #(s1 - s0); \
and RT0, RMASK, r0, lsr#(8 - 2); \
eor r1, RT1; \
\
ldr RT2, [CTXs0, RT2]; \
and RT1, RMASK, r0, lsl#2; \
ldr RT3, [CTXs0, RT3]; \
add RT1, #(s3 - s2); \
ldr RT0, [CTXs2, RT0]; \
add RT2, RT3; \
ldr RT1, [CTXs2, RT1]; \
\
and RT3, RMASK, r1, lsr#(24 - 2); \
eor RT2, RT0; \
and RT0, RMASK, r1, lsr#(16 - 2); \
add RT2, RT1; \
add RT0, #(s1 - s0); \
and RT1, RMASK, r1, lsr#(8 - 2); \
eor l0, RT2; \
\
ldr RT3, [CTXs0, RT3]; \
and RT2, RMASK, r1, lsl#2; \
ldr RT0, [CTXs0, RT0]; \
add RT2, #(s3 - s2); \
ldr RT1, [CTXs2, RT1]; \
eor l1, RKEYL; \
ldr RT2, [CTXs2, RT2]; \
\
eor r0, RKEYR; \
add RT3, RT0; \
eor r1, RKEYR; \
eor RT3, RT1; \
eor l0, RKEYL; \
add RT3, RT2; \
set_nextk(RKEYL, (p - s2) + (4 * (n) + ((dec) * 4))); \
eor l1, RT3; \
set_nextk(RKEYR, (p - s2) + (4 * (n) + (!(dec) * 4)));
#define load_n_add_roundkey_enc2(n) \
load_roundkey_enc(n); \
eor RL0, RKEYL; \
eor RR0, RKEYR; \
eor RL1, RKEYL; \
eor RR1, RKEYR; \
load_roundkey_enc((n) + 2);
#define next_key(reg, offs) \
ldr reg, [CTXs2, #(offs)];
#define dummy(x, y) /* do nothing */
#define round_enc2(n, load_next_key) \
F2((n) + 2, RL0, RR0, RL1, RR1, load_next_key, 0);
#define load_n_add_roundkey_dec2(n) \
load_roundkey_dec(n); \
eor RL0, RKEYL; \
eor RR0, RKEYR; \
eor RL1, RKEYL; \
eor RR1, RKEYR; \
load_roundkey_dec((n) - 2);
#define round_dec2(n, load_next_key) \
F2((n) - 3, RL0, RR0, RL1, RR1, load_next_key, 1);
#define read_block2_aligned(rin, l0, r0, l1, r1, convert, rtmp) \
ldr l0, [rin, #(0)]; \
ldr r0, [rin, #(4)]; \
convert(l0, rtmp); \
ldr l1, [rin, #(8)]; \
convert(r0, rtmp); \
ldr r1, [rin, #(12)]; \
convert(l1, rtmp); \
convert(r1, rtmp);
#define write_block2_aligned(rout, l0, r0, l1, r1, convert, rtmp) \
convert(l0, rtmp); \
convert(r0, rtmp); \
convert(l1, rtmp); \
str l0, [rout, #(0)]; \
convert(r1, rtmp); \
str r0, [rout, #(4)]; \
str l1, [rout, #(8)]; \
str r1, [rout, #(12)];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads allowed */
#define read_block2(rin, l0, r0, l1, r1, rtmp0) \
read_block2_aligned(rin, l0, r0, l1, r1, host_to_be, rtmp0)
#define write_block2(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
write_block2_aligned(rout, l0, r0, l1, r1, be_to_host, rtmp0)
#define read_block2_host(rin, l0, r0, l1, r1, rtmp0) \
read_block2_aligned(rin, l0, r0, l1, r1, host_to_host, rtmp0)
#define write_block2_host(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
write_block2_aligned(rout, l0, r0, l1, r1, host_to_host, rtmp0)
#else
/* need to handle unaligned reads by byte reads */
#define read_block2(rin, l0, r0, l1, r1, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_be(l0, rin, 0, rtmp0); \
ldr_unaligned_be(r0, rin, 4, rtmp0); \
ldr_unaligned_be(l1, rin, 8, rtmp0); \
ldr_unaligned_be(r1, rin, 12, rtmp0); \
b 2f; \
1:;\
read_block2_aligned(rin, l0, r0, l1, r1, host_to_be, rtmp0); \
2:;
#define write_block2(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_be(l0, rout, 0, rtmp0, rtmp1); \
str_unaligned_be(r0, rout, 4, rtmp0, rtmp1); \
str_unaligned_be(l1, rout, 8, rtmp0, rtmp1); \
str_unaligned_be(r1, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block2_aligned(rout, l0, r0, l1, r1, be_to_host, rtmp0); \
2:;
#define read_block2_host(rin, l0, r0, l1, r1, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_host(l0, rin, 0, rtmp0); \
ldr_unaligned_host(r0, rin, 4, rtmp0); \
ldr_unaligned_host(l1, rin, 8, rtmp0); \
ldr_unaligned_host(r1, rin, 12, rtmp0); \
b 2f; \
1:;\
read_block2_aligned(rin, l0, r0, l1, r1, host_to_host, rtmp0); \
2:;
#define write_block2_host(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_host(l0, rout, 0, rtmp0, rtmp1); \
str_unaligned_host(r0, rout, 4, rtmp0, rtmp1); \
str_unaligned_host(l1, rout, 8, rtmp0, rtmp1); \
str_unaligned_host(r1, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block2_aligned(rout, l0, r0, l1, r1, host_to_host, rtmp0); \
2:;
#endif
.align 3
.type _gcry_blowfish_arm_enc_blk2,%function;
_gcry_blowfish_arm_enc_blk2:
/* input:
* preloaded: CTX
* [RL0, RR0], [RL1, RR1]: src
* output:
* [RR0, RL0], [RR1, RL1]: dst
*/
push {RT0,%lr};
add CTXs2, CTXs0, #(s2 - s0);
mov RMASK, #(0xff << 2); /* byte mask */
load_n_add_roundkey_enc2(0);
round_enc2(2, next_key);
round_enc2(4, next_key);
round_enc2(6, next_key);
round_enc2(8, next_key);
round_enc2(10, next_key);
round_enc2(12, next_key);
round_enc2(14, next_key);
round_enc2(16, dummy);
host_to_be(RR0, RT0);
host_to_be(RL0, RT0);
host_to_be(RR1, RT0);
host_to_be(RL1, RT0);
pop {RT0,%pc};
.size _gcry_blowfish_arm_enc_blk2,.-_gcry_blowfish_arm_enc_blk2;
.align 3
.globl _gcry_blowfish_arm_cfb_dec;
.type _gcry_blowfish_arm_cfb_dec,%function;
_gcry_blowfish_arm_cfb_dec:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit)
*/
push {%r2, %r4-%r11, %ip, %lr};
mov %lr, %r3;
/* Load input (iv/%r3 is aligned, src/%r2 might not be) */
ldm %r3, {RL0, RR0};
host_to_be(RL0, RT0);
host_to_be(RR0, RT0);
read_block(%r2, 0, RL1, RR1, RT0);
/* Update IV, load src[1] and save to iv[0] */
read_block_host(%r2, 8, %r5, %r6, RT0);
stm %lr, {%r5, %r6};
bl _gcry_blowfish_arm_enc_blk2;
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r1: dst, %r0: %src */
pop {%r0};
/* dst = src ^ result */
read_block2_host(%r0, %r5, %r6, %r7, %r8, %lr);
eor %r5, %r4;
eor %r6, %r3;
eor %r7, %r10;
eor %r8, %r9;
write_block2_host(%r1, %r5, %r6, %r7, %r8, %r9, %r10);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_blowfish_arm_cfb_dec,.-_gcry_blowfish_arm_cfb_dec;
.align 3
.globl _gcry_blowfish_arm_ctr_enc;
.type _gcry_blowfish_arm_ctr_enc,%function;
_gcry_blowfish_arm_ctr_enc:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit, big-endian)
*/
push {%r2, %r4-%r11, %ip, %lr};
mov %lr, %r3;
/* Load IV (big => host endian) */
read_block_aligned(%lr, 0, RL0, RR0, be_to_host, RT0);
/* Construct IVs */
adds RR1, RR0, #1; /* +1 */
adc RL1, RL0, #0;
adds %r6, RR1, #1; /* +2 */
adc %r5, RL1, #0;
/* Store new IV (host => big-endian) */
write_block_aligned(%lr, 0, %r5, %r6, host_to_be, RT0);
bl _gcry_blowfish_arm_enc_blk2;
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r1: dst, %r0: %src */
pop {%r0};
/* XOR key-stream with plaintext */
read_block2_host(%r0, %r5, %r6, %r7, %r8, %lr);
eor %r5, %r4;
eor %r6, %r3;
eor %r7, %r10;
eor %r8, %r9;
write_block2_host(%r1, %r5, %r6, %r7, %r8, %r9, %r10);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_blowfish_arm_ctr_enc,.-_gcry_blowfish_arm_ctr_enc;
.align 3
.type _gcry_blowfish_arm_dec_blk2,%function;
_gcry_blowfish_arm_dec_blk2:
/* input:
* preloaded: CTX
* [RL0, RR0], [RL1, RR1]: src
* output:
* [RR0, RL0], [RR1, RL1]: dst
*/
add CTXs2, CTXs0, #(s2 - s0);
mov RMASK, #(0xff << 2); /* byte mask */
load_n_add_roundkey_dec2(17);
round_dec2(15, next_key);
round_dec2(13, next_key);
round_dec2(11, next_key);
round_dec2(9, next_key);
round_dec2(7, next_key);
round_dec2(5, next_key);
round_dec2(3, next_key);
round_dec2(1, dummy);
host_to_be(RR0, RT0);
host_to_be(RL0, RT0);
host_to_be(RR1, RT0);
host_to_be(RL1, RT0);
b .Ldec_cbc_tail;
.ltorg
.size _gcry_blowfish_arm_dec_blk2,.-_gcry_blowfish_arm_dec_blk2;
.align 3
.globl _gcry_blowfish_arm_cbc_dec;
.type _gcry_blowfish_arm_cbc_dec,%function;
_gcry_blowfish_arm_cbc_dec:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit)
*/
push {%r2-%r11, %ip, %lr};
read_block2(%r2, RL0, RR0, RL1, RR1, RT0);
/* dec_blk2 is only used by cbc_dec, jump directly in/out instead
* of function call. */
b _gcry_blowfish_arm_dec_blk2;
.Ldec_cbc_tail:
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r0: %src, %r1: dst, %r2: iv */
pop {%r0, %r2};
/* load IV+1 (src[0]) to %r7:%r8. Might be unaligned. */
read_block_host(%r0, 0, %r7, %r8, %r5);
/* load IV (iv[0]) to %r5:%r6. 'iv' is aligned. */
ldm %r2, {%r5, %r6};
/* out[1] ^= IV+1 */
eor %r10, %r7;
eor %r9, %r8;
/* out[0] ^= IV */
eor %r4, %r5;
eor %r3, %r6;
/* load IV+2 (src[1]) to %r7:%r8. Might be unaligned. */
read_block_host(%r0, 8, %r7, %r8, %r5);
/* store IV+2 to iv[0] (aligned). */
stm %r2, {%r7, %r8};
/* store result to dst[0-3]. Might be unaligned. */
write_block2_host(%r1, %r4, %r3, %r10, %r9, %r5, %r6);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_blowfish_arm_cbc_dec,.-_gcry_blowfish_arm_cbc_dec;
#endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/
#endif /*__ARM_ARCH >= 6*/
diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h
index fa5b2e8e..5ef2564d 100644
--- a/cipher/bufhelp.h
+++ b/cipher/bufhelp.h
@@ -1,385 +1,385 @@
/* bufhelp.h - Some buffer manipulation helpers
* Copyright (C) 2012-2017 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRYPT_BUFHELP_H
#define GCRYPT_BUFHELP_H
#include "g10lib.h"
#include "bithelp.h"
#undef BUFHELP_UNALIGNED_ACCESS
#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
/* Compiler is supports attributes needed for automatically issuing unaligned
memory access instructions.
*/
# define BUFHELP_UNALIGNED_ACCESS 1
#endif
#ifndef BUFHELP_UNALIGNED_ACCESS
/* Functions for loading and storing unaligned u32 values of different
endianness. */
static inline u32 buf_get_be32(const void *_buf)
{
const byte *in = _buf;
return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \
((u32)in[2] << 8) | (u32)in[3];
}
static inline u32 buf_get_le32(const void *_buf)
{
const byte *in = _buf;
return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \
((u32)in[1] << 8) | (u32)in[0];
}
static inline void buf_put_be32(void *_buf, u32 val)
{
byte *out = _buf;
out[0] = val >> 24;
out[1] = val >> 16;
out[2] = val >> 8;
out[3] = val;
}
static inline void buf_put_le32(void *_buf, u32 val)
{
byte *out = _buf;
out[3] = val >> 24;
out[2] = val >> 16;
out[1] = val >> 8;
out[0] = val;
}
/* Functions for loading and storing unaligned u64 values of different
endianness. */
static inline u64 buf_get_be64(const void *_buf)
{
const byte *in = _buf;
return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \
((u64)in[2] << 40) | ((u64)in[3] << 32) | \
((u64)in[4] << 24) | ((u64)in[5] << 16) | \
((u64)in[6] << 8) | (u64)in[7];
}
static inline u64 buf_get_le64(const void *_buf)
{
const byte *in = _buf;
return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \
((u64)in[5] << 40) | ((u64)in[4] << 32) | \
((u64)in[3] << 24) | ((u64)in[2] << 16) | \
((u64)in[1] << 8) | (u64)in[0];
}
static inline void buf_put_be64(void *_buf, u64 val)
{
byte *out = _buf;
out[0] = val >> 56;
out[1] = val >> 48;
out[2] = val >> 40;
out[3] = val >> 32;
out[4] = val >> 24;
out[5] = val >> 16;
out[6] = val >> 8;
out[7] = val;
}
static inline void buf_put_le64(void *_buf, u64 val)
{
byte *out = _buf;
out[7] = val >> 56;
out[6] = val >> 48;
out[5] = val >> 40;
out[4] = val >> 32;
out[3] = val >> 24;
out[2] = val >> 16;
out[1] = val >> 8;
out[0] = val;
}
#else /*BUFHELP_UNALIGNED_ACCESS*/
typedef struct bufhelp_u32_s
{
u32 a;
} __attribute__((packed, aligned(1), may_alias)) bufhelp_u32_t;
/* Functions for loading and storing unaligned u32 values of different
endianness. */
static inline u32 buf_get_be32(const void *_buf)
{
return be_bswap32(((const bufhelp_u32_t *)_buf)->a);
}
static inline u32 buf_get_le32(const void *_buf)
{
return le_bswap32(((const bufhelp_u32_t *)_buf)->a);
}
static inline void buf_put_be32(void *_buf, u32 val)
{
bufhelp_u32_t *out = _buf;
out->a = be_bswap32(val);
}
static inline void buf_put_le32(void *_buf, u32 val)
{
bufhelp_u32_t *out = _buf;
out->a = le_bswap32(val);
}
typedef struct bufhelp_u64_s
{
u64 a;
} __attribute__((packed, aligned(1), may_alias)) bufhelp_u64_t;
/* Functions for loading and storing unaligned u64 values of different
endianness. */
static inline u64 buf_get_be64(const void *_buf)
{
return be_bswap64(((const bufhelp_u64_t *)_buf)->a);
}
static inline u64 buf_get_le64(const void *_buf)
{
return le_bswap64(((const bufhelp_u64_t *)_buf)->a);
}
static inline void buf_put_be64(void *_buf, u64 val)
{
bufhelp_u64_t *out = _buf;
out->a = be_bswap64(val);
}
static inline void buf_put_le64(void *_buf, u64 val)
{
bufhelp_u64_t *out = _buf;
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*/
diff --git a/cipher/camellia-aarch64.S b/cipher/camellia-aarch64.S
index f4980862..65c05c0d 100644
--- a/cipher/camellia-aarch64.S
+++ b/cipher/camellia-aarch64.S
@@ -1,586 +1,586 @@
/* camellia-aarch64.S - ARMv8/AArch64 assembly implementation of Camellia
* cipher
*
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include "asm-common-aarch64.h"
#if defined(__AARCH64EL__)
#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
.text
/* struct camellia_ctx: */
#define key_table 0
/* register macros */
#define CTX x0
#define RDST x1
#define RSRC x2
#define RKEYBITS w3
#define RTAB1 x4
#define RTAB2 x5
#define RTAB3 x6
#define RTAB4 x7
#define RMASK w8
#define IL w9
#define IR w10
#define xIL x9
#define xIR x10
#define XL w11
#define XR w12
#define YL w13
#define YR w14
#define RT0 w15
#define RT1 w16
#define RT2 w17
#define RT3 w19
#define xRT0 x15
#define xRT1 x16
#define xRT2 x17
#define xRT3 x19
#ifdef __AARCH64EL__
#define host_to_be(reg, rtmp) \
rev reg, reg;
#define be_to_host(reg, rtmp) \
rev reg, reg;
#else
/* nop on big-endian */
#define host_to_be(reg, rtmp) /*_*/
#define be_to_host(reg, rtmp) /*_*/
#endif
#define ldr_input_aligned_be(rin, a, b, c, d, rtmp) \
ldr a, [rin, #0]; \
ldr b, [rin, #4]; \
be_to_host(a, rtmp); \
ldr c, [rin, #8]; \
be_to_host(b, rtmp); \
ldr d, [rin, #12]; \
be_to_host(c, rtmp); \
be_to_host(d, rtmp);
#define str_output_aligned_be(rout, a, b, c, d, rtmp) \
be_to_host(a, rtmp); \
be_to_host(b, rtmp); \
str a, [rout, #0]; \
be_to_host(c, rtmp); \
str b, [rout, #4]; \
be_to_host(d, rtmp); \
str c, [rout, #8]; \
str d, [rout, #12];
/* unaligned word reads/writes allowed */
#define ldr_input_be(rin, ra, rb, rc, rd, rtmp) \
ldr_input_aligned_be(rin, ra, rb, rc, rd, rtmp)
#define str_output_be(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
str_output_aligned_be(rout, ra, rb, rc, rd, rtmp0)
/**********************************************************************
1-way camellia
**********************************************************************/
#define roundsm(xl, xr, kl, kr, yl, yr) \
ldr RT2, [CTX, #(key_table + ((kl) * 4))]; \
and IR, RMASK, xr, lsl#(4); /*sp1110*/ \
ldr RT3, [CTX, #(key_table + ((kr) * 4))]; \
and IL, RMASK, xl, lsr#(24 - 4); /*sp1110*/ \
and RT0, RMASK, xr, lsr#(16 - 4); /*sp3033*/ \
ldr IR, [RTAB1, xIR]; \
and RT1, RMASK, xl, lsr#(8 - 4); /*sp3033*/ \
eor yl, yl, RT2; \
ldr IL, [RTAB1, xIL]; \
eor yr, yr, RT3; \
\
ldr RT0, [RTAB3, xRT0]; \
ldr RT1, [RTAB3, xRT1]; \
\
and RT2, RMASK, xr, lsr#(24 - 4); /*sp0222*/ \
and RT3, RMASK, xl, lsr#(16 - 4); /*sp0222*/ \
\
eor IR, IR, RT0; \
eor IL, IL, RT1; \
\
ldr RT2, [RTAB2, xRT2]; \
and RT0, RMASK, xr, lsr#(8 - 4); /*sp4404*/ \
ldr RT3, [RTAB2, xRT3]; \
and RT1, RMASK, xl, lsl#(4); /*sp4404*/ \
\
ldr RT0, [RTAB4, xRT0]; \
ldr RT1, [RTAB4, xRT1]; \
\
eor IR, IR, RT2; \
eor IL, IL, RT3; \
eor IR, IR, RT0; \
eor IL, IL, RT1; \
\
eor IR, IR, IL; \
eor yr, yr, IL, ror#8; \
eor yl, yl, IR; \
eor yr, yr, IR;
#define enc_rounds(n) \
roundsm(XL, XR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, XL, XR);
#define dec_rounds(n) \
roundsm(XL, XR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, XL, XR);
/* perform FL and FL⁻¹ */
#define fls(ll, lr, rl, rr, kll, klr, krl, krr) \
ldr RT0, [CTX, #(key_table + ((kll) * 4))]; \
ldr RT2, [CTX, #(key_table + ((krr) * 4))]; \
and RT0, RT0, ll; \
ldr RT3, [CTX, #(key_table + ((krl) * 4))]; \
orr RT2, RT2, rr; \
ldr RT1, [CTX, #(key_table + ((klr) * 4))]; \
eor rl, rl, RT2; \
eor lr, lr, RT0, ror#31; \
and RT3, RT3, rl; \
orr RT1, RT1, lr; \
eor ll, ll, RT1; \
eor rr, rr, RT3, ror#31;
#define enc_fls(n) \
fls(XL, XR, YL, YR, \
(n) * 2 + 0, (n) * 2 + 1, \
(n) * 2 + 2, (n) * 2 + 3);
#define dec_fls(n) \
fls(XL, XR, YL, YR, \
(n) * 2 + 2, (n) * 2 + 3, \
(n) * 2 + 0, (n) * 2 + 1);
#define inpack(n) \
ldr_input_be(RSRC, XL, XR, YL, YR, RT0); \
ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \
ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \
eor XL, XL, RT0; \
eor XR, XR, RT1;
#define outunpack(n) \
ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \
ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \
eor YL, YL, RT0; \
eor YR, YR, RT1; \
str_output_be(RDST, YL, YR, XL, XR, RT0, RT1);
.globl _gcry_camellia_arm_encrypt_block
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
* w3: keybitlen
*/
adr RTAB1, _gcry_camellia_arm_tables;
mov RMASK, #(0xff<<4); /* byte mask */
add RTAB2, RTAB1, #(1 * 4);
add RTAB3, RTAB1, #(2 * 4);
add RTAB4, RTAB1, #(3 * 4);
inpack(0);
enc_rounds(0);
enc_fls(8);
enc_rounds(8);
enc_fls(16);
enc_rounds(16);
cmp RKEYBITS, #(16 * 8);
bne .Lenc_256;
outunpack(24);
CFI_REMEMBER_STATE()
ldp x19, x30, [sp], #16
CFI_ADJUST_CFA_OFFSET(-16)
CFI_RESTORE(x19)
CFI_RESTORE(x30)
ret;
CFI_RESTORE_STATE()
.ltorg
.Lenc_256:
enc_fls(24);
enc_rounds(24);
outunpack(32);
ldp x19, x30, [sp], #16
CFI_ADJUST_CFA_OFFSET(-16)
CFI_RESTORE(x19)
CFI_RESTORE(x30)
ret;
CFI_ENDPROC()
.ltorg
ELF(.size _gcry_camellia_arm_encrypt_block,.-_gcry_camellia_arm_encrypt_block;)
.globl _gcry_camellia_arm_decrypt_block
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
* w3: keybitlen
*/
adr RTAB1, _gcry_camellia_arm_tables;
mov RMASK, #(0xff<<4); /* byte mask */
add RTAB2, RTAB1, #(1 * 4);
add RTAB3, RTAB1, #(2 * 4);
add RTAB4, RTAB1, #(3 * 4);
cmp RKEYBITS, #(16 * 8);
bne .Ldec_256;
inpack(24);
.Ldec_128:
dec_rounds(16);
dec_fls(16);
dec_rounds(8);
dec_fls(8);
dec_rounds(0);
outunpack(0);
CFI_REMEMBER_STATE()
ldp x19, x30, [sp], #16
CFI_ADJUST_CFA_OFFSET(-16)
CFI_RESTORE(x19)
CFI_RESTORE(x30)
ret;
CFI_RESTORE_STATE()
.ltorg
.Ldec_256:
inpack(32);
dec_rounds(24);
dec_fls(24);
b .Ldec_128;
CFI_ENDPROC()
.ltorg
ELF(.size _gcry_camellia_arm_decrypt_block,.-_gcry_camellia_arm_decrypt_block;)
/* Encryption/Decryption tables */
ELF(.type _gcry_camellia_arm_tables,@object;)
.balign 32
_gcry_camellia_arm_tables:
.Lcamellia_sp1110:
.long 0x70707000
.Lcamellia_sp0222:
.long 0x00e0e0e0
.Lcamellia_sp3033:
.long 0x38003838
.Lcamellia_sp4404:
.long 0x70700070
.long 0x82828200, 0x00050505, 0x41004141, 0x2c2c002c
.long 0x2c2c2c00, 0x00585858, 0x16001616, 0xb3b300b3
.long 0xececec00, 0x00d9d9d9, 0x76007676, 0xc0c000c0
.long 0xb3b3b300, 0x00676767, 0xd900d9d9, 0xe4e400e4
.long 0x27272700, 0x004e4e4e, 0x93009393, 0x57570057
.long 0xc0c0c000, 0x00818181, 0x60006060, 0xeaea00ea
.long 0xe5e5e500, 0x00cbcbcb, 0xf200f2f2, 0xaeae00ae
.long 0xe4e4e400, 0x00c9c9c9, 0x72007272, 0x23230023
.long 0x85858500, 0x000b0b0b, 0xc200c2c2, 0x6b6b006b
.long 0x57575700, 0x00aeaeae, 0xab00abab, 0x45450045
.long 0x35353500, 0x006a6a6a, 0x9a009a9a, 0xa5a500a5
.long 0xeaeaea00, 0x00d5d5d5, 0x75007575, 0xeded00ed
.long 0x0c0c0c00, 0x00181818, 0x06000606, 0x4f4f004f
.long 0xaeaeae00, 0x005d5d5d, 0x57005757, 0x1d1d001d
.long 0x41414100, 0x00828282, 0xa000a0a0, 0x92920092
.long 0x23232300, 0x00464646, 0x91009191, 0x86860086
.long 0xefefef00, 0x00dfdfdf, 0xf700f7f7, 0xafaf00af
.long 0x6b6b6b00, 0x00d6d6d6, 0xb500b5b5, 0x7c7c007c
.long 0x93939300, 0x00272727, 0xc900c9c9, 0x1f1f001f
.long 0x45454500, 0x008a8a8a, 0xa200a2a2, 0x3e3e003e
.long 0x19191900, 0x00323232, 0x8c008c8c, 0xdcdc00dc
.long 0xa5a5a500, 0x004b4b4b, 0xd200d2d2, 0x5e5e005e
.long 0x21212100, 0x00424242, 0x90009090, 0x0b0b000b
.long 0xededed00, 0x00dbdbdb, 0xf600f6f6, 0xa6a600a6
.long 0x0e0e0e00, 0x001c1c1c, 0x07000707, 0x39390039
.long 0x4f4f4f00, 0x009e9e9e, 0xa700a7a7, 0xd5d500d5
.long 0x4e4e4e00, 0x009c9c9c, 0x27002727, 0x5d5d005d
.long 0x1d1d1d00, 0x003a3a3a, 0x8e008e8e, 0xd9d900d9
.long 0x65656500, 0x00cacaca, 0xb200b2b2, 0x5a5a005a
.long 0x92929200, 0x00252525, 0x49004949, 0x51510051
.long 0xbdbdbd00, 0x007b7b7b, 0xde00dede, 0x6c6c006c
.long 0x86868600, 0x000d0d0d, 0x43004343, 0x8b8b008b
.long 0xb8b8b800, 0x00717171, 0x5c005c5c, 0x9a9a009a
.long 0xafafaf00, 0x005f5f5f, 0xd700d7d7, 0xfbfb00fb
.long 0x8f8f8f00, 0x001f1f1f, 0xc700c7c7, 0xb0b000b0
.long 0x7c7c7c00, 0x00f8f8f8, 0x3e003e3e, 0x74740074
.long 0xebebeb00, 0x00d7d7d7, 0xf500f5f5, 0x2b2b002b
.long 0x1f1f1f00, 0x003e3e3e, 0x8f008f8f, 0xf0f000f0
.long 0xcecece00, 0x009d9d9d, 0x67006767, 0x84840084
.long 0x3e3e3e00, 0x007c7c7c, 0x1f001f1f, 0xdfdf00df
.long 0x30303000, 0x00606060, 0x18001818, 0xcbcb00cb
.long 0xdcdcdc00, 0x00b9b9b9, 0x6e006e6e, 0x34340034
.long 0x5f5f5f00, 0x00bebebe, 0xaf00afaf, 0x76760076
.long 0x5e5e5e00, 0x00bcbcbc, 0x2f002f2f, 0x6d6d006d
.long 0xc5c5c500, 0x008b8b8b, 0xe200e2e2, 0xa9a900a9
.long 0x0b0b0b00, 0x00161616, 0x85008585, 0xd1d100d1
.long 0x1a1a1a00, 0x00343434, 0x0d000d0d, 0x04040004
.long 0xa6a6a600, 0x004d4d4d, 0x53005353, 0x14140014
.long 0xe1e1e100, 0x00c3c3c3, 0xf000f0f0, 0x3a3a003a
.long 0x39393900, 0x00727272, 0x9c009c9c, 0xdede00de
.long 0xcacaca00, 0x00959595, 0x65006565, 0x11110011
.long 0xd5d5d500, 0x00ababab, 0xea00eaea, 0x32320032
.long 0x47474700, 0x008e8e8e, 0xa300a3a3, 0x9c9c009c
.long 0x5d5d5d00, 0x00bababa, 0xae00aeae, 0x53530053
.long 0x3d3d3d00, 0x007a7a7a, 0x9e009e9e, 0xf2f200f2
.long 0xd9d9d900, 0x00b3b3b3, 0xec00ecec, 0xfefe00fe
.long 0x01010100, 0x00020202, 0x80008080, 0xcfcf00cf
.long 0x5a5a5a00, 0x00b4b4b4, 0x2d002d2d, 0xc3c300c3
.long 0xd6d6d600, 0x00adadad, 0x6b006b6b, 0x7a7a007a
.long 0x51515100, 0x00a2a2a2, 0xa800a8a8, 0x24240024
.long 0x56565600, 0x00acacac, 0x2b002b2b, 0xe8e800e8
.long 0x6c6c6c00, 0x00d8d8d8, 0x36003636, 0x60600060
.long 0x4d4d4d00, 0x009a9a9a, 0xa600a6a6, 0x69690069
.long 0x8b8b8b00, 0x00171717, 0xc500c5c5, 0xaaaa00aa
.long 0x0d0d0d00, 0x001a1a1a, 0x86008686, 0xa0a000a0
.long 0x9a9a9a00, 0x00353535, 0x4d004d4d, 0xa1a100a1
.long 0x66666600, 0x00cccccc, 0x33003333, 0x62620062
.long 0xfbfbfb00, 0x00f7f7f7, 0xfd00fdfd, 0x54540054
.long 0xcccccc00, 0x00999999, 0x66006666, 0x1e1e001e
.long 0xb0b0b000, 0x00616161, 0x58005858, 0xe0e000e0
.long 0x2d2d2d00, 0x005a5a5a, 0x96009696, 0x64640064
.long 0x74747400, 0x00e8e8e8, 0x3a003a3a, 0x10100010
.long 0x12121200, 0x00242424, 0x09000909, 0x00000000
.long 0x2b2b2b00, 0x00565656, 0x95009595, 0xa3a300a3
.long 0x20202000, 0x00404040, 0x10001010, 0x75750075
.long 0xf0f0f000, 0x00e1e1e1, 0x78007878, 0x8a8a008a
.long 0xb1b1b100, 0x00636363, 0xd800d8d8, 0xe6e600e6
.long 0x84848400, 0x00090909, 0x42004242, 0x09090009
.long 0x99999900, 0x00333333, 0xcc00cccc, 0xdddd00dd
.long 0xdfdfdf00, 0x00bfbfbf, 0xef00efef, 0x87870087
.long 0x4c4c4c00, 0x00989898, 0x26002626, 0x83830083
.long 0xcbcbcb00, 0x00979797, 0xe500e5e5, 0xcdcd00cd
.long 0xc2c2c200, 0x00858585, 0x61006161, 0x90900090
.long 0x34343400, 0x00686868, 0x1a001a1a, 0x73730073
.long 0x7e7e7e00, 0x00fcfcfc, 0x3f003f3f, 0xf6f600f6
.long 0x76767600, 0x00ececec, 0x3b003b3b, 0x9d9d009d
.long 0x05050500, 0x000a0a0a, 0x82008282, 0xbfbf00bf
.long 0x6d6d6d00, 0x00dadada, 0xb600b6b6, 0x52520052
.long 0xb7b7b700, 0x006f6f6f, 0xdb00dbdb, 0xd8d800d8
.long 0xa9a9a900, 0x00535353, 0xd400d4d4, 0xc8c800c8
.long 0x31313100, 0x00626262, 0x98009898, 0xc6c600c6
.long 0xd1d1d100, 0x00a3a3a3, 0xe800e8e8, 0x81810081
.long 0x17171700, 0x002e2e2e, 0x8b008b8b, 0x6f6f006f
.long 0x04040400, 0x00080808, 0x02000202, 0x13130013
.long 0xd7d7d700, 0x00afafaf, 0xeb00ebeb, 0x63630063
.long 0x14141400, 0x00282828, 0x0a000a0a, 0xe9e900e9
.long 0x58585800, 0x00b0b0b0, 0x2c002c2c, 0xa7a700a7
.long 0x3a3a3a00, 0x00747474, 0x1d001d1d, 0x9f9f009f
.long 0x61616100, 0x00c2c2c2, 0xb000b0b0, 0xbcbc00bc
.long 0xdedede00, 0x00bdbdbd, 0x6f006f6f, 0x29290029
.long 0x1b1b1b00, 0x00363636, 0x8d008d8d, 0xf9f900f9
.long 0x11111100, 0x00222222, 0x88008888, 0x2f2f002f
.long 0x1c1c1c00, 0x00383838, 0x0e000e0e, 0xb4b400b4
.long 0x32323200, 0x00646464, 0x19001919, 0x78780078
.long 0x0f0f0f00, 0x001e1e1e, 0x87008787, 0x06060006
.long 0x9c9c9c00, 0x00393939, 0x4e004e4e, 0xe7e700e7
.long 0x16161600, 0x002c2c2c, 0x0b000b0b, 0x71710071
.long 0x53535300, 0x00a6a6a6, 0xa900a9a9, 0xd4d400d4
.long 0x18181800, 0x00303030, 0x0c000c0c, 0xabab00ab
.long 0xf2f2f200, 0x00e5e5e5, 0x79007979, 0x88880088
.long 0x22222200, 0x00444444, 0x11001111, 0x8d8d008d
.long 0xfefefe00, 0x00fdfdfd, 0x7f007f7f, 0x72720072
.long 0x44444400, 0x00888888, 0x22002222, 0xb9b900b9
.long 0xcfcfcf00, 0x009f9f9f, 0xe700e7e7, 0xf8f800f8
.long 0xb2b2b200, 0x00656565, 0x59005959, 0xacac00ac
.long 0xc3c3c300, 0x00878787, 0xe100e1e1, 0x36360036
.long 0xb5b5b500, 0x006b6b6b, 0xda00dada, 0x2a2a002a
.long 0x7a7a7a00, 0x00f4f4f4, 0x3d003d3d, 0x3c3c003c
.long 0x91919100, 0x00232323, 0xc800c8c8, 0xf1f100f1
.long 0x24242400, 0x00484848, 0x12001212, 0x40400040
.long 0x08080800, 0x00101010, 0x04000404, 0xd3d300d3
.long 0xe8e8e800, 0x00d1d1d1, 0x74007474, 0xbbbb00bb
.long 0xa8a8a800, 0x00515151, 0x54005454, 0x43430043
.long 0x60606000, 0x00c0c0c0, 0x30003030, 0x15150015
.long 0xfcfcfc00, 0x00f9f9f9, 0x7e007e7e, 0xadad00ad
.long 0x69696900, 0x00d2d2d2, 0xb400b4b4, 0x77770077
.long 0x50505000, 0x00a0a0a0, 0x28002828, 0x80800080
.long 0xaaaaaa00, 0x00555555, 0x55005555, 0x82820082
.long 0xd0d0d000, 0x00a1a1a1, 0x68006868, 0xecec00ec
.long 0xa0a0a000, 0x00414141, 0x50005050, 0x27270027
.long 0x7d7d7d00, 0x00fafafa, 0xbe00bebe, 0xe5e500e5
.long 0xa1a1a100, 0x00434343, 0xd000d0d0, 0x85850085
.long 0x89898900, 0x00131313, 0xc400c4c4, 0x35350035
.long 0x62626200, 0x00c4c4c4, 0x31003131, 0x0c0c000c
.long 0x97979700, 0x002f2f2f, 0xcb00cbcb, 0x41410041
.long 0x54545400, 0x00a8a8a8, 0x2a002a2a, 0xefef00ef
.long 0x5b5b5b00, 0x00b6b6b6, 0xad00adad, 0x93930093
.long 0x1e1e1e00, 0x003c3c3c, 0x0f000f0f, 0x19190019
.long 0x95959500, 0x002b2b2b, 0xca00caca, 0x21210021
.long 0xe0e0e000, 0x00c1c1c1, 0x70007070, 0x0e0e000e
.long 0xffffff00, 0x00ffffff, 0xff00ffff, 0x4e4e004e
.long 0x64646400, 0x00c8c8c8, 0x32003232, 0x65650065
.long 0xd2d2d200, 0x00a5a5a5, 0x69006969, 0xbdbd00bd
.long 0x10101000, 0x00202020, 0x08000808, 0xb8b800b8
.long 0xc4c4c400, 0x00898989, 0x62006262, 0x8f8f008f
.long 0x00000000, 0x00000000, 0x00000000, 0xebeb00eb
.long 0x48484800, 0x00909090, 0x24002424, 0xcece00ce
.long 0xa3a3a300, 0x00474747, 0xd100d1d1, 0x30300030
.long 0xf7f7f700, 0x00efefef, 0xfb00fbfb, 0x5f5f005f
.long 0x75757500, 0x00eaeaea, 0xba00baba, 0xc5c500c5
.long 0xdbdbdb00, 0x00b7b7b7, 0xed00eded, 0x1a1a001a
.long 0x8a8a8a00, 0x00151515, 0x45004545, 0xe1e100e1
.long 0x03030300, 0x00060606, 0x81008181, 0xcaca00ca
.long 0xe6e6e600, 0x00cdcdcd, 0x73007373, 0x47470047
.long 0xdadada00, 0x00b5b5b5, 0x6d006d6d, 0x3d3d003d
.long 0x09090900, 0x00121212, 0x84008484, 0x01010001
.long 0x3f3f3f00, 0x007e7e7e, 0x9f009f9f, 0xd6d600d6
.long 0xdddddd00, 0x00bbbbbb, 0xee00eeee, 0x56560056
.long 0x94949400, 0x00292929, 0x4a004a4a, 0x4d4d004d
.long 0x87878700, 0x000f0f0f, 0xc300c3c3, 0x0d0d000d
.long 0x5c5c5c00, 0x00b8b8b8, 0x2e002e2e, 0x66660066
.long 0x83838300, 0x00070707, 0xc100c1c1, 0xcccc00cc
.long 0x02020200, 0x00040404, 0x01000101, 0x2d2d002d
.long 0xcdcdcd00, 0x009b9b9b, 0xe600e6e6, 0x12120012
.long 0x4a4a4a00, 0x00949494, 0x25002525, 0x20200020
.long 0x90909000, 0x00212121, 0x48004848, 0xb1b100b1
.long 0x33333300, 0x00666666, 0x99009999, 0x99990099
.long 0x73737300, 0x00e6e6e6, 0xb900b9b9, 0x4c4c004c
.long 0x67676700, 0x00cecece, 0xb300b3b3, 0xc2c200c2
.long 0xf6f6f600, 0x00ededed, 0x7b007b7b, 0x7e7e007e
.long 0xf3f3f300, 0x00e7e7e7, 0xf900f9f9, 0x05050005
.long 0x9d9d9d00, 0x003b3b3b, 0xce00cece, 0xb7b700b7
.long 0x7f7f7f00, 0x00fefefe, 0xbf00bfbf, 0x31310031
.long 0xbfbfbf00, 0x007f7f7f, 0xdf00dfdf, 0x17170017
.long 0xe2e2e200, 0x00c5c5c5, 0x71007171, 0xd7d700d7
.long 0x52525200, 0x00a4a4a4, 0x29002929, 0x58580058
.long 0x9b9b9b00, 0x00373737, 0xcd00cdcd, 0x61610061
.long 0xd8d8d800, 0x00b1b1b1, 0x6c006c6c, 0x1b1b001b
.long 0x26262600, 0x004c4c4c, 0x13001313, 0x1c1c001c
.long 0xc8c8c800, 0x00919191, 0x64006464, 0x0f0f000f
.long 0x37373700, 0x006e6e6e, 0x9b009b9b, 0x16160016
.long 0xc6c6c600, 0x008d8d8d, 0x63006363, 0x18180018
.long 0x3b3b3b00, 0x00767676, 0x9d009d9d, 0x22220022
.long 0x81818100, 0x00030303, 0xc000c0c0, 0x44440044
.long 0x96969600, 0x002d2d2d, 0x4b004b4b, 0xb2b200b2
.long 0x6f6f6f00, 0x00dedede, 0xb700b7b7, 0xb5b500b5
.long 0x4b4b4b00, 0x00969696, 0xa500a5a5, 0x91910091
.long 0x13131300, 0x00262626, 0x89008989, 0x08080008
.long 0xbebebe00, 0x007d7d7d, 0x5f005f5f, 0xa8a800a8
.long 0x63636300, 0x00c6c6c6, 0xb100b1b1, 0xfcfc00fc
.long 0x2e2e2e00, 0x005c5c5c, 0x17001717, 0x50500050
.long 0xe9e9e900, 0x00d3d3d3, 0xf400f4f4, 0xd0d000d0
.long 0x79797900, 0x00f2f2f2, 0xbc00bcbc, 0x7d7d007d
.long 0xa7a7a700, 0x004f4f4f, 0xd300d3d3, 0x89890089
.long 0x8c8c8c00, 0x00191919, 0x46004646, 0x97970097
.long 0x9f9f9f00, 0x003f3f3f, 0xcf00cfcf, 0x5b5b005b
.long 0x6e6e6e00, 0x00dcdcdc, 0x37003737, 0x95950095
.long 0xbcbcbc00, 0x00797979, 0x5e005e5e, 0xffff00ff
.long 0x8e8e8e00, 0x001d1d1d, 0x47004747, 0xd2d200d2
.long 0x29292900, 0x00525252, 0x94009494, 0xc4c400c4
.long 0xf5f5f500, 0x00ebebeb, 0xfa00fafa, 0x48480048
.long 0xf9f9f900, 0x00f3f3f3, 0xfc00fcfc, 0xf7f700f7
.long 0xb6b6b600, 0x006d6d6d, 0x5b005b5b, 0xdbdb00db
.long 0x2f2f2f00, 0x005e5e5e, 0x97009797, 0x03030003
.long 0xfdfdfd00, 0x00fbfbfb, 0xfe00fefe, 0xdada00da
.long 0xb4b4b400, 0x00696969, 0x5a005a5a, 0x3f3f003f
.long 0x59595900, 0x00b2b2b2, 0xac00acac, 0x94940094
.long 0x78787800, 0x00f0f0f0, 0x3c003c3c, 0x5c5c005c
.long 0x98989800, 0x00313131, 0x4c004c4c, 0x02020002
.long 0x06060600, 0x000c0c0c, 0x03000303, 0x4a4a004a
.long 0x6a6a6a00, 0x00d4d4d4, 0x35003535, 0x33330033
.long 0xe7e7e700, 0x00cfcfcf, 0xf300f3f3, 0x67670067
.long 0x46464600, 0x008c8c8c, 0x23002323, 0xf3f300f3
.long 0x71717100, 0x00e2e2e2, 0xb800b8b8, 0x7f7f007f
.long 0xbababa00, 0x00757575, 0x5d005d5d, 0xe2e200e2
.long 0xd4d4d400, 0x00a9a9a9, 0x6a006a6a, 0x9b9b009b
.long 0x25252500, 0x004a4a4a, 0x92009292, 0x26260026
.long 0xababab00, 0x00575757, 0xd500d5d5, 0x37370037
.long 0x42424200, 0x00848484, 0x21002121, 0x3b3b003b
.long 0x88888800, 0x00111111, 0x44004444, 0x96960096
.long 0xa2a2a200, 0x00454545, 0x51005151, 0x4b4b004b
.long 0x8d8d8d00, 0x001b1b1b, 0xc600c6c6, 0xbebe00be
.long 0xfafafa00, 0x00f5f5f5, 0x7d007d7d, 0x2e2e002e
.long 0x72727200, 0x00e4e4e4, 0x39003939, 0x79790079
.long 0x07070700, 0x000e0e0e, 0x83008383, 0x8c8c008c
.long 0xb9b9b900, 0x00737373, 0xdc00dcdc, 0x6e6e006e
.long 0x55555500, 0x00aaaaaa, 0xaa00aaaa, 0x8e8e008e
.long 0xf8f8f800, 0x00f1f1f1, 0x7c007c7c, 0xf5f500f5
.long 0xeeeeee00, 0x00dddddd, 0x77007777, 0xb6b600b6
.long 0xacacac00, 0x00595959, 0x56005656, 0xfdfd00fd
.long 0x0a0a0a00, 0x00141414, 0x05000505, 0x59590059
.long 0x36363600, 0x006c6c6c, 0x1b001b1b, 0x98980098
.long 0x49494900, 0x00929292, 0xa400a4a4, 0x6a6a006a
.long 0x2a2a2a00, 0x00545454, 0x15001515, 0x46460046
.long 0x68686800, 0x00d0d0d0, 0x34003434, 0xbaba00ba
.long 0x3c3c3c00, 0x00787878, 0x1e001e1e, 0x25250025
.long 0x38383800, 0x00707070, 0x1c001c1c, 0x42420042
.long 0xf1f1f100, 0x00e3e3e3, 0xf800f8f8, 0xa2a200a2
.long 0xa4a4a400, 0x00494949, 0x52005252, 0xfafa00fa
.long 0x40404000, 0x00808080, 0x20002020, 0x07070007
.long 0x28282800, 0x00505050, 0x14001414, 0x55550055
.long 0xd3d3d300, 0x00a7a7a7, 0xe900e9e9, 0xeeee00ee
.long 0x7b7b7b00, 0x00f6f6f6, 0xbd00bdbd, 0x0a0a000a
.long 0xbbbbbb00, 0x00777777, 0xdd00dddd, 0x49490049
.long 0xc9c9c900, 0x00939393, 0xe400e4e4, 0x68680068
.long 0x43434300, 0x00868686, 0xa100a1a1, 0x38380038
.long 0xc1c1c100, 0x00838383, 0xe000e0e0, 0xa4a400a4
.long 0x15151500, 0x002a2a2a, 0x8a008a8a, 0x28280028
.long 0xe3e3e300, 0x00c7c7c7, 0xf100f1f1, 0x7b7b007b
.long 0xadadad00, 0x005b5b5b, 0xd600d6d6, 0xc9c900c9
.long 0xf4f4f400, 0x00e9e9e9, 0x7a007a7a, 0xc1c100c1
.long 0x77777700, 0x00eeeeee, 0xbb00bbbb, 0xe3e300e3
.long 0xc7c7c700, 0x008f8f8f, 0xe300e3e3, 0xf4f400f4
.long 0x80808000, 0x00010101, 0x40004040, 0xc7c700c7
.long 0x9e9e9e00, 0x003d3d3d, 0x4f004f4f, 0x9e9e009e
ELF(.size _gcry_camellia_arm_tables,.-_gcry_camellia_arm_tables;)
#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
#endif /*__AARCH64EL__*/
diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S
index e16d4f61..5036b1aa 100644
--- a/cipher/camellia-aesni-avx-amd64.S
+++ b/cipher/camellia-aesni-avx-amd64.S
@@ -1,2647 +1,2647 @@
/* camellia-avx-aesni-amd64.S - AES-NI/AVX implementation of Camellia cipher
*
* Copyright (C) 2013-2015 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/>.
+ * License along with this program; if not, see <https://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(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)
#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;
/**********************************************************************
16-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 roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2, t3, t4, t5, t6, \
t7, mem_cd, key) \
/* \
* S-function with AES subbytes \
*/ \
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; \
vpshufb t4, x7, x7; \
vpshufb t4, x1, x1; \
vpshufb t4, x4, x4; \
vpshufb t4, x2, x2; \
vpshufb t4, x5, x5; \
vpshufb t4, x3, x3; \
vpshufb t4, x6, x6; \
\
/* prefilter sboxes 1, 2 and 3 */ \
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(x4, t0, t1, t7, t6); \
filter_8bit(x2, t0, t1, t7, t6); \
filter_8bit(x5, t0, t1, t7, t6); \
\
/* prefilter sbox 4 */ \
vpxor t4, t4, t4; \
filter_8bit(x3, t2, t3, t7, t6); \
filter_8bit(x6, t2, t3, t7, t6); \
\
/* AES subbytes + AES shift rows */ \
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, x4, x4; \
vaesenclast t4, x2, x2; \
vaesenclast t4, x5, x5; \
vaesenclast t4, x3, x3; \
vaesenclast t4, x6, x6; \
\
/* postfilter sboxes 1 and 4 */ \
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 rRIP, t4; \
vmovdqa .Lpost_tf_hi_s2 rRIP, t5; \
filter_8bit(x2, t2, t3, t7, t6); \
filter_8bit(x5, t2, t3, t7, t6); \
\
vpxor t6, t6, t6; \
vmovq key, t0; \
\
/* postfilter sbox 2 */ \
filter_8bit(x1, t4, t5, t7, t2); \
filter_8bit(x4, t4, t5, t7, t2); \
\
vpsrldq $5, t0, t5; \
vpsrldq $1, t0, t1; \
vpsrldq $2, t0, t2; \
vpsrldq $3, t0, t3; \
vpsrldq $4, t0, t4; \
vpshufb t6, t0, t0; \
vpshufb t6, t1, t1; \
vpshufb t6, t2, t2; \
vpshufb t6, t3, t3; \
vpshufb t6, t4, t4; \
vpsrldq $2, t5, t7; \
vpshufb t6, t7, t7; \
\
/* P-function */ \
vpxor x5, x0, x0; \
vpxor x6, x1, x1; \
vpxor x7, x2, x2; \
vpxor x4, x3, x3; \
\
vpxor x2, x4, x4; \
vpxor x3, x5, x5; \
vpxor x0, x6, x6; \
vpxor x1, x7, x7; \
\
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 t3, x4, x4; \
vpxor 0 * 16(mem_cd), x4, x4; \
\
vpxor t2, x5, x5; \
vpxor 1 * 16(mem_cd), x5, x5; \
\
vpsrldq $1, t5, t3; \
vpshufb t6, t5, t5; \
vpshufb t6, t3, t6; \
\
vpxor t1, x6, x6; \
vpxor 2 * 16(mem_cd), x6, x6; \
\
vpxor t0, x7, x7; \
vpxor 3 * 16(mem_cd), x7, x7; \
\
vpxor t7, x0, x0; \
vpxor 4 * 16(mem_cd), x0, x0; \
\
vpxor t6, x1, x1; \
vpxor 5 * 16(mem_cd), x1, x1; \
\
vpxor t5, x2, x2; \
vpxor 6 * 16(mem_cd), x2, x2; \
\
vpxor t4, x3, x3; \
vpxor 7 * 16(mem_cd), x3, x3;
/*
* 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_roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
y6, y7, mem_ab, mem_cd, i, dir, store_ab) \
roundsm16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
y6, y7, mem_cd, (key_table + (i) * 8)(CTX)); \
\
vmovdqu x4, 0 * 16(mem_cd); \
vmovdqu x5, 1 * 16(mem_cd); \
vmovdqu x6, 2 * 16(mem_cd); \
vmovdqu x7, 3 * 16(mem_cd); \
vmovdqu x0, 4 * 16(mem_cd); \
vmovdqu x1, 5 * 16(mem_cd); \
vmovdqu x2, 6 * 16(mem_cd); \
vmovdqu x3, 7 * 16(mem_cd); \
\
roundsm16(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 x0, 0 * 16(mem_ab); \
vmovdqu x1, 1 * 16(mem_ab); \
vmovdqu x2, 2 * 16(mem_ab); \
vmovdqu x3, 3 * 16(mem_ab); \
vmovdqu x4, 4 * 16(mem_ab); \
vmovdqu x5, 5 * 16(mem_ab); \
vmovdqu x6, 6 * 16(mem_ab); \
vmovdqu x7, 7 * 16(mem_ab);
#define enc_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
y6, y7, mem_ab, mem_cd, i) \
two_roundsm16(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_roundsm16(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_roundsm16(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_rounds16(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
y6, y7, mem_ab, mem_cd, i) \
two_roundsm16(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_roundsm16(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_roundsm16(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_16(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 fls16(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); \
*/ \
vpxor tt0, tt0, tt0; \
vmovd kll, 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; \
\
vpand l0, t0, t0; \
vpand l1, t1, t1; \
vpand l2, t2, t2; \
vpand l3, t3, t3; \
\
rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
\
vpxor l4, t0, l4; \
vmovdqu l4, 4 * 16(l); \
vpxor l5, t1, l5; \
vmovdqu l5, 5 * 16(l); \
vpxor l6, t2, l6; \
vmovdqu l6, 6 * 16(l); \
vpxor l7, t3, l7; \
vmovdqu l7, 7 * 16(l); \
\
/* \
* t2 = krr; \
* t2 |= rr; \
* rl ^= t2; \
*/ \
\
vmovd krr, 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 4 * 16(r), t0, t0; \
vpor 5 * 16(r), t1, t1; \
vpor 6 * 16(r), t2, t2; \
vpor 7 * 16(r), t3, t3; \
\
vpxor 0 * 16(r), t0, t0; \
vpxor 1 * 16(r), t1, t1; \
vpxor 2 * 16(r), t2, t2; \
vpxor 3 * 16(r), t3, t3; \
vmovdqu t0, 0 * 16(r); \
vmovdqu t1, 1 * 16(r); \
vmovdqu t2, 2 * 16(r); \
vmovdqu t3, 3 * 16(r); \
\
/* \
* t2 = krl; \
* t2 &= rl; \
* rr ^= rol32(t2, 1); \
*/ \
vmovd krl, 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; \
\
vpand 0 * 16(r), t0, t0; \
vpand 1 * 16(r), t1, t1; \
vpand 2 * 16(r), t2, t2; \
vpand 3 * 16(r), t3, t3; \
\
rol32_1_16(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
\
vpxor 4 * 16(r), t0, t0; \
vpxor 5 * 16(r), t1, t1; \
vpxor 6 * 16(r), t2, t2; \
vpxor 7 * 16(r), t3, t3; \
vmovdqu t0, 4 * 16(r); \
vmovdqu t1, 5 * 16(r); \
vmovdqu t2, 6 * 16(r); \
vmovdqu t3, 7 * 16(r); \
\
/* \
* t0 = klr; \
* t0 |= lr; \
* ll ^= t0; \
*/ \
\
vmovd klr, 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 * 16(l); \
vpxor l1, t1, l1; \
vmovdqu l1, 1 * 16(l); \
vpxor l2, t2, l2; \
vmovdqu l2, 2 * 16(l); \
vpxor l3, t3, l3; \
vmovdqu l3, 3 * 16(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); \
\
vmovdqu .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 */
#define transpose_8x8b(a, b, c, d, e, f, g, h, t0, t1, t2, t3, t4) \
vpunpcklbw a, b, t0; \
vpunpckhbw a, b, b; \
\
vpunpcklbw c, d, t1; \
vpunpckhbw c, d, d; \
\
vpunpcklbw e, f, t2; \
vpunpckhbw e, f, f; \
\
vpunpcklbw g, h, t3; \
vpunpckhbw g, h, h; \
\
vpunpcklwd t0, t1, g; \
vpunpckhwd t0, t1, t0; \
\
vpunpcklwd b, d, t1; \
vpunpckhwd b, d, e; \
\
vpunpcklwd t2, t3, c; \
vpunpckhwd t2, t3, t2; \
\
vpunpcklwd f, h, t3; \
vpunpckhwd f, h, b; \
\
vpunpcklwd e, b, t4; \
vpunpckhwd e, b, b; \
\
vpunpcklwd t1, t3, e; \
vpunpckhwd t1, t3, f; \
\
vmovdqa .Ltranspose_8x8_shuf rRIP, t3; \
\
vpunpcklwd g, c, d; \
vpunpckhwd g, c, c; \
\
vpunpcklwd t0, t2, t1; \
vpunpckhwd t0, t2, h; \
\
vpunpckhqdq b, h, a; \
vpshufb t3, a, a; \
vpunpcklqdq b, h, b; \
vpshufb t3, b, b; \
\
vpunpckhqdq e, d, g; \
vpshufb t3, g, g; \
vpunpcklqdq e, d, h; \
vpshufb t3, h, h; \
\
vpunpckhqdq f, c, e; \
vpshufb t3, e, e; \
vpunpcklqdq f, c, f; \
vpshufb t3, f, f; \
\
vpunpckhqdq t4, t1, c; \
vpshufb t3, c, c; \
vpunpcklqdq t4, t1, d; \
vpshufb t3, d, d;
/* load blocks to registers and apply pre-whitening */
#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 rRIP, x0, x0; \
\
vpxor 0 * 16(rio), x0, y7; \
vpxor 1 * 16(rio), x0, y6; \
vpxor 2 * 16(rio), x0, y5; \
vpxor 3 * 16(rio), x0, y4; \
vpxor 4 * 16(rio), x0, y3; \
vpxor 5 * 16(rio), x0, y2; \
vpxor 6 * 16(rio), x0, y1; \
vpxor 7 * 16(rio), x0, y0; \
vpxor 8 * 16(rio), x0, x7; \
vpxor 9 * 16(rio), x0, x6; \
vpxor 10 * 16(rio), x0, x5; \
vpxor 11 * 16(rio), x0, x4; \
vpxor 12 * 16(rio), x0, x3; \
vpxor 13 * 16(rio), x0, x2; \
vpxor 14 * 16(rio), x0, x1; \
vpxor 15 * 16(rio), x0, x0;
/* byteslice pre-whitened blocks and store to temporary memory */
#define inpack16_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 * 16(mem_ab); \
vmovdqu x1, 1 * 16(mem_ab); \
vmovdqu x2, 2 * 16(mem_ab); \
vmovdqu x3, 3 * 16(mem_ab); \
vmovdqu x4, 4 * 16(mem_ab); \
vmovdqu x5, 5 * 16(mem_ab); \
vmovdqu x6, 6 * 16(mem_ab); \
vmovdqu x7, 7 * 16(mem_ab); \
vmovdqu y0, 0 * 16(mem_cd); \
vmovdqu y1, 1 * 16(mem_cd); \
vmovdqu y2, 2 * 16(mem_cd); \
vmovdqu y3, 3 * 16(mem_cd); \
vmovdqu y4, 4 * 16(mem_cd); \
vmovdqu y5, 5 * 16(mem_cd); \
vmovdqu y6, 6 * 16(mem_cd); \
vmovdqu y7, 7 * 16(mem_cd);
/* de-byteslice, apply post-whitening and store blocks */
#define outunpack16(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; \
\
vmovq 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 * 16(rio); \
vmovdqu x1, 1 * 16(rio); \
vmovdqu x2, 2 * 16(rio); \
vmovdqu x3, 3 * 16(rio); \
vmovdqu x4, 4 * 16(rio); \
vmovdqu x5, 5 * 16(rio); \
vmovdqu x6, 6 * 16(rio); \
vmovdqu x7, 7 * 16(rio); \
vmovdqu y0, 8 * 16(rio); \
vmovdqu y1, 9 * 16(rio); \
vmovdqu y2, 10 * 16(rio); \
vmovdqu y3, 11 * 16(rio); \
vmovdqu y4, 12 * 16(rio); \
vmovdqu y5, 13 * 16(rio); \
vmovdqu y6, 14 * 16(rio); \
vmovdqu y7, 15 * 16(rio);
.text
.align 16
#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);
.Lpack_bswap:
.long 0x00010203
.long 0x04050607
.long 0x80808080
.long 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
/* shuffle mask for 8x8 byte transpose */
.Ltranspose_8x8_shuf:
.byte 0, 1, 4, 5, 2, 3, 6, 7, 8+0, 8+1, 8+4, 8+5, 8+2, 8+3, 8+6, 8+7
.align 4
/* 4-bit mask */
.L0f0f0f0f:
.long 0x0f0f0f0f
.align 8
ELF(.type __camellia_enc_blk16,@function;)
__camellia_enc_blk16:
/* input:
* %rdi: ctx, CTX
* %rax: temporary storage, 256 bytes
* %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;
inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rax, %rcx);
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);
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;
.Lenc_done:
/* load CD for output */
vmovdqu 0 * 16(%rcx), %xmm8;
vmovdqu 1 * 16(%rcx), %xmm9;
vmovdqu 2 * 16(%rcx), %xmm10;
vmovdqu 3 * 16(%rcx), %xmm11;
vmovdqu 4 * 16(%rcx), %xmm12;
vmovdqu 5 * 16(%rcx), %xmm13;
vmovdqu 6 * 16(%rcx), %xmm14;
vmovdqu 7 * 16(%rcx), %xmm15;
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));
enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rax, %rcx, 24);
jmp .Lenc_done;
CFI_ENDPROC();
ELF(.size __camellia_enc_blk16,.-__camellia_enc_blk16;)
.align 8
ELF(.type __camellia_dec_blk16,@function;)
__camellia_dec_blk16:
/* input:
* %rdi: ctx, CTX
* %rax: temporary storage, 256 bytes
* %r8d: 24 for 16 byte key, 32 for larger
* %xmm0..%xmm15: 16 encrypted blocks
* output:
* %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();
leaq 8 * 16(%rax), %rcx;
inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rax, %rcx);
cmpl $32, %r8d;
je .Ldec_max32;
.Ldec_max24:
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));
dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rax, %rcx, 8);
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));
dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rax, %rcx, 0);
/* load CD for output */
vmovdqu 0 * 16(%rcx), %xmm8;
vmovdqu 1 * 16(%rcx), %xmm9;
vmovdqu 2 * 16(%rcx), %xmm10;
vmovdqu 3 * 16(%rcx), %xmm11;
vmovdqu 4 * 16(%rcx), %xmm12;
vmovdqu 5 * 16(%rcx), %xmm13;
vmovdqu 6 * 16(%rcx), %xmm14;
vmovdqu 7 * 16(%rcx), %xmm15;
outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%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;
CFI_ENDPROC();
ELF(.size __camellia_dec_blk16,.-__camellia_dec_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_camellia_aesni_avx_ctr_enc
ELF(.type _gcry_camellia_aesni_avx_ctr_enc,@function;)
_gcry_camellia_aesni_avx_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (16 blocks)
* %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;
subq $(16 * 16), %rsp;
andq $~31, %rsp;
movq %rsp, %rax;
vmovdqa .Lbswap128_mask rRIP, %xmm14;
/* load IV and byteswap */
vmovdqu (%rcx), %xmm15;
vmovdqu %xmm15, 15 * 16(%rax);
vpshufb %xmm14, %xmm15, %xmm0; /* be => le */
vpcmpeqd %xmm15, %xmm15, %xmm15;
vpsrldq $8, %xmm15, %xmm15; /* low: -1, high: 0 */
/* construct IVs */
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm13;
vmovdqu %xmm13, 14 * 16(%rax);
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm13;
vmovdqu %xmm13, 13 * 16(%rax);
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm12;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm11;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm10;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm9;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm8;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm7;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm6;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm5;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm4;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm3;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm2;
inc_le128(%xmm0, %xmm15, %xmm13);
vpshufb %xmm14, %xmm0, %xmm1;
inc_le128(%xmm0, %xmm15, %xmm13);
vmovdqa %xmm0, %xmm13;
vpshufb %xmm14, %xmm0, %xmm0;
inc_le128(%xmm13, %xmm15, %xmm14);
vpshufb .Lbswap128_mask rRIP, %xmm13, %xmm13; /* le => be */
vmovdqu %xmm13, (%rcx);
/* inpack16_pre: */
vmovq (key_table)(CTX), %xmm15;
vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
vpxor %xmm0, %xmm15, %xmm0;
vpxor %xmm1, %xmm15, %xmm1;
vpxor %xmm2, %xmm15, %xmm2;
vpxor %xmm3, %xmm15, %xmm3;
vpxor %xmm4, %xmm15, %xmm4;
vpxor %xmm5, %xmm15, %xmm5;
vpxor %xmm6, %xmm15, %xmm6;
vpxor %xmm7, %xmm15, %xmm7;
vpxor %xmm8, %xmm15, %xmm8;
vpxor %xmm9, %xmm15, %xmm9;
vpxor %xmm10, %xmm15, %xmm10;
vpxor %xmm11, %xmm15, %xmm11;
vpxor %xmm12, %xmm15, %xmm12;
vpxor 13 * 16(%rax), %xmm15, %xmm13;
vpxor 14 * 16(%rax), %xmm15, %xmm14;
vpxor 15 * 16(%rax), %xmm15, %xmm15;
call __camellia_enc_blk16;
vpxor 0 * 16(%rdx), %xmm7, %xmm7;
vpxor 1 * 16(%rdx), %xmm6, %xmm6;
vpxor 2 * 16(%rdx), %xmm5, %xmm5;
vpxor 3 * 16(%rdx), %xmm4, %xmm4;
vpxor 4 * 16(%rdx), %xmm3, %xmm3;
vpxor 5 * 16(%rdx), %xmm2, %xmm2;
vpxor 6 * 16(%rdx), %xmm1, %xmm1;
vpxor 7 * 16(%rdx), %xmm0, %xmm0;
vpxor 8 * 16(%rdx), %xmm15, %xmm15;
vpxor 9 * 16(%rdx), %xmm14, %xmm14;
vpxor 10 * 16(%rdx), %xmm13, %xmm13;
vpxor 11 * 16(%rdx), %xmm12, %xmm12;
vpxor 12 * 16(%rdx), %xmm11, %xmm11;
vpxor 13 * 16(%rdx), %xmm10, %xmm10;
vpxor 14 * 16(%rdx), %xmm9, %xmm9;
vpxor 15 * 16(%rdx), %xmm8, %xmm8;
write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
%xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
%xmm8, %rsi);
vzeroall;
leave;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_ctr_enc,.-_gcry_camellia_aesni_avx_ctr_enc;)
.align 8
.globl _gcry_camellia_aesni_avx_cbc_dec
ELF(.type _gcry_camellia_aesni_avx_cbc_dec,@function;)
_gcry_camellia_aesni_avx_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (16 blocks)
* %rdx: src (16 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 */
inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
%xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
%xmm15, %rdx, (key_table)(CTX, %r8, 8));
subq $(16 * 16), %rsp;
andq $~31, %rsp;
movq %rsp, %rax;
call __camellia_dec_blk16;
/* XOR output with IV */
vpxor (%r9), %xmm7, %xmm7;
vpxor (0 * 16)(%rdx), %xmm6, %xmm6;
vpxor (1 * 16)(%rdx), %xmm5, %xmm5;
vpxor (2 * 16)(%rdx), %xmm4, %xmm4;
vpxor (3 * 16)(%rdx), %xmm3, %xmm3;
vpxor (4 * 16)(%rdx), %xmm2, %xmm2;
vpxor (5 * 16)(%rdx), %xmm1, %xmm1;
vpxor (6 * 16)(%rdx), %xmm0, %xmm0;
vpxor (7 * 16)(%rdx), %xmm15, %xmm15;
vpxor (8 * 16)(%rdx), %xmm14, %xmm14;
vpxor (9 * 16)(%rdx), %xmm13, %xmm13;
vpxor (10 * 16)(%rdx), %xmm12, %xmm12;
vpxor (11 * 16)(%rdx), %xmm11, %xmm11;
vpxor (12 * 16)(%rdx), %xmm10, %xmm10;
vpxor (13 * 16)(%rdx), %xmm9, %xmm9;
vpxor (14 * 16)(%rdx), %xmm8, %xmm8;
movq (15 * 16 + 0)(%rdx), %r10;
movq (15 * 16 + 8)(%rdx), %r11;
write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
%xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
%xmm8, %rsi);
/* store new IV */
movq %r10, (0)(%r9);
movq %r11, (8)(%r9);
vzeroall;
leave;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_cbc_dec,.-_gcry_camellia_aesni_avx_cbc_dec;)
.align 8
.globl _gcry_camellia_aesni_avx_cfb_dec
ELF(.type _gcry_camellia_aesni_avx_cfb_dec,@function;)
_gcry_camellia_aesni_avx_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (16 blocks)
* %rdx: src (16 blocks)
* %rcx: iv
*/
CFI_STARTPROC();
pushq %rbp;
CFI_PUSH(%rbp);
movq %rsp, %rbp;
CFI_DEF_CFA_REGISTER(%rbp);
vzeroupper;
subq $(16 * 16), %rsp;
andq $~31, %rsp;
movq %rsp, %rax;
/* inpack16_pre: */
vmovq (key_table)(CTX), %xmm0;
vpshufb .Lpack_bswap rRIP, %xmm0, %xmm0;
vpxor (%rcx), %xmm0, %xmm15;
vmovdqu 15 * 16(%rdx), %xmm1;
vmovdqu %xmm1, (%rcx); /* store new IV */
vpxor 0 * 16(%rdx), %xmm0, %xmm14;
vpxor 1 * 16(%rdx), %xmm0, %xmm13;
vpxor 2 * 16(%rdx), %xmm0, %xmm12;
vpxor 3 * 16(%rdx), %xmm0, %xmm11;
vpxor 4 * 16(%rdx), %xmm0, %xmm10;
vpxor 5 * 16(%rdx), %xmm0, %xmm9;
vpxor 6 * 16(%rdx), %xmm0, %xmm8;
vpxor 7 * 16(%rdx), %xmm0, %xmm7;
vpxor 8 * 16(%rdx), %xmm0, %xmm6;
vpxor 9 * 16(%rdx), %xmm0, %xmm5;
vpxor 10 * 16(%rdx), %xmm0, %xmm4;
vpxor 11 * 16(%rdx), %xmm0, %xmm3;
vpxor 12 * 16(%rdx), %xmm0, %xmm2;
vpxor 13 * 16(%rdx), %xmm0, %xmm1;
vpxor 14 * 16(%rdx), %xmm0, %xmm0;
call __camellia_enc_blk16;
vpxor 0 * 16(%rdx), %xmm7, %xmm7;
vpxor 1 * 16(%rdx), %xmm6, %xmm6;
vpxor 2 * 16(%rdx), %xmm5, %xmm5;
vpxor 3 * 16(%rdx), %xmm4, %xmm4;
vpxor 4 * 16(%rdx), %xmm3, %xmm3;
vpxor 5 * 16(%rdx), %xmm2, %xmm2;
vpxor 6 * 16(%rdx), %xmm1, %xmm1;
vpxor 7 * 16(%rdx), %xmm0, %xmm0;
vpxor 8 * 16(%rdx), %xmm15, %xmm15;
vpxor 9 * 16(%rdx), %xmm14, %xmm14;
vpxor 10 * 16(%rdx), %xmm13, %xmm13;
vpxor 11 * 16(%rdx), %xmm12, %xmm12;
vpxor 12 * 16(%rdx), %xmm11, %xmm11;
vpxor 13 * 16(%rdx), %xmm10, %xmm10;
vpxor 14 * 16(%rdx), %xmm9, %xmm9;
vpxor 15 * 16(%rdx), %xmm8, %xmm8;
write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
%xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
%xmm8, %rsi);
vzeroall;
leave;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec;)
.align 8
.globl _gcry_camellia_aesni_avx_ocb_enc
ELF(.type _gcry_camellia_aesni_avx_ocb_enc,@function;)
_gcry_camellia_aesni_avx_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();
pushq %rbp;
CFI_PUSH(%rbp);
movq %rsp, %rbp;
CFI_DEF_CFA_REGISTER(%rbp);
vzeroupper;
subq $(16 * 16 + 4 * 8), %rsp;
andq $~31, %rsp;
movq %rsp, %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;
/* 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), %xmm14, %xmm14; \
vpxor xreg, %xmm15, %xmm15; \
vpxor xreg, %xmm14, xreg; \
vmovdqu %xmm14, (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, %xmm0);
vmovdqu %xmm0, (15 * 16)(%rax);
OCB_INPUT(1, %r11, %xmm0);
vmovdqu %xmm0, (14 * 16)(%rax);
OCB_INPUT(2, %r12, %xmm13);
OCB_INPUT(3, %r13, %xmm12);
movq (4 * 8)(%r9), %r10;
movq (5 * 8)(%r9), %r11;
movq (6 * 8)(%r9), %r12;
movq (7 * 8)(%r9), %r13;
OCB_INPUT(4, %r10, %xmm11);
OCB_INPUT(5, %r11, %xmm10);
OCB_INPUT(6, %r12, %xmm9);
OCB_INPUT(7, %r13, %xmm8);
movq (8 * 8)(%r9), %r10;
movq (9 * 8)(%r9), %r11;
movq (10 * 8)(%r9), %r12;
movq (11 * 8)(%r9), %r13;
OCB_INPUT(8, %r10, %xmm7);
OCB_INPUT(9, %r11, %xmm6);
OCB_INPUT(10, %r12, %xmm5);
OCB_INPUT(11, %r13, %xmm4);
movq (12 * 8)(%r9), %r10;
movq (13 * 8)(%r9), %r11;
movq (14 * 8)(%r9), %r12;
movq (15 * 8)(%r9), %r13;
OCB_INPUT(12, %r10, %xmm3);
OCB_INPUT(13, %r11, %xmm2);
OCB_INPUT(14, %r12, %xmm1);
OCB_INPUT(15, %r13, %xmm0);
#undef OCB_INPUT
vmovdqu %xmm14, (%rcx);
vmovdqu %xmm15, (%r8);
/* inpack16_pre: */
vmovq (key_table)(CTX), %xmm15;
vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
vpxor %xmm0, %xmm15, %xmm0;
vpxor %xmm1, %xmm15, %xmm1;
vpxor %xmm2, %xmm15, %xmm2;
vpxor %xmm3, %xmm15, %xmm3;
vpxor %xmm4, %xmm15, %xmm4;
vpxor %xmm5, %xmm15, %xmm5;
vpxor %xmm6, %xmm15, %xmm6;
vpxor %xmm7, %xmm15, %xmm7;
vpxor %xmm8, %xmm15, %xmm8;
vpxor %xmm9, %xmm15, %xmm9;
vpxor %xmm10, %xmm15, %xmm10;
vpxor %xmm11, %xmm15, %xmm11;
vpxor %xmm12, %xmm15, %xmm12;
vpxor %xmm13, %xmm15, %xmm13;
vpxor 14 * 16(%rax), %xmm15, %xmm14;
vpxor 15 * 16(%rax), %xmm15, %xmm15;
call __camellia_enc_blk16;
vpxor 0 * 16(%rsi), %xmm7, %xmm7;
vpxor 1 * 16(%rsi), %xmm6, %xmm6;
vpxor 2 * 16(%rsi), %xmm5, %xmm5;
vpxor 3 * 16(%rsi), %xmm4, %xmm4;
vpxor 4 * 16(%rsi), %xmm3, %xmm3;
vpxor 5 * 16(%rsi), %xmm2, %xmm2;
vpxor 6 * 16(%rsi), %xmm1, %xmm1;
vpxor 7 * 16(%rsi), %xmm0, %xmm0;
vpxor 8 * 16(%rsi), %xmm15, %xmm15;
vpxor 9 * 16(%rsi), %xmm14, %xmm14;
vpxor 10 * 16(%rsi), %xmm13, %xmm13;
vpxor 11 * 16(%rsi), %xmm12, %xmm12;
vpxor 12 * 16(%rsi), %xmm11, %xmm11;
vpxor 13 * 16(%rsi), %xmm10, %xmm10;
vpxor 14 * 16(%rsi), %xmm9, %xmm9;
vpxor 15 * 16(%rsi), %xmm8, %xmm8;
write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
%xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
%xmm8, %rsi);
vzeroall;
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;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_ocb_enc,.-_gcry_camellia_aesni_avx_ocb_enc;)
.align 8
.globl _gcry_camellia_aesni_avx_ocb_dec
ELF(.type _gcry_camellia_aesni_avx_ocb_dec,@function;)
_gcry_camellia_aesni_avx_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();
pushq %rbp;
CFI_PUSH(%rbp);
movq %rsp, %rbp;
CFI_DEF_CFA_REGISTER(%rbp);
vzeroupper;
subq $(16 * 16 + 4 * 8), %rsp;
andq $~31, %rsp;
movq %rsp, %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;
/* 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), %xmm15, %xmm15; \
vpxor xreg, %xmm15, xreg; \
vmovdqu %xmm15, (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, %xmm0);
vmovdqu %xmm0, (15 * 16)(%rax);
OCB_INPUT(1, %r11, %xmm14);
OCB_INPUT(2, %r12, %xmm13);
OCB_INPUT(3, %r13, %xmm12);
movq (4 * 8)(%r9), %r10;
movq (5 * 8)(%r9), %r11;
movq (6 * 8)(%r9), %r12;
movq (7 * 8)(%r9), %r13;
OCB_INPUT(4, %r10, %xmm11);
OCB_INPUT(5, %r11, %xmm10);
OCB_INPUT(6, %r12, %xmm9);
OCB_INPUT(7, %r13, %xmm8);
movq (8 * 8)(%r9), %r10;
movq (9 * 8)(%r9), %r11;
movq (10 * 8)(%r9), %r12;
movq (11 * 8)(%r9), %r13;
OCB_INPUT(8, %r10, %xmm7);
OCB_INPUT(9, %r11, %xmm6);
OCB_INPUT(10, %r12, %xmm5);
OCB_INPUT(11, %r13, %xmm4);
movq (12 * 8)(%r9), %r10;
movq (13 * 8)(%r9), %r11;
movq (14 * 8)(%r9), %r12;
movq (15 * 8)(%r9), %r13;
OCB_INPUT(12, %r10, %xmm3);
OCB_INPUT(13, %r11, %xmm2);
OCB_INPUT(14, %r12, %xmm1);
OCB_INPUT(15, %r13, %xmm0);
#undef OCB_INPUT
vmovdqu %xmm15, (%rcx);
movq %r8, %r10;
cmpl $128, key_bitlength(CTX);
movl $32, %r8d;
movl $24, %r9d;
cmovel %r9d, %r8d; /* max */
/* inpack16_pre: */
vmovq (key_table)(CTX, %r8, 8), %xmm15;
vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
vpxor %xmm0, %xmm15, %xmm0;
vpxor %xmm1, %xmm15, %xmm1;
vpxor %xmm2, %xmm15, %xmm2;
vpxor %xmm3, %xmm15, %xmm3;
vpxor %xmm4, %xmm15, %xmm4;
vpxor %xmm5, %xmm15, %xmm5;
vpxor %xmm6, %xmm15, %xmm6;
vpxor %xmm7, %xmm15, %xmm7;
vpxor %xmm8, %xmm15, %xmm8;
vpxor %xmm9, %xmm15, %xmm9;
vpxor %xmm10, %xmm15, %xmm10;
vpxor %xmm11, %xmm15, %xmm11;
vpxor %xmm12, %xmm15, %xmm12;
vpxor %xmm13, %xmm15, %xmm13;
vpxor %xmm14, %xmm15, %xmm14;
vpxor 15 * 16(%rax), %xmm15, %xmm15;
call __camellia_dec_blk16;
vpxor 0 * 16(%rsi), %xmm7, %xmm7;
vpxor 1 * 16(%rsi), %xmm6, %xmm6;
vpxor 2 * 16(%rsi), %xmm5, %xmm5;
vpxor 3 * 16(%rsi), %xmm4, %xmm4;
vpxor 4 * 16(%rsi), %xmm3, %xmm3;
vpxor 5 * 16(%rsi), %xmm2, %xmm2;
vpxor 6 * 16(%rsi), %xmm1, %xmm1;
vpxor 7 * 16(%rsi), %xmm0, %xmm0;
vmovdqu %xmm7, (7 * 16)(%rax);
vpxor 8 * 16(%rsi), %xmm15, %xmm15;
vpxor 9 * 16(%rsi), %xmm14, %xmm14;
vpxor 10 * 16(%rsi), %xmm13, %xmm13;
vpxor 11 * 16(%rsi), %xmm12, %xmm12;
vpxor 12 * 16(%rsi), %xmm11, %xmm11;
vpxor 13 * 16(%rsi), %xmm10, %xmm10;
vpxor 14 * 16(%rsi), %xmm9, %xmm9;
vpxor 15 * 16(%rsi), %xmm8, %xmm8;
/* Checksum_i = Checksum_{i-1} xor P_i */
vpxor (%r10), %xmm7, %xmm7;
vpxor %xmm6, %xmm7, %xmm7;
vpxor %xmm5, %xmm7, %xmm7;
vpxor %xmm4, %xmm7, %xmm7;
vpxor %xmm3, %xmm7, %xmm7;
vpxor %xmm2, %xmm7, %xmm7;
vpxor %xmm1, %xmm7, %xmm7;
vpxor %xmm0, %xmm7, %xmm7;
vpxor %xmm15, %xmm7, %xmm7;
vpxor %xmm14, %xmm7, %xmm7;
vpxor %xmm13, %xmm7, %xmm7;
vpxor %xmm12, %xmm7, %xmm7;
vpxor %xmm11, %xmm7, %xmm7;
vpxor %xmm10, %xmm7, %xmm7;
vpxor %xmm9, %xmm7, %xmm7;
vpxor %xmm8, %xmm7, %xmm7;
vmovdqu %xmm7, (%r10);
vmovdqu (7 * 16)(%rax), %xmm7;
write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0,
%xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
%xmm8, %rsi);
vzeroall;
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;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_ocb_dec,.-_gcry_camellia_aesni_avx_ocb_dec;)
.align 8
.globl _gcry_camellia_aesni_avx_ocb_auth
ELF(.type _gcry_camellia_aesni_avx_ocb_auth,@function;)
_gcry_camellia_aesni_avx_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 * 16 + 4 * 8), %rsp;
andq $~31, %rsp;
movq %rsp, %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;
/* 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), %xmm15, %xmm15; \
vpxor xreg, %xmm15, 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, %xmm0);
vmovdqu %xmm0, (15 * 16)(%rax);
OCB_INPUT(1, %r11, %xmm14);
OCB_INPUT(2, %r12, %xmm13);
OCB_INPUT(3, %r13, %xmm12);
movq (4 * 8)(%r8), %r10;
movq (5 * 8)(%r8), %r11;
movq (6 * 8)(%r8), %r12;
movq (7 * 8)(%r8), %r13;
OCB_INPUT(4, %r10, %xmm11);
OCB_INPUT(5, %r11, %xmm10);
OCB_INPUT(6, %r12, %xmm9);
OCB_INPUT(7, %r13, %xmm8);
movq (8 * 8)(%r8), %r10;
movq (9 * 8)(%r8), %r11;
movq (10 * 8)(%r8), %r12;
movq (11 * 8)(%r8), %r13;
OCB_INPUT(8, %r10, %xmm7);
OCB_INPUT(9, %r11, %xmm6);
OCB_INPUT(10, %r12, %xmm5);
OCB_INPUT(11, %r13, %xmm4);
movq (12 * 8)(%r8), %r10;
movq (13 * 8)(%r8), %r11;
movq (14 * 8)(%r8), %r12;
movq (15 * 8)(%r8), %r13;
OCB_INPUT(12, %r10, %xmm3);
OCB_INPUT(13, %r11, %xmm2);
OCB_INPUT(14, %r12, %xmm1);
OCB_INPUT(15, %r13, %xmm0);
#undef OCB_INPUT
vmovdqu %xmm15, (%rdx);
movq %rcx, %r10;
/* inpack16_pre: */
vmovq (key_table)(CTX), %xmm15;
vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
vpxor %xmm0, %xmm15, %xmm0;
vpxor %xmm1, %xmm15, %xmm1;
vpxor %xmm2, %xmm15, %xmm2;
vpxor %xmm3, %xmm15, %xmm3;
vpxor %xmm4, %xmm15, %xmm4;
vpxor %xmm5, %xmm15, %xmm5;
vpxor %xmm6, %xmm15, %xmm6;
vpxor %xmm7, %xmm15, %xmm7;
vpxor %xmm8, %xmm15, %xmm8;
vpxor %xmm9, %xmm15, %xmm9;
vpxor %xmm10, %xmm15, %xmm10;
vpxor %xmm11, %xmm15, %xmm11;
vpxor %xmm12, %xmm15, %xmm12;
vpxor %xmm13, %xmm15, %xmm13;
vpxor %xmm14, %xmm15, %xmm14;
vpxor 15 * 16(%rax), %xmm15, %xmm15;
call __camellia_enc_blk16;
vpxor %xmm7, %xmm6, %xmm6;
vpxor %xmm5, %xmm4, %xmm4;
vpxor %xmm3, %xmm2, %xmm2;
vpxor %xmm1, %xmm0, %xmm0;
vpxor %xmm15, %xmm14, %xmm14;
vpxor %xmm13, %xmm12, %xmm12;
vpxor %xmm11, %xmm10, %xmm10;
vpxor %xmm9, %xmm8, %xmm8;
vpxor %xmm6, %xmm4, %xmm4;
vpxor %xmm2, %xmm0, %xmm0;
vpxor %xmm14, %xmm12, %xmm12;
vpxor %xmm10, %xmm8, %xmm8;
vpxor %xmm4, %xmm0, %xmm0;
vpxor %xmm12, %xmm8, %xmm8;
vpxor %xmm0, %xmm8, %xmm0;
vpxor (%r10), %xmm0, %xmm0;
vmovdqu %xmm0, (%r10);
vzeroall;
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;
CFI_LEAVE();
ret;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx_ocb_auth,.-_gcry_camellia_aesni_avx_ocb_auth;)
/*
* IN:
* ab: 64-bit AB state
* cd: 64-bit CD state
*/
#define camellia_f(ab, x, t0, t1, t2, t3, t4, inv_shift_row, sbox4mask, \
_0f0f0f0fmask, pre_s1lo_mask, pre_s1hi_mask, key) \
vmovq key, t0; \
vpxor x, x, t3; \
\
vpxor ab, t0, x; \
\
/* \
* S-function with AES subbytes \
*/ \
\
/* input rotation for sbox4 (<<< 1) */ \
vpand x, sbox4mask, t0; \
vpandn x, sbox4mask, x; \
vpaddw t0, t0, t1; \
vpsrlw $7, t0, t0; \
vpor t0, t1, t0; \
vpand sbox4mask, t0, t0; \
vpor t0, x, x; \
\
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); \
\
/* AES subbytes + AES shift rows + AES inv shift rows */ \
vaesenclast t3, x, x; \
\
/* postfilter sboxes */ \
filter_8bit(x, t0, t1, _0f0f0f0fmask, t2); \
\
/* output rotation for sbox2 (<<< 1) */ \
/* output rotation for sbox3 (>>> 1) */ \
vpshufb inv_shift_row, x, t1; \
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 rRIP, t0, t0; \
vpor t1, t3, t1; \
\
vpxor x, t4, t4; \
vpshufb .Lsp3033303303303033mask rRIP, t1, t1; \
vpxor t4, t0, t0; \
vpxor t1, t0, t0; \
vpsrldq $8, t0, x; \
vpxor t0, x, x;
#define vec_rol128(in, out, nrol, t0) \
vpshufd $0x4e, in, out; \
vpsllq $(nrol), in, t0; \
vpsrlq $(64-(nrol)), out, out; \
vpaddd t0, out, out;
#define vec_ror128(in, out, nror, t0) \
vpshufd $0x4e, in, out; \
vpsrlq $(nror), in, t0; \
vpsllq $(64-(nror)), out, out; \
vpaddd t0, out, out;
.align 16
.Linv_shift_row_and_unpcklbw:
.byte 0x00, 0xff, 0x0d, 0xff, 0x0a, 0xff, 0x07, 0xff
.byte 0x04, 0xff, 0x01, 0xff, 0x0e, 0xff, 0x0b, 0xff
.Lsp0044440444044404mask:
.long 0xffff0404, 0x0404ff04;
.long 0x0d0dff0d, 0x0d0dff0d;
.Lsp1110111010011110mask:
.long 0x000000ff, 0x000000ff;
.long 0x0bffff0b, 0x0b0b0bff;
.Lsp0222022222000222mask:
.long 0xff060606, 0xff060606;
.long 0x0c0cffff, 0xff0c0c0c;
.Lsp3033303303303033mask:
.long 0x04ff0404, 0x04ff0404;
.long 0xff0a0aff, 0x0aff0a0a;
.Lsbox4_input_mask:
.byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00;
.Lsigma1:
.long 0x3BCC908B, 0xA09E667F;
.Lsigma2:
.long 0x4CAA73B2, 0xB67AE858;
.Lsigma3:
.long 0xE94F82BE, 0xC6EF372F;
.Lsigma4:
.long 0xF1D36F1C, 0x54FF53A5;
.Lsigma5:
.long 0xDE682D1D, 0x10E527FA;
.Lsigma6:
.long 0xB3E6C1FD, 0xB05688C2;
.align 8
ELF(.type __camellia_avx_setup128,@function;)
__camellia_avx_setup128:
/* input:
* %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 rRIP, KL128, KL128;
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
*/
vpsrldq $8, KL128, %xmm2;
vmovdqa KL128, %xmm3;
vpslldq $8, %xmm3, %xmm3;
vpsrldq $8, %xmm3, %xmm3;
camellia_f(%xmm2, %xmm4, %xmm1,
%xmm5, %xmm6, %xmm7, %xmm8,
%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 rRIP);
camellia_f(%xmm2, %xmm3, %xmm1,
%xmm5, %xmm6, %xmm7, %xmm8,
%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 rRIP);
vpslldq $8, %xmm3, %xmm3;
vpxor %xmm4, %xmm2, %xmm2;
vpsrldq $8, %xmm3, %xmm3;
vpslldq $8, %xmm2, KA128;
vpor %xmm3, KA128, KA128;
/*
* Generate subkeys
*/
vmovdqu KA128, cmll_sub(24, CTX);
vec_rol128(KL128, %xmm3, 15, %xmm15);
vec_rol128(KA128, %xmm4, 15, %xmm15);
vec_rol128(KA128, %xmm5, 30, %xmm15);
vec_rol128(KL128, %xmm6, 45, %xmm15);
vec_rol128(KA128, %xmm7, 45, %xmm15);
vec_rol128(KL128, %xmm8, 60, %xmm15);
vec_rol128(KA128, %xmm9, 60, %xmm15);
vec_ror128(KL128, %xmm10, 128-77, %xmm15);
/* absorb kw2 to other subkeys */
vpslldq $8, KL128, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, KA128, KA128;
vpxor %xmm15, %xmm3, %xmm3;
vpxor %xmm15, %xmm4, %xmm4;
/* subl(1) ^= subr(1) & ~subr(9); */
vpandn %xmm15, %xmm5, %xmm13;
vpslldq $12, %xmm13, %xmm13;
vpsrldq $8, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm5, %xmm14;
vpslld $1, %xmm14, %xmm11;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm11, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm6, %xmm6;
vpxor %xmm15, %xmm8, %xmm8;
vpxor %xmm15, %xmm9, %xmm9;
/* subl(1) ^= subr(1) & ~subr(17); */
vpandn %xmm15, %xmm10, %xmm13;
vpslldq $12, %xmm13, %xmm13;
vpsrldq $8, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm10, %xmm14;
vpslld $1, %xmm14, %xmm11;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm11, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpshufd $0x1b, KL128, KL128;
vpshufd $0x1b, KA128, KA128;
vpshufd $0x1b, %xmm3, %xmm3;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm5, %xmm5;
vpshufd $0x1b, %xmm6, %xmm6;
vpshufd $0x1b, %xmm7, %xmm7;
vpshufd $0x1b, %xmm8, %xmm8;
vpshufd $0x1b, %xmm9, %xmm9;
vpshufd $0x1b, %xmm10, %xmm10;
vmovdqu KL128, cmll_sub(0, CTX);
vpshufd $0x1b, KL128, KL128;
vmovdqu KA128, cmll_sub(2, CTX);
vmovdqu %xmm3, cmll_sub(4, CTX);
vmovdqu %xmm4, cmll_sub(6, CTX);
vmovdqu %xmm5, cmll_sub(8, CTX);
vmovdqu %xmm6, cmll_sub(10, CTX);
vpsrldq $8, %xmm8, %xmm8;
vmovq %xmm7, cmll_sub(12, CTX);
vmovq %xmm8, cmll_sub(13, CTX);
vmovdqu %xmm9, cmll_sub(14, CTX);
vmovdqu %xmm10, cmll_sub(16, CTX);
vmovdqu cmll_sub(24, CTX), KA128;
vec_ror128(KL128, %xmm3, 128 - 94, %xmm7);
vec_ror128(KA128, %xmm4, 128 - 94, %xmm7);
vec_ror128(KL128, %xmm5, 128 - 111, %xmm7);
vec_ror128(KA128, %xmm6, 128 - 111, %xmm7);
vpxor %xmm15, %xmm3, %xmm3;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm5, %xmm5;
vpslldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm6, %xmm6;
/* absorb kw4 to other subkeys */
vpslldq $8, %xmm6, %xmm15;
vpxor %xmm15, %xmm5, %xmm5;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm3, %xmm3;
/* subl(25) ^= subr(25) & ~subr(16); */
vpshufd $0x1b, cmll_sub(16, CTX), %xmm10;
vpandn %xmm15, %xmm10, %xmm13;
vpslldq $4, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(25) & subl(16), subr(25) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm10, %xmm14;
vpslld $1, %xmm14, %xmm11;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm11, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpshufd $0x1b, %xmm3, %xmm3;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm5, %xmm5;
vpshufd $0x1b, %xmm6, %xmm6;
vmovdqu %xmm3, cmll_sub(18, CTX);
vmovdqu %xmm4, cmll_sub(20, CTX);
vmovdqu %xmm5, cmll_sub(22, CTX);
vmovdqu %xmm6, cmll_sub(24, CTX);
vpshufd $0x1b, cmll_sub(14, CTX), %xmm3;
vpshufd $0x1b, cmll_sub(12, CTX), %xmm4;
vpshufd $0x1b, cmll_sub(10, CTX), %xmm5;
vpshufd $0x1b, cmll_sub(8, CTX), %xmm6;
vpxor %xmm15, %xmm3, %xmm3;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm5, %xmm5;
/* subl(25) ^= subr(25) & ~subr(8); */
vpandn %xmm15, %xmm6, %xmm13;
vpslldq $4, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(25) & subl(8), subr(25) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm6, %xmm14;
vpslld $1, %xmm14, %xmm11;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm11, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpshufd $0x1b, %xmm3, %xmm3;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm5, %xmm5;
vmovdqu %xmm3, cmll_sub(14, CTX);
vmovdqu %xmm4, cmll_sub(12, CTX);
vmovdqu %xmm5, cmll_sub(10, CTX);
vpshufd $0x1b, cmll_sub(6, CTX), %xmm6;
vpshufd $0x1b, cmll_sub(4, CTX), %xmm4;
vpshufd $0x1b, cmll_sub(2, CTX), %xmm2;
vpshufd $0x1b, cmll_sub(0, CTX), %xmm0;
vpxor %xmm15, %xmm6, %xmm6;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm2, %xmm2;
vpxor %xmm15, %xmm0, %xmm0;
vpshufd $0x1b, %xmm6, %xmm6;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm2, %xmm2;
vpshufd $0x1b, %xmm0, %xmm0;
vpsrldq $8, %xmm2, %xmm3;
vpsrldq $8, %xmm4, %xmm5;
vpsrldq $8, %xmm6, %xmm7;
/*
* key XOR is end of F-function.
*/
vpxor %xmm2, %xmm0, %xmm0;
vpxor %xmm4, %xmm2, %xmm2;
vmovq %xmm0, cmll_sub(0, CTX);
vmovq %xmm3, cmll_sub(2, CTX);
vpxor %xmm5, %xmm3, %xmm3;
vpxor %xmm6, %xmm4, %xmm4;
vpxor %xmm7, %xmm5, %xmm5;
vmovq %xmm2, cmll_sub(3, CTX);
vmovq %xmm3, cmll_sub(4, CTX);
vmovq %xmm4, cmll_sub(5, CTX);
vmovq %xmm5, cmll_sub(6, CTX);
vmovq cmll_sub(7, CTX), %xmm7;
vmovq cmll_sub(8, CTX), %xmm8;
vmovq cmll_sub(9, CTX), %xmm9;
vmovq cmll_sub(10, CTX), %xmm10;
/* tl = subl(10) ^ (subr(10) & ~subr(8)); */
vpandn %xmm10, %xmm8, %xmm15;
vpsrldq $4, %xmm15, %xmm15;
vpxor %xmm15, %xmm10, %xmm0;
/* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */
vpand %xmm8, %xmm0, %xmm15;
vpslld $1, %xmm15, %xmm14;
vpsrld $31, %xmm15, %xmm15;
vpaddd %xmm14, %xmm15, %xmm15;
vpslldq $12, %xmm15, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm0, %xmm0;
vpxor %xmm0, %xmm6, %xmm6;
vmovq %xmm6, cmll_sub(7, CTX);
vmovq cmll_sub(11, CTX), %xmm11;
vmovq cmll_sub(12, CTX), %xmm12;
vmovq cmll_sub(13, CTX), %xmm13;
vmovq cmll_sub(14, CTX), %xmm14;
vmovq cmll_sub(15, CTX), %xmm15;
/* tl = subl(7) ^ (subr(7) & ~subr(9)); */
vpandn %xmm7, %xmm9, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm7, %xmm0;
/* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */
vpand %xmm9, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vpxor %xmm11, %xmm0, %xmm0;
vpxor %xmm12, %xmm10, %xmm10;
vpxor %xmm13, %xmm11, %xmm11;
vpxor %xmm14, %xmm12, %xmm12;
vpxor %xmm15, %xmm13, %xmm13;
vmovq %xmm0, cmll_sub(10, CTX);
vmovq %xmm10, cmll_sub(11, CTX);
vmovq %xmm11, cmll_sub(12, CTX);
vmovq %xmm12, cmll_sub(13, CTX);
vmovq %xmm13, cmll_sub(14, CTX);
vmovq cmll_sub(16, CTX), %xmm6;
vmovq cmll_sub(17, CTX), %xmm7;
vmovq cmll_sub(18, CTX), %xmm8;
vmovq cmll_sub(19, CTX), %xmm9;
vmovq cmll_sub(20, CTX), %xmm10;
/* tl = subl(18) ^ (subr(18) & ~subr(16)); */
vpandn %xmm8, %xmm6, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm8, %xmm0;
/* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */
vpand %xmm6, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vpxor %xmm14, %xmm0, %xmm0;
vmovq %xmm0, cmll_sub(15, CTX);
/* tl = subl(15) ^ (subr(15) & ~subr(17)); */
vpandn %xmm15, %xmm7, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm15, %xmm0;
/* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */
vpand %xmm7, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vmovq cmll_sub(21, CTX), %xmm1;
vmovq cmll_sub(22, CTX), %xmm2;
vmovq cmll_sub(23, CTX), %xmm3;
vmovq cmll_sub(24, CTX), %xmm4;
vpxor %xmm9, %xmm0, %xmm0;
vpxor %xmm10, %xmm8, %xmm8;
vpxor %xmm1, %xmm9, %xmm9;
vpxor %xmm2, %xmm10, %xmm10;
vpxor %xmm3, %xmm1, %xmm1;
vpxor %xmm4, %xmm3, %xmm3;
vmovq %xmm0, cmll_sub(18, CTX);
vmovq %xmm8, cmll_sub(19, CTX);
vmovq %xmm9, cmll_sub(20, CTX);
vmovq %xmm10, cmll_sub(21, CTX);
vmovq %xmm1, cmll_sub(22, CTX);
vmovq %xmm2, cmll_sub(23, CTX);
vmovq %xmm3, cmll_sub(24, CTX);
/* kw2 and kw4 are unused now. */
movq $0, cmll_sub(1, CTX);
movq $0, cmll_sub(25, CTX);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size __camellia_avx_setup128,.-__camellia_avx_setup128;)
.align 8
ELF(.type __camellia_avx_setup256,@function;)
__camellia_avx_setup256:
/* input:
* %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 rRIP, KL128, KL128;
vpshufb .Lbswap128_mask rRIP, KR128, KR128;
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
*/
vpxor KL128, KR128, %xmm3;
vpsrldq $8, KR128, %xmm6;
vpsrldq $8, %xmm3, %xmm2;
vpslldq $8, %xmm3, %xmm3;
vpsrldq $8, %xmm3, %xmm3;
camellia_f(%xmm2, %xmm4, %xmm5,
%xmm7, %xmm8, %xmm9, %xmm10,
%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 rRIP);
vpxor %xmm6, %xmm2, %xmm2;
camellia_f(%xmm2, %xmm3, %xmm5,
%xmm7, %xmm8, %xmm9, %xmm10,
%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 rRIP);
vpslldq $8, %xmm3, %xmm3;
vpxor %xmm4, %xmm2, %xmm2;
vpsrldq $8, %xmm3, %xmm3;
vpslldq $8, %xmm2, KA128;
vpor %xmm3, KA128, KA128;
/*
* Generate KB
*/
vpxor KA128, KR128, %xmm3;
vpsrldq $8, %xmm3, %xmm4;
vpslldq $8, %xmm3, %xmm3;
vpsrldq $8, %xmm3, %xmm3;
camellia_f(%xmm4, %xmm5, %xmm6,
%xmm7, %xmm8, %xmm9, %xmm10,
%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 rRIP);
vpslldq $8, %xmm3, %xmm3;
vpxor %xmm5, %xmm4, %xmm4;
vpsrldq $8, %xmm3, %xmm3;
vpslldq $8, %xmm4, %xmm4;
vpor %xmm3, %xmm4, KB128;
/*
* Generate subkeys
*/
vmovdqu KB128, cmll_sub(32, CTX);
vec_rol128(KR128, %xmm4, 15, %xmm15);
vec_rol128(KA128, %xmm5, 15, %xmm15);
vec_rol128(KR128, %xmm6, 30, %xmm15);
vec_rol128(KB128, %xmm7, 30, %xmm15);
vec_rol128(KL128, %xmm8, 45, %xmm15);
vec_rol128(KA128, %xmm9, 45, %xmm15);
vec_rol128(KL128, %xmm10, 60, %xmm15);
vec_rol128(KR128, %xmm11, 60, %xmm15);
vec_rol128(KB128, %xmm12, 60, %xmm15);
/* absorb kw2 to other subkeys */
vpslldq $8, KL128, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, KB128, KB128;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm5, %xmm5;
/* subl(1) ^= subr(1) & ~subr(9); */
vpandn %xmm15, %xmm6, %xmm13;
vpslldq $12, %xmm13, %xmm13;
vpsrldq $8, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm6, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm7, %xmm7;
vpxor %xmm15, %xmm8, %xmm8;
vpxor %xmm15, %xmm9, %xmm9;
vpshufd $0x1b, KL128, KL128;
vpshufd $0x1b, KB128, KB128;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm5, %xmm5;
vpshufd $0x1b, %xmm6, %xmm6;
vpshufd $0x1b, %xmm7, %xmm7;
vpshufd $0x1b, %xmm8, %xmm8;
vpshufd $0x1b, %xmm9, %xmm9;
vmovdqu KL128, cmll_sub(0, CTX);
vpshufd $0x1b, KL128, KL128;
vmovdqu KB128, cmll_sub(2, CTX);
vmovdqu %xmm4, cmll_sub(4, CTX);
vmovdqu %xmm5, cmll_sub(6, CTX);
vmovdqu %xmm6, cmll_sub(8, CTX);
vmovdqu %xmm7, cmll_sub(10, CTX);
vmovdqu %xmm8, cmll_sub(12, CTX);
vmovdqu %xmm9, cmll_sub(14, CTX);
vmovdqu cmll_sub(32, CTX), KB128;
/* subl(1) ^= subr(1) & ~subr(17); */
vpandn %xmm15, %xmm10, %xmm13;
vpslldq $12, %xmm13, %xmm13;
vpsrldq $8, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm10, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm11, %xmm11;
vpxor %xmm15, %xmm12, %xmm12;
vec_ror128(KL128, %xmm4, 128-77, %xmm14);
vec_ror128(KA128, %xmm5, 128-77, %xmm14);
vec_ror128(KR128, %xmm6, 128-94, %xmm14);
vec_ror128(KA128, %xmm7, 128-94, %xmm14);
vec_ror128(KL128, %xmm8, 128-111, %xmm14);
vec_ror128(KB128, %xmm9, 128-111, %xmm14);
vpxor %xmm15, %xmm4, %xmm4;
vpshufd $0x1b, %xmm10, %xmm10;
vpshufd $0x1b, %xmm11, %xmm11;
vpshufd $0x1b, %xmm12, %xmm12;
vpshufd $0x1b, %xmm4, %xmm4;
vmovdqu %xmm10, cmll_sub(16, CTX);
vmovdqu %xmm11, cmll_sub(18, CTX);
vmovdqu %xmm12, cmll_sub(20, CTX);
vmovdqu %xmm4, cmll_sub(22, CTX);
/* subl(1) ^= subr(1) & ~subr(25); */
vpandn %xmm15, %xmm5, %xmm13;
vpslldq $12, %xmm13, %xmm13;
vpsrldq $8, %xmm13, %xmm13;
vpxor %xmm13, %xmm15, %xmm15;
/* dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm5, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm6, %xmm6;
vpxor %xmm15, %xmm7, %xmm7;
vpxor %xmm15, %xmm8, %xmm8;
vpslldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm9, %xmm9;
/* absorb kw4 to other subkeys */
vpslldq $8, %xmm9, %xmm15;
vpxor %xmm15, %xmm8, %xmm8;
vpxor %xmm15, %xmm7, %xmm7;
vpxor %xmm15, %xmm6, %xmm6;
/* subl(33) ^= subr(33) & ~subr(24); */
vpandn %xmm15, %xmm5, %xmm14;
vpslldq $4, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
/* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm5, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpshufd $0x1b, %xmm5, %xmm5;
vpshufd $0x1b, %xmm6, %xmm6;
vpshufd $0x1b, %xmm7, %xmm7;
vpshufd $0x1b, %xmm8, %xmm8;
vpshufd $0x1b, %xmm9, %xmm9;
vmovdqu %xmm5, cmll_sub(24, CTX);
vmovdqu %xmm6, cmll_sub(26, CTX);
vmovdqu %xmm7, cmll_sub(28, CTX);
vmovdqu %xmm8, cmll_sub(30, CTX);
vmovdqu %xmm9, cmll_sub(32, CTX);
vpshufd $0x1b, cmll_sub(22, CTX), %xmm0;
vpshufd $0x1b, cmll_sub(20, CTX), %xmm1;
vpshufd $0x1b, cmll_sub(18, CTX), %xmm2;
vpshufd $0x1b, cmll_sub(16, CTX), %xmm3;
vpshufd $0x1b, cmll_sub(14, CTX), %xmm4;
vpshufd $0x1b, cmll_sub(12, CTX), %xmm5;
vpshufd $0x1b, cmll_sub(10, CTX), %xmm6;
vpshufd $0x1b, cmll_sub(8, CTX), %xmm7;
vpxor %xmm15, %xmm0, %xmm0;
vpxor %xmm15, %xmm1, %xmm1;
vpxor %xmm15, %xmm2, %xmm2;
/* subl(33) ^= subr(33) & ~subr(24); */
vpandn %xmm15, %xmm3, %xmm14;
vpslldq $4, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
/* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm3, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm5, %xmm5;
vpxor %xmm15, %xmm6, %xmm6;
vpshufd $0x1b, %xmm0, %xmm0;
vpshufd $0x1b, %xmm1, %xmm1;
vpshufd $0x1b, %xmm2, %xmm2;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm5, %xmm5;
vpshufd $0x1b, %xmm6, %xmm6;
vmovdqu %xmm0, cmll_sub(22, CTX);
vmovdqu %xmm1, cmll_sub(20, CTX);
vmovdqu %xmm2, cmll_sub(18, CTX);
vmovdqu %xmm4, cmll_sub(14, CTX);
vmovdqu %xmm5, cmll_sub(12, CTX);
vmovdqu %xmm6, cmll_sub(10, CTX);
vpshufd $0x1b, cmll_sub(6, CTX), %xmm6;
vpshufd $0x1b, cmll_sub(4, CTX), %xmm4;
vpshufd $0x1b, cmll_sub(2, CTX), %xmm2;
vpshufd $0x1b, cmll_sub(0, CTX), %xmm0;
/* subl(33) ^= subr(33) & ~subr(24); */
vpandn %xmm15, %xmm7, %xmm14;
vpslldq $4, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
/* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */
vpand %xmm15, %xmm7, %xmm14;
vpslld $1, %xmm14, %xmm13;
vpsrld $31, %xmm14, %xmm14;
vpaddd %xmm13, %xmm14, %xmm14;
vpsrldq $12, %xmm14, %xmm14;
vpslldq $8, %xmm14, %xmm14;
vpxor %xmm14, %xmm15, %xmm15;
vpxor %xmm15, %xmm6, %xmm6;
vpxor %xmm15, %xmm4, %xmm4;
vpxor %xmm15, %xmm2, %xmm2;
vpxor %xmm15, %xmm0, %xmm0;
vpshufd $0x1b, %xmm6, %xmm6;
vpshufd $0x1b, %xmm4, %xmm4;
vpshufd $0x1b, %xmm2, %xmm2;
vpshufd $0x1b, %xmm0, %xmm0;
vpsrldq $8, %xmm2, %xmm3;
vpsrldq $8, %xmm4, %xmm5;
vpsrldq $8, %xmm6, %xmm7;
/*
* key XOR is end of F-function.
*/
vpxor %xmm2, %xmm0, %xmm0;
vpxor %xmm4, %xmm2, %xmm2;
vmovq %xmm0, cmll_sub(0, CTX);
vmovq %xmm3, cmll_sub(2, CTX);
vpxor %xmm5, %xmm3, %xmm3;
vpxor %xmm6, %xmm4, %xmm4;
vpxor %xmm7, %xmm5, %xmm5;
vmovq %xmm2, cmll_sub(3, CTX);
vmovq %xmm3, cmll_sub(4, CTX);
vmovq %xmm4, cmll_sub(5, CTX);
vmovq %xmm5, cmll_sub(6, CTX);
vmovq cmll_sub(7, CTX), %xmm7;
vmovq cmll_sub(8, CTX), %xmm8;
vmovq cmll_sub(9, CTX), %xmm9;
vmovq cmll_sub(10, CTX), %xmm10;
/* tl = subl(10) ^ (subr(10) & ~subr(8)); */
vpandn %xmm10, %xmm8, %xmm15;
vpsrldq $4, %xmm15, %xmm15;
vpxor %xmm15, %xmm10, %xmm0;
/* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */
vpand %xmm8, %xmm0, %xmm15;
vpslld $1, %xmm15, %xmm14;
vpsrld $31, %xmm15, %xmm15;
vpaddd %xmm14, %xmm15, %xmm15;
vpslldq $12, %xmm15, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm0, %xmm0;
vpxor %xmm0, %xmm6, %xmm6;
vmovq %xmm6, cmll_sub(7, CTX);
vmovq cmll_sub(11, CTX), %xmm11;
vmovq cmll_sub(12, CTX), %xmm12;
vmovq cmll_sub(13, CTX), %xmm13;
vmovq cmll_sub(14, CTX), %xmm14;
vmovq cmll_sub(15, CTX), %xmm15;
/* tl = subl(7) ^ (subr(7) & ~subr(9)); */
vpandn %xmm7, %xmm9, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm7, %xmm0;
/* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */
vpand %xmm9, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vpxor %xmm11, %xmm0, %xmm0;
vpxor %xmm12, %xmm10, %xmm10;
vpxor %xmm13, %xmm11, %xmm11;
vpxor %xmm14, %xmm12, %xmm12;
vpxor %xmm15, %xmm13, %xmm13;
vmovq %xmm0, cmll_sub(10, CTX);
vmovq %xmm10, cmll_sub(11, CTX);
vmovq %xmm11, cmll_sub(12, CTX);
vmovq %xmm12, cmll_sub(13, CTX);
vmovq %xmm13, cmll_sub(14, CTX);
vmovq cmll_sub(16, CTX), %xmm6;
vmovq cmll_sub(17, CTX), %xmm7;
vmovq cmll_sub(18, CTX), %xmm8;
vmovq cmll_sub(19, CTX), %xmm9;
vmovq cmll_sub(20, CTX), %xmm10;
/* tl = subl(18) ^ (subr(18) & ~subr(16)); */
vpandn %xmm8, %xmm6, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm8, %xmm0;
/* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */
vpand %xmm6, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vpxor %xmm14, %xmm0, %xmm0;
vmovq %xmm0, cmll_sub(15, CTX);
/* tl = subl(15) ^ (subr(15) & ~subr(17)); */
vpandn %xmm15, %xmm7, %xmm1;
vpsrldq $4, %xmm1, %xmm1;
vpxor %xmm1, %xmm15, %xmm0;
/* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */
vpand %xmm7, %xmm0, %xmm1;
vpslld $1, %xmm1, %xmm2;
vpsrld $31, %xmm1, %xmm1;
vpaddd %xmm2, %xmm1, %xmm1;
vpslldq $12, %xmm1, %xmm1;
vpsrldq $8, %xmm1, %xmm1;
vpxor %xmm1, %xmm0, %xmm0;
vmovq cmll_sub(21, CTX), %xmm1;
vmovq cmll_sub(22, CTX), %xmm2;
vmovq cmll_sub(23, CTX), %xmm3;
vmovq cmll_sub(24, CTX), %xmm4;
vpxor %xmm9, %xmm0, %xmm0;
vpxor %xmm10, %xmm8, %xmm8;
vpxor %xmm1, %xmm9, %xmm9;
vpxor %xmm2, %xmm10, %xmm10;
vpxor %xmm3, %xmm1, %xmm1;
vmovq %xmm0, cmll_sub(18, CTX);
vmovq %xmm8, cmll_sub(19, CTX);
vmovq %xmm9, cmll_sub(20, CTX);
vmovq %xmm10, cmll_sub(21, CTX);
vmovq %xmm1, cmll_sub(22, CTX);
vmovq cmll_sub(25, CTX), %xmm5;
vmovq cmll_sub(26, CTX), %xmm6;
vmovq cmll_sub(27, CTX), %xmm7;
vmovq cmll_sub(28, CTX), %xmm8;
vmovq cmll_sub(29, CTX), %xmm9;
vmovq cmll_sub(30, CTX), %xmm10;
vmovq cmll_sub(31, CTX), %xmm11;
vmovq cmll_sub(32, CTX), %xmm12;
/* tl = subl(26) ^ (subr(26) & ~subr(24)); */
vpandn %xmm6, %xmm4, %xmm15;
vpsrldq $4, %xmm15, %xmm15;
vpxor %xmm15, %xmm6, %xmm0;
/* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */
vpand %xmm4, %xmm0, %xmm15;
vpslld $1, %xmm15, %xmm14;
vpsrld $31, %xmm15, %xmm15;
vpaddd %xmm14, %xmm15, %xmm15;
vpslldq $12, %xmm15, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm0, %xmm0;
vpxor %xmm0, %xmm2, %xmm2;
vmovq %xmm2, cmll_sub(23, CTX);
/* tl = subl(23) ^ (subr(23) & ~subr(25)); */
vpandn %xmm3, %xmm5, %xmm15;
vpsrldq $4, %xmm15, %xmm15;
vpxor %xmm15, %xmm3, %xmm0;
/* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */
vpand %xmm5, %xmm0, %xmm15;
vpslld $1, %xmm15, %xmm14;
vpsrld $31, %xmm15, %xmm15;
vpaddd %xmm14, %xmm15, %xmm15;
vpslldq $12, %xmm15, %xmm15;
vpsrldq $8, %xmm15, %xmm15;
vpxor %xmm15, %xmm0, %xmm0;
vpxor %xmm7, %xmm0, %xmm0;
vpxor %xmm8, %xmm6, %xmm6;
vpxor %xmm9, %xmm7, %xmm7;
vpxor %xmm10, %xmm8, %xmm8;
vpxor %xmm11, %xmm9, %xmm9;
vpxor %xmm12, %xmm11, %xmm11;
vmovq %xmm0, cmll_sub(26, CTX);
vmovq %xmm6, cmll_sub(27, CTX);
vmovq %xmm7, cmll_sub(28, CTX);
vmovq %xmm8, cmll_sub(29, CTX);
vmovq %xmm9, cmll_sub(30, CTX);
vmovq %xmm10, cmll_sub(31, CTX);
vmovq %xmm11, cmll_sub(32, CTX);
/* kw2 and kw4 are unused now. */
movq $0, cmll_sub(1, CTX);
movq $0, cmll_sub(33, CTX);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size __camellia_avx_setup256,.-__camellia_avx_setup256;)
.align 8
.globl _gcry_camellia_aesni_avx_keygen
ELF(.type _gcry_camellia_aesni_avx_keygen,@function;)
_gcry_camellia_aesni_avx_keygen:
/* input:
* %rdi: ctx, CTX
* %rsi: key
* %rdx: keylen
*/
CFI_STARTPROC();
vzeroupper;
vmovdqu (%rsi), %xmm0;
cmpl $24, %edx;
jb __camellia_avx_setup128;
je .Lprepare_key192;
vmovdqu 16(%rsi), %xmm1;
jmp __camellia_avx_setup256;
.Lprepare_key192:
vpcmpeqd %xmm2, %xmm2, %xmm2;
vmovq 16(%rsi), %xmm1;
vpxor %xmm1, %xmm2, %xmm2;
vpslldq $8, %xmm2, %xmm2;
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)*/
#endif /*__x86_64*/
diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S
index cc01c774..9bcc2a12 100644
--- a/cipher/camellia-aesni-avx2-amd64.S
+++ b/cipher/camellia-aesni-avx2-amd64.S
@@ -1,1810 +1,1810 @@
/* camellia-avx2-aesni-amd64.S - AES-NI/AVX2 implementation of Camellia cipher
*
* Copyright (C) 2013-2015 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/>.
+ * License along with this program; if not, see <https://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(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)
#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
/**********************************************************************
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); \
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 rRIP, t0; \
vbroadcasti128 .Lpost_tf_hi_s1 rRIP, 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 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
* %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;
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;
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();
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;
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 _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)
*/
CFI_STARTPROC();
pushq %rbp;
CFI_PUSH(%rbp);
movq %rsp, %rbp;
CFI_DEF_CFA_REGISTER(%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 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;
CFI_ENDPROC();
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
*/
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;
CFI_ENDPROC();
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
*/
CFI_STARTPROC();
pushq %rbp;
CFI_PUSH(%rbp);
movq %rsp, %rbp;
CFI_DEF_CFA_REGISTER(%rbp);
vzeroupper;
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;
CFI_ENDPROC();
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])
*/
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);
/* 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;
CFI_ENDPROC();
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])
*/
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;
CFI_ENDPROC();
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])
*/
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);
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;
CFI_ENDPROC();
ELF(.size _gcry_camellia_aesni_avx2_ocb_auth,.-_gcry_camellia_aesni_avx2_ocb_auth;)
#endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)*/
#endif /*__x86_64*/
diff --git a/cipher/camellia-arm.S b/cipher/camellia-arm.S
index a3d87d11..70c3dbb6 100644
--- a/cipher/camellia-arm.S
+++ b/cipher/camellia-arm.S
@@ -1,626 +1,626 @@
/* camellia-arm.S - ARM assembly implementation of Camellia cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.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
/* struct camellia_ctx: */
#define key_table 0
/* register macros */
#define CTX %r0
#define RTAB1 %ip
#define RTAB3 %r1
#define RMASK %lr
#define IL %r2
#define IR %r3
#define XL %r4
#define XR %r5
#define YL %r6
#define YR %r7
#define RT0 %r8
#define RT1 %r9
#define RT2 %r10
#define RT3 %r11
/* helper macros */
#define ldr_unaligned_be(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 3)]; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 0)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_be(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 3)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 2)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 1)]; \
strb rtmp0, [rdst, #((offs) + 0)];
#ifdef __ARMEL__
#ifdef HAVE_ARM_ARCH_V6
#define host_to_be(reg, rtmp) \
rev reg, reg;
#define be_to_host(reg, rtmp) \
rev reg, reg;
#else
#define host_to_be(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#define be_to_host(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#endif
#else
/* nop on big-endian */
#define host_to_be(reg, rtmp) /*_*/
#define be_to_host(reg, rtmp) /*_*/
#endif
#define ldr_input_aligned_be(rin, a, b, c, d, rtmp) \
ldr a, [rin, #0]; \
ldr b, [rin, #4]; \
be_to_host(a, rtmp); \
ldr c, [rin, #8]; \
be_to_host(b, rtmp); \
ldr d, [rin, #12]; \
be_to_host(c, rtmp); \
be_to_host(d, rtmp);
#define str_output_aligned_be(rout, a, b, c, d, rtmp) \
be_to_host(a, rtmp); \
be_to_host(b, rtmp); \
str a, [rout, #0]; \
be_to_host(c, rtmp); \
str b, [rout, #4]; \
be_to_host(d, rtmp); \
str c, [rout, #8]; \
str d, [rout, #12];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads/writes allowed */
#define ldr_input_be(rin, ra, rb, rc, rd, rtmp) \
ldr_input_aligned_be(rin, ra, rb, rc, rd, rtmp)
#define str_output_be(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
str_output_aligned_be(rout, ra, rb, rc, rd, rtmp0)
#else
/* need to handle unaligned reads/writes by byte reads */
#define ldr_input_be(rin, ra, rb, rc, rd, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_be(ra, rin, 0, rtmp0); \
ldr_unaligned_be(rb, rin, 4, rtmp0); \
ldr_unaligned_be(rc, rin, 8, rtmp0); \
ldr_unaligned_be(rd, rin, 12, rtmp0); \
b 2f; \
1:;\
ldr_input_aligned_be(rin, ra, rb, rc, rd, rtmp0); \
2:;
#define str_output_be(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_be(ra, rout, 0, rtmp0, rtmp1); \
str_unaligned_be(rb, rout, 4, rtmp0, rtmp1); \
str_unaligned_be(rc, rout, 8, rtmp0, rtmp1); \
str_unaligned_be(rd, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
str_output_aligned_be(rout, ra, rb, rc, rd, rtmp0); \
2:;
#endif
/**********************************************************************
1-way camellia
**********************************************************************/
#define roundsm(xl, xr, kl, kr, yl, yr) \
ldr RT2, [CTX, #(key_table + ((kl) * 4))]; \
and IR, RMASK, xr, lsl#(4); /*sp1110*/ \
ldr RT3, [CTX, #(key_table + ((kr) * 4))]; \
and IL, RMASK, xl, lsr#(24 - 4); /*sp1110*/ \
and RT0, RMASK, xr, lsr#(16 - 4); /*sp3033*/ \
ldr IR, [RTAB1, IR]; \
and RT1, RMASK, xl, lsr#(8 - 4); /*sp3033*/ \
eor yl, RT2; \
ldr IL, [RTAB1, IL]; \
eor yr, RT3; \
\
ldr RT0, [RTAB3, RT0]; \
add RTAB1, #4; \
ldr RT1, [RTAB3, RT1]; \
add RTAB3, #4; \
\
and RT2, RMASK, xr, lsr#(24 - 4); /*sp0222*/ \
and RT3, RMASK, xl, lsr#(16 - 4); /*sp0222*/ \
\
eor IR, RT0; \
eor IL, RT1; \
\
ldr RT2, [RTAB1, RT2]; \
and RT0, RMASK, xr, lsr#(8 - 4); /*sp4404*/ \
ldr RT3, [RTAB1, RT3]; \
and RT1, RMASK, xl, lsl#(4); /*sp4404*/ \
\
ldr RT0, [RTAB3, RT0]; \
sub RTAB1, #4; \
ldr RT1, [RTAB3, RT1]; \
sub RTAB3, #4; \
\
eor IR, RT2; \
eor IL, RT3; \
eor IR, RT0; \
eor IL, RT1; \
\
eor IR, IL; \
eor yr, yr, IL, ror#8; \
eor yl, IR; \
eor yr, IR;
#define enc_rounds(n) \
roundsm(XL, XR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, XL, XR);
#define dec_rounds(n) \
roundsm(XL, XR, ((n) + 7) * 2 + 0, ((n) + 7) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 6) * 2 + 0, ((n) + 6) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 5) * 2 + 0, ((n) + 5) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 4) * 2 + 0, ((n) + 4) * 2 + 1, XL, XR); \
roundsm(XL, XR, ((n) + 3) * 2 + 0, ((n) + 3) * 2 + 1, YL, YR); \
roundsm(YL, YR, ((n) + 2) * 2 + 0, ((n) + 2) * 2 + 1, XL, XR);
/* perform FL and FL⁻¹ */
#define fls(ll, lr, rl, rr, kll, klr, krl, krr) \
ldr RT0, [CTX, #(key_table + ((kll) * 4))]; \
ldr RT2, [CTX, #(key_table + ((krr) * 4))]; \
and RT0, ll; \
ldr RT3, [CTX, #(key_table + ((krl) * 4))]; \
orr RT2, rr; \
ldr RT1, [CTX, #(key_table + ((klr) * 4))]; \
eor rl, RT2; \
eor lr, lr, RT0, ror#31; \
and RT3, rl; \
orr RT1, lr; \
eor ll, RT1; \
eor rr, rr, RT3, ror#31;
#define enc_fls(n) \
fls(XL, XR, YL, YR, \
(n) * 2 + 0, (n) * 2 + 1, \
(n) * 2 + 2, (n) * 2 + 3);
#define dec_fls(n) \
fls(XL, XR, YL, YR, \
(n) * 2 + 2, (n) * 2 + 3, \
(n) * 2 + 0, (n) * 2 + 1);
#define inpack(n) \
ldr_input_be(%r2, XL, XR, YL, YR, RT0); \
ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \
ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \
eor XL, RT0; \
eor XR, RT1;
#define outunpack(n) \
ldr RT0, [CTX, #(key_table + ((n) * 8) + 0)]; \
ldr RT1, [CTX, #(key_table + ((n) * 8) + 4)]; \
eor YL, RT0; \
eor YR, RT1; \
str_output_be(%r1, YL, YR, XL, XR, RT0, RT1);
.align 3
.globl _gcry_camellia_arm_encrypt_block
.type _gcry_camellia_arm_encrypt_block,%function;
_gcry_camellia_arm_encrypt_block:
/* input:
* %r0: keytable
* %r1: dst
* %r2: src
* %r3: keybitlen
*/
push {%r1, %r4-%r11, %ip, %lr};
GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3);
mov RMASK, #0xff;
add RTAB3, RTAB1, #(2 * 4);
push {%r3};
mov RMASK, RMASK, lsl#4 /* byte mask */
inpack(0);
enc_rounds(0);
enc_fls(8);
enc_rounds(8);
enc_fls(16);
enc_rounds(16);
pop {RT0};
cmp RT0, #(16 * 8);
bne .Lenc_256;
pop {%r1};
outunpack(24);
pop {%r4-%r11, %ip, %pc};
.ltorg
.Lenc_256:
enc_fls(24);
enc_rounds(24);
pop {%r1};
outunpack(32);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_camellia_arm_encrypt_block,.-_gcry_camellia_arm_encrypt_block;
.align 3
.globl _gcry_camellia_arm_decrypt_block
.type _gcry_camellia_arm_decrypt_block,%function;
_gcry_camellia_arm_decrypt_block:
/* input:
* %r0: keytable
* %r1: dst
* %r2: src
* %r3: keybitlen
*/
push {%r1, %r4-%r11, %ip, %lr};
GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3);
mov RMASK, #0xff;
add RTAB3, RTAB1, #(2 * 4);
mov RMASK, RMASK, lsl#4 /* byte mask */
cmp %r3, #(16 * 8);
bne .Ldec_256;
inpack(24);
.Ldec_128:
dec_rounds(16);
dec_fls(16);
dec_rounds(8);
dec_fls(8);
dec_rounds(0);
pop {%r1};
outunpack(0);
pop {%r4-%r11, %ip, %pc};
.ltorg
.Ldec_256:
inpack(32);
dec_rounds(24);
dec_fls(24);
b .Ldec_128;
.ltorg
.size _gcry_camellia_arm_decrypt_block,.-_gcry_camellia_arm_decrypt_block;
.data
/* Encryption/Decryption tables */
.align 5
.Lcamellia_sp1110:
.long 0x70707000
.Lcamellia_sp0222:
.long 0x00e0e0e0
.Lcamellia_sp3033:
.long 0x38003838
.Lcamellia_sp4404:
.long 0x70700070
.long 0x82828200, 0x00050505, 0x41004141, 0x2c2c002c
.long 0x2c2c2c00, 0x00585858, 0x16001616, 0xb3b300b3
.long 0xececec00, 0x00d9d9d9, 0x76007676, 0xc0c000c0
.long 0xb3b3b300, 0x00676767, 0xd900d9d9, 0xe4e400e4
.long 0x27272700, 0x004e4e4e, 0x93009393, 0x57570057
.long 0xc0c0c000, 0x00818181, 0x60006060, 0xeaea00ea
.long 0xe5e5e500, 0x00cbcbcb, 0xf200f2f2, 0xaeae00ae
.long 0xe4e4e400, 0x00c9c9c9, 0x72007272, 0x23230023
.long 0x85858500, 0x000b0b0b, 0xc200c2c2, 0x6b6b006b
.long 0x57575700, 0x00aeaeae, 0xab00abab, 0x45450045
.long 0x35353500, 0x006a6a6a, 0x9a009a9a, 0xa5a500a5
.long 0xeaeaea00, 0x00d5d5d5, 0x75007575, 0xeded00ed
.long 0x0c0c0c00, 0x00181818, 0x06000606, 0x4f4f004f
.long 0xaeaeae00, 0x005d5d5d, 0x57005757, 0x1d1d001d
.long 0x41414100, 0x00828282, 0xa000a0a0, 0x92920092
.long 0x23232300, 0x00464646, 0x91009191, 0x86860086
.long 0xefefef00, 0x00dfdfdf, 0xf700f7f7, 0xafaf00af
.long 0x6b6b6b00, 0x00d6d6d6, 0xb500b5b5, 0x7c7c007c
.long 0x93939300, 0x00272727, 0xc900c9c9, 0x1f1f001f
.long 0x45454500, 0x008a8a8a, 0xa200a2a2, 0x3e3e003e
.long 0x19191900, 0x00323232, 0x8c008c8c, 0xdcdc00dc
.long 0xa5a5a500, 0x004b4b4b, 0xd200d2d2, 0x5e5e005e
.long 0x21212100, 0x00424242, 0x90009090, 0x0b0b000b
.long 0xededed00, 0x00dbdbdb, 0xf600f6f6, 0xa6a600a6
.long 0x0e0e0e00, 0x001c1c1c, 0x07000707, 0x39390039
.long 0x4f4f4f00, 0x009e9e9e, 0xa700a7a7, 0xd5d500d5
.long 0x4e4e4e00, 0x009c9c9c, 0x27002727, 0x5d5d005d
.long 0x1d1d1d00, 0x003a3a3a, 0x8e008e8e, 0xd9d900d9
.long 0x65656500, 0x00cacaca, 0xb200b2b2, 0x5a5a005a
.long 0x92929200, 0x00252525, 0x49004949, 0x51510051
.long 0xbdbdbd00, 0x007b7b7b, 0xde00dede, 0x6c6c006c
.long 0x86868600, 0x000d0d0d, 0x43004343, 0x8b8b008b
.long 0xb8b8b800, 0x00717171, 0x5c005c5c, 0x9a9a009a
.long 0xafafaf00, 0x005f5f5f, 0xd700d7d7, 0xfbfb00fb
.long 0x8f8f8f00, 0x001f1f1f, 0xc700c7c7, 0xb0b000b0
.long 0x7c7c7c00, 0x00f8f8f8, 0x3e003e3e, 0x74740074
.long 0xebebeb00, 0x00d7d7d7, 0xf500f5f5, 0x2b2b002b
.long 0x1f1f1f00, 0x003e3e3e, 0x8f008f8f, 0xf0f000f0
.long 0xcecece00, 0x009d9d9d, 0x67006767, 0x84840084
.long 0x3e3e3e00, 0x007c7c7c, 0x1f001f1f, 0xdfdf00df
.long 0x30303000, 0x00606060, 0x18001818, 0xcbcb00cb
.long 0xdcdcdc00, 0x00b9b9b9, 0x6e006e6e, 0x34340034
.long 0x5f5f5f00, 0x00bebebe, 0xaf00afaf, 0x76760076
.long 0x5e5e5e00, 0x00bcbcbc, 0x2f002f2f, 0x6d6d006d
.long 0xc5c5c500, 0x008b8b8b, 0xe200e2e2, 0xa9a900a9
.long 0x0b0b0b00, 0x00161616, 0x85008585, 0xd1d100d1
.long 0x1a1a1a00, 0x00343434, 0x0d000d0d, 0x04040004
.long 0xa6a6a600, 0x004d4d4d, 0x53005353, 0x14140014
.long 0xe1e1e100, 0x00c3c3c3, 0xf000f0f0, 0x3a3a003a
.long 0x39393900, 0x00727272, 0x9c009c9c, 0xdede00de
.long 0xcacaca00, 0x00959595, 0x65006565, 0x11110011
.long 0xd5d5d500, 0x00ababab, 0xea00eaea, 0x32320032
.long 0x47474700, 0x008e8e8e, 0xa300a3a3, 0x9c9c009c
.long 0x5d5d5d00, 0x00bababa, 0xae00aeae, 0x53530053
.long 0x3d3d3d00, 0x007a7a7a, 0x9e009e9e, 0xf2f200f2
.long 0xd9d9d900, 0x00b3b3b3, 0xec00ecec, 0xfefe00fe
.long 0x01010100, 0x00020202, 0x80008080, 0xcfcf00cf
.long 0x5a5a5a00, 0x00b4b4b4, 0x2d002d2d, 0xc3c300c3
.long 0xd6d6d600, 0x00adadad, 0x6b006b6b, 0x7a7a007a
.long 0x51515100, 0x00a2a2a2, 0xa800a8a8, 0x24240024
.long 0x56565600, 0x00acacac, 0x2b002b2b, 0xe8e800e8
.long 0x6c6c6c00, 0x00d8d8d8, 0x36003636, 0x60600060
.long 0x4d4d4d00, 0x009a9a9a, 0xa600a6a6, 0x69690069
.long 0x8b8b8b00, 0x00171717, 0xc500c5c5, 0xaaaa00aa
.long 0x0d0d0d00, 0x001a1a1a, 0x86008686, 0xa0a000a0
.long 0x9a9a9a00, 0x00353535, 0x4d004d4d, 0xa1a100a1
.long 0x66666600, 0x00cccccc, 0x33003333, 0x62620062
.long 0xfbfbfb00, 0x00f7f7f7, 0xfd00fdfd, 0x54540054
.long 0xcccccc00, 0x00999999, 0x66006666, 0x1e1e001e
.long 0xb0b0b000, 0x00616161, 0x58005858, 0xe0e000e0
.long 0x2d2d2d00, 0x005a5a5a, 0x96009696, 0x64640064
.long 0x74747400, 0x00e8e8e8, 0x3a003a3a, 0x10100010
.long 0x12121200, 0x00242424, 0x09000909, 0x00000000
.long 0x2b2b2b00, 0x00565656, 0x95009595, 0xa3a300a3
.long 0x20202000, 0x00404040, 0x10001010, 0x75750075
.long 0xf0f0f000, 0x00e1e1e1, 0x78007878, 0x8a8a008a
.long 0xb1b1b100, 0x00636363, 0xd800d8d8, 0xe6e600e6
.long 0x84848400, 0x00090909, 0x42004242, 0x09090009
.long 0x99999900, 0x00333333, 0xcc00cccc, 0xdddd00dd
.long 0xdfdfdf00, 0x00bfbfbf, 0xef00efef, 0x87870087
.long 0x4c4c4c00, 0x00989898, 0x26002626, 0x83830083
.long 0xcbcbcb00, 0x00979797, 0xe500e5e5, 0xcdcd00cd
.long 0xc2c2c200, 0x00858585, 0x61006161, 0x90900090
.long 0x34343400, 0x00686868, 0x1a001a1a, 0x73730073
.long 0x7e7e7e00, 0x00fcfcfc, 0x3f003f3f, 0xf6f600f6
.long 0x76767600, 0x00ececec, 0x3b003b3b, 0x9d9d009d
.long 0x05050500, 0x000a0a0a, 0x82008282, 0xbfbf00bf
.long 0x6d6d6d00, 0x00dadada, 0xb600b6b6, 0x52520052
.long 0xb7b7b700, 0x006f6f6f, 0xdb00dbdb, 0xd8d800d8
.long 0xa9a9a900, 0x00535353, 0xd400d4d4, 0xc8c800c8
.long 0x31313100, 0x00626262, 0x98009898, 0xc6c600c6
.long 0xd1d1d100, 0x00a3a3a3, 0xe800e8e8, 0x81810081
.long 0x17171700, 0x002e2e2e, 0x8b008b8b, 0x6f6f006f
.long 0x04040400, 0x00080808, 0x02000202, 0x13130013
.long 0xd7d7d700, 0x00afafaf, 0xeb00ebeb, 0x63630063
.long 0x14141400, 0x00282828, 0x0a000a0a, 0xe9e900e9
.long 0x58585800, 0x00b0b0b0, 0x2c002c2c, 0xa7a700a7
.long 0x3a3a3a00, 0x00747474, 0x1d001d1d, 0x9f9f009f
.long 0x61616100, 0x00c2c2c2, 0xb000b0b0, 0xbcbc00bc
.long 0xdedede00, 0x00bdbdbd, 0x6f006f6f, 0x29290029
.long 0x1b1b1b00, 0x00363636, 0x8d008d8d, 0xf9f900f9
.long 0x11111100, 0x00222222, 0x88008888, 0x2f2f002f
.long 0x1c1c1c00, 0x00383838, 0x0e000e0e, 0xb4b400b4
.long 0x32323200, 0x00646464, 0x19001919, 0x78780078
.long 0x0f0f0f00, 0x001e1e1e, 0x87008787, 0x06060006
.long 0x9c9c9c00, 0x00393939, 0x4e004e4e, 0xe7e700e7
.long 0x16161600, 0x002c2c2c, 0x0b000b0b, 0x71710071
.long 0x53535300, 0x00a6a6a6, 0xa900a9a9, 0xd4d400d4
.long 0x18181800, 0x00303030, 0x0c000c0c, 0xabab00ab
.long 0xf2f2f200, 0x00e5e5e5, 0x79007979, 0x88880088
.long 0x22222200, 0x00444444, 0x11001111, 0x8d8d008d
.long 0xfefefe00, 0x00fdfdfd, 0x7f007f7f, 0x72720072
.long 0x44444400, 0x00888888, 0x22002222, 0xb9b900b9
.long 0xcfcfcf00, 0x009f9f9f, 0xe700e7e7, 0xf8f800f8
.long 0xb2b2b200, 0x00656565, 0x59005959, 0xacac00ac
.long 0xc3c3c300, 0x00878787, 0xe100e1e1, 0x36360036
.long 0xb5b5b500, 0x006b6b6b, 0xda00dada, 0x2a2a002a
.long 0x7a7a7a00, 0x00f4f4f4, 0x3d003d3d, 0x3c3c003c
.long 0x91919100, 0x00232323, 0xc800c8c8, 0xf1f100f1
.long 0x24242400, 0x00484848, 0x12001212, 0x40400040
.long 0x08080800, 0x00101010, 0x04000404, 0xd3d300d3
.long 0xe8e8e800, 0x00d1d1d1, 0x74007474, 0xbbbb00bb
.long 0xa8a8a800, 0x00515151, 0x54005454, 0x43430043
.long 0x60606000, 0x00c0c0c0, 0x30003030, 0x15150015
.long 0xfcfcfc00, 0x00f9f9f9, 0x7e007e7e, 0xadad00ad
.long 0x69696900, 0x00d2d2d2, 0xb400b4b4, 0x77770077
.long 0x50505000, 0x00a0a0a0, 0x28002828, 0x80800080
.long 0xaaaaaa00, 0x00555555, 0x55005555, 0x82820082
.long 0xd0d0d000, 0x00a1a1a1, 0x68006868, 0xecec00ec
.long 0xa0a0a000, 0x00414141, 0x50005050, 0x27270027
.long 0x7d7d7d00, 0x00fafafa, 0xbe00bebe, 0xe5e500e5
.long 0xa1a1a100, 0x00434343, 0xd000d0d0, 0x85850085
.long 0x89898900, 0x00131313, 0xc400c4c4, 0x35350035
.long 0x62626200, 0x00c4c4c4, 0x31003131, 0x0c0c000c
.long 0x97979700, 0x002f2f2f, 0xcb00cbcb, 0x41410041
.long 0x54545400, 0x00a8a8a8, 0x2a002a2a, 0xefef00ef
.long 0x5b5b5b00, 0x00b6b6b6, 0xad00adad, 0x93930093
.long 0x1e1e1e00, 0x003c3c3c, 0x0f000f0f, 0x19190019
.long 0x95959500, 0x002b2b2b, 0xca00caca, 0x21210021
.long 0xe0e0e000, 0x00c1c1c1, 0x70007070, 0x0e0e000e
.long 0xffffff00, 0x00ffffff, 0xff00ffff, 0x4e4e004e
.long 0x64646400, 0x00c8c8c8, 0x32003232, 0x65650065
.long 0xd2d2d200, 0x00a5a5a5, 0x69006969, 0xbdbd00bd
.long 0x10101000, 0x00202020, 0x08000808, 0xb8b800b8
.long 0xc4c4c400, 0x00898989, 0x62006262, 0x8f8f008f
.long 0x00000000, 0x00000000, 0x00000000, 0xebeb00eb
.long 0x48484800, 0x00909090, 0x24002424, 0xcece00ce
.long 0xa3a3a300, 0x00474747, 0xd100d1d1, 0x30300030
.long 0xf7f7f700, 0x00efefef, 0xfb00fbfb, 0x5f5f005f
.long 0x75757500, 0x00eaeaea, 0xba00baba, 0xc5c500c5
.long 0xdbdbdb00, 0x00b7b7b7, 0xed00eded, 0x1a1a001a
.long 0x8a8a8a00, 0x00151515, 0x45004545, 0xe1e100e1
.long 0x03030300, 0x00060606, 0x81008181, 0xcaca00ca
.long 0xe6e6e600, 0x00cdcdcd, 0x73007373, 0x47470047
.long 0xdadada00, 0x00b5b5b5, 0x6d006d6d, 0x3d3d003d
.long 0x09090900, 0x00121212, 0x84008484, 0x01010001
.long 0x3f3f3f00, 0x007e7e7e, 0x9f009f9f, 0xd6d600d6
.long 0xdddddd00, 0x00bbbbbb, 0xee00eeee, 0x56560056
.long 0x94949400, 0x00292929, 0x4a004a4a, 0x4d4d004d
.long 0x87878700, 0x000f0f0f, 0xc300c3c3, 0x0d0d000d
.long 0x5c5c5c00, 0x00b8b8b8, 0x2e002e2e, 0x66660066
.long 0x83838300, 0x00070707, 0xc100c1c1, 0xcccc00cc
.long 0x02020200, 0x00040404, 0x01000101, 0x2d2d002d
.long 0xcdcdcd00, 0x009b9b9b, 0xe600e6e6, 0x12120012
.long 0x4a4a4a00, 0x00949494, 0x25002525, 0x20200020
.long 0x90909000, 0x00212121, 0x48004848, 0xb1b100b1
.long 0x33333300, 0x00666666, 0x99009999, 0x99990099
.long 0x73737300, 0x00e6e6e6, 0xb900b9b9, 0x4c4c004c
.long 0x67676700, 0x00cecece, 0xb300b3b3, 0xc2c200c2
.long 0xf6f6f600, 0x00ededed, 0x7b007b7b, 0x7e7e007e
.long 0xf3f3f300, 0x00e7e7e7, 0xf900f9f9, 0x05050005
.long 0x9d9d9d00, 0x003b3b3b, 0xce00cece, 0xb7b700b7
.long 0x7f7f7f00, 0x00fefefe, 0xbf00bfbf, 0x31310031
.long 0xbfbfbf00, 0x007f7f7f, 0xdf00dfdf, 0x17170017
.long 0xe2e2e200, 0x00c5c5c5, 0x71007171, 0xd7d700d7
.long 0x52525200, 0x00a4a4a4, 0x29002929, 0x58580058
.long 0x9b9b9b00, 0x00373737, 0xcd00cdcd, 0x61610061
.long 0xd8d8d800, 0x00b1b1b1, 0x6c006c6c, 0x1b1b001b
.long 0x26262600, 0x004c4c4c, 0x13001313, 0x1c1c001c
.long 0xc8c8c800, 0x00919191, 0x64006464, 0x0f0f000f
.long 0x37373700, 0x006e6e6e, 0x9b009b9b, 0x16160016
.long 0xc6c6c600, 0x008d8d8d, 0x63006363, 0x18180018
.long 0x3b3b3b00, 0x00767676, 0x9d009d9d, 0x22220022
.long 0x81818100, 0x00030303, 0xc000c0c0, 0x44440044
.long 0x96969600, 0x002d2d2d, 0x4b004b4b, 0xb2b200b2
.long 0x6f6f6f00, 0x00dedede, 0xb700b7b7, 0xb5b500b5
.long 0x4b4b4b00, 0x00969696, 0xa500a5a5, 0x91910091
.long 0x13131300, 0x00262626, 0x89008989, 0x08080008
.long 0xbebebe00, 0x007d7d7d, 0x5f005f5f, 0xa8a800a8
.long 0x63636300, 0x00c6c6c6, 0xb100b1b1, 0xfcfc00fc
.long 0x2e2e2e00, 0x005c5c5c, 0x17001717, 0x50500050
.long 0xe9e9e900, 0x00d3d3d3, 0xf400f4f4, 0xd0d000d0
.long 0x79797900, 0x00f2f2f2, 0xbc00bcbc, 0x7d7d007d
.long 0xa7a7a700, 0x004f4f4f, 0xd300d3d3, 0x89890089
.long 0x8c8c8c00, 0x00191919, 0x46004646, 0x97970097
.long 0x9f9f9f00, 0x003f3f3f, 0xcf00cfcf, 0x5b5b005b
.long 0x6e6e6e00, 0x00dcdcdc, 0x37003737, 0x95950095
.long 0xbcbcbc00, 0x00797979, 0x5e005e5e, 0xffff00ff
.long 0x8e8e8e00, 0x001d1d1d, 0x47004747, 0xd2d200d2
.long 0x29292900, 0x00525252, 0x94009494, 0xc4c400c4
.long 0xf5f5f500, 0x00ebebeb, 0xfa00fafa, 0x48480048
.long 0xf9f9f900, 0x00f3f3f3, 0xfc00fcfc, 0xf7f700f7
.long 0xb6b6b600, 0x006d6d6d, 0x5b005b5b, 0xdbdb00db
.long 0x2f2f2f00, 0x005e5e5e, 0x97009797, 0x03030003
.long 0xfdfdfd00, 0x00fbfbfb, 0xfe00fefe, 0xdada00da
.long 0xb4b4b400, 0x00696969, 0x5a005a5a, 0x3f3f003f
.long 0x59595900, 0x00b2b2b2, 0xac00acac, 0x94940094
.long 0x78787800, 0x00f0f0f0, 0x3c003c3c, 0x5c5c005c
.long 0x98989800, 0x00313131, 0x4c004c4c, 0x02020002
.long 0x06060600, 0x000c0c0c, 0x03000303, 0x4a4a004a
.long 0x6a6a6a00, 0x00d4d4d4, 0x35003535, 0x33330033
.long 0xe7e7e700, 0x00cfcfcf, 0xf300f3f3, 0x67670067
.long 0x46464600, 0x008c8c8c, 0x23002323, 0xf3f300f3
.long 0x71717100, 0x00e2e2e2, 0xb800b8b8, 0x7f7f007f
.long 0xbababa00, 0x00757575, 0x5d005d5d, 0xe2e200e2
.long 0xd4d4d400, 0x00a9a9a9, 0x6a006a6a, 0x9b9b009b
.long 0x25252500, 0x004a4a4a, 0x92009292, 0x26260026
.long 0xababab00, 0x00575757, 0xd500d5d5, 0x37370037
.long 0x42424200, 0x00848484, 0x21002121, 0x3b3b003b
.long 0x88888800, 0x00111111, 0x44004444, 0x96960096
.long 0xa2a2a200, 0x00454545, 0x51005151, 0x4b4b004b
.long 0x8d8d8d00, 0x001b1b1b, 0xc600c6c6, 0xbebe00be
.long 0xfafafa00, 0x00f5f5f5, 0x7d007d7d, 0x2e2e002e
.long 0x72727200, 0x00e4e4e4, 0x39003939, 0x79790079
.long 0x07070700, 0x000e0e0e, 0x83008383, 0x8c8c008c
.long 0xb9b9b900, 0x00737373, 0xdc00dcdc, 0x6e6e006e
.long 0x55555500, 0x00aaaaaa, 0xaa00aaaa, 0x8e8e008e
.long 0xf8f8f800, 0x00f1f1f1, 0x7c007c7c, 0xf5f500f5
.long 0xeeeeee00, 0x00dddddd, 0x77007777, 0xb6b600b6
.long 0xacacac00, 0x00595959, 0x56005656, 0xfdfd00fd
.long 0x0a0a0a00, 0x00141414, 0x05000505, 0x59590059
.long 0x36363600, 0x006c6c6c, 0x1b001b1b, 0x98980098
.long 0x49494900, 0x00929292, 0xa400a4a4, 0x6a6a006a
.long 0x2a2a2a00, 0x00545454, 0x15001515, 0x46460046
.long 0x68686800, 0x00d0d0d0, 0x34003434, 0xbaba00ba
.long 0x3c3c3c00, 0x00787878, 0x1e001e1e, 0x25250025
.long 0x38383800, 0x00707070, 0x1c001c1c, 0x42420042
.long 0xf1f1f100, 0x00e3e3e3, 0xf800f8f8, 0xa2a200a2
.long 0xa4a4a400, 0x00494949, 0x52005252, 0xfafa00fa
.long 0x40404000, 0x00808080, 0x20002020, 0x07070007
.long 0x28282800, 0x00505050, 0x14001414, 0x55550055
.long 0xd3d3d300, 0x00a7a7a7, 0xe900e9e9, 0xeeee00ee
.long 0x7b7b7b00, 0x00f6f6f6, 0xbd00bdbd, 0x0a0a000a
.long 0xbbbbbb00, 0x00777777, 0xdd00dddd, 0x49490049
.long 0xc9c9c900, 0x00939393, 0xe400e4e4, 0x68680068
.long 0x43434300, 0x00868686, 0xa100a1a1, 0x38380038
.long 0xc1c1c100, 0x00838383, 0xe000e0e0, 0xa4a400a4
.long 0x15151500, 0x002a2a2a, 0x8a008a8a, 0x28280028
.long 0xe3e3e300, 0x00c7c7c7, 0xf100f1f1, 0x7b7b007b
.long 0xadadad00, 0x005b5b5b, 0xd600d6d6, 0xc9c900c9
.long 0xf4f4f400, 0x00e9e9e9, 0x7a007a7a, 0xc1c100c1
.long 0x77777700, 0x00eeeeee, 0xbb00bbbb, 0xe3e300e3
.long 0xc7c7c700, 0x008f8f8f, 0xe300e3e3, 0xf4f400f4
.long 0x80808000, 0x00010101, 0x40004040, 0xc7c700c7
.long 0x9e9e9e00, 0x003d3d3d, 0x4f004f4f, 0x9e9e009e
#endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/
#endif /*__ARM_ARCH >= 6*/
diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c
index 4b0989ea..4e6fc988 100644
--- a/cipher/camellia-glue.c
+++ b/cipher/camellia-glue.c
@@ -1,1078 +1,1078 @@
/* camellia-glue.c - Glue for the Camellia cipher
* Copyright (C) 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 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/* I put all the libgcrypt-specific stuff in this file to keep the
camellia.c/camellia.h files exactly as provided by NTT. If they
update their code, this should make it easier to bring the changes
in. - dshaw
There is one small change which needs to be done: Include the
following code at the top of camellia.h: */
#if 0
/* To use Camellia with libraries it is often useful to keep the name
* space of the library clean. The following macro is thus useful:
*
* #define CAMELLIA_EXT_SYM_PREFIX foo_
*
* This prefixes all external symbols with "foo_".
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef CAMELLIA_EXT_SYM_PREFIX
#define CAMELLIA_PREFIX1(x,y) x ## y
#define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y)
#define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x)
#define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen)
#define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock)
#define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock)
#define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128)
#define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256)
#define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128)
#define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256)
#define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128)
#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192)
#define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256)
#endif /*CAMELLIA_EXT_SYM_PREFIX*/
#endif /* Code sample. */
#include <config.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "camellia.h"
#include "bufhelp.h"
#include "cipher-internal.h"
#include "cipher-selftest.h"
/* Helper macro to force alignment to 16 bytes. */
#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# define ATTR_ALIGNED_16 __attribute__ ((aligned (16)))
#else
# define ATTR_ALIGNED_16
#endif
/* USE_AESNI 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_AVX2 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
typedef struct
{
KEY_TABLE_TYPE keytable;
int keybitlength;
#ifdef USE_AESNI_AVX
unsigned int use_aesni_avx:1; /* AES-NI/AVX implementation shall be used. */
#endif /*USE_AESNI_AVX*/
#ifdef USE_AESNI_AVX2
unsigned int use_aesni_avx2:1;/* AES-NI/AVX2 implementation shall be used. */
#endif /*USE_AESNI_AVX2*/
} CAMELLIA_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_AESNI_AVX) || defined(USE_AESNI_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_AESNI_AVX
/* Assembler implementations of Camellia using AES-NI and AVX. Process data
in 16 block same time.
*/
extern void _gcry_camellia_aesni_avx_ctr_enc(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *ctr) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_cbc_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_cfb_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_ocb_enc(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_ocb_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_ocb_auth(CAMELLIA_context *ctx,
const unsigned char *abuf,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx_keygen(CAMELLIA_context *ctx,
const unsigned char *key,
unsigned int keylen) ASM_FUNC_ABI;
#endif
#ifdef USE_AESNI_AVX2
/* Assembler implementations of Camellia using AES-NI and AVX2. Process data
in 32 block same time.
*/
extern void _gcry_camellia_aesni_avx2_ctr_enc(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *ctr) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx2_cbc_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_avx2_cfb_dec(CAMELLIA_context *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_camellia_aesni_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_aesni_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_aesni_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 gcry_err_code_t
camellia_setkey(void *c, const byte *key, unsigned keylen,
gcry_cipher_hd_t hd)
{
CAMELLIA_context *ctx=c;
static int initialized=0;
static const char *selftest_failed=NULL;
#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
unsigned int hwf = _gcry_get_hw_features ();
#endif
(void)hd;
if(keylen!=16 && keylen!=24 && keylen!=32)
return GPG_ERR_INV_KEYLEN;
if(!initialized)
{
initialized=1;
selftest_failed=selftest();
if(selftest_failed)
log_error("%s\n",selftest_failed);
}
if(selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
#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
ctx->keybitlength=keylen*8;
if (0)
{ }
#ifdef USE_AESNI_AVX
else if (ctx->use_aesni_avx)
_gcry_camellia_aesni_avx_keygen(ctx, key, keylen);
else
#endif
{
Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable);
_gcry_burn_stack
((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */
+(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */
+0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */
+3*2*sizeof(void*) /* Function calls. */
);
}
return 0;
}
#ifdef USE_ARM_ASM
/* Assembly implementations of Camellia. */
extern void _gcry_camellia_arm_encrypt_block(const KEY_TABLE_TYPE keyTable,
byte *outbuf, const byte *inbuf,
const int keybits);
extern void _gcry_camellia_arm_decrypt_block(const KEY_TABLE_TYPE keyTable,
byte *outbuf, const byte *inbuf,
const int keybits);
static void Camellia_EncryptBlock(const int keyBitLength,
const unsigned char *plaintext,
const KEY_TABLE_TYPE keyTable,
unsigned char *cipherText)
{
_gcry_camellia_arm_encrypt_block(keyTable, cipherText, plaintext,
keyBitLength);
}
static void Camellia_DecryptBlock(const int keyBitLength,
const unsigned char *cipherText,
const KEY_TABLE_TYPE keyTable,
unsigned char *plaintext)
{
_gcry_camellia_arm_decrypt_block(keyTable, plaintext, cipherText,
keyBitLength);
}
#ifdef __aarch64__
# define CAMELLIA_encrypt_stack_burn_size (0)
# define CAMELLIA_decrypt_stack_burn_size (0)
#else
# define CAMELLIA_encrypt_stack_burn_size (15*4)
# define CAMELLIA_decrypt_stack_burn_size (15*4)
#endif
static unsigned int
camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
{
CAMELLIA_context *ctx = c;
Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size);
}
static unsigned int
camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
{
CAMELLIA_context *ctx=c;
Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size);
}
#else /*USE_ARM_ASM*/
static unsigned int
camellia_encrypt(void *c, byte *outbuf, const byte *inbuf)
{
CAMELLIA_context *ctx=c;
Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
#define CAMELLIA_encrypt_stack_burn_size \
(sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
+4*sizeof(u32)+4*sizeof(u32) \
+2*sizeof(u32*)+4*sizeof(u32) \
+2*2*sizeof(void*) /* Function calls. */ \
)
return /*burn_stack*/ (CAMELLIA_encrypt_stack_burn_size);
}
static unsigned int
camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
{
CAMELLIA_context *ctx=c;
Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf);
#define CAMELLIA_decrypt_stack_burn_size \
(sizeof(int)+2*sizeof(unsigned char *)+sizeof(void*/*KEY_TABLE_TYPE*/) \
+4*sizeof(u32)+4*sizeof(u32) \
+2*sizeof(u32*)+4*sizeof(u32) \
+2*2*sizeof(void*) /* Function calls. */ \
)
return /*burn_stack*/ (CAMELLIA_decrypt_stack_burn_size);
}
#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 CAMELLIA_BLOCK_SIZE. */
void
_gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
CAMELLIA_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned char tmpbuf[CAMELLIA_BLOCK_SIZE];
int burn_stack_depth = CAMELLIA_encrypt_stack_burn_size;
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
{
int did_use_aesni_avx2 = 0;
/* Process data in 32 block chunks. */
while (nblocks >= 32)
{
_gcry_camellia_aesni_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
nblocks -= 32;
outbuf += 32 * CAMELLIA_BLOCK_SIZE;
inbuf += 32 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx2 = 1;
}
if (did_use_aesni_avx2)
{
int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx2_burn_stack_depth)
burn_stack_depth = avx2_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
/* TODO: use caching instead? */
}
#endif
#ifdef USE_AESNI_AVX
if (ctx->use_aesni_avx)
{
int did_use_aesni_avx = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_camellia_aesni_avx_ctr_enc(ctx, outbuf, inbuf, ctr);
nblocks -= 16;
outbuf += 16 * CAMELLIA_BLOCK_SIZE;
inbuf += 16 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx = 1;
}
if (did_use_aesni_avx)
{
int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx_burn_stack_depth)
burn_stack_depth = avx_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
/* TODO: use caching instead? */
}
#endif
for ( ;nblocks; nblocks-- )
{
/* Encrypt the counter. */
Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf);
/* XOR the input with the encrypted counter and store in output. */
cipher_block_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE);
outbuf += CAMELLIA_BLOCK_SIZE;
inbuf += CAMELLIA_BLOCK_SIZE;
/* Increment the counter. */
cipher_block_add(ctr, 1, CAMELLIA_BLOCK_SIZE);
}
wipememory(tmpbuf, sizeof(tmpbuf));
_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. */
void
_gcry_camellia_cbc_dec(void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
CAMELLIA_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned char savebuf[CAMELLIA_BLOCK_SIZE];
int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size;
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
{
int did_use_aesni_avx2 = 0;
/* Process data in 32 block chunks. */
while (nblocks >= 32)
{
_gcry_camellia_aesni_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
nblocks -= 32;
outbuf += 32 * CAMELLIA_BLOCK_SIZE;
inbuf += 32 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx2 = 1;
}
if (did_use_aesni_avx2)
{
int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 +
2 * sizeof(void *) + ASM_EXTRA_STACK;;
if (burn_stack_depth < avx2_burn_stack_depth)
burn_stack_depth = avx2_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_AESNI_AVX
if (ctx->use_aesni_avx)
{
int did_use_aesni_avx = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_camellia_aesni_avx_cbc_dec(ctx, outbuf, inbuf, iv);
nblocks -= 16;
outbuf += 16 * CAMELLIA_BLOCK_SIZE;
inbuf += 16 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx = 1;
}
if (did_use_aesni_avx)
{
int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx_burn_stack_depth)
burn_stack_depth = avx_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
for ( ;nblocks; nblocks-- )
{
/* INBUF is needed later and it may be identical to OUTBUF, so store
the intermediate result to SAVEBUF. */
Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf);
cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf,
CAMELLIA_BLOCK_SIZE);
inbuf += CAMELLIA_BLOCK_SIZE;
outbuf += CAMELLIA_BLOCK_SIZE;
}
wipememory(savebuf, sizeof(savebuf));
_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. */
void
_gcry_camellia_cfb_dec(void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
CAMELLIA_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size;
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
{
int did_use_aesni_avx2 = 0;
/* Process data in 32 block chunks. */
while (nblocks >= 32)
{
_gcry_camellia_aesni_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
nblocks -= 32;
outbuf += 32 * CAMELLIA_BLOCK_SIZE;
inbuf += 32 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx2 = 1;
}
if (did_use_aesni_avx2)
{
int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx2_burn_stack_depth)
burn_stack_depth = avx2_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_AESNI_AVX
if (ctx->use_aesni_avx)
{
int did_use_aesni_avx = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_camellia_aesni_avx_cfb_dec(ctx, outbuf, inbuf, iv);
nblocks -= 16;
outbuf += 16 * CAMELLIA_BLOCK_SIZE;
inbuf += 16 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx = 1;
}
if (did_use_aesni_avx)
{
int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx_burn_stack_depth)
burn_stack_depth = avx_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
for ( ;nblocks; nblocks-- )
{
Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv);
cipher_block_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
outbuf += CAMELLIA_BLOCK_SIZE;
inbuf += CAMELLIA_BLOCK_SIZE;
}
_gcry_burn_stack(burn_stack_depth);
}
/* Bulk encryption/decryption of complete blocks in OCB mode. */
size_t
_gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks, int encrypt)
{
#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
CAMELLIA_context *ctx = (void *)&c->context.c;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
int burn_stack_depth;
u64 blkn = c->u_mode.ocb.data_nblocks;
burn_stack_depth = encrypt ? CAMELLIA_encrypt_stack_burn_size :
CAMELLIA_decrypt_stack_burn_size;
#else
(void)c;
(void)outbuf_arg;
(void)inbuf_arg;
(void)encrypt;
#endif
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
{
int did_use_aesni_avx2 = 0;
u64 Ls[32];
unsigned int n = 32 - (blkn % 32);
u64 *l;
int i;
if (nblocks >= 32)
{
for (i = 0; i < 32; i += 8)
{
/* Use u64 to store pointers for x32 support (assembly function
* assumes 64-bit pointers). */
Ls[(i + 0 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 1 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
Ls[(i + 2 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 3 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
Ls[(i + 4 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 5 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
Ls[(i + 6 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
}
Ls[(7 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
Ls[(15 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[4];
Ls[(23 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
l = &Ls[(31 + n) % 32];
/* Process data in 32 block chunks. */
while (nblocks >= 32)
{
blkn += 32;
*l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 32);
if (encrypt)
_gcry_camellia_aesni_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
else
_gcry_camellia_aesni_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
nblocks -= 32;
outbuf += 32 * CAMELLIA_BLOCK_SIZE;
inbuf += 32 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx2 = 1;
}
}
if (did_use_aesni_avx2)
{
int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx2_burn_stack_depth)
burn_stack_depth = avx2_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_AESNI_AVX
if (ctx->use_aesni_avx)
{
int did_use_aesni_avx = 0;
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_camellia_aesni_avx_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
else
_gcry_camellia_aesni_avx_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
nblocks -= 16;
outbuf += 16 * CAMELLIA_BLOCK_SIZE;
inbuf += 16 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx = 1;
}
}
if (did_use_aesni_avx)
{
int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx_burn_stack_depth)
burn_stack_depth = avx_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
c->u_mode.ocb.data_nblocks = blkn;
if (burn_stack_depth)
_gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
#endif
return nblocks;
}
/* Bulk authentication of complete blocks in OCB mode. */
size_t
_gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
size_t nblocks)
{
#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
CAMELLIA_context *ctx = (void *)&c->context.c;
const unsigned char *abuf = abuf_arg;
int burn_stack_depth;
u64 blkn = c->u_mode.ocb.aad_nblocks;
burn_stack_depth = CAMELLIA_encrypt_stack_burn_size;
#else
(void)c;
(void)abuf_arg;
#endif
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
{
int did_use_aesni_avx2 = 0;
u64 Ls[32];
unsigned int n = 32 - (blkn % 32);
u64 *l;
int i;
if (nblocks >= 32)
{
for (i = 0; i < 32; i += 8)
{
/* Use u64 to store pointers for x32 support (assembly function
* assumes 64-bit pointers). */
Ls[(i + 0 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 1 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
Ls[(i + 2 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 3 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
Ls[(i + 4 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
Ls[(i + 5 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
Ls[(i + 6 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
}
Ls[(7 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
Ls[(15 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[4];
Ls[(23 + n) % 32] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
l = &Ls[(31 + n) % 32];
/* Process data in 32 block chunks. */
while (nblocks >= 32)
{
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);
nblocks -= 32;
abuf += 32 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx2 = 1;
}
}
if (did_use_aesni_avx2)
{
int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx2_burn_stack_depth)
burn_stack_depth = avx2_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_AESNI_AVX
if (ctx->use_aesni_avx)
{
int did_use_aesni_avx = 0;
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_camellia_aesni_avx_ocb_auth(ctx, abuf,
c->u_mode.ocb.aad_offset,
c->u_mode.ocb.aad_sum, Ls);
nblocks -= 16;
abuf += 16 * CAMELLIA_BLOCK_SIZE;
did_use_aesni_avx = 1;
}
}
if (did_use_aesni_avx)
{
int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
2 * sizeof(void *) + ASM_EXTRA_STACK;
if (burn_stack_depth < avx_burn_stack_depth)
burn_stack_depth = avx_burn_stack_depth;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
c->u_mode.ocb.aad_nblocks = blkn;
if (burn_stack_depth)
_gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
#endif
return nblocks;
}
/* Run the self-tests for CAMELLIA-CTR-128, tests IV increment of bulk CTR
encryption. Returns NULL on success. */
static const char*
selftest_ctr_128 (void)
{
const int nblocks = 32+16+1;
const int blocksize = CAMELLIA_BLOCK_SIZE;
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);
}
/* Run the self-tests for CAMELLIA-CBC-128, tests bulk CBC decryption.
Returns NULL on success. */
static const char*
selftest_cbc_128 (void)
{
const int nblocks = 32+16+2;
const int blocksize = CAMELLIA_BLOCK_SIZE;
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);
}
/* Run the self-tests for CAMELLIA-CFB-128, tests bulk CFB decryption.
Returns NULL on success. */
static const char*
selftest_cfb_128 (void)
{
const int nblocks = 32+16+2;
const int blocksize = CAMELLIA_BLOCK_SIZE;
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);
}
static const char *
selftest(void)
{
CAMELLIA_context ctx;
byte scratch[16];
const char *r;
/* These test vectors are from RFC-3713 */
static const byte plaintext[]=
{
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
};
static const byte key_128[]=
{
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
};
static const byte ciphertext_128[]=
{
0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73,
0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43
};
static const byte key_192[]=
{
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,
0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77
};
static const byte ciphertext_192[]=
{
0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8,
0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9
};
static const byte key_256[]=
{
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,
0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,
0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff
};
static const byte ciphertext_256[]=
{
0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c,
0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09
};
camellia_setkey(&ctx,key_128,sizeof(key_128),NULL);
camellia_encrypt(&ctx,scratch,plaintext);
if(memcmp(scratch,ciphertext_128,sizeof(ciphertext_128))!=0)
return "CAMELLIA-128 test encryption failed.";
camellia_decrypt(&ctx,scratch,scratch);
if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
return "CAMELLIA-128 test decryption failed.";
camellia_setkey(&ctx,key_192,sizeof(key_192),NULL);
camellia_encrypt(&ctx,scratch,plaintext);
if(memcmp(scratch,ciphertext_192,sizeof(ciphertext_192))!=0)
return "CAMELLIA-192 test encryption failed.";
camellia_decrypt(&ctx,scratch,scratch);
if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
return "CAMELLIA-192 test decryption failed.";
camellia_setkey(&ctx,key_256,sizeof(key_256),NULL);
camellia_encrypt(&ctx,scratch,plaintext);
if(memcmp(scratch,ciphertext_256,sizeof(ciphertext_256))!=0)
return "CAMELLIA-256 test encryption failed.";
camellia_decrypt(&ctx,scratch,scratch);
if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
return "CAMELLIA-256 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;
}
/* These oids are from
- <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>,
+ <https://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>,
retrieved May 1, 2007. */
static 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},
{"0.3.4401.5.3.1.9.3", GCRY_CIPHER_MODE_OFB},
{"0.3.4401.5.3.1.9.4", GCRY_CIPHER_MODE_CFB},
{ NULL }
};
static 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},
{"0.3.4401.5.3.1.9.23", GCRY_CIPHER_MODE_OFB},
{"0.3.4401.5.3.1.9.24", GCRY_CIPHER_MODE_CFB},
{ NULL }
};
static 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},
{"0.3.4401.5.3.1.9.43", GCRY_CIPHER_MODE_OFB},
{"0.3.4401.5.3.1.9.44", GCRY_CIPHER_MODE_CFB},
{ NULL }
};
gcry_cipher_spec_t _gcry_cipher_spec_camellia128 =
{
GCRY_CIPHER_CAMELLIA128, {0, 0},
"CAMELLIA128",NULL,camellia128_oids,CAMELLIA_BLOCK_SIZE,128,
sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
};
gcry_cipher_spec_t _gcry_cipher_spec_camellia192 =
{
GCRY_CIPHER_CAMELLIA192, {0, 0},
"CAMELLIA192",NULL,camellia192_oids,CAMELLIA_BLOCK_SIZE,192,
sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
};
gcry_cipher_spec_t _gcry_cipher_spec_camellia256 =
{
GCRY_CIPHER_CAMELLIA256, {0, 0},
"CAMELLIA256",NULL,camellia256_oids,CAMELLIA_BLOCK_SIZE,256,
sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt
};
diff --git a/cipher/camellia.c b/cipher/camellia.c
index e7085a7e..3461ad4e 100644
--- a/cipher/camellia.c
+++ b/cipher/camellia.c
@@ -1,1413 +1,1413 @@
/* camellia.h ver 1.2.0
*
* Copyright (C) 2006,2007
* NTT (Nippon Telegraph and Telephone Corporation).
*
* 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 program; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Algorithm Specification
- * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ * https://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
*/
#include <config.h>
#include <string.h>
#include <stdlib.h>
#include "types.h"
#include "bufhelp.h"
#include "camellia.h"
typedef byte u8;
/* key constants */
#define CAMELLIA_SIGMA1L (0xA09E667FL)
#define CAMELLIA_SIGMA1R (0x3BCC908BL)
#define CAMELLIA_SIGMA2L (0xB67AE858L)
#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
#define CAMELLIA_SIGMA3L (0xC6EF372FL)
#define CAMELLIA_SIGMA3R (0xE94F82BEL)
#define CAMELLIA_SIGMA4L (0x54FF53A5L)
#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
#define CAMELLIA_SIGMA5L (0x10E527FAL)
#define CAMELLIA_SIGMA5R (0xDE682D1DL)
#define CAMELLIA_SIGMA6L (0xB05688C2L)
#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
/*
* macros
*/
#if defined(_MSC_VER)
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));}
#else /* not MS-VC */
# define GETU32(pt) buf_get_be32(pt)
# define PUTU32(ct, st) buf_put_be32(ct, st)
#endif
#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2])
#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1])
/* rotation right shift 1byte */
#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
/* rotation left shift 1bit */
#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
/* rotation left shift 1byte */
#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \
do { \
w0 = ll; \
ll = (ll << bits) + (lr >> (32 - bits)); \
lr = (lr << bits) + (rl >> (32 - bits)); \
rl = (rl << bits) + (rr >> (32 - bits)); \
rr = (rr << bits) + (w0 >> (32 - bits)); \
} while(0)
#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \
do { \
w0 = ll; \
w1 = lr; \
ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \
lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \
rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \
rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \
} while(0)
#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \
do { \
il = xl ^ kl; \
ir = xr ^ kr; \
t0 = il >> 16; \
t1 = ir >> 16; \
yl = CAMELLIA_SP1110(ir & 0xff) \
^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \
^ CAMELLIA_SP3033(t1 & 0xff) \
^ CAMELLIA_SP4404((ir >> 8) & 0xff); \
yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \
^ CAMELLIA_SP0222(t0 & 0xff) \
^ CAMELLIA_SP3033((il >> 8) & 0xff) \
^ CAMELLIA_SP4404(il & 0xff); \
yl ^= yr; \
yr = CAMELLIA_RR8(yr); \
yr ^= yl; \
} while(0)
/*
* for speed up
*
*/
#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
do { \
t0 = kll; \
t0 &= ll; \
lr ^= CAMELLIA_RL1(t0); \
t1 = klr; \
t1 |= lr; \
ll ^= t1; \
\
t2 = krr; \
t2 |= rr; \
rl ^= t2; \
t3 = krl; \
t3 &= rl; \
rr ^= CAMELLIA_RL1(t3); \
} while(0)
#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \
do { \
yl ^= kl; \
yr ^= kr; \
ir = CAMELLIA_SP1110(xr & 0xff) \
^ CAMELLIA_SP0222((xr >> 24) & 0xff) \
^ CAMELLIA_SP3033((xr >> 16) & 0xff) \
^ CAMELLIA_SP4404((xr >> 8) & 0xff); \
il = CAMELLIA_SP1110((xl >> 24) & 0xff) \
^ CAMELLIA_SP0222((xl >> 16) & 0xff) \
^ CAMELLIA_SP3033((xl >> 8) & 0xff) \
^ CAMELLIA_SP4404(xl & 0xff); \
ir ^= il; \
il = CAMELLIA_RR8(il); \
il ^= ir; \
yl ^= ir; \
yr ^= il; \
} while(0)
static const u32 camellia_sp1110[256] = {
0x70707000,0x82828200,0x2c2c2c00,0xececec00,
0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
0xe4e4e400,0x85858500,0x57575700,0x35353500,
0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
0x45454500,0x19191900,0xa5a5a500,0x21212100,
0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
0x74747400,0x12121200,0x2b2b2b00,0x20202000,
0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
0x34343400,0x7e7e7e00,0x76767600,0x05050500,
0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
0x14141400,0x58585800,0x3a3a3a00,0x61616100,
0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
0x53535300,0x18181800,0xf2f2f200,0x22222200,
0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
0x60606000,0xfcfcfc00,0x69696900,0x50505000,
0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
0xa1a1a100,0x89898900,0x62626200,0x97979700,
0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
0x10101000,0xc4c4c400,0x00000000,0x48484800,
0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
0x87878700,0x5c5c5c00,0x83838300,0x02020200,
0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
0x78787800,0x98989800,0x06060600,0x6a6a6a00,
0xe7e7e700,0x46464600,0x71717100,0xbababa00,
0xd4d4d400,0x25252500,0xababab00,0x42424200,
0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
0x72727200,0x07070700,0xb9b9b900,0x55555500,
0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
0x36363600,0x49494900,0x2a2a2a00,0x68686800,
0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
};
static const u32 camellia_sp0222[256] = {
0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
0x00e8e8e8,0x00242424,0x00565656,0x00404040,
0x00e1e1e1,0x00636363,0x00090909,0x00333333,
0x00bfbfbf,0x00989898,0x00979797,0x00858585,
0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
0x00dadada,0x006f6f6f,0x00535353,0x00626262,
0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
0x00bdbdbd,0x00363636,0x00222222,0x00383838,
0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
0x00484848,0x00101010,0x00d1d1d1,0x00515151,
0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
0x00202020,0x00898989,0x00000000,0x00909090,
0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
0x009b9b9b,0x00949494,0x00212121,0x00666666,
0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
0x00030303,0x002d2d2d,0x00dedede,0x00969696,
0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
0x00787878,0x00707070,0x00e3e3e3,0x00494949,
0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
0x00777777,0x00939393,0x00868686,0x00838383,
0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
};
static const u32 camellia_sp3033[256] = {
0x38003838,0x41004141,0x16001616,0x76007676,
0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
0x75007575,0x06000606,0x57005757,0xa000a0a0,
0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
0xfd00fdfd,0x66006666,0x58005858,0x96009696,
0x3a003a3a,0x09000909,0x95009595,0x10001010,
0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
0xef00efef,0x26002626,0xe500e5e5,0x61006161,
0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
0x12001212,0x04000404,0x74007474,0x54005454,
0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
0x55005555,0x68006868,0x50005050,0xbe00bebe,
0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
0x70007070,0xff00ffff,0x32003232,0x69006969,
0x08000808,0x62006262,0x00000000,0x24002424,
0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
0x45004545,0x81008181,0x73007373,0x6d006d6d,
0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
0xe600e6e6,0x25002525,0x48004848,0x99009999,
0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
0x7c007c7c,0x77007777,0x56005656,0x05000505,
0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
};
static const u32 camellia_sp4404[256] = {
0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
0x14140014,0x3a3a003a,0xdede00de,0x11110011,
0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
0x24240024,0xe8e800e8,0x60600060,0x69690069,
0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
0x10100010,0x00000000,0xa3a300a3,0x75750075,
0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
0x87870087,0x83830083,0xcdcd00cd,0x90900090,
0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
0x81810081,0x6f6f006f,0x13130013,0x63630063,
0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
0x78780078,0x06060006,0xe7e700e7,0x71710071,
0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
0x15150015,0xadad00ad,0x77770077,0x80800080,
0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
0x85850085,0x35350035,0x0c0c000c,0x41410041,
0xefef00ef,0x93930093,0x19190019,0x21210021,
0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
0x12120012,0x20200020,0xb1b100b1,0x99990099,
0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
0x0f0f000f,0x16160016,0x18180018,0x22220022,
0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
0x03030003,0xdada00da,0x3f3f003f,0x94940094,
0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
0x49490049,0x68680068,0x38380038,0xa4a400a4,
0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
};
/**
* Stuff related to the Camellia key schedule
*/
#define subl(x) subL[(x)]
#define subr(x) subR[(x)]
void camellia_setup128(const unsigned char *key, u32 *subkey)
{
u32 kll, klr, krl, krr;
u32 il, ir, t0, t1, w0, w1;
u32 kw4l, kw4r, dw, tl, tr;
u32 subL[26];
u32 subR[26];
/**
* k == kll || klr || krl || krr (|| is concatination)
*/
kll = GETU32(key );
klr = GETU32(key + 4);
krl = GETU32(key + 8);
krr = GETU32(key + 12);
/**
* generate KL dependent subkeys
*/
subl(0) = kll; subr(0) = klr;
subl(1) = krl; subr(1) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(4) = kll; subr(4) = klr;
subl(5) = krl; subr(5) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
subl(10) = kll; subr(10) = klr;
subl(11) = krl; subr(11) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(13) = krl; subr(13) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
subl(16) = kll; subr(16) = klr;
subl(17) = krl; subr(17) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
subl(18) = kll; subr(18) = klr;
subl(19) = krl; subr(19) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
subl(22) = kll; subr(22) = klr;
subl(23) = krl; subr(23) = krr;
/* generate KA */
kll = subl(0); klr = subr(0);
krl = subl(1); krr = subr(1);
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
w0, w1, il, ir, t0, t1);
krl ^= w0; krr ^= w1;
CAMELLIA_F(krl, krr,
CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
kll, klr, il, ir, t0, t1);
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
krl, krr, il, ir, t0, t1);
krl ^= w0; krr ^= w1;
CAMELLIA_F(krl, krr,
CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
w0, w1, il, ir, t0, t1);
kll ^= w0; klr ^= w1;
/* generate KA dependent subkeys */
subl(2) = kll; subr(2) = klr;
subl(3) = krl; subr(3) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(6) = kll; subr(6) = klr;
subl(7) = krl; subr(7) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(8) = kll; subr(8) = klr;
subl(9) = krl; subr(9) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(12) = kll; subr(12) = klr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(14) = kll; subr(14) = klr;
subl(15) = krl; subr(15) = krr;
CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
subl(20) = kll; subr(20) = klr;
subl(21) = krl; subr(21) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
subl(24) = kll; subr(24) = klr;
subl(25) = krl; subr(25) = krr;
/* absorb kw2 to other subkeys */
subl(3) ^= subl(1); subr(3) ^= subr(1);
subl(5) ^= subl(1); subr(5) ^= subr(1);
subl(7) ^= subl(1); subr(7) ^= subr(1);
subl(1) ^= subr(1) & ~subr(9);
dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
subl(11) ^= subl(1); subr(11) ^= subr(1);
subl(13) ^= subl(1); subr(13) ^= subr(1);
subl(15) ^= subl(1); subr(15) ^= subr(1);
subl(1) ^= subr(1) & ~subr(17);
dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
subl(19) ^= subl(1); subr(19) ^= subr(1);
subl(21) ^= subl(1); subr(21) ^= subr(1);
subl(23) ^= subl(1); subr(23) ^= subr(1);
subl(24) ^= subl(1); subr(24) ^= subr(1);
/* absorb kw4 to other subkeys */
kw4l = subl(25); kw4r = subr(25);
subl(22) ^= kw4l; subr(22) ^= kw4r;
subl(20) ^= kw4l; subr(20) ^= kw4r;
subl(18) ^= kw4l; subr(18) ^= kw4r;
kw4l ^= kw4r & ~subr(16);
dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
subl(14) ^= kw4l; subr(14) ^= kw4r;
subl(12) ^= kw4l; subr(12) ^= kw4r;
subl(10) ^= kw4l; subr(10) ^= kw4r;
kw4l ^= kw4r & ~subr(8);
dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
subl(6) ^= kw4l; subr(6) ^= kw4r;
subl(4) ^= kw4l; subr(4) ^= kw4r;
subl(2) ^= kw4l; subr(2) ^= kw4r;
subl(0) ^= kw4l; subr(0) ^= kw4r;
/* key XOR is end of F-function */
CamelliaSubkeyL(0) = subl(0) ^ subl(2);
CamelliaSubkeyR(0) = subr(0) ^ subr(2);
CamelliaSubkeyL(2) = subl(3);
CamelliaSubkeyR(2) = subr(3);
CamelliaSubkeyL(3) = subl(2) ^ subl(4);
CamelliaSubkeyR(3) = subr(2) ^ subr(4);
CamelliaSubkeyL(4) = subl(3) ^ subl(5);
CamelliaSubkeyR(4) = subr(3) ^ subr(5);
CamelliaSubkeyL(5) = subl(4) ^ subl(6);
CamelliaSubkeyR(5) = subr(4) ^ subr(6);
CamelliaSubkeyL(6) = subl(5) ^ subl(7);
CamelliaSubkeyR(6) = subr(5) ^ subr(7);
tl = subl(10) ^ (subr(10) & ~subr(8));
dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(7) = subl(6) ^ tl;
CamelliaSubkeyR(7) = subr(6) ^ tr;
CamelliaSubkeyL(8) = subl(8);
CamelliaSubkeyR(8) = subr(8);
CamelliaSubkeyL(9) = subl(9);
CamelliaSubkeyR(9) = subr(9);
tl = subl(7) ^ (subr(7) & ~subr(9));
dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(10) = tl ^ subl(11);
CamelliaSubkeyR(10) = tr ^ subr(11);
CamelliaSubkeyL(11) = subl(10) ^ subl(12);
CamelliaSubkeyR(11) = subr(10) ^ subr(12);
CamelliaSubkeyL(12) = subl(11) ^ subl(13);
CamelliaSubkeyR(12) = subr(11) ^ subr(13);
CamelliaSubkeyL(13) = subl(12) ^ subl(14);
CamelliaSubkeyR(13) = subr(12) ^ subr(14);
CamelliaSubkeyL(14) = subl(13) ^ subl(15);
CamelliaSubkeyR(14) = subr(13) ^ subr(15);
tl = subl(18) ^ (subr(18) & ~subr(16));
dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(15) = subl(14) ^ tl;
CamelliaSubkeyR(15) = subr(14) ^ tr;
CamelliaSubkeyL(16) = subl(16);
CamelliaSubkeyR(16) = subr(16);
CamelliaSubkeyL(17) = subl(17);
CamelliaSubkeyR(17) = subr(17);
tl = subl(15) ^ (subr(15) & ~subr(17));
dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(18) = tl ^ subl(19);
CamelliaSubkeyR(18) = tr ^ subr(19);
CamelliaSubkeyL(19) = subl(18) ^ subl(20);
CamelliaSubkeyR(19) = subr(18) ^ subr(20);
CamelliaSubkeyL(20) = subl(19) ^ subl(21);
CamelliaSubkeyR(20) = subr(19) ^ subr(21);
CamelliaSubkeyL(21) = subl(20) ^ subl(22);
CamelliaSubkeyR(21) = subr(20) ^ subr(22);
CamelliaSubkeyL(22) = subl(21) ^ subl(23);
CamelliaSubkeyR(22) = subr(21) ^ subr(23);
CamelliaSubkeyL(23) = subl(22);
CamelliaSubkeyR(23) = subr(22);
CamelliaSubkeyL(24) = subl(24) ^ subl(23);
CamelliaSubkeyR(24) = subr(24) ^ subr(23);
return;
}
void camellia_setup256(const unsigned char *key, u32 *subkey)
{
u32 kll,klr,krl,krr; /* left half of key */
u32 krll,krlr,krrl,krrr; /* right half of key */
u32 il, ir, t0, t1, w0, w1; /* temporary variables */
u32 kw4l, kw4r, dw, tl, tr;
u32 subL[34];
u32 subR[34];
/**
* key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
* (|| is concatination)
*/
kll = GETU32(key );
klr = GETU32(key + 4);
krl = GETU32(key + 8);
krr = GETU32(key + 12);
krll = GETU32(key + 16);
krlr = GETU32(key + 20);
krrl = GETU32(key + 24);
krrr = GETU32(key + 28);
/* generate KL dependent subkeys */
subl(0) = kll; subr(0) = klr;
subl(1) = krl; subr(1) = krr;
CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
subl(12) = kll; subr(12) = klr;
subl(13) = krl; subr(13) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(16) = kll; subr(16) = klr;
subl(17) = krl; subr(17) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
subl(22) = kll; subr(22) = klr;
subl(23) = krl; subr(23) = krr;
CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
subl(30) = kll; subr(30) = klr;
subl(31) = krl; subr(31) = krr;
/* generate KR dependent subkeys */
CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
subl(4) = krll; subr(4) = krlr;
subl(5) = krrl; subr(5) = krrr;
CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
subl(8) = krll; subr(8) = krlr;
subl(9) = krrl; subr(9) = krrr;
CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
subl(18) = krll; subr(18) = krlr;
subl(19) = krrl; subr(19) = krrr;
CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
subl(26) = krll; subr(26) = krlr;
subl(27) = krrl; subr(27) = krrr;
CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
/* generate KA */
kll = subl(0) ^ krll; klr = subr(0) ^ krlr;
krl = subl(1) ^ krrl; krr = subr(1) ^ krrr;
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
w0, w1, il, ir, t0, t1);
krl ^= w0; krr ^= w1;
CAMELLIA_F(krl, krr,
CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
kll, klr, il, ir, t0, t1);
kll ^= krll; klr ^= krlr;
CAMELLIA_F(kll, klr,
CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
krl, krr, il, ir, t0, t1);
krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
CAMELLIA_F(krl, krr,
CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
w0, w1, il, ir, t0, t1);
kll ^= w0; klr ^= w1;
/* generate KB */
krll ^= kll; krlr ^= klr;
krrl ^= krl; krrr ^= krr;
CAMELLIA_F(krll, krlr,
CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
w0, w1, il, ir, t0, t1);
krrl ^= w0; krrr ^= w1;
CAMELLIA_F(krrl, krrr,
CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
w0, w1, il, ir, t0, t1);
krll ^= w0; krlr ^= w1;
/* generate KA dependent subkeys */
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
subl(6) = kll; subr(6) = klr;
subl(7) = krl; subr(7) = krr;
CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
subl(14) = kll; subr(14) = klr;
subl(15) = krl; subr(15) = krr;
subl(24) = klr; subr(24) = krl;
subl(25) = krr; subr(25) = kll;
CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
subl(28) = kll; subr(28) = klr;
subl(29) = krl; subr(29) = krr;
/* generate KB dependent subkeys */
subl(2) = krll; subr(2) = krlr;
subl(3) = krrl; subr(3) = krrr;
CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
subl(10) = krll; subr(10) = krlr;
subl(11) = krrl; subr(11) = krrr;
CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
subl(20) = krll; subr(20) = krlr;
subl(21) = krrl; subr(21) = krrr;
CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
subl(32) = krll; subr(32) = krlr;
subl(33) = krrl; subr(33) = krrr;
/* absorb kw2 to other subkeys */
subl(3) ^= subl(1); subr(3) ^= subr(1);
subl(5) ^= subl(1); subr(5) ^= subr(1);
subl(7) ^= subl(1); subr(7) ^= subr(1);
subl(1) ^= subr(1) & ~subr(9);
dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw);
subl(11) ^= subl(1); subr(11) ^= subr(1);
subl(13) ^= subl(1); subr(13) ^= subr(1);
subl(15) ^= subl(1); subr(15) ^= subr(1);
subl(1) ^= subr(1) & ~subr(17);
dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw);
subl(19) ^= subl(1); subr(19) ^= subr(1);
subl(21) ^= subl(1); subr(21) ^= subr(1);
subl(23) ^= subl(1); subr(23) ^= subr(1);
subl(1) ^= subr(1) & ~subr(25);
dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw);
subl(27) ^= subl(1); subr(27) ^= subr(1);
subl(29) ^= subl(1); subr(29) ^= subr(1);
subl(31) ^= subl(1); subr(31) ^= subr(1);
subl(32) ^= subl(1); subr(32) ^= subr(1);
/* absorb kw4 to other subkeys */
kw4l = subl(33); kw4r = subr(33);
subl(30) ^= kw4l; subr(30) ^= kw4r;
subl(28) ^= kw4l; subr(28) ^= kw4r;
subl(26) ^= kw4l; subr(26) ^= kw4r;
kw4l ^= kw4r & ~subr(24);
dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw);
subl(22) ^= kw4l; subr(22) ^= kw4r;
subl(20) ^= kw4l; subr(20) ^= kw4r;
subl(18) ^= kw4l; subr(18) ^= kw4r;
kw4l ^= kw4r & ~subr(16);
dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw);
subl(14) ^= kw4l; subr(14) ^= kw4r;
subl(12) ^= kw4l; subr(12) ^= kw4r;
subl(10) ^= kw4l; subr(10) ^= kw4r;
kw4l ^= kw4r & ~subr(8);
dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw);
subl(6) ^= kw4l; subr(6) ^= kw4r;
subl(4) ^= kw4l; subr(4) ^= kw4r;
subl(2) ^= kw4l; subr(2) ^= kw4r;
subl(0) ^= kw4l; subr(0) ^= kw4r;
/* key XOR is end of F-function */
CamelliaSubkeyL(0) = subl(0) ^ subl(2);
CamelliaSubkeyR(0) = subr(0) ^ subr(2);
CamelliaSubkeyL(2) = subl(3);
CamelliaSubkeyR(2) = subr(3);
CamelliaSubkeyL(3) = subl(2) ^ subl(4);
CamelliaSubkeyR(3) = subr(2) ^ subr(4);
CamelliaSubkeyL(4) = subl(3) ^ subl(5);
CamelliaSubkeyR(4) = subr(3) ^ subr(5);
CamelliaSubkeyL(5) = subl(4) ^ subl(6);
CamelliaSubkeyR(5) = subr(4) ^ subr(6);
CamelliaSubkeyL(6) = subl(5) ^ subl(7);
CamelliaSubkeyR(6) = subr(5) ^ subr(7);
tl = subl(10) ^ (subr(10) & ~subr(8));
dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(7) = subl(6) ^ tl;
CamelliaSubkeyR(7) = subr(6) ^ tr;
CamelliaSubkeyL(8) = subl(8);
CamelliaSubkeyR(8) = subr(8);
CamelliaSubkeyL(9) = subl(9);
CamelliaSubkeyR(9) = subr(9);
tl = subl(7) ^ (subr(7) & ~subr(9));
dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(10) = tl ^ subl(11);
CamelliaSubkeyR(10) = tr ^ subr(11);
CamelliaSubkeyL(11) = subl(10) ^ subl(12);
CamelliaSubkeyR(11) = subr(10) ^ subr(12);
CamelliaSubkeyL(12) = subl(11) ^ subl(13);
CamelliaSubkeyR(12) = subr(11) ^ subr(13);
CamelliaSubkeyL(13) = subl(12) ^ subl(14);
CamelliaSubkeyR(13) = subr(12) ^ subr(14);
CamelliaSubkeyL(14) = subl(13) ^ subl(15);
CamelliaSubkeyR(14) = subr(13) ^ subr(15);
tl = subl(18) ^ (subr(18) & ~subr(16));
dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(15) = subl(14) ^ tl;
CamelliaSubkeyR(15) = subr(14) ^ tr;
CamelliaSubkeyL(16) = subl(16);
CamelliaSubkeyR(16) = subr(16);
CamelliaSubkeyL(17) = subl(17);
CamelliaSubkeyR(17) = subr(17);
tl = subl(15) ^ (subr(15) & ~subr(17));
dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(18) = tl ^ subl(19);
CamelliaSubkeyR(18) = tr ^ subr(19);
CamelliaSubkeyL(19) = subl(18) ^ subl(20);
CamelliaSubkeyR(19) = subr(18) ^ subr(20);
CamelliaSubkeyL(20) = subl(19) ^ subl(21);
CamelliaSubkeyR(20) = subr(19) ^ subr(21);
CamelliaSubkeyL(21) = subl(20) ^ subl(22);
CamelliaSubkeyR(21) = subr(20) ^ subr(22);
CamelliaSubkeyL(22) = subl(21) ^ subl(23);
CamelliaSubkeyR(22) = subr(21) ^ subr(23);
tl = subl(26) ^ (subr(26) & ~subr(24));
dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(23) = subl(22) ^ tl;
CamelliaSubkeyR(23) = subr(22) ^ tr;
CamelliaSubkeyL(24) = subl(24);
CamelliaSubkeyR(24) = subr(24);
CamelliaSubkeyL(25) = subl(25);
CamelliaSubkeyR(25) = subr(25);
tl = subl(23) ^ (subr(23) & ~subr(25));
dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw);
CamelliaSubkeyL(26) = tl ^ subl(27);
CamelliaSubkeyR(26) = tr ^ subr(27);
CamelliaSubkeyL(27) = subl(26) ^ subl(28);
CamelliaSubkeyR(27) = subr(26) ^ subr(28);
CamelliaSubkeyL(28) = subl(27) ^ subl(29);
CamelliaSubkeyR(28) = subr(27) ^ subr(29);
CamelliaSubkeyL(29) = subl(28) ^ subl(30);
CamelliaSubkeyR(29) = subr(28) ^ subr(30);
CamelliaSubkeyL(30) = subl(29) ^ subl(31);
CamelliaSubkeyR(30) = subr(29) ^ subr(31);
CamelliaSubkeyL(31) = subl(30);
CamelliaSubkeyR(31) = subr(30);
CamelliaSubkeyL(32) = subl(32) ^ subl(31);
CamelliaSubkeyR(32) = subr(32) ^ subr(31);
return;
}
void camellia_setup192(const unsigned char *key, u32 *subkey)
{
unsigned char kk[32];
u32 krll, krlr, krrl,krrr;
memcpy(kk, key, 24);
memcpy((unsigned char *)&krll, key+16,4);
memcpy((unsigned char *)&krlr, key+20,4);
krrl = ~krll;
krrr = ~krlr;
memcpy(kk+24, (unsigned char *)&krrl, 4);
memcpy(kk+28, (unsigned char *)&krrr, 4);
camellia_setup256(kk, subkey);
return;
}
#ifndef USE_ARM_ASM
/**
* Stuff related to camellia encryption/decryption
*
* "io" must be 4byte aligned and big-endian data.
*/
void camellia_encrypt128(const u32 *subkey, u32 *blocks)
{
u32 il, ir, t0, t1;
u32 io[4];
io[0] = blocks[0];
io[1] = blocks[1];
io[2] = blocks[2];
io[3] = blocks[3];
/* pre whitening but absorb kw2*/
io[0] ^= CamelliaSubkeyL(0);
io[1] ^= CamelliaSubkeyR(0);
/* main iteration */
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(2),CamelliaSubkeyR(2),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(3),CamelliaSubkeyR(3),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(4),CamelliaSubkeyR(4),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(5),CamelliaSubkeyR(5),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(6),CamelliaSubkeyR(6),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(7),CamelliaSubkeyR(7),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(8),CamelliaSubkeyR(8),
CamelliaSubkeyL(9),CamelliaSubkeyR(9),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(10),CamelliaSubkeyR(10),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(11),CamelliaSubkeyR(11),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(12),CamelliaSubkeyR(12),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(13),CamelliaSubkeyR(13),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(14),CamelliaSubkeyR(14),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(15),CamelliaSubkeyR(15),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(16),CamelliaSubkeyR(16),
CamelliaSubkeyL(17),CamelliaSubkeyR(17),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(18),CamelliaSubkeyR(18),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(19),CamelliaSubkeyR(19),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(20),CamelliaSubkeyR(20),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(21),CamelliaSubkeyR(21),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(22),CamelliaSubkeyR(22),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(23),CamelliaSubkeyR(23),
io[0],io[1],il,ir,t0,t1);
/* post whitening but kw4 */
io[2] ^= CamelliaSubkeyL(24);
io[3] ^= CamelliaSubkeyR(24);
t0 = io[0];
t1 = io[1];
io[0] = io[2];
io[1] = io[3];
io[2] = t0;
io[3] = t1;
blocks[0] = io[0];
blocks[1] = io[1];
blocks[2] = io[2];
blocks[3] = io[3];
return;
}
void camellia_decrypt128(const u32 *subkey, u32 *blocks)
{
u32 il,ir,t0,t1; /* temporary valiables */
u32 io[4];
io[0] = blocks[0];
io[1] = blocks[1];
io[2] = blocks[2];
io[3] = blocks[3];
/* pre whitening but absorb kw2*/
io[0] ^= CamelliaSubkeyL(24);
io[1] ^= CamelliaSubkeyR(24);
/* main iteration */
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(23),CamelliaSubkeyR(23),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(22),CamelliaSubkeyR(22),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(21),CamelliaSubkeyR(21),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(20),CamelliaSubkeyR(20),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(19),CamelliaSubkeyR(19),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(18),CamelliaSubkeyR(18),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(17),CamelliaSubkeyR(17),
CamelliaSubkeyL(16),CamelliaSubkeyR(16),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(15),CamelliaSubkeyR(15),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(14),CamelliaSubkeyR(14),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(13),CamelliaSubkeyR(13),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(12),CamelliaSubkeyR(12),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(11),CamelliaSubkeyR(11),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(10),CamelliaSubkeyR(10),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(9),CamelliaSubkeyR(9),
CamelliaSubkeyL(8),CamelliaSubkeyR(8),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(7),CamelliaSubkeyR(7),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(6),CamelliaSubkeyR(6),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(5),CamelliaSubkeyR(5),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(4),CamelliaSubkeyR(4),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(3),CamelliaSubkeyR(3),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(2),CamelliaSubkeyR(2),
io[0],io[1],il,ir,t0,t1);
/* post whitening but kw4 */
io[2] ^= CamelliaSubkeyL(0);
io[3] ^= CamelliaSubkeyR(0);
t0 = io[0];
t1 = io[1];
io[0] = io[2];
io[1] = io[3];
io[2] = t0;
io[3] = t1;
blocks[0] = io[0];
blocks[1] = io[1];
blocks[2] = io[2];
blocks[3] = io[3];
return;
}
/**
* stuff for 192 and 256bit encryption/decryption
*/
void camellia_encrypt256(const u32 *subkey, u32 *blocks)
{
u32 il,ir,t0,t1; /* temporary valiables */
u32 io[4];
io[0] = blocks[0];
io[1] = blocks[1];
io[2] = blocks[2];
io[3] = blocks[3];
/* pre whitening but absorb kw2*/
io[0] ^= CamelliaSubkeyL(0);
io[1] ^= CamelliaSubkeyR(0);
/* main iteration */
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(2),CamelliaSubkeyR(2),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(3),CamelliaSubkeyR(3),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(4),CamelliaSubkeyR(4),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(5),CamelliaSubkeyR(5),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(6),CamelliaSubkeyR(6),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(7),CamelliaSubkeyR(7),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(8),CamelliaSubkeyR(8),
CamelliaSubkeyL(9),CamelliaSubkeyR(9),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(10),CamelliaSubkeyR(10),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(11),CamelliaSubkeyR(11),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(12),CamelliaSubkeyR(12),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(13),CamelliaSubkeyR(13),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(14),CamelliaSubkeyR(14),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(15),CamelliaSubkeyR(15),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(16),CamelliaSubkeyR(16),
CamelliaSubkeyL(17),CamelliaSubkeyR(17),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(18),CamelliaSubkeyR(18),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(19),CamelliaSubkeyR(19),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(20),CamelliaSubkeyR(20),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(21),CamelliaSubkeyR(21),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(22),CamelliaSubkeyR(22),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(23),CamelliaSubkeyR(23),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(24),CamelliaSubkeyR(24),
CamelliaSubkeyL(25),CamelliaSubkeyR(25),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(26),CamelliaSubkeyR(26),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(27),CamelliaSubkeyR(27),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(28),CamelliaSubkeyR(28),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(29),CamelliaSubkeyR(29),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(30),CamelliaSubkeyR(30),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(31),CamelliaSubkeyR(31),
io[0],io[1],il,ir,t0,t1);
/* post whitening but kw4 */
io[2] ^= CamelliaSubkeyL(32);
io[3] ^= CamelliaSubkeyR(32);
t0 = io[0];
t1 = io[1];
io[0] = io[2];
io[1] = io[3];
io[2] = t0;
io[3] = t1;
blocks[0] = io[0];
blocks[1] = io[1];
blocks[2] = io[2];
blocks[3] = io[3];
return;
}
void camellia_decrypt256(const u32 *subkey, u32 *blocks)
{
u32 il,ir,t0,t1; /* temporary valiables */
u32 io[4];
io[0] = blocks[0];
io[1] = blocks[1];
io[2] = blocks[2];
io[3] = blocks[3];
/* pre whitening but absorb kw2*/
io[0] ^= CamelliaSubkeyL(32);
io[1] ^= CamelliaSubkeyR(32);
/* main iteration */
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(31),CamelliaSubkeyR(31),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(30),CamelliaSubkeyR(30),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(29),CamelliaSubkeyR(29),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(28),CamelliaSubkeyR(28),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(27),CamelliaSubkeyR(27),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(26),CamelliaSubkeyR(26),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(25),CamelliaSubkeyR(25),
CamelliaSubkeyL(24),CamelliaSubkeyR(24),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(23),CamelliaSubkeyR(23),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(22),CamelliaSubkeyR(22),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(21),CamelliaSubkeyR(21),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(20),CamelliaSubkeyR(20),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(19),CamelliaSubkeyR(19),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(18),CamelliaSubkeyR(18),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(17),CamelliaSubkeyR(17),
CamelliaSubkeyL(16),CamelliaSubkeyR(16),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(15),CamelliaSubkeyR(15),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(14),CamelliaSubkeyR(14),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(13),CamelliaSubkeyR(13),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(12),CamelliaSubkeyR(12),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(11),CamelliaSubkeyR(11),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(10),CamelliaSubkeyR(10),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_FLS(io[0],io[1],io[2],io[3],
CamelliaSubkeyL(9),CamelliaSubkeyR(9),
CamelliaSubkeyL(8),CamelliaSubkeyR(8),
t0,t1,il,ir);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(7),CamelliaSubkeyR(7),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(6),CamelliaSubkeyR(6),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(5),CamelliaSubkeyR(5),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(4),CamelliaSubkeyR(4),
io[0],io[1],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[0],io[1],
CamelliaSubkeyL(3),CamelliaSubkeyR(3),
io[2],io[3],il,ir,t0,t1);
CAMELLIA_ROUNDSM(io[2],io[3],
CamelliaSubkeyL(2),CamelliaSubkeyR(2),
io[0],io[1],il,ir,t0,t1);
/* post whitening but kw4 */
io[2] ^= CamelliaSubkeyL(0);
io[3] ^= CamelliaSubkeyR(0);
t0 = io[0];
t1 = io[1];
io[0] = io[2];
io[1] = io[3];
io[2] = t0;
io[3] = t1;
blocks[0] = io[0];
blocks[1] = io[1];
blocks[2] = io[2];
blocks[3] = io[3];
return;
}
#endif /*!USE_ARM_ASM*/
/***
*
* API for compatibility
*/
void Camellia_Ekeygen(const int keyBitLength,
const unsigned char *rawKey,
KEY_TABLE_TYPE keyTable)
{
switch(keyBitLength) {
case 128:
camellia_setup128(rawKey, keyTable);
break;
case 192:
camellia_setup192(rawKey, keyTable);
break;
case 256:
camellia_setup256(rawKey, keyTable);
break;
default:
break;
}
}
#ifndef USE_ARM_ASM
void Camellia_EncryptBlock(const int keyBitLength,
const unsigned char *plaintext,
const KEY_TABLE_TYPE keyTable,
unsigned char *ciphertext)
{
u32 tmp[4];
tmp[0] = GETU32(plaintext);
tmp[1] = GETU32(plaintext + 4);
tmp[2] = GETU32(plaintext + 8);
tmp[3] = GETU32(plaintext + 12);
switch (keyBitLength) {
case 128:
camellia_encrypt128(keyTable, tmp);
break;
case 192:
/* fall through */
case 256:
camellia_encrypt256(keyTable, tmp);
break;
default:
break;
}
PUTU32(ciphertext, tmp[0]);
PUTU32(ciphertext + 4, tmp[1]);
PUTU32(ciphertext + 8, tmp[2]);
PUTU32(ciphertext + 12, tmp[3]);
}
void Camellia_DecryptBlock(const int keyBitLength,
const unsigned char *ciphertext,
const KEY_TABLE_TYPE keyTable,
unsigned char *plaintext)
{
u32 tmp[4];
tmp[0] = GETU32(ciphertext);
tmp[1] = GETU32(ciphertext + 4);
tmp[2] = GETU32(ciphertext + 8);
tmp[3] = GETU32(ciphertext + 12);
switch (keyBitLength) {
case 128:
camellia_decrypt128(keyTable, tmp);
break;
case 192:
/* fall through */
case 256:
camellia_decrypt256(keyTable, tmp);
break;
default:
break;
}
PUTU32(plaintext, tmp[0]);
PUTU32(plaintext + 4, tmp[1]);
PUTU32(plaintext + 8, tmp[2]);
PUTU32(plaintext + 12, tmp[3]);
}
#endif /*!USE_ARM_ASM*/
diff --git a/cipher/cast5-amd64.S b/cipher/cast5-amd64.S
index 82f67890..e8c4b7a9 100644
--- a/cipher/cast5-amd64.S
+++ b/cipher/cast5-amd64.S
@@ -1,663 +1,663 @@
/* cast5-amd64.S - AMD64 assembly implementation of CAST5 cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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(USE_CAST5)
#include "asm-common-amd64.h"
.text
.extern _gcry_cast5_s1to4;
#define s1 0
#define s2 (s1 + (4 * 256))
#define s3 (s2 + (4 * 256))
#define s4 (s3 + (4 * 256))
/* structure of CAST5_context: */
#define Km 0
#define Kr (Km + (16 * 4))
/* register macros */
#define CTX %rdi
#define RIO %rsi
#define RTAB %r8
#define RLR0 %r9
#define RLR1 %r10
#define RLR2 %r11
#define RLR3 %r12
#define RLR0d %r9d
#define RLR1d %r10d
#define RLR2d %r11d
#define RLR3d %r12d
#define RX0 %rax
#define RX1 %rbx
#define RX2 %rdx
#define RX0d %eax
#define RX1d %ebx
#define RX2d %edx
#define RX0bl %al
#define RX1bl %bl
#define RX2bl %dl
#define RX0bh %ah
#define RX1bh %bh
#define RX2bh %dh
#define RKR %rcx
#define RKRd %ecx
#define RKRbl %cl
#define RT0 %rbp
#define RT1 %rsi
#define RT0d %ebp
#define RT1d %esi
#define RKM0d %r13d
#define RKM1d %r14d
/***********************************************************************
* 1-way cast5
***********************************************************************/
#define dummy(x)
#define shr_kr(none) \
shrq $8, RKR;
#define F(km, load_next_kr, op0, op1, op2, op3) \
op0 ## l RLR0d, km ## d; \
roll RKRbl, km ## d; \
rorq $32, RLR0; \
movzbl km ## bh, RT0d; \
movzbl km ## bl, RT1d; \
roll $16, km ## d; \
movl s1(RTAB,RT0,4), RT0d; \
op1 ## l s2(RTAB,RT1,4), RT0d; \
load_next_kr(kr_next); \
movzbl km ## bh, RT1d; \
movzbl km ## bl, km ## d; \
op2 ## l s3(RTAB,RT1,4), RT0d; \
op3 ## l s4(RTAB,km,4), RT0d; \
xorq RT0, RLR0;
#define F1(km, load_next_kr) \
F(##km, load_next_kr, add, xor, sub, add)
#define F2(km, load_next_kr) \
F(##km, load_next_kr, xor, sub, add, xor)
#define F3(km, load_next_kr) \
F(##km, load_next_kr, sub, add, xor, sub)
#define get_round_km(n, km) \
movl Km+4*(n)(CTX), km;
#define get_round_kr_enc(n) \
movq $0x1010101010101010, RKR; \
\
/* merge rorl rk and rorl $16 */ \
xorq Kr+(n)(CTX), RKR;
#define get_round_kr_dec(n) \
movq $0x1010101010101010, RKR; \
\
/* merge rorl rk and rorl $16 */ \
xorq Kr+(n - 7)(CTX), RKR; \
bswapq RKR;
#define round_enc(n, FA, FB, fn1, fn2) \
get_round_km(n + 1, RX2d); \
FA(RX0, fn1); \
get_round_km(n + 2, RX0d); \
FB(RX2, fn2);
#define round_enc_last(n, FXA, FXB) \
get_round_km(n + 1, RX2d); \
\
FXA(RX0, shr_kr); \
FXB(RX2, dummy);
#define round_enc_1(n, FA, FB) \
round_enc(n, FA, FB, shr_kr, shr_kr)
#define round_enc_2(n, FA, FB) \
round_enc(n, FA, FB, shr_kr, dummy)
#define round_dec(n, FA, FB, fn1, fn2) \
get_round_km(n - 1, RX2d); \
FA(RX0, fn1); \
get_round_km(n - 2, RX0d); \
FB(RX2, fn2);
#define round_dec_last(n, FXA, FXB) \
get_round_km(n - 1, RX2d); \
FXA(RX0, shr_kr); \
FXB(RX2, dummy);
#define round_dec_1(n, FA, FB) \
round_dec(n, FA, FB, shr_kr, shr_kr)
#define round_dec_2(n, FA, FB) \
round_dec(n, FA, FB, shr_kr, dummy)
#define read_block() \
movq (RIO), RLR0; \
bswapq RLR0;
#define write_block() \
bswapq RLR0; \
rorq $32, RLR0; \
movq RLR0, (RIO);
.align 8
.globl _gcry_cast5_amd64_encrypt_block
ELF(.type _gcry_cast5_amd64_encrypt_block,@function;)
_gcry_cast5_amd64_encrypt_block:
/* input:
* %rdi: ctx, CTX
* %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;
GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
movq %rdx, RIO;
read_block();
get_round_km(0, RX0d);
get_round_kr_enc(0);
round_enc_1(0, F1, F2);
round_enc_1(2, F3, F1);
round_enc_1(4, F2, F3);
round_enc_2(6, F1, F2);
get_round_kr_enc(8);
round_enc_1(8, F3, F1);
round_enc_1(10, F2, F3);
round_enc_1(12, F1, F2);
round_enc_last(14, F3, F1);
movq %r10, RIO;
write_block();
popq %rbx;
CFI_POP(%rbx);
popq %rbp;
CFI_POP(%rbp);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_cast5_amd64_encrypt_block,.-_gcry_cast5_amd64_encrypt_block;)
.align 8
.globl _gcry_cast5_amd64_decrypt_block
ELF(.type _gcry_cast5_amd64_decrypt_block,@function;)
_gcry_cast5_amd64_decrypt_block:
/* input:
* %rdi: ctx, CTX
* %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;
GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
movq %rdx, RIO;
read_block();
get_round_km(15, RX0d);
get_round_kr_dec(15);
round_dec_1(15, F1, F3);
round_dec_1(13, F2, F1);
round_dec_1(11, F3, F2);
round_dec_2(9, F1, F3);
get_round_kr_dec(7);
round_dec_1(7, F2, F1);
round_dec_1(5, F3, F2);
round_dec_1(3, F1, F3);
round_dec_last(1, F2, F1);
movq %r10, RIO;
write_block();
popq %rbx;
CFI_POP(%rbx);
popq %rbp;
CFI_POP(%rbp);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_cast5_amd64_decrypt_block,.-_gcry_cast5_amd64_decrypt_block;)
/**********************************************************************
4-way cast5, four blocks parallel
**********************************************************************/
#define F_tail(rlr, rx, op1, op2, op3) \
movzbl rx ## bh, RT0d; \
movzbl rx ## bl, RT1d; \
roll $16, rx ## d; \
movl s1(RTAB,RT0,4), RT0d; \
op1 ## l s2(RTAB,RT1,4), RT0d; \
movzbl rx ## bh, RT1d; \
movzbl rx ## bl, rx ## d; \
op2 ## l s3(RTAB,RT1,4), RT0d; \
op3 ## l s4(RTAB,rx,4), RT0d; \
xorq RT0, rlr;
#define F4(km, load_next_kr, op0, op1, op2, op3) \
movl km, RX0d; \
op0 ## l RLR0d, RX0d; \
roll RKRbl, RX0d; \
rorq $32, RLR0; \
\
movl km, RX1d; \
op0 ## l RLR1d, RX1d; \
roll RKRbl, RX1d; \
rorq $32, RLR1; \
\
movl km, RX2d; \
op0 ## l RLR2d, RX2d; \
roll RKRbl, RX2d; \
rorq $32, RLR2; \
\
F_tail(RLR0, RX0, op1, op2, op3); \
F_tail(RLR1, RX1, op1, op2, op3); \
F_tail(RLR2, RX2, op1, op2, op3); \
\
movl km, RX0d; \
op0 ## l RLR3d, RX0d; \
roll RKRbl, RX0d; \
load_next_kr(); \
rorq $32, RLR3; \
\
F_tail(RLR3, RX0, op1, op2, op3);
#define F4_1(km, load_next_kr) \
F4(km, load_next_kr, add, xor, sub, add)
#define F4_2(km, load_next_kr) \
F4(km, load_next_kr, xor, sub, add, xor)
#define F4_3(km, load_next_kr) \
F4(km, load_next_kr, sub, add, xor, sub)
#define round_enc4(n, FA, FB, fn1, fn2) \
get_round_km(n + 1, RKM1d); \
FA(RKM0d, fn1); \
get_round_km(n + 2, RKM0d); \
FB(RKM1d, fn2);
#define round_enc_last4(n, FXA, FXB) \
get_round_km(n + 1, RKM1d); \
FXA(RKM0d, shr_kr); \
FXB(RKM1d, dummy);
#define round_enc4_1(n, FA, FB) \
round_enc4(n, FA, FB, shr_kr, shr_kr);
#define round_enc4_2(n, FA, FB) \
round_enc4(n, FA, FB, shr_kr, dummy);
#define round_dec4(n, FA, FB, fn1, fn2) \
get_round_km(n - 1, RKM1d); \
FA(RKM0d, fn1); \
get_round_km(n - 2, RKM0d); \
FB(RKM1d, fn2);
#define round_dec_last4(n, FXA, FXB) \
get_round_km(n - 1, RKM1d); \
FXA(RKM0d, shr_kr); \
FXB(RKM1d, dummy);
#define round_dec4_1(n, FA, FB) \
round_dec4(n, FA, FB, shr_kr, shr_kr);
#define round_dec4_2(n, FA, FB) \
round_dec4(n, FA, FB, shr_kr, dummy);
#define inbswap_block4(a, b, c, d) \
bswapq a; \
bswapq b; \
bswapq c; \
bswapq d;
#define outbswap_block4(a, b, c, d) \
bswapq a; \
bswapq b; \
bswapq c; \
bswapq d; \
rorq $32, a; \
rorq $32, b; \
rorq $32, c; \
rorq $32, d;
.align 8
ELF(.type __cast5_enc_blk4,@function;)
__cast5_enc_blk4:
/* input:
* %rdi: ctx, CTX
* RLR0,RLR1,RLR2,RLR3: four input plaintext blocks
* output:
* RLR0,RLR1,RLR2,RLR3: four output ciphertext blocks
*/
CFI_STARTPROC();
GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
get_round_km(0, RKM0d);
get_round_kr_enc(0);
round_enc4_1(0, F4_1, F4_2);
round_enc4_1(2, F4_3, F4_1);
round_enc4_1(4, F4_2, F4_3);
round_enc4_2(6, F4_1, F4_2);
get_round_kr_enc(8);
round_enc4_1(8, F4_3, F4_1);
round_enc4_1(10, F4_2, F4_3);
round_enc4_1(12, F4_1, F4_2);
round_enc_last4(14, F4_3, F4_1);
outbswap_block4(RLR0, RLR1, RLR2, RLR3);
ret;
CFI_ENDPROC();
ELF(.size __cast5_enc_blk4,.-__cast5_enc_blk4;)
.align 8
ELF(.type __cast5_dec_blk4,@function;)
__cast5_dec_blk4:
/* input:
* %rdi: ctx, CTX
* RLR0,RLR1,RLR2,RLR3: four input ciphertext blocks
* output:
* RLR0,RLR1,RLR2,RLR3: four output plaintext blocks
*/
CFI_STARTPROC();
GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
inbswap_block4(RLR0, RLR1, RLR2, RLR3);
get_round_km(15, RKM0d);
get_round_kr_dec(15);
round_dec4_1(15, F4_1, F4_3);
round_dec4_1(13, F4_2, F4_1);
round_dec4_1(11, F4_3, F4_2);
round_dec4_2(9, F4_1, F4_3);
get_round_kr_dec(7);
round_dec4_1(7, F4_2, F4_1);
round_dec4_1(5, F4_3, F4_2);
round_dec4_1(3, F4_1, F4_3);
round_dec_last4(1, F4_2, F4_1);
outbswap_block4(RLR0, RLR1, RLR2, RLR3);
CFI_ENDPROC();
ret;
ELF(.size __cast5_dec_blk4,.-__cast5_dec_blk4;)
.align 8
.globl _gcry_cast5_amd64_ctr_enc
ELF(.type _gcry_cast5_amd64_ctr_enc,@function;)
_gcry_cast5_amd64_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %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;
bswapq RX0;
movq RX0, RLR0;
/* construct IVs */
leaq 1(RX0), RLR1;
leaq 2(RX0), RLR2;
leaq 3(RX0), RLR3;
leaq 4(RX0), RX0;
bswapq RX0;
/* store new IV */
movq RX0, (%rcx);
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;
xorq 1 * 8(%r14), RLR1;
xorq 2 * 8(%r14), RLR2;
xorq 3 * 8(%r14), RLR3;
movq RLR0, 0 * 8(%r13);
movq RLR1, 1 * 8(%r13);
movq RLR2, 2 * 8(%r13);
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;
CFI_POP(%rbp);
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _gcry_cast5_amd64_ctr_enc,.-_gcry_cast5_amd64_ctr_enc;)
.align 8
.globl _gcry_cast5_amd64_cbc_dec
ELF(.type _gcry_cast5_amd64_cbc_dec,@function;)
_gcry_cast5_amd64_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %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;
movq 1 * 8(%rdx), RLR1;
movq 2 * 8(%rdx), RLR2;
movq 3 * 8(%rdx), RLR3;
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;
xorq 0 * 8(RX0), RLR1;
xorq 1 * 8(RX0), RLR2;
xorq 2 * 8(RX0), RLR3;
movq %r14, (RX2); /* store new IV */
movq RLR0, 0 * 8(RX1);
movq RLR1, 1 * 8(RX1);
movq RLR2, 2 * 8(RX1);
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;
CFI_POP(%rbp);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_cast5_amd64_cbc_dec,.-_gcry_cast5_amd64_cbc_dec;)
.align 8
.globl _gcry_cast5_amd64_cfb_dec
ELF(.type _gcry_cast5_amd64_cfb_dec,@function;)
_gcry_cast5_amd64_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %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;
movq 0 * 8(%rdx), RLR1;
movq 1 * 8(%rdx), RLR2;
movq 2 * 8(%rdx), RLR3;
inbswap_block4(RLR0, RLR1, RLR2, RLR3);
/* Update IV */
movq 3 * 8(%rdx), %rdx;
movq %rdx, (%rcx);
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;
xorq 2 * 8(%rdx), RLR2;
xorq 3 * 8(%rdx), RLR3;
movq RLR0, 0 * 8(%rcx);
movq RLR1, 1 * 8(%rcx);
movq RLR2, 2 * 8(%rcx);
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;
CFI_POP(%rbp);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_cast5_amd64_cfb_dec,.-_gcry_cast5_amd64_cfb_dec;)
#endif /*defined(USE_CAST5)*/
#endif /*__x86_64*/
diff --git a/cipher/cast5-arm.S b/cipher/cast5-arm.S
index 76ddd2e3..e0e3a332 100644
--- a/cipher/cast5-arm.S
+++ b/cipher/cast5-arm.S
@@ -1,728 +1,728 @@
/* cast5-arm.S - ARM assembly implementation of CAST5 cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.arm
.extern _gcry_cast5_s1to4;
#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
/* structure of crypto context */
#define Km 0
#define Kr (Km + (16 * 4))
#define Kr_arm_enc (Kr + (16))
#define Kr_arm_dec (Kr_arm_enc + (16))
/* register macros */
#define CTX %r0
#define Rs1 %r7
#define Rs2 %r8
#define Rs3 %r9
#define Rs4 %r10
#define RMASK %r11
#define RKM %r1
#define RKR %r2
#define RL0 %r3
#define RR0 %r4
#define RL1 %r9
#define RR1 %r10
#define RT0 %lr
#define RT1 %ip
#define RT2 %r5
#define RT3 %r6
/* helper macros */
#define ldr_unaligned_le(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 0)]; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 3)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_le(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 0)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 1)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 2)]; \
strb rtmp0, [rdst, #((offs) + 3)];
#define ldr_unaligned_be(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 3)]; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 0)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_be(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 3)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 2)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 1)]; \
strb rtmp0, [rdst, #((offs) + 0)];
#ifdef __ARMEL__
#define ldr_unaligned_host ldr_unaligned_le
#define str_unaligned_host str_unaligned_le
/* bswap on little-endian */
#ifdef HAVE_ARM_ARCH_V6
#define host_to_be(reg, rtmp) \
rev reg, reg;
#define be_to_host(reg, rtmp) \
rev reg, reg;
#else
#define host_to_be(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#define be_to_host(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#endif
#else
#define ldr_unaligned_host ldr_unaligned_be
#define str_unaligned_host str_unaligned_be
/* nop on big-endian */
#define host_to_be(reg, rtmp) /*_*/
#define be_to_host(reg, rtmp) /*_*/
#endif
#define host_to_host(x, y) /*_*/
/**********************************************************************
1-way cast5
**********************************************************************/
#define dummy(n) /*_*/
#define load_kr(n) \
ldr RKR, [CTX, #(Kr_arm_enc + (n))]; /* Kr[n] */
#define load_dec_kr(n) \
ldr RKR, [CTX, #(Kr_arm_dec + (n) - 3)]; /* Kr[n] */
#define load_km(n) \
ldr RKM, [CTX, #(Km + (n) * 4)]; /* Km[n] */
#define shift_kr(dummy) \
mov RKR, RKR, lsr #8;
#define F(n, rl, rr, op1, op2, op3, op4, dec, loadkm, shiftkr, loadkr) \
op1 RKM, rr; \
mov RKM, RKM, ror RKR; \
\
and RT0, RMASK, RKM, ror #(24); \
and RT1, RMASK, RKM, lsr #(16); \
and RT2, RMASK, RKM, lsr #(8); \
ldr RT0, [Rs1, RT0]; \
and RT3, RMASK, RKM; \
ldr RT1, [Rs2, RT1]; \
shiftkr(RKR); \
\
ldr RT2, [Rs3, RT2]; \
\
op2 RT0, RT1; \
ldr RT3, [Rs4, RT3]; \
op3 RT0, RT2; \
loadkm((n) + (1 - ((dec) * 2))); \
op4 RT0, RT3; \
loadkr((n) + (1 - ((dec) * 2))); \
eor rl, RT0;
#define F1(n, rl, rr, dec, loadkm, shiftkr, loadkr) \
F(n, rl, rr, add, eor, sub, add, dec, loadkm, shiftkr, loadkr)
#define F2(n, rl, rr, dec, loadkm, shiftkr, loadkr) \
F(n, rl, rr, eor, sub, add, eor, dec, loadkm, shiftkr, loadkr)
#define F3(n, rl, rr, dec, loadkm, shiftkr, loadkr) \
F(n, rl, rr, sub, add, eor, sub, dec, loadkm, shiftkr, loadkr)
#define enc_round(n, Fx, rl, rr, loadkm, shiftkr, loadkr) \
Fx(n, rl, rr, 0, loadkm, shiftkr, loadkr)
#define dec_round(n, Fx, rl, rr, loadkm, shiftkr, loadkr) \
Fx(n, rl, rr, 1, loadkm, shiftkr, loadkr)
#define read_block_aligned(rin, offs, l0, r0, convert, rtmp) \
ldr l0, [rin, #((offs) + 0)]; \
ldr r0, [rin, #((offs) + 4)]; \
convert(l0, rtmp); \
convert(r0, rtmp);
#define write_block_aligned(rout, offs, l0, r0, convert, rtmp) \
convert(l0, rtmp); \
convert(r0, rtmp); \
str l0, [rout, #((offs) + 0)]; \
str r0, [rout, #((offs) + 4)];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads allowed */
#define read_block(rin, offs, l0, r0, rtmp0) \
read_block_aligned(rin, offs, l0, r0, host_to_be, rtmp0)
#define write_block(rout, offs, r0, l0, rtmp0, rtmp1) \
write_block_aligned(rout, offs, r0, l0, be_to_host, rtmp0)
#define read_block_host(rin, offs, l0, r0, rtmp0) \
read_block_aligned(rin, offs, l0, r0, host_to_host, rtmp0)
#define write_block_host(rout, offs, r0, l0, rtmp0, rtmp1) \
write_block_aligned(rout, offs, r0, l0, host_to_host, rtmp0)
#else
/* need to handle unaligned reads by byte reads */
#define read_block(rin, offs, l0, r0, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_be(l0, rin, (offs) + 0, rtmp0); \
ldr_unaligned_be(r0, rin, (offs) + 4, rtmp0); \
b 2f; \
1:;\
read_block_aligned(rin, offs, l0, r0, host_to_be, rtmp0); \
2:;
#define write_block(rout, offs, l0, r0, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_be(l0, rout, (offs) + 0, rtmp0, rtmp1); \
str_unaligned_be(r0, rout, (offs) + 4, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block_aligned(rout, offs, l0, r0, be_to_host, rtmp0); \
2:;
#define read_block_host(rin, offs, l0, r0, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_host(l0, rin, (offs) + 0, rtmp0); \
ldr_unaligned_host(r0, rin, (offs) + 4, rtmp0); \
b 2f; \
1:;\
read_block_aligned(rin, offs, l0, r0, host_to_host, rtmp0); \
2:;
#define write_block_host(rout, offs, l0, r0, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_host(l0, rout, (offs) + 0, rtmp0, rtmp1); \
str_unaligned_host(r0, rout, (offs) + 4, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block_aligned(rout, offs, l0, r0, host_to_host, rtmp0); \
2:;
#endif
.align 3
.globl _gcry_cast5_arm_encrypt_block
.type _gcry_cast5_arm_encrypt_block,%function;
_gcry_cast5_arm_encrypt_block:
/* input:
* %r0: CTX
* %r1: dst
* %r2: src
*/
push {%r1, %r4-%r11, %ip, %lr};
GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2);
mov RMASK, #(0xff << 2);
add Rs2, Rs1, #(0x100*4);
add Rs3, Rs1, #(0x100*4*2);
add Rs4, Rs1, #(0x100*4*3);
read_block(%r2, 0, RL0, RR0, RT0);
load_km(0);
load_kr(0);
enc_round(0, F1, RL0, RR0, load_km, shift_kr, dummy);
enc_round(1, F2, RR0, RL0, load_km, shift_kr, dummy);
enc_round(2, F3, RL0, RR0, load_km, shift_kr, dummy);
enc_round(3, F1, RR0, RL0, load_km, dummy, load_kr);
enc_round(4, F2, RL0, RR0, load_km, shift_kr, dummy);
enc_round(5, F3, RR0, RL0, load_km, shift_kr, dummy);
enc_round(6, F1, RL0, RR0, load_km, shift_kr, dummy);
enc_round(7, F2, RR0, RL0, load_km, dummy, load_kr);
enc_round(8, F3, RL0, RR0, load_km, shift_kr, dummy);
enc_round(9, F1, RR0, RL0, load_km, shift_kr, dummy);
enc_round(10, F2, RL0, RR0, load_km, shift_kr, dummy);
enc_round(11, F3, RR0, RL0, load_km, dummy, load_kr);
enc_round(12, F1, RL0, RR0, load_km, shift_kr, dummy);
enc_round(13, F2, RR0, RL0, load_km, shift_kr, dummy);
enc_round(14, F3, RL0, RR0, load_km, shift_kr, dummy);
enc_round(15, F1, RR0, RL0, dummy, dummy, dummy);
ldr %r1, [%sp], #4;
write_block(%r1, 0, RR0, RL0, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_cast5_arm_encrypt_block,.-_gcry_cast5_arm_encrypt_block;
.align 3
.globl _gcry_cast5_arm_decrypt_block
.type _gcry_cast5_arm_decrypt_block,%function;
_gcry_cast5_arm_decrypt_block:
/* input:
* %r0: CTX
* %r1: dst
* %r2: src
*/
push {%r1, %r4-%r11, %ip, %lr};
GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2);
mov RMASK, #(0xff << 2);
add Rs2, Rs1, #(0x100 * 4);
add Rs3, Rs1, #(0x100 * 4 * 2);
add Rs4, Rs1, #(0x100 * 4 * 3);
read_block(%r2, 0, RL0, RR0, RT0);
load_km(15);
load_dec_kr(15);
dec_round(15, F1, RL0, RR0, load_km, shift_kr, dummy);
dec_round(14, F3, RR0, RL0, load_km, shift_kr, dummy);
dec_round(13, F2, RL0, RR0, load_km, shift_kr, dummy);
dec_round(12, F1, RR0, RL0, load_km, dummy, load_dec_kr);
dec_round(11, F3, RL0, RR0, load_km, shift_kr, dummy);
dec_round(10, F2, RR0, RL0, load_km, shift_kr, dummy);
dec_round(9, F1, RL0, RR0, load_km, shift_kr, dummy);
dec_round(8, F3, RR0, RL0, load_km, dummy, load_dec_kr);
dec_round(7, F2, RL0, RR0, load_km, shift_kr, dummy);
dec_round(6, F1, RR0, RL0, load_km, shift_kr, dummy);
dec_round(5, F3, RL0, RR0, load_km, shift_kr, dummy);
dec_round(4, F2, RR0, RL0, load_km, dummy, load_dec_kr);
dec_round(3, F1, RL0, RR0, load_km, shift_kr, dummy);
dec_round(2, F3, RR0, RL0, load_km, shift_kr, dummy);
dec_round(1, F2, RL0, RR0, load_km, shift_kr, dummy);
dec_round(0, F1, RR0, RL0, dummy, dummy, dummy);
ldr %r1, [%sp], #4;
write_block(%r1, 0, RR0, RL0, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_cast5_arm_decrypt_block,.-_gcry_cast5_arm_decrypt_block;
/**********************************************************************
2-way cast5
**********************************************************************/
#define F_2w(n, rl0, rr0, rl1, rr1, op1, op2, op3, op4, dec, loadkm, shiftkr, \
loadkr) \
op1 RT3, RKM, rr0; \
op1 RKM, RKM, rr1; \
mov RT3, RT3, ror RKR; \
mov RKM, RKM, ror RKR; \
\
and RT0, RMASK, RT3, ror #(24); \
and RT1, RMASK, RT3, lsr #(16); \
and RT2, RMASK, RT3, lsr #(8); \
and RT3, RMASK, RT3; \
\
ldr RT0, [Rs1, RT0]; \
add RT2, #(0x100 * 4); \
ldr RT1, [Rs2, RT1]; \
add RT3, #(0x100 * 4 * 2); \
\
ldr RT2, [Rs2, RT2]; \
\
op2 RT0, RT1; \
ldr RT3, [Rs2, RT3]; \
and RT1, RMASK, RKM, ror #(24); \
op3 RT0, RT2; \
and RT2, RMASK, RKM, lsr #(16); \
op4 RT0, RT3; \
and RT3, RMASK, RKM, lsr #(8); \
eor rl0, RT0; \
add RT3, #(0x100 * 4); \
ldr RT1, [Rs1, RT1]; \
and RT0, RMASK, RKM; \
ldr RT2, [Rs2, RT2]; \
add RT0, #(0x100 * 4 * 2); \
\
ldr RT3, [Rs2, RT3]; \
\
op2 RT1, RT2; \
ldr RT0, [Rs2, RT0]; \
op3 RT1, RT3; \
loadkm((n) + (1 - ((dec) * 2))); \
op4 RT1, RT0; \
loadkr((n) + (1 - ((dec) * 2))); \
shiftkr(RKR); \
eor rl1, RT1;
#define F1_2w(n, rl0, rr0, rl1, rr1, dec, loadkm, shiftkr, loadkr) \
F_2w(n, rl0, rr0, rl1, rr1, add, eor, sub, add, dec, \
loadkm, shiftkr, loadkr)
#define F2_2w(n, rl0, rr0, rl1, rr1, dec, loadkm, shiftkr, loadkr) \
F_2w(n, rl0, rr0, rl1, rr1, eor, sub, add, eor, dec, \
loadkm, shiftkr, loadkr)
#define F3_2w(n, rl0, rr0, rl1, rr1, dec, loadkm, shiftkr, loadkr) \
F_2w(n, rl0, rr0, rl1, rr1, sub, add, eor, sub, dec, \
loadkm, shiftkr, loadkr)
#define enc_round2(n, Fx, rl, rr, loadkm, shiftkr, loadkr) \
Fx##_2w(n, rl##0, rr##0, rl##1, rr##1, 0, loadkm, shiftkr, loadkr)
#define dec_round2(n, Fx, rl, rr, loadkm, shiftkr, loadkr) \
Fx##_2w(n, rl##0, rr##0, rl##1, rr##1, 1, loadkm, shiftkr, loadkr)
#define read_block2_aligned(rin, l0, r0, l1, r1, convert, rtmp) \
ldr l0, [rin, #(0)]; \
ldr r0, [rin, #(4)]; \
convert(l0, rtmp); \
ldr l1, [rin, #(8)]; \
convert(r0, rtmp); \
ldr r1, [rin, #(12)]; \
convert(l1, rtmp); \
convert(r1, rtmp);
#define write_block2_aligned(rout, l0, r0, l1, r1, convert, rtmp) \
convert(l0, rtmp); \
convert(r0, rtmp); \
convert(l1, rtmp); \
str l0, [rout, #(0)]; \
convert(r1, rtmp); \
str r0, [rout, #(4)]; \
str l1, [rout, #(8)]; \
str r1, [rout, #(12)];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads allowed */
#define read_block2(rin, l0, r0, l1, r1, rtmp0) \
read_block2_aligned(rin, l0, r0, l1, r1, host_to_be, rtmp0)
#define write_block2(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
write_block2_aligned(rout, l0, r0, l1, r1, be_to_host, rtmp0)
#define read_block2_host(rin, l0, r0, l1, r1, rtmp0) \
read_block2_aligned(rin, l0, r0, l1, r1, host_to_host, rtmp0)
#define write_block2_host(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
write_block2_aligned(rout, l0, r0, l1, r1, host_to_host, rtmp0)
#else
/* need to handle unaligned reads by byte reads */
#define read_block2(rin, l0, r0, l1, r1, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_be(l0, rin, 0, rtmp0); \
ldr_unaligned_be(r0, rin, 4, rtmp0); \
ldr_unaligned_be(l1, rin, 8, rtmp0); \
ldr_unaligned_be(r1, rin, 12, rtmp0); \
b 2f; \
1:;\
read_block2_aligned(rin, l0, r0, l1, r1, host_to_be, rtmp0); \
2:;
#define write_block2(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_be(l0, rout, 0, rtmp0, rtmp1); \
str_unaligned_be(r0, rout, 4, rtmp0, rtmp1); \
str_unaligned_be(l1, rout, 8, rtmp0, rtmp1); \
str_unaligned_be(r1, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block2_aligned(rout, l0, r0, l1, r1, be_to_host, rtmp0); \
2:;
#define read_block2_host(rin, l0, r0, l1, r1, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_host(l0, rin, 0, rtmp0); \
ldr_unaligned_host(r0, rin, 4, rtmp0); \
ldr_unaligned_host(l1, rin, 8, rtmp0); \
ldr_unaligned_host(r1, rin, 12, rtmp0); \
b 2f; \
1:;\
read_block2_aligned(rin, l0, r0, l1, r1, host_to_host, rtmp0); \
2:;
#define write_block2_host(rout, l0, r0, l1, r1, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_host(l0, rout, 0, rtmp0, rtmp1); \
str_unaligned_host(r0, rout, 4, rtmp0, rtmp1); \
str_unaligned_host(l1, rout, 8, rtmp0, rtmp1); \
str_unaligned_host(r1, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
write_block2_aligned(rout, l0, r0, l1, r1, host_to_host, rtmp0); \
2:;
#endif
.align 3
.type _gcry_cast5_arm_enc_blk2,%function;
_gcry_cast5_arm_enc_blk2:
/* input:
* preloaded: CTX
* [RL0, RR0], [RL1, RR1]: src
* output:
* [RR0, RL0], [RR1, RL1]: dst
*/
push {%lr};
GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2);
mov RMASK, #(0xff << 2);
add Rs2, Rs1, #(0x100 * 4);
load_km(0);
load_kr(0);
enc_round2(0, F1, RL, RR, load_km, shift_kr, dummy);
enc_round2(1, F2, RR, RL, load_km, shift_kr, dummy);
enc_round2(2, F3, RL, RR, load_km, shift_kr, dummy);
enc_round2(3, F1, RR, RL, load_km, dummy, load_kr);
enc_round2(4, F2, RL, RR, load_km, shift_kr, dummy);
enc_round2(5, F3, RR, RL, load_km, shift_kr, dummy);
enc_round2(6, F1, RL, RR, load_km, shift_kr, dummy);
enc_round2(7, F2, RR, RL, load_km, dummy, load_kr);
enc_round2(8, F3, RL, RR, load_km, shift_kr, dummy);
enc_round2(9, F1, RR, RL, load_km, shift_kr, dummy);
enc_round2(10, F2, RL, RR, load_km, shift_kr, dummy);
enc_round2(11, F3, RR, RL, load_km, dummy, load_kr);
enc_round2(12, F1, RL, RR, load_km, shift_kr, dummy);
enc_round2(13, F2, RR, RL, load_km, shift_kr, dummy);
enc_round2(14, F3, RL, RR, load_km, shift_kr, dummy);
enc_round2(15, F1, RR, RL, dummy, dummy, dummy);
host_to_be(RR0, RT0);
host_to_be(RL0, RT0);
host_to_be(RR1, RT0);
host_to_be(RL1, RT0);
pop {%pc};
.ltorg
.size _gcry_cast5_arm_enc_blk2,.-_gcry_cast5_arm_enc_blk2;
.align 3
.globl _gcry_cast5_arm_cfb_dec;
.type _gcry_cast5_arm_cfb_dec,%function;
_gcry_cast5_arm_cfb_dec:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit)
*/
push {%r1, %r2, %r4-%r11, %ip, %lr};
mov %lr, %r3;
/* Load input (iv/%r3 is aligned, src/%r2 might not be) */
ldm %r3, {RL0, RR0};
host_to_be(RL0, RT1);
host_to_be(RR0, RT1);
read_block(%r2, 0, RL1, RR1, %ip);
/* Update IV, load src[1] and save to iv[0] */
read_block_host(%r2, 8, %r5, %r6, %r7);
stm %lr, {%r5, %r6};
bl _gcry_cast5_arm_enc_blk2;
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r0: dst, %r1: %src */
pop {%r0, %r1};
/* dst = src ^ result */
read_block2_host(%r1, %r5, %r6, %r7, %r8, %lr);
eor %r5, %r4;
eor %r6, %r3;
eor %r7, %r10;
eor %r8, %r9;
write_block2_host(%r0, %r5, %r6, %r7, %r8, %r1, %r2);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_cast5_arm_cfb_dec,.-_gcry_cast5_arm_cfb_dec;
.align 3
.globl _gcry_cast5_arm_ctr_enc;
.type _gcry_cast5_arm_ctr_enc,%function;
_gcry_cast5_arm_ctr_enc:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit, big-endian)
*/
push {%r1, %r2, %r4-%r11, %ip, %lr};
mov %lr, %r3;
/* Load IV (big => host endian) */
read_block_aligned(%lr, 0, RL0, RR0, be_to_host, RT1);
/* Construct IVs */
adds RR1, RR0, #1; /* +1 */
adc RL1, RL0, #0;
adds %r6, RR1, #1; /* +2 */
adc %r5, RL1, #0;
/* Store new IV (host => big-endian) */
write_block_aligned(%lr, 0, %r5, %r6, host_to_be, RT1);
bl _gcry_cast5_arm_enc_blk2;
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r0: dst, %r1: %src */
pop {%r0, %r1};
/* XOR key-stream with plaintext */
read_block2_host(%r1, %r5, %r6, %r7, %r8, %lr);
eor %r5, %r4;
eor %r6, %r3;
eor %r7, %r10;
eor %r8, %r9;
write_block2_host(%r0, %r5, %r6, %r7, %r8, %r1, %r2);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_cast5_arm_ctr_enc,.-_gcry_cast5_arm_ctr_enc;
.align 3
.type _gcry_cast5_arm_dec_blk2,%function;
_gcry_cast5_arm_dec_blk2:
/* input:
* preloaded: CTX
* [RL0, RR0], [RL1, RR1]: src
* output:
* [RR0, RL0], [RR1, RL1]: dst
*/
GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2);
mov RMASK, #(0xff << 2);
add Rs2, Rs1, #(0x100 * 4);
load_km(15);
load_dec_kr(15);
dec_round2(15, F1, RL, RR, load_km, shift_kr, dummy);
dec_round2(14, F3, RR, RL, load_km, shift_kr, dummy);
dec_round2(13, F2, RL, RR, load_km, shift_kr, dummy);
dec_round2(12, F1, RR, RL, load_km, dummy, load_dec_kr);
dec_round2(11, F3, RL, RR, load_km, shift_kr, dummy);
dec_round2(10, F2, RR, RL, load_km, shift_kr, dummy);
dec_round2(9, F1, RL, RR, load_km, shift_kr, dummy);
dec_round2(8, F3, RR, RL, load_km, dummy, load_dec_kr);
dec_round2(7, F2, RL, RR, load_km, shift_kr, dummy);
dec_round2(6, F1, RR, RL, load_km, shift_kr, dummy);
dec_round2(5, F3, RL, RR, load_km, shift_kr, dummy);
dec_round2(4, F2, RR, RL, load_km, dummy, load_dec_kr);
dec_round2(3, F1, RL, RR, load_km, shift_kr, dummy);
dec_round2(2, F3, RR, RL, load_km, shift_kr, dummy);
dec_round2(1, F2, RL, RR, load_km, shift_kr, dummy);
dec_round2(0, F1, RR, RL, dummy, dummy, dummy);
host_to_be(RR0, RT0);
host_to_be(RL0, RT0);
host_to_be(RR1, RT0);
host_to_be(RL1, RT0);
b .Ldec_cbc_tail;
.ltorg
.size _gcry_cast5_arm_dec_blk2,.-_gcry_cast5_arm_dec_blk2;
.align 3
.globl _gcry_cast5_arm_cbc_dec;
.type _gcry_cast5_arm_cbc_dec,%function;
_gcry_cast5_arm_cbc_dec:
/* input:
* %r0: CTX
* %r1: dst (2 blocks)
* %r2: src (2 blocks)
* %r3: iv (64bit)
*/
push {%r1-%r11, %ip, %lr};
read_block2(%r2, RL0, RR0, RL1, RR1, RT0);
/* dec_blk2 is only used by cbc_dec, jump directly in/out instead
* of function call. */
b _gcry_cast5_arm_dec_blk2;
.Ldec_cbc_tail:
/* result in RR0:RL0, RR1:RL1 = %r4:%r3, %r10:%r9 */
/* %r0: dst, %r1: %src, %r2: iv */
pop {%r0-%r2};
/* load IV+1 (src[0]) to %r7:%r8. Might be unaligned. */
read_block_host(%r1, 0, %r7, %r8, %r5);
/* load IV (iv[0]) to %r5:%r6. 'iv' is aligned. */
ldm %r2, {%r5, %r6};
/* out[1] ^= IV+1 */
eor %r10, %r7;
eor %r9, %r8;
/* out[0] ^= IV */
eor %r4, %r5;
eor %r3, %r6;
/* load IV+2 (src[1]) to %r7:%r8. Might be unaligned. */
read_block_host(%r1, 8, %r7, %r8, %r5);
/* store IV+2 to iv[0] (aligned). */
stm %r2, {%r7, %r8};
/* store result to dst[0-3]. Might be unaligned. */
write_block2_host(%r0, %r4, %r3, %r10, %r9, %r5, %r6);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_cast5_arm_cbc_dec,.-_gcry_cast5_arm_cbc_dec;
#endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/
#endif /*__ARM_ARCH >= 6*/
diff --git a/cipher/chacha20-aarch64.S b/cipher/chacha20-aarch64.S
index 07b4bb5c..cde3519e 100644
--- a/cipher/chacha20-aarch64.S
+++ b/cipher/chacha20-aarch64.S
@@ -1,307 +1,307 @@
/* chacha20-aarch64.S - ARMv8/AArch64 accelerated chacha20 blocks function
*
* Copyright (C) 2017,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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Based on D. J. Bernstein reference implementation at
- * http://cr.yp.to/chacha.html:
+ * https://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
/* 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
/**********************************************************************
helper macros
**********************************************************************/
#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) \
eor x.16b, x.16b, x.16b;
/**********************************************************************
4-way chacha20
**********************************************************************/
#define ROTATE2(dst1,dst2,c,src1,src2) \
shl dst1.4s, src1.4s, #(c); \
shl dst2.4s, src2.4s, #(c); \
sri dst1.4s, src1.4s, #(32 - (c)); \
sri dst2.4s, src2.4s, #(32 - (c));
#define ROTATE2_16(dst1,dst2,src1,src2) \
rev32 dst1.8h, src1.8h; \
rev32 dst2.8h, src2.8h;
#define XOR(d,s1,s2) \
eor d.16b, s2.16b, s1.16b;
#define PLUS(ds,s) \
add ds.4s, ds.4s, s.4s;
#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_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, .Linc_counter);
add INPUT_CTR, INPUT, #(12*4);
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
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,VTMP0,VTMP1)
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,VTMP0,VTMP1)
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,VTMP0,VTMP1)
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,VTMP0,VTMP1)
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
CFI_ENDPROC()
ELF(.size _gcry_chacha20_aarch64_blocks4, .-_gcry_chacha20_aarch64_blocks4;)
#endif
diff --git a/cipher/chacha20-amd64-avx2.S b/cipher/chacha20-amd64-avx2.S
index de6263b6..cb655c48 100644
--- a/cipher/chacha20-amd64-avx2.S
+++ b/cipher/chacha20-amd64-avx2.S
@@ -1,783 +1,783 @@
/* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Based on D. J. Bernstein reference implementation at
- * http://cr.yp.to/chacha.html:
+ * https://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;
CFI_ENDPROC();
ELF(.size _gcry_chacha20_amd64_avx2_blocks8,
.-_gcry_chacha20_amd64_avx2_blocks8;)
/**********************************************************************
8-way stitched chacha20-poly1305
**********************************************************************/
.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 $(8 * 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);
# rounds 0,1
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART1(0 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(1 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(2 * 16),
POLY1305_BLOCK_PART2())
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(3 * 16))
# rounds 2,3
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);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART1(4 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(5 * 16),
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(),
POLY1305_BLOCK_PART1(6 * 16),
POLY1305_BLOCK_PART2())
# rounds 4,5
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(7 * 16))
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART1(8 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(9 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3())
# rounds 6,7
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(10 * 16),
POLY1305_BLOCK_PART2())
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(11 * 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);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART1(12 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
# rounds 8,9
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(13 * 16),
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(14 * 16),
POLY1305_BLOCK_PART2())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(15 * 16))
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
# rounds 10,11
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART1(16 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(17 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(18 * 16),
POLY1305_BLOCK_PART2())
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(19 * 16))
# rounds 12,13
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);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART1(20 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(21 * 16),
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(),
POLY1305_BLOCK_PART1(22 * 16),
POLY1305_BLOCK_PART2())
# rounds 14,15
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(23 * 16))
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART1(24 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(25 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3())
# rounds 16,17
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(26 * 16),
POLY1305_BLOCK_PART2())
vmovdqa (STACK_TMP)(%rsp), X15;
vmovdqa X8, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X6, X10, X14, X3, X7, X11, X15, tmp:=,X8,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(27 * 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);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART1(28 * 16),
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
# rounds 18,19
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(29 * 16),
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(30 * 16),
POLY1305_BLOCK_PART2())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(31 * 16))
vmovdqa (STACK_TMP)(%rsp), X8;
vmovdqa X15, (STACK_TMP)(%rsp);
QUARTERROUND2(X2, X7, X8, X13, X3, X4, X9, X14, tmp:=,X15,
POLY1305_BLOCK_PART2(),
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
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 (32 * 16)(POLY_RSRC), POLY_RSRC;
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;
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
index 6bbf12fc..2cd85e94 100644
--- a/cipher/chacha20-amd64-ssse3.S
+++ b/cipher/chacha20-amd64-ssse3.S
@@ -1,1255 +1,1255 @@
/* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Based on D. J. Bernstein reference implementation at
- * http://cr.yp.to/chacha.html:
+ * https://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;
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;
CFI_ENDPROC();
ELF(.size _gcry_chacha20_amd64_ssse3_blocks1,
.-_gcry_chacha20_amd64_ssse3_blocks1;)
/**********************************************************************
4-way stitched chacha20-poly1305
**********************************************************************/
.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 $(8 * 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);
/* rounds 0,1 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART1(0 * 16),
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(),
POLY1305_BLOCK_PART4())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(1 * 16))
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_PART2(),
POLY1305_BLOCK_PART3())
/* rounds 2,3 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
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_PART1(2 * 16),
POLY1305_BLOCK_PART2())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART3(),
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(),
POLY1305_BLOCK_PART1(3 * 16))
/* rounds 4,5 */
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())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART1(4 * 16),
POLY1305_BLOCK_PART2())
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_PART3(),
POLY1305_BLOCK_PART4())
/* rounds 6,7 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(5 * 16))
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_PART2(),
POLY1305_BLOCK_PART3())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
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_PART1(6 * 16),
POLY1305_BLOCK_PART2())
/* rounds 8,9 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
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_PART5(),
POLY1305_BLOCK_PART1(7 * 16))
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())
/* rounds 10,11 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART1(8 * 16),
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(),
POLY1305_BLOCK_PART4())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(9 * 16))
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_PART2(),
POLY1305_BLOCK_PART3())
/* rounds 12,13 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
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_PART1(10 * 16),
POLY1305_BLOCK_PART2())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART3(),
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(),
POLY1305_BLOCK_PART1(11 * 16))
/* rounds 14,15 */
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())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART1(12 * 16),
POLY1305_BLOCK_PART2())
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_PART3(),
POLY1305_BLOCK_PART4())
/* rounds 16,17 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART5(),
POLY1305_BLOCK_PART1(13 * 16))
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_PART2(),
POLY1305_BLOCK_PART3())
QUARTERROUND2(X0, X5, X10, X15, X1, X6, X11, X12, tmp:=,X8,X9,
POLY1305_BLOCK_PART4(),
POLY1305_BLOCK_PART5())
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_PART1(14 * 16),
POLY1305_BLOCK_PART2())
/* rounds 18,19 */
QUARTERROUND2(X0, X4, X8, X12, X1, X5, X9, X13, tmp:=,X11,X15,
POLY1305_BLOCK_PART3(),
POLY1305_BLOCK_PART4())
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_PART5(),
POLY1305_BLOCK_PART1(15 * 16))
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())
/* 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 (16 * 16)(POLY_RSRC), POLY_RSRC;
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;
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 $(8 * 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. */
POLY1305_BLOCK_PART1(0 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
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();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(1 * 16);
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(2 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART1(3 * 16);
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART1(4 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
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();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(5 * 16);
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(6 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART1(7 * 16);
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
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)(POLY_RSRC), POLY_RSRC;
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. */
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);
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();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(1 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART1(2 * 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);
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();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART1(3 * 16);
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART2();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART3();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
POLY1305_BLOCK_PART4();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
POLY1305_BLOCK_PART5();
QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
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)(POLY_RSRC), POLY_RSRC;
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;
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*/
diff --git a/cipher/chacha20-armv7-neon.S b/cipher/chacha20-armv7-neon.S
index 33a43df1..c35486dc 100644
--- a/cipher/chacha20-armv7-neon.S
+++ b/cipher/chacha20-armv7-neon.S
@@ -1,393 +1,393 @@
/* chacha20-armv7-neon.S - ARMv7 NEON implementation of ChaCha20 cipher
*
* Copyright (C) 2017,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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Based on D. J. Bernstein reference implementation at
- * http://cr.yp.to/chacha.html:
+ * https://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)
.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
/* 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) veor x,x,x;
/**********************************************************************
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
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
.size _gcry_chacha20_armv7_neon_blocks4, .-_gcry_chacha20_armv7_neon_blocks4;
#endif
diff --git a/cipher/chacha20.c b/cipher/chacha20.c
index 48fff625..13f1d215 100644
--- a/cipher/chacha20.c
+++ b/cipher/chacha20.c
@@ -1,979 +1,979 @@
/* chacha20.c - Bernstein's ChaCha20 cipher
* Copyright (C) 2014,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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* For a description of the algorithm, see:
- * http://cr.yp.to/chacha.html
+ * https://cr.yp.to/chacha.html
*/
/*
* Based on D. J. Bernstein reference implementation at
- * http://cr.yp.to/chacha.html:
+ * https://cr.yp.to/chacha.html:
*
* chacha-regs.c version 20080118
* D. J. Bernstein
* Public domain.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "cipher-internal.h"
#include "bufhelp.h"
#define CHACHA20_MIN_KEY_SIZE 16 /* Bytes. */
#define CHACHA20_MAX_KEY_SIZE 32 /* Bytes. */
#define CHACHA20_BLOCK_SIZE 64 /* Bytes. */
#define CHACHA20_MIN_IV_SIZE 8 /* Bytes. */
#define CHACHA20_MAX_IV_SIZE 12 /* Bytes. */
#define CHACHA20_CTR_SIZE 16 /* Bytes. */
/* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
#undef USE_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_GCC_INLINE_ASM_AVX2) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# define USE_AVX2 1
#endif
/* 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_ARMV7_NEON 1
# endif
#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
/* 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(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
# define ASM_FUNC_ABI __attribute__((sysv_abi))
#else
# define ASM_FUNC_ABI
#endif
typedef struct CHACHA20_context_s
{
u32 input[16];
unsigned char pad[CHACHA20_BLOCK_SIZE];
unsigned int unused; /* bytes in the pad. */
int use_ssse3:1;
int use_avx2:1;
int use_neon:1;
} CHACHA20_context_t;
#ifdef USE_SSSE3
unsigned int _gcry_chacha20_amd64_ssse3_blocks4(u32 *state, byte *dst,
const byte *src,
size_t nblks) ASM_FUNC_ABI;
unsigned int _gcry_chacha20_amd64_ssse3_blocks1(u32 *state, byte *dst,
const byte *src,
size_t nblks) ASM_FUNC_ABI;
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_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_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_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);
#endif /* USE_AARCH64_SIMD */
static const char *selftest (void);
#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 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 BUF_XOR_LE32(dst, src, offset, x) \
buf_put_le32((dst) + (offset), buf_get_le32((src) + (offset)) ^ (x))
static unsigned int
do_chacha20_blocks (u32 *input, byte *dst, const byte *src, size_t nblks)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
unsigned int i;
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;
nblks--;
}
/* burn_stack */
return (17 * sizeof(u32) + 6 * sizeof(void *));
}
static unsigned int
chacha20_blocks (CHACHA20_context_t *ctx, byte *dst, const byte *src,
size_t nblks)
{
#ifdef USE_SSSE3
if (ctx->use_ssse3)
{
return _gcry_chacha20_amd64_ssse3_blocks1(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,
unsigned int keylen)
{
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 */
{
key += 16;
constants = sigma;
}
else /* 128 bits */
{
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)
{
if (ivlen == CHACHA20_CTR_SIZE)
{
ctx->input[12] = buf_get_le32 (iv + 0);
ctx->input[13] = buf_get_le32 (iv + 4);
ctx->input[14] = buf_get_le32 (iv + 8);
ctx->input[15] = buf_get_le32 (iv + 12);
}
else if (ivlen == CHACHA20_MAX_IV_SIZE)
{
ctx->input[12] = 0;
ctx->input[13] = buf_get_le32 (iv + 0);
ctx->input[14] = buf_get_le32 (iv + 4);
ctx->input[15] = buf_get_le32 (iv + 8);
}
else if (ivlen == CHACHA20_MIN_IV_SIZE)
{
ctx->input[12] = 0;
ctx->input[13] = 0;
ctx->input[14] = buf_get_le32 (iv + 0);
ctx->input[15] = buf_get_le32 (iv + 4);
}
else
{
ctx->input[12] = 0;
ctx->input[13] = 0;
ctx->input[14] = 0;
ctx->input[15] = 0;
}
}
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)
{
static int initialized;
static const char *selftest_failed;
unsigned int features = _gcry_get_hw_features ();
if (!initialized)
{
initialized = 1;
selftest_failed = selftest ();
if (selftest_failed)
log_error ("CHACHA20 selftest failed (%s)\n", selftest_failed);
}
if (selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
if (keylen != CHACHA20_MAX_KEY_SIZE && keylen != CHACHA20_MIN_KEY_SIZE)
return GPG_ERR_INV_KEYLEN;
#ifdef USE_SSSE3
ctx->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
#endif
#ifdef USE_AVX2
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
(void)features;
chacha20_keysetup (ctx, key, keylen);
/* We default to a zero nonce. */
chacha20_setiv (ctx, NULL, 0);
return 0;
}
static gcry_err_code_t
chacha20_setkey (void *context, const byte *key, unsigned int keylen,
gcry_cipher_hd_t hd)
{
CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
gcry_err_code_t rc = chacha20_do_setkey (ctx, key, keylen);
(void)hd;
_gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
return rc;
}
static unsigned int
do_chacha20_encrypt_stream_tail (CHACHA20_context_t *ctx, byte *outbuf,
const byte *inbuf, size_t length)
{
static const unsigned char zero_pad[CHACHA20_BLOCK_SIZE] = { 0, };
unsigned int nburn, burn = 0;
#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
#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
#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
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;
}
static void
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 = 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);
length -= n;
outbuf += n;
inbuf += n;
ctx->unused -= n;
if (!length)
return;
gcry_assert (!ctx->unused);
}
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)
{
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);
}
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 = _gcry_chacha20_amd64_avx2_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;
}
#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
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
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;
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;
}
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 = (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);
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
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;
}
static const char *
selftest (void)
{
byte ctxbuf[sizeof(CHACHA20_context_t) + 15];
CHACHA20_context_t *ctx;
byte scratch[127 + 1];
byte buf[512 + 64 + 4];
int i;
/* From draft-strombergson-chacha-test-vectors */
static byte key_1[] = {
0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78,
0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35,
0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb,
0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d
};
static const byte nonce_1[] =
{ 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21 };
static const byte plaintext_1[127] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const byte ciphertext_1[127] = {
0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9,
0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06,
0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00,
0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf,
0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd,
0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f,
0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f,
0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92,
0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9,
0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36,
0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1,
0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38,
0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea,
0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0,
0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27,
0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33
};
/* 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, NULL);
chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
scratch[sizeof (scratch) - 1] = 0;
chacha20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1))
return "ChaCha20 encryption test 1 failed.";
if (scratch[sizeof (scratch) - 1])
return "ChaCha20 wrote too much.";
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))
return "ChaCha20 decryption test 1 failed.";
for (i = 0; i < sizeof buf; i++)
buf[i] = i;
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, 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);
chacha20_encrypt_stream (ctx, buf + (sizeof buf) - 1,
buf + (sizeof buf) - 1, 1);
for (i = 0; i < sizeof buf; i++)
if (buf[i] != (byte) i)
return "ChaCha20 encryption test 2 failed.";
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, NULL);
chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
chacha20_encrypt_stream (ctx, buf, buf, sizeof buf);
for (i = 0; i < sizeof buf; i++)
if (buf[i] != (byte) i)
return "ChaCha20 encryption test 3 failed.";
return NULL;
}
gcry_cipher_spec_t _gcry_cipher_spec_chacha20 = {
GCRY_CIPHER_CHACHA20,
{0, 0}, /* flags */
"CHACHA20", /* name */
NULL, /* aliases */
NULL, /* oids */
1, /* blocksize in bytes. */
CHACHA20_MAX_KEY_SIZE * 8, /* standard key length in bits. */
sizeof (CHACHA20_context_t),
chacha20_setkey,
NULL,
NULL,
chacha20_encrypt_stream,
chacha20_encrypt_stream,
NULL,
NULL,
chacha20_setiv
};
diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c
index c182657e..017d3304 100644
--- a/cipher/cipher-aeswrap.c
+++ b/cipher/cipher-aeswrap.c
@@ -1,209 +1,209 @@
/* cipher-aeswrap.c - Generic AESWRAP mode implementation
* Copyright (C) 2009, 2011 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/>.
+ * License along with this program; if not, see <https://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"
/* 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 )
{
int j, x;
size_t n, i;
unsigned char *r, *a, *b;
unsigned char t[8];
unsigned int burn, nburn;
#if MAX_BLOCKSIZE < 8
#error Invalid block size
#endif
/* 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;
n = inbuflen / 8;
/* We need at least two 64 bit blocks. */
if (n < 2)
return GPG_ERR_INV_ARG;
burn = 0;
r = outbuf;
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++)
{
/* B := AES_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;
}
/* A := MSB_64(B) ^ t */
cipher_block_xor(a, b, t, 8);
/* R[i] := LSB_64(B) */
memcpy (r+i*8, b+8, 8);
}
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
/* Perform the AES-Unwrap 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,
byte *outbuf, size_t outbuflen,
const byte *inbuf, size_t inbuflen)
{
int j, x;
size_t n, i;
unsigned char *r, *a, *b;
unsigned char t[8];
unsigned int burn, nburn;
#if MAX_BLOCKSIZE < 8
#error Invalid block size
#endif
/* 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;
n = inbuflen / 8;
/* We need at least three 64 bit blocks. */
if (n < 3)
return GPG_ERR_INV_ARG;
burn = 0;
r = outbuf;
a = c->lastiv; /* We use c->LASTIV as buffer for A. */
b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */
/* Copy the inbuf to the outbuf and save A. */
memcpy (a, inbuf, 8);
memmove (r, inbuf+8, inbuflen-8);
n--; /* Reduce to actual number of data blocks. */
/* t := 6 * n */
i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */
for (x=0; x < 8 && x < sizeof (i); x++)
t[7-x] = i >> (8*x);
for (; x < 8; x++)
t[7-x] = 0;
for (j = 5; j >= 0; j--)
{
for (i = n; i >= 1; i--)
{
/* B := AES_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;
}
/* A := MSB_64(B) */
memcpy (a, b, 8);
/* R[i] := LSB_64(B) */
memcpy (r+(i-1)*8, b+8, 8);
}
}
/* 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
{
for (j=0, x=0; x < 8; x++)
if (a[x] != 0xa6)
{
j=1;
break;
}
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return j? GPG_ERR_CHECKSUM : 0;
}
diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c
index d4df1e72..fbb5e790 100644
--- a/cipher/cipher-cbc.c
+++ b/cipher/cipher-cbc.c
@@ -1,292 +1,292 @@
/* cipher-cbc.c - Generic CBC mode implementation
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2005, 2007, 2008, 2009, 2011 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/>.
+ * License along with this program; if not, see <https://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 "./cipher-internal.h"
#include "bufhelp.h"
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)
{
unsigned int burn, nburn;
size_t n;
burn = 0;
if (c->bulk.cbc_enc)
{
c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
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++ )
{
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 (!is_cbc_cmac)
outbuf += blocksize;
}
if (ivp != c->u_iv.iv)
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--;
}
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_mask) == 0)
restbytes = blocksize;
else
restbytes = inbuflen & blocksize_mask;
outbuf -= blocksize;
for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
{
b = inbuf[i];
outbuf[blocksize + i] = outbuf[i];
outbuf[i] = b ^ *ivp++;
}
for (; i < blocksize; i++)
outbuf[i] = 0 ^ *ivp++;
nburn = enc_fn (&c->context.c, outbuf, outbuf);
burn = nburn > burn ? nburn : burn;
cipher_block_cpy (c->u_iv.iv, outbuf, blocksize);
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
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)
{
unsigned int burn, nburn;
size_t n;
burn = 0;
if (c->bulk.cbc_dec)
{
c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
}
else
{
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;
cipher_block_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf,
blocksize);
inbuf += blocksize;
outbuf += 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_mask) == 0)
restbytes = blocksize;
else
restbytes = inbuflen & blocksize_mask;
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 );
burn = nburn > burn ? nburn : burn;
buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes);
buf_cpy (outbuf + blocksize, outbuf, restbytes);
for(i=restbytes; i < blocksize; i++)
c->u_iv.iv[i] = outbuf[i];
nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv);
burn = nburn > burn ? nburn : burn;
cipher_block_xor(outbuf, outbuf, c->lastiv, blocksize);
/* c->lastiv is now really lastlastiv, does this matter? */
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c
index dcb268d0..c6a0ec9b 100644
--- a/cipher/cipher-ccm.c
+++ b/cipher/cipher-ccm.c
@@ -1,415 +1,415 @@
/* cipher-ccm.c - CTR mode with CBC-MAC mode implementation
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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 set_burn(burn, nburn) do { \
unsigned int __nburn = (nburn); \
(burn) = (burn) > __nburn ? (burn) : __nburn; } while (0)
static unsigned int
do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
int do_padding)
{
const unsigned int blocksize = 16;
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
unsigned char tmp[blocksize];
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;
do
{
if (inlen + unused < blocksize || unused > 0)
{
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;
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. */
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;
}
if (c->bulk.cbc_enc)
{
nblocks = inlen / blocksize;
c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, tmp, inbuf, nblocks, 1);
inbuf += nblocks * blocksize;
inlen -= nblocks * blocksize;
wipememory (tmp, sizeof(tmp));
}
else
{
while (inlen >= 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 ));
inlen -= blocksize;
inbuf += blocksize;
}
}
}
while (inlen > 0);
c->u_mode.ccm.mac_unused = unused;
if (burn)
burn += 4 * sizeof(void *);
return burn;
}
gcry_err_code_t
_gcry_cipher_ccm_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
size_t noncelen)
{
unsigned int marks_key;
size_t L = 15 - noncelen;
size_t L_;
L_ = L - 1;
if (!nonce)
return GPG_ERR_INV_ARG;
/* Length field must be 2, 3, ..., or 8. */
if (L < 2 || L > 8)
return GPG_ERR_INV_LENGTH;
/* Reset state */
marks_key = c->marks.key;
memset (&c->u_mode, 0, sizeof(c->u_mode));
memset (&c->marks, 0, sizeof(c->marks));
memset (&c->u_iv, 0, sizeof(c->u_iv));
memset (&c->u_ctr, 0, sizeof(c->u_ctr));
memset (c->lastiv, 0, sizeof(c->lastiv));
c->unused = 0;
c->marks.key = marks_key;
/* Setup CTR */
c->u_ctr.ctr[0] = L_;
memcpy (&c->u_ctr.ctr[1], nonce, noncelen);
memset (&c->u_ctr.ctr[1 + noncelen], 0, L);
/* Setup IV */
c->u_iv.iv[0] = L_;
memcpy (&c->u_iv.iv[1], nonce, noncelen);
/* Add (8 * M_ + 64 * flags) to iv[0] and set iv[noncelen + 1 ... 15] later
in set_aad. */
memset (&c->u_iv.iv[1 + noncelen], 0, L);
c->u_mode.ccm.nonce = 1;
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
_gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, u64 encryptlen, u64 aadlen,
u64 taglen)
{
unsigned int burn = 0;
unsigned char b0[16];
size_t noncelen = 15 - (c->u_iv.iv[0] + 1);
u64 M = taglen;
u64 M_;
int i;
M_ = (M - 2) / 2;
/* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */
if ((M_ * 2 + 2) != M || M < 4 || M > 16)
return GPG_ERR_INV_LENGTH;
if (!c->u_mode.ccm.nonce || c->marks.tag)
return GPG_ERR_INV_STATE;
if (c->u_mode.ccm.lengths)
return GPG_ERR_INV_STATE;
c->u_mode.ccm.authlen = taglen;
c->u_mode.ccm.encryptlen = encryptlen;
c->u_mode.ccm.aadlen = aadlen;
/* Complete IV setup. */
c->u_iv.iv[0] += (aadlen > 0) * 64 + M_ * 8;
for (i = 16 - 1; i >= 1 + noncelen; i--)
{
c->u_iv.iv[i] = encryptlen & 0xff;
encryptlen >>= 8;
}
memcpy (b0, c->u_iv.iv, 16);
memset (c->u_iv.iv, 0, 16);
set_burn (burn, do_cbc_mac (c, b0, 16, 0));
if (aadlen == 0)
{
/* Do nothing. */
}
else if (aadlen > 0 && aadlen <= (unsigned int)0xfeff)
{
b0[0] = (aadlen >> 8) & 0xff;
b0[1] = aadlen & 0xff;
set_burn (burn, do_cbc_mac (c, b0, 2, 0));
}
else if (aadlen > 0xfeff && aadlen <= (unsigned int)0xffffffff)
{
b0[0] = 0xff;
b0[1] = 0xfe;
buf_put_be32(&b0[2], aadlen);
set_burn (burn, do_cbc_mac (c, b0, 6, 0));
}
else if (aadlen > (unsigned int)0xffffffff)
{
b0[0] = 0xff;
b0[1] = 0xff;
buf_put_be64(&b0[2], aadlen);
set_burn (burn, do_cbc_mac (c, b0, 10, 0));
}
/* Generate S_0 and increase counter. */
set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_mode.ccm.s0,
c->u_ctr.ctr ));
c->u_ctr.ctr[15]++;
if (burn)
_gcry_burn_stack (burn + sizeof(void *) * 5);
c->u_mode.ccm.lengths = 1;
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
_gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
size_t abuflen)
{
unsigned int burn;
if (abuflen > 0 && !abuf)
return GPG_ERR_INV_ARG;
if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->marks.tag)
return GPG_ERR_INV_STATE;
if (abuflen > c->u_mode.ccm.aadlen)
return GPG_ERR_INV_LENGTH;
c->u_mode.ccm.aadlen -= abuflen;
burn = do_cbc_mac (c, abuf, abuflen, c->u_mode.ccm.aadlen == 0);
if (burn)
_gcry_burn_stack (burn + sizeof(void *) * 5);
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
_gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
size_t outbuflen, int check)
{
unsigned int burn;
if (!outbuf || outbuflen == 0)
return GPG_ERR_INV_ARG;
/* Tag length must be same as initial authlen. */
if (c->u_mode.ccm.authlen != outbuflen)
return GPG_ERR_INV_LENGTH;
if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0)
return GPG_ERR_INV_STATE;
/* Initial encrypt length must match with length of actual data processed. */
if (c->u_mode.ccm.encryptlen > 0)
return GPG_ERR_UNFINISHED;
if (!c->marks.tag)
{
burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */
/* Add S_0 */
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);
wipememory (c->u_mode.ccm.macbuf, 16);
if (burn)
_gcry_burn_stack (burn + sizeof(void *) * 5);
c->marks.tag = 1;
}
if (!check)
{
memcpy (outbuf, c->u_iv.iv, outbuflen);
return GPG_ERR_NO_ERROR;
}
else
{
return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ?
GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
}
}
gcry_err_code_t
_gcry_cipher_ccm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
size_t taglen)
{
return _gcry_cipher_ccm_tag (c, outtag, taglen, 0);
}
gcry_err_code_t
_gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
size_t taglen)
{
return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1);
}
gcry_err_code_t
_gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
size_t outbuflen, const unsigned char *inbuf,
size_t inbuflen)
{
gcry_err_code_t err = 0;
unsigned int burn = 0;
unsigned int nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
c->u_mode.ccm.aadlen > 0)
return GPG_ERR_INV_STATE;
if (inbuflen > c->u_mode.ccm.encryptlen)
return GPG_ERR_INV_LENGTH;
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 err;
}
gcry_err_code_t
_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 = 0;
unsigned int burn = 0;
unsigned int nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
c->u_mode.ccm.aadlen > 0)
return GPG_ERR_INV_STATE;
if (inbuflen > c->u_mode.ccm.encryptlen)
return GPG_ERR_INV_LENGTH;
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;
}
if (burn)
_gcry_burn_stack (burn + sizeof(void *) * 5);
return err;
}
diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c
index 012c6c13..3c05ba67 100644
--- a/cipher/cipher-cfb.c
+++ b/cipher/cipher-cfb.c
@@ -1,317 +1,317 @@
/* cipher-cfb.c - Generic CFB mode implementation
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2005, 2007, 2008, 2009, 2011 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/>.
+ * License along with this program; if not, see <https://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_cfb_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
unsigned char *ivp;
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
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;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if ( inbuflen <= c->unused )
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV and store input into IV. */
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor_2dst(outbuf, ivp, inbuf, inbuflen);
c->unused -= inbuflen;
return 0;
}
burn = 0;
if ( c->unused )
{
/* XOR the input with the IV and store input into IV */
inbuflen -= c->unused;
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor_2dst(outbuf, ivp, inbuf, c->unused);
outbuf += c->unused;
inbuf += c->unused;
c->unused = 0;
}
/* Now we can process complete blocks. We use a loop as long as we
have at least 2 blocks and use conditions for the rest. This
also allows to use a bulk encryption function if available. */
if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
{
size_t nblocks = inbuflen >> blocksize_shift;
c->bulk.cfb_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_x_2 )
{
/* Encrypt the IV. */
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. */
cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
inbuf += blocksize;
inbuflen -= blocksize;
}
}
if ( inbuflen >= blocksize )
{
/* Save the current IV and then encrypt the IV. */
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 */
cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
inbuf += blocksize;
inbuflen -= blocksize;
}
if ( inbuflen )
{
/* Save the current IV and then encrypt the IV. */
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;
/* Apply the XOR. */
c->unused -= inbuflen;
buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, inbuflen);
outbuf += inbuflen;
inbuf += inbuflen;
inbuflen = 0;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
gcry_err_code_t
_gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
unsigned char *ivp;
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
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;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if (inbuflen <= c->unused)
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV and store input into IV. */
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor_n_copy(outbuf, ivp, inbuf, inbuflen);
c->unused -= inbuflen;
return 0;
}
burn = 0;
if (c->unused)
{
/* XOR the input with the IV and store input into IV. */
inbuflen -= c->unused;
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor_n_copy(outbuf, ivp, inbuf, c->unused);
outbuf += c->unused;
inbuf += c->unused;
c->unused = 0;
}
/* Now we can process complete blocks. We use a loop as long as we
have at least 2 blocks and use conditions for the rest. This
also allows to use a bulk encryption function if available. */
if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
{
size_t nblocks = inbuflen >> blocksize_shift;
c->bulk.cfb_dec (&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_x_2 )
{
/* Encrypt the IV. */
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. */
cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
inbuf += blocksize;
inbuflen -= blocksize;
}
}
if (inbuflen >= blocksize )
{
/* Save the current IV and then encrypt the IV. */
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 */
cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
inbuf += blocksize;
inbuflen -= blocksize;
}
if (inbuflen)
{
/* Save the current IV and then encrypt the IV. */
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;
/* Apply the XOR. */
c->unused -= inbuflen;
buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, inbuflen);
outbuf += inbuflen;
inbuf += inbuflen;
inbuflen = 0;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
gcry_err_code_t
_gcry_cipher_cfb8_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
unsigned int burn, nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
burn = 0;
while ( inbuflen > 0)
{
int i;
/* Encrypt the IV. */
nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
outbuf[0] = c->lastiv[0] ^ inbuf[0];
/* Bitshift iv by 8 bit to the left */
for (i = 0; i < blocksize-1; i++)
c->u_iv.iv[i] = c->u_iv.iv[i+1];
/* append cipher text to iv */
c->u_iv.iv[blocksize-1] = outbuf[0];
outbuf += 1;
inbuf += 1;
inbuflen -= 1;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
gcry_err_code_t
_gcry_cipher_cfb8_decrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
unsigned int burn, nburn;
unsigned char appendee;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
burn = 0;
while (inbuflen > 0)
{
int i;
/* Encrypt the IV. */
nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
/* inbuf might == outbuf, make sure we keep the value
so we can append it later */
appendee = inbuf[0];
outbuf[0] = inbuf[0] ^ c->lastiv[0];
/* Bitshift iv by 8 bit to the left */
for (i = 0; i < blocksize-1; i++)
c->u_iv.iv[i] = c->u_iv.iv[i+1];
c->u_iv.iv[blocksize-1] = appendee;
outbuf += 1;
inbuf += 1;
inbuflen -= 1;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c
index 4efd1e19..6e518823 100644
--- a/cipher/cipher-cmac.c
+++ b/cipher/cipher-cmac.c
@@ -1,292 +1,292 @@
/* cmac.c - CMAC, Cipher-based MAC.
* Copyright (C) 2013,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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "cipher.h"
#include "cipher-internal.h"
#include "bufhelp.h"
#define set_burn(burn, nburn) do { \
unsigned int __nburn = (nburn); \
(burn) = (burn) > __nburn ? (burn) : __nburn; } while (0)
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;
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;
if (ctx->tag)
return GPG_ERR_INV_STATE;
if (!inbuf)
return GPG_ERR_INV_ARG;
if (inlen == 0)
return 0;
/* Last block is needed for cmac_final. */
if (ctx->mac_unused + inlen <= blocksize)
{
buf_cpy (&ctx->macbuf[ctx->mac_unused], inbuf, inlen);
ctx->mac_unused += inlen;
inbuf += inlen;
inlen -= inlen;
return 0;
}
if (ctx->mac_unused)
{
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;
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_shift;
nblocks -= ((nblocks << blocksize_shift) == inlen);
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)
{
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;
}
/* Make sure that last block is passed to cmac_final. */
if (inlen == 0)
BUG ();
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;
}
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;
unsigned int burn;
int i, j;
union
{
size_t _aligned;
byte buf[MAX_BLOCKSIZE];
} u;
/* 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_CIPHER_MODE;
if (MAX_BLOCKSIZE < blocksize)
BUG ();
/* encrypt zero block */
memset (u.buf, 0, blocksize);
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 */ ;
for (j = 0; j < 2; j++)
{
/* Generate subkeys K1 and K2 */
carry = 0;
for (i = blocksize - 1; i >= 0; i--)
{
bi = u.buf[i];
t = carry | (bi << 1);
carry = bi >> 7;
u.buf[i] = t & 0xff;
ctx->subkeys[j][i] = u.buf[i];
}
u.buf[blocksize - 1] ^= carry ? rb : 0;
ctx->subkeys[j][blocksize - 1] = u.buf[blocksize - 1];
}
wipememory (&u, sizeof (u));
if (burn)
_gcry_burn_stack (burn + 4 * sizeof (void *));
return 0;
}
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 = 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 GPG_ERR_INV_CIPHER_MODE;
if (count == blocksize)
subkey = ctx->subkeys[0]; /* K1 */
else
{
subkey = ctx->subkeys[1]; /* K2 */
ctx->macbuf[count++] = 0x80;
while (count < blocksize)
ctx->macbuf[count++] = 0;
}
cipher_block_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize);
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 *));
ctx->mac_unused = 0;
return 0;
}
static gcry_err_code_t
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 (!ctx->tag)
{
ret = _gcry_cmac_final (c, ctx);
if (ret != 0)
return ret;
ctx->tag = 1;
}
if (!check)
{
memcpy (tag, ctx->u_iv.iv, taglen);
return GPG_ERR_NO_ERROR;
}
else
{
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;
/* 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;
return _gcry_cmac_write (c, &c->u_mode.cmac, abuf, abuflen);
}
gcry_err_code_t
_gcry_cipher_cmac_get_tag (gcry_cipher_hd_t c,
unsigned char *outtag, size_t taglen)
{
return cmac_tag (c, &c->u_mode.cmac, outtag, taglen, 0);
}
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, &c->u_mode.cmac, (unsigned char *) intag, taglen, 1);
}
gcry_err_code_t
_gcry_cipher_cmac_set_subkeys (gcry_cipher_hd_t c)
{
return _gcry_cmac_generate_subkeys (c, &c->u_mode.cmac);
}
diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c
index 5f0afc2f..eff708c6 100644
--- a/cipher/cipher-ctr.c
+++ b/cipher/cipher-ctr.c
@@ -1,120 +1,120 @@
/* cipher-ctr.c - Generic CTR mode implementation
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2005, 2007, 2008, 2009, 2011 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/>.
+ * License along with this program; if not, see <https://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_ctr_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
size_t n;
int i;
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize_shift = _gcry_blocksize_shift(c);
size_t blocksize = 1 << blocksize_shift;
size_t nblocks;
unsigned int burn, nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
burn = 0;
/* First process a left over encrypted counter. */
if (c->unused)
{
gcry_assert (c->unused < blocksize);
i = blocksize - c->unused;
n = c->unused > inbuflen ? inbuflen : c->unused;
buf_xor(outbuf, inbuf, &c->lastiv[i], n);
c->unused -= n;
inbuf += n;
outbuf += n;
inbuflen -= n;
}
/* Use a bulk method if available. */
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_shift;
outbuf += nblocks << blocksize_shift;
inbuflen -= nblocks << blocksize_shift;
}
/* If we don't have a bulk method use the standard method. We also
use this method for the a remaining partial block. */
if (inbuflen)
{
unsigned char tmp[MAX_BLOCKSIZE];
n = blocksize;
do
{
nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr);
burn = nburn > burn ? nburn : burn;
cipher_block_add(c->u_ctr.ctr, 1, blocksize);
if (inbuflen < blocksize)
break;
cipher_block_xor(outbuf, inbuf, tmp, blocksize);
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;
if (c->unused)
buf_cpy (c->lastiv+n, tmp+n, c->unused);
wipememory (tmp, sizeof tmp);
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
diff --git a/cipher/cipher-eax.c b/cipher/cipher-eax.c
index 08f815a9..f76e016f 100644
--- a/cipher/cipher-eax.c
+++ b/cipher/cipher-eax.c
@@ -1,289 +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/>.
+ * License along with this program; if not, see <https://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
index a801a5e5..fec6151f 100644
--- a/cipher/cipher-gcm-armv7-neon.S
+++ b/cipher/cipher-gcm-armv7-neon.S
@@ -1,341 +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/>.
+ * License along with this program; if not, see <https://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) veor reg, reg;
/*
* 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
diff --git a/cipher/cipher-gcm-armv8-aarch32-ce.S b/cipher/cipher-gcm-armv8-aarch32-ce.S
index 1de66a16..b7804c8b 100644
--- a/cipher/cipher-gcm-armv8-aarch32-ce.S
+++ b/cipher/cipher-gcm-armv8-aarch32-ce.S
@@ -1,433 +1,433 @@
/* cipher-gcm-armv8-aarch32-ce.S - ARM/CE accelerated GHASH
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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_AARCH32_CRYPTO)
.syntax unified
.arch armv8-a
.fpu crypto-neon-fp-armv8
.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 rbuf2 q4
#define rbuf2_l d8
#define rbuf2_h d9
#define rbuf3 q5
#define rbuf3_l d10
#define rbuf3_h d11
#define rh2 q6
#define rh2_l d12
#define rh2_h d13
#define rh3 q7
#define rh3_l d14
#define rh3_h d15
#define rh4 q8
#define rh4_l d16
#define rh4_h d17
#define rr2 q9
#define rr2_l d18
#define rr2_h d19
#define rr3 q10
#define rr3_l d20
#define rr3_h d21
#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
/* 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, t, interleave_op) \
veor t##_h, b##_l, b##_h; \
veor t##_l, a##_l, a##_h; \
vmull.p64 r0, a##_l, b##_l; \
vmull.p64 r1, a##_h, b##_h; \
vmull.p64 t, t##_h, t##_l; \
interleave_op; \
veor t, r0; \
veor t, r1; \
veor r0##_h, t##_l; \
veor r1##_l, t##_h;
/* Input: 'aA' and 'bA', Output: 'r0A:r1A' (low 128-bits in r0A, high in r1A)
* Note: 'r1A' may be 'aA' or 'bA', 'r0A' must not be either 'aA' or 'bA'.
* Input: 'aB' and 'bB', Output: 'r0B:r1B' (low 128-bits in r0B, high in r1B)
* Note: 'r1B' may be 'aB' or 'bB', 'r0B' must not be either 'aB' or 'bB'.
*/
#define PMUL_128x128_2(r0A, r1A, aA, bA, r0B, r1B, aB, bB, tA, tB, interleave_op) \
veor tA##_h, bA##_l, bA##_h; \
veor tA##_l, aA##_l, aA##_h; \
veor tB##_h, bB##_l, bB##_h; \
veor tB##_l, aB##_l, aB##_h; \
vmull.p64 r0A, aA##_l, bA##_l; \
vmull.p64 r1A, aA##_h, bA##_h; \
vmull.p64 tA, tA##_h, tA##_l; \
vmull.p64 r0B, aB##_l, bB##_l; \
vmull.p64 r1B, aB##_h, bB##_h; \
vmull.p64 tB, tB##_h, tB##_l; \
interleave_op; \
veor tA, r0A; \
veor tA, r1A; \
veor tB, r0B; \
veor tB, r1B; \
veor r0A##_h, tA##_l; \
veor r1A##_l, tA##_h; \
veor r0B##_h, tB##_l; \
veor r1B##_l, tB##_h; \
/* Input: 'r0:r1', Output: 'a' */
#define REDUCTION(a, r0, r1, rconst, t, interleave_op) \
vmull.p64 t, r0##_l, rconst; \
veor r0##_h, t##_l; \
veor r1##_l, t##_h; \
interleave_op; \
vmull.p64 t, r0##_h, rconst; \
veor r1, t; \
veor a, r0, r1;
#define _(...) __VA_ARGS__
#define __ _()
/* Other functional macros */
#define CLEAR_REG(reg) veor reg, reg;
/*
* unsigned int _gcry_ghash_armv8_ce_pmull (void *gcm_key, byte *result,
* const byte *buf, size_t nblocks,
* void *gcm_table);
*/
.align 3
.globl _gcry_ghash_armv8_ce_pmull
.type _gcry_ghash_armv8_ce_pmull,%function;
_gcry_ghash_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 .Ldo_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 .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
vrev64.8 rbuf, rbuf /* byte-swap */
vrev64.8 rbuf1, rbuf1 /* byte-swap */
vrev64.8 rbuf2, rbuf2 /* byte-swap */
vrev64.8 rbuf3, rbuf3 /* byte-swap */
vext.8 rbuf, rbuf, rbuf, #8
vext.8 rbuf1, rbuf1, rbuf1, #8
vext.8 rbuf2, rbuf2, rbuf2, #8
vext.8 rbuf3, rbuf3, rbuf3, #8
veor rhash, rhash, rbuf /* in0 ^ hash */
blo .Lend_4
.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,
_(vrev64.8 rbuf, rbuf))
vld1.64 {rbuf2}, [r2]!
vrev64.8 rbuf1, rbuf1
veor rr0, rr0, rr2
veor rr1, rr1, rr3
cmp r3, #4
vext.8 rbuf, rbuf, rbuf, #8
vext.8 rbuf1, rbuf1, rbuf1, #8
veor rr0, rr0, rhash
veor rr1, rr1, rbuf3
vld1.64 {rbuf3}, [r2]!
REDUCTION(rhash, rr0, rr1, rrconst_h, rt1,
_(vrev64.8 rbuf2, rbuf2;
vrev64.8 rbuf3, rbuf3))
vext.8 rbuf2, rbuf2, rbuf2, #8
vext.8 rbuf3, rbuf3, rbuf3, #8
veor rhash, rhash, rbuf /* in0 ^ hash */
bhs .Loop_4
.Lend_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 .Ldone
.Less_than_4:
/* 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]!
subs r3, r3, #1
PMUL_128x128(rr0, rr1, rhash, rh1, rt0, _(vrev64.8 rbuf, rbuf))
REDUCTION(rhash, rr0, rr1, rrconst_h, rt0, _(vext.8 rbuf, rbuf, rbuf, #8))
veor rhash, rhash, rbuf
bne .Loop
.Lend:
PMUL_128x128(rr0, rr1, rhash, rh1, rt0, _(CLEAR_REG(rbuf)))
REDUCTION(rhash, rr0, rr1, rrconst_h, 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)
vst1.64 {rhash}, [r1]
CLEAR_REG(rhash)
.Ldo_nothing:
mov r0, #0
pop {r4-r6, pc}
.size _gcry_ghash_armv8_ce_pmull,.-_gcry_ghash_armv8_ce_pmull;
/*
* void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
*/
.align 3
.globl _gcry_ghash_setup_armv8_ce_pmull
.type _gcry_ghash_setup_armv8_ce_pmull,%function;
_gcry_ghash_setup_armv8_ce_pmull:
/* input:
* r0: gcm_key
* r1: gcm_table
*/
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 */
/* H² */
PMUL_128x128(rr0, rr1, rbuf1, rh1, rt0, __)
REDUCTION(rh2, rr0, rr1, rrconst_h, rt0, __)
vmov rhash, rh2
GCM_LSH_1(r1, rh2_l, rh2_h, rrconst_h, rbuf1_l, rbuf1_h, rt1_l) /* H²<<<1 */
add r1, r1, #16
/* H³ */
PMUL_128x128(rr0, rr1, rhash, rh1, rt1, __)
REDUCTION(rh3, rr0, rr1, rrconst_h, rt1, __)
/* H⁴ */
PMUL_128x128(rr0, rr1, rhash, rbuf1, rt0, __)
REDUCTION(rh4, rr0, rr1, rrconst_h, rt0, __)
GCM_LSH_1(r1, rh3_l, rh3_h, rrconst_h, rt0_l, rt0_h, rt1_l) /* H³<<<1 */
add r1, r1, #16
GCM_LSH_1(r1, rh4_l, rh4_h, rrconst_h, rt0_l, rt0_h, rt1_l) /* H⁴<<<1 */
CLEAR_REG(rt0)
CLEAR_REG(rt1)
CLEAR_REG(rr1)
CLEAR_REG(rr0)
CLEAR_REG(rh1)
CLEAR_REG(rh2)
CLEAR_REG(rh3)
CLEAR_REG(rh4)
CLEAR_REG(rhash)
CLEAR_REG(rbuf1)
CLEAR_REG(rrconst)
vpop {q4-q7}
bx lr
.size _gcry_ghash_setup_armv8_ce_pmull,.-_gcry_ghash_setup_armv8_ce_pmull;
#endif
diff --git a/cipher/cipher-gcm-armv8-aarch64-ce.S b/cipher/cipher-gcm-armv8-aarch64-ce.S
index b0c2cccc..9005896a 100644
--- a/cipher/cipher-gcm-armv8-aarch64-ce.S
+++ b/cipher/cipher-gcm-armv8-aarch64-ce.S
@@ -1,422 +1,422 @@
/* cipher-gcm-armv8-aarch64-ce.S - ARM/CE accelerated GHASH
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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
/* Constants */
.align 4
gcry_gcm_reduction_constant:
.Lrconst:
.quad 0x87
/* Register macros */
#define rhash v0
#define rr0 v1
#define rr1 v2
#define rbuf v3
#define rbuf1 v4
#define rbuf2 v5
#define rbuf3 v6
#define rbuf4 v7
#define rbuf5 v8
#define rr2 v9
#define rr3 v10
#define rr4 v11
#define rr5 v12
#define rr6 v13
#define rr7 v14
#define rr8 v15
#define rr9 v16
#define rrconst v18
#define rh1 v19
#define rh2 v20
#define rh3 v21
#define rh4 v22
#define rh5 v23
#define rh6 v24
#define t0 v25
#define t1 v26
#define t2 v27
#define t3 v28
#define t4 v29
#define t5 v30
#define vZZ v31
/* 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) */
#define PMUL_128x128(r0, r1, a, b, T0, T1, interleave_op) \
ext T0.16b, b.16b, b.16b, #8; \
pmull r0.1q, a.1d, b.1d; \
pmull2 r1.1q, a.2d, b.2d; \
pmull T1.1q, a.1d, T0.1d; \
pmull2 T0.1q, a.2d, T0.2d; \
interleave_op; \
eor T0.16b, T0.16b, T1.16b; \
ext T1.16b, vZZ.16b, T0.16b, #8; \
ext T0.16b, T0.16b, vZZ.16b, #8; \
eor r0.16b, r0.16b, T1.16b; \
eor r1.16b, r1.16b, T0.16b;
/* Input: 'aA' and 'bA', Output: 'r0A:r1A' (low 128-bits in r0A, high in r1A)
* Input: 'aB' and 'bB', Output: 'r0B:r1B' (low 128-bits in r0B, high in r1B)
* Input: 'aC' and 'bC', Output: 'r0C:r1C' (low 128-bits in r0C, high in r1C)
*/
#define PMUL_128x128_3(r0A, r1A, aA, bA, t0A, t1A, \
r0B, r1B, aB, bB, t0B, t1B, \
r0C, r1C, aC, bC, t0C, t1C, interleave_op) \
ext t0A.16b, bA.16b, bA.16b, #8; \
pmull r0A.1q, aA.1d, bA.1d; \
pmull2 r1A.1q, aA.2d, bA.2d; \
ext t0B.16b, bB.16b, bB.16b, #8; \
pmull r0B.1q, aB.1d, bB.1d; \
pmull2 r1B.1q, aB.2d, bB.2d; \
ext t0C.16b, bC.16b, bC.16b, #8; \
pmull r0C.1q, aC.1d, bC.1d; \
pmull2 r1C.1q, aC.2d, bC.2d; \
pmull t1A.1q, aA.1d, t0A.1d; \
pmull2 t0A.1q, aA.2d, t0A.2d; \
pmull t1B.1q, aB.1d, t0B.1d; \
pmull2 t0B.1q, aB.2d, t0B.2d; \
pmull t1C.1q, aC.1d, t0C.1d; \
pmull2 t0C.1q, aC.2d, t0C.2d; \
eor t0A.16b, t0A.16b, t1A.16b; \
eor t0B.16b, t0B.16b, t1B.16b; \
eor t0C.16b, t0C.16b, t1C.16b; \
interleave_op; \
ext t1A.16b, vZZ.16b, t0A.16b, #8; \
ext t0A.16b, t0A.16b, vZZ.16b, #8; \
ext t1B.16b, vZZ.16b, t0B.16b, #8; \
ext t0B.16b, t0B.16b, vZZ.16b, #8; \
ext t1C.16b, vZZ.16b, t0C.16b, #8; \
ext t0C.16b, t0C.16b, vZZ.16b, #8; \
eor r0A.16b, r0A.16b, t1A.16b; \
eor r1A.16b, r1A.16b, t0A.16b; \
eor r0B.16b, r0B.16b, t1B.16b; \
eor r1B.16b, r1B.16b, t0B.16b; \
eor r0C.16b, r0C.16b, t1C.16b; \
eor r1C.16b, r1C.16b, t0C.16b; \
/* Input: 'r0:r1', Output: 'a' */
#define REDUCTION(a, r0, r1, rconst, T0, T1, interleave_op1, interleave_op2, \
interleave_op3) \
pmull2 T0.1q, r1.2d, rconst.2d; \
interleave_op1; \
ext T1.16b, T0.16b, vZZ.16b, #8; \
ext T0.16b, vZZ.16b, T0.16b, #8; \
interleave_op2; \
eor r1.16b, r1.16b, T1.16b; \
eor r0.16b, r0.16b, T0.16b; \
pmull T0.1q, r1.1d, rconst.1d; \
interleave_op3; \
eor a.16b, r0.16b, T0.16b;
/* Other functional macros */
#define _(...) __VA_ARGS__
#define __ _()
#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
#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]!; \
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; \
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,
* const byte *buf, size_t nblocks,
* void *gcm_table);
*/
.align 3
.globl _gcry_ghash_armv8_ce_pmull
ELF(.type _gcry_ghash_armv8_ce_pmull,%function;)
_gcry_ghash_armv8_ce_pmull:
/* input:
* x0: gcm_key
* x1: result/hash
* x2: buf
* x3: nblocks
* x4: gcm_table
*/
CFI_STARTPROC();
cbz x3, .Ldo_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 .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)
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 .Lend_6
.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))
eor rr0.16b, rr0.16b, rr2.16b
eor rr1.16b, rr1.16b, rr3.16b
rbit rbuf.16b, rbuf.16b
eor rr0.16b, rr0.16b, rr6.16b
eor rr1.16b, rr1.16b, rr7.16b
rbit rbuf1.16b, rbuf1.16b
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),
_(rbit rbuf3.16b, rbuf3.16b),
_(rbit rbuf4.16b, rbuf4.16b))
rbit rbuf5.16b, rbuf5.16b
eor rhash.16b, rhash.16b, rbuf.16b
b.hs .Loop_6
.Lend_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, .Ldone
.Less_than_6:
/* Handle remaining blocks. */
ld1 {rbuf.16b}, [x2], #16
sub x3, x3, #1
rbit rbuf.16b, rbuf.16b /* bit-swap */
eor rhash.16b, rhash.16b, rbuf.16b
cbz x3, .Lend
.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),
_(rbit rbuf.16b, rbuf.16b),
__)
eor rhash.16b, rhash.16b, rbuf.16b
cbnz x3, .Loop
.Lend:
PMUL_128x128(rr0, rr1, rh1, rhash, t0, t1, _(CLEAR_REG(rbuf)))
REDUCTION(rhash, rr0, rr1, rrconst, t0, t1, __, _(CLEAR_REG(rh1)), __)
.Ldone:
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)
.Ldo_nothing:
mov x0, #0
ret
CFI_ENDPROC()
ELF(.size _gcry_ghash_armv8_ce_pmull,.-_gcry_ghash_armv8_ce_pmull;)
/*
* void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
*/
.align 3
.globl _gcry_ghash_setup_armv8_ce_pmull
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)
/* H¹ */
ld1 {rh1.16b}, [x0]
rbit rh1.16b, rh1.16b
st1 {rh1.16b}, [x0]
ld1r {rrconst.2d}, [x2]
/* H² */
PMUL_128x128(rr0, rr1, rh1, rh1, t0, t1, __)
REDUCTION(rh2, rr0, rr1, rrconst, t0, t1, __, __, __)
/* H³ */
PMUL_128x128(rr0, rr1, rh2, rh1, t0, t1, __)
REDUCTION(rh3, rr0, rr1, rrconst, t0, t1, __, __, __)
/* H⁴ */
PMUL_128x128(rr0, rr1, rh2, rh2, t0, t1, __)
REDUCTION(rh4, rr0, rr1, rrconst, t0, t1, __, __, __)
/* H⁵ */
PMUL_128x128(rr0, rr1, rh2, rh3, t0, t1, __)
REDUCTION(rh5, rr0, rr1, rrconst, t0, t1, __, __, __)
/* H⁶ */
PMUL_128x128(rr0, rr1, rh3, rh3, t0, t1, __)
REDUCTION(rh6, rr0, rr1, rrconst, t0, t1, __, __, __)
st1 {rh2.16b-rh4.16b}, [x1], #(3*16)
st1 {rh5.16b-rh6.16b}, [x1]
ret
CFI_ENDPROC()
ELF(.size _gcry_ghash_setup_armv8_ce_pmull,.-_gcry_ghash_setup_armv8_ce_pmull;)
#endif
diff --git a/cipher/cipher-gcm-intel-pclmul.c b/cipher/cipher-gcm-intel-pclmul.c
index 8e109ba3..a182b3a8 100644
--- a/cipher/cipher-gcm-intel-pclmul.c
+++ b/cipher/cipher-gcm-intel-pclmul.c
@@ -1,704 +1,704 @@
/* cipher-gcm-intel-pclmul.c - Intel PCLMUL accelerated Galois Counter Mode
* implementation
* Copyright (C) 2013-2014,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/>.
+ * License along with this program; if not, see <https://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"
#ifdef GCM_USE_INTEL_PCLMUL
#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
/*
Intel PCLMUL ghash based on white paper:
"Intel® Carry-Less Multiplication Instruction and its Usage for Computing the
GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis.
*/
static 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 inline void gfmul_pclmul(void)
{
/* Input: XMM0 and XMM1, Output: XMM1. Input XMM0 stays unmodified.
Input must be converted to little-endian.
*/
asm volatile (/* gfmul, xmm0 has operator a and xmm1 has operator b. */
"pshufd $78, %%xmm0, %%xmm2\n\t"
"pshufd $78, %%xmm1, %%xmm4\n\t"
"pxor %%xmm0, %%xmm2\n\t" /* xmm2 holds a0+a1 */
"pxor %%xmm1, %%xmm4\n\t" /* xmm4 holds b0+b1 */
"movdqa %%xmm0, %%xmm3\n\t"
"pclmulqdq $0, %%xmm1, %%xmm3\n\t" /* xmm3 holds a0*b0 */
"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 %%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 */
::: "memory" );
reduction();
}
static 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 (/* perform clmul and merge results... */
"movdqu 2*16(%[h_table]), %%xmm2\n\t" /* Load H4 */
"movdqu 0*16(%[buf]), %%xmm5\n\t"
"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"
"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"
"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"
"pshufb %[be_mask], %%xmm2\n\t" /* be => le */
:
: [buf] "r" (buf),
[h_table] "r" (h_table),
[be_mask] "m" (*be_mask)
: "memory" );
asm volatile ("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) */
"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 */
:
: [h_1] "m" (*(const unsigned char *)h_1)
: "memory" );
reduction();
}
#ifdef __x86_64__
static 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 (/* 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"
"pshufb %%xmm15, %%xmm5\n\t" /* be => 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"
"pshufb %%xmm15, %%xmm5\n\t" /* be => 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"
"pshufb %%xmm15, %%xmm5\n\t" /* be => 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"
"pshufb %%xmm15, %%xmm5\n\t" /* be => 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 */
:
: [buf] "r" (buf),
[h_table] "r" (h_table)
: "memory" );
reduction();
}
#endif
static 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
_gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c)
{
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[10 * 16];
/* 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
/* Swap endianness of hsub. */
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__
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_table] "r" (c->u_mode.gcm.gcm_table)
: "memory");
gfmul_pclmul (); /* H²<<<1•H⁴ => H⁶ */
asm volatile ("movdqu %%xmm1, 4*16(%[h_table])\n\t"
"movdqu 1*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, 5*16(%[h_table])\n\t"
"movdqu 2*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, 6*16(%[h_table])\n\t"
:
: [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"
"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"
"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
}
unsigned int
_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;
#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 ("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)
: "memory" );
#ifdef __x86_64__
if (nblocks >= 8)
{
/* 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)
{
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] "m" (*buf), [be_mask] "m" (*be_mask)
: "memory" );
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)
: "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;
}
#if __clang__
# pragma clang attribute pop
#endif
#endif /* GCM_USE_INTEL_PCLMUL */
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 11f119aa..7e3e26bd 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -1,1111 +1,1111 @@
/* cipher-gcm.c - Generic Galois Counter Mode implementation
* Copyright (C) 2013 Dmitry Eremin-Solenikov
* Copyright (C) 2013, 2018-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/>.
+ * License along with this program; if not, see <https://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"
#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);
#endif
#ifdef GCM_USE_ARM_PMULL
extern void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
extern unsigned int _gcry_ghash_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)
{
_gcry_ghash_setup_armv8_ce_pmull(c->u_mode.gcm.u_ghash_key.key,
c->u_mode.gcm.gcm_table);
}
static unsigned int
ghash_armv8_ce_pmull (gcry_cipher_hd_t c, byte *result, const byte *buf,
size_t nblocks)
{
return _gcry_ghash_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_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 inline
void prefetch_table(const void *tab, size_t len)
{
const volatile byte *vtab = tab;
size_t i;
for (i = 0; i < len; 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];
}
(void)vtab[len - 1];
}
static inline void
do_prefetch_tables (const void *gcmM, size_t gcmM_size)
{
prefetch_table(gcmM, gcmM_size);
prefetch_table(gcmR, sizeof(gcmR));
}
#ifdef GCM_TABLES_USE_U64
static void
bshift (u64 * b0, u64 * b1)
{
u64 t[2], mask;
t[0] = *b0;
t[1] = *b1;
mask = -(t[1] & 1) & 0xe1;
mask <<= 56;
*b1 = (t[1] >> 1) ^ (t[0] << 63);
*b0 = (t[0] >> 1) ^ mask;
}
static void
do_fillM (unsigned char *h, u64 *M)
{
int i, j;
M[0 + 0] = 0;
M[0 + 16] = 0;
M[8 + 0] = buf_get_be64 (h + 0);
M[8 + 16] = buf_get_be64 (h + 8);
for (i = 4; i > 0; i /= 2)
{
M[i + 0] = M[2 * i + 0];
M[i + 16] = M[2 * i + 16];
bshift (&M[i], &M[i + 16]);
}
for (i = 2; i < 16; i *= 2)
for (j = 1; j < i; j++)
{
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
do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM)
{
u64 V[2];
u64 tmp[2];
const u64 *M;
u64 T;
u32 A;
int i;
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. */
M = &gcmM[(V[1] & 0xf) + 32];
V[1] >>= 4;
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 = 6;
while (1)
{
M = &gcmM[(V[1] & 0xf) + 32];
V[1] >>= 4;
A = tmp[1] & 0xff;
T = tmp[0];
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];
tmp[1] ^= M[16];
if (i == 0)
break;
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;
}
buf_put_be64 (result + 0, tmp[0]);
buf_put_be64 (result + 8, tmp[1]);
return (sizeof(V) + sizeof(T) + sizeof(tmp) +
sizeof(int)*2 + sizeof(void*)*5);
}
#else /*!GCM_TABLES_USE_U64*/
static void
bshift (u32 * M, int i)
{
u32 t[4], mask;
t[0] = M[i * 4 + 0];
t[1] = M[i * 4 + 1];
t[2] = M[i * 4 + 2];
t[3] = M[i * 4 + 3];
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);
M[i * 4 + 1] = (t[1] >> 1) ^ (t[0] << 31);
M[i * 4 + 0] = (t[0] >> 1) ^ (mask << 24);
}
static void
do_fillM (unsigned char *h, u32 *M)
{
int i, j;
M[0 * 4 + 0] = 0;
M[0 * 4 + 1] = 0;
M[0 * 4 + 2] = 0;
M[0 * 4 + 3] = 0;
M[8 * 4 + 0] = buf_get_be32 (h + 0);
M[8 * 4 + 1] = buf_get_be32 (h + 4);
M[8 * 4 + 2] = buf_get_be32 (h + 8);
M[8 * 4 + 3] = buf_get_be32 (h + 12);
for (i = 4; i > 0; i /= 2)
{
M[i * 4 + 0] = M[2 * i * 4 + 0];
M[i * 4 + 1] = M[2 * i * 4 + 1];
M[i * 4 + 2] = M[2 * i * 4 + 2];
M[i * 4 + 3] = M[2 * i * 4 + 3];
bshift (M, i);
}
for (i = 2; i < 16; i *= 2)
for (j = 1; j < i; j++)
{
M[(i + j) * 4 + 0] = M[i * 4 + 0] ^ M[j * 4 + 0];
M[(i + j) * 4 + 1] = M[i * 4 + 1] ^ M[j * 4 + 1];
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
do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM)
{
byte V[16];
u32 tmp[4];
u32 v;
const u32 *M, *m;
u32 T[3];
int i;
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 + 64];
v = (v & 0xf0) >> 4;
m = &gcmM[v * 4];
v = V[--i];
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 + 64];
v = (v & 0xf0) >> 4;
m = &gcmM[v * 4];
T[0] = tmp[0];
T[1] = tmp[1];
T[2] = tmp[2];
tmp[0] = (T[0] >> 8) ^ ((u32) gcmR[tmp[3] & 0xff] << 16) ^ m[0];
tmp[1] = (T[0] << 24) ^ (tmp[1] >> 8) ^ m[1];
tmp[2] = (T[1] << 24) ^ (tmp[2] >> 8) ^ m[2];
tmp[3] = (T[2] << 24) ^ (tmp[3] >> 8) ^ m[3];
tmp[0] ^= M[0];
tmp[1] ^= M[1];
tmp[2] ^= M[2];
tmp[3] ^= M[3];
if (i == 0)
break;
v = V[--i];
}
buf_put_be32 (result + 0, tmp[0]);
buf_put_be32 (result + 4, tmp[1]);
buf_put_be32 (result + 8, tmp[2]);
buf_put_be32 (result + 12, tmp[3]);
return (sizeof(V) + sizeof(T) + sizeof(tmp) +
sizeof(int)*2 + sizeof(void*)*6);
}
#endif /*!GCM_TABLES_USE_U64*/
#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
static unsigned long
bshift (unsigned long *b)
{
unsigned long c;
int i;
c = b[3] & 1;
for (i = 3; i > 0; i--)
{
b[i] = (b[i] >> 1) | (b[i - 1] << 31);
}
b[i] >>= 1;
return c;
}
static unsigned int
do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf)
{
unsigned long V[4];
int i, j;
byte *p;
#ifdef WORDS_BIGENDIAN
p = result;
#else
unsigned long T[4];
cipher_block_xor (V, result, buf, 16);
for (i = 0; i < 4; i++)
{
V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8;
V[i] = (V[i] & 0x0000ffff) << 16 | (V[i] & 0xffff0000) >> 16;
}
p = (byte *) T;
#endif
memset (p, 0, 16);
for (i = 0; i < 16; i++)
{
for (j = 0x80; j; j >>= 1)
{
if (hsub[i] & j)
cipher_block_xor (p, p, V, 16);
if (bshift (V))
V[0] ^= 0xe1000000;
}
}
#ifndef WORDS_BIGENDIAN
for (i = 0, p = (byte *) T; i < 16; i += 4, p += 4)
{
result[i + 0] = p[3];
result[i + 1] = p[2];
result[i + 2] = p[1];
result[i + 3] = p[0];
}
#endif
return (sizeof(V) + sizeof(T) + sizeof(int)*2 + sizeof(void*)*5);
}
#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 */
static unsigned int
ghash_internal (gcry_cipher_hd_t c, byte *result, const byte *buf,
size_t nblocks)
{
const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
unsigned int burn = 0;
prefetch_tables (c);
while (nblocks)
{
burn = GHASH (c, result, buf);
buf += blocksize;
nblocks--;
}
return burn + (burn ? 5*sizeof(void*) : 0);
}
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
if (0)
;
#ifdef GCM_USE_INTEL_PCLMUL
else if (features & HWF_INTEL_PCLMUL)
{
c->u_mode.gcm.ghash_fn = _gcry_ghash_intel_pclmul;
_gcry_ghash_setup_intel_pclmul (c);
}
#endif
#ifdef GCM_USE_ARM_PMULL
else if (features & HWF_ARM_PMULL)
{
c->u_mode.gcm.ghash_fn = ghash_armv8_ce_pmull;
ghash_setup_armv8_ce_pmull (c);
}
#endif
#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
else
{
c->u_mode.gcm.ghash_fn = ghash_internal;
fillM (c);
}
}
static inline void
gcm_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 u32
gcm_add32_be128 (byte *ctr, unsigned int add)
{
/* 'ctr' must be aligned to four bytes. */
const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
u32 *pval = (u32 *)(void *)(ctr + blocksize - sizeof(u32));
u32 val;
val = be_bswap32(*pval) + add;
*pval = be_bswap32(val);
return val; /* return result as host-endian value */
}
static inline int
gcm_check_datalen (u32 ctr[2])
{
/* len(plaintext) <= 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 inline int
gcm_check_aadlen_or_ivlen (u32 ctr[2])
{
/* len(aad/iv) <= 2^64-1 bits ~= 2^61-1 bytes */
if (ctr[1] > 0x1fffffffU)
return 0;
if (ctr[1] < 0x1fffffffU)
return 1;
if (ctr[0] <= 0xffffffffU)
return 1;
return 0;
}
static void
do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf,
size_t buflen, int do_padding)
{
unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
unsigned int unused = c->u_mode.gcm.mac_unused;
ghash_fn_t ghash_fn = c->u_mode.gcm.ghash_fn;
size_t nblocks, n;
unsigned int burn = 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)
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. */
burn = ghash_fn (c, hash, c->u_mode.gcm.macbuf, 1);
unused = 0;
}
nblocks = buflen / blocksize;
if (nblocks)
{
burn = ghash_fn (c, hash, buf, nblocks);
buf += blocksize * nblocks;
buflen -= blocksize * nblocks;
}
}
while (buflen > 0);
c->u_mode.gcm.mac_unused = unused;
if (burn)
_gcry_burn_stack (burn);
}
static gcry_err_code_t
gcm_ctr_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
const byte *inbuf, size_t inbuflen)
{
gcry_err_code_t err = 0;
while (inbuflen)
{
u32 nblocks_to_overflow;
u32 num_ctr_increments;
u32 curr_ctr_low;
size_t currlen = inbuflen;
byte ctr_copy[GCRY_GCM_BLOCK_LEN];
int fix_ctr = 0;
/* GCM CTR increments only least significant 32-bits, without carry
* to upper 96-bits of counter. Using generic CTR implementation
* directly would carry 32-bit overflow to upper 96-bit. Detect
* if input length is long enough to cause overflow, and limit
* input length so that CTR overflow happen but updated CTR value is
* not used to encrypt further input. After overflow, upper 96 bits
* of CTR are restored to cancel out modification done by generic CTR
* encryption. */
if (inbuflen > c->unused)
{
curr_ctr_low = gcm_add32_be128 (c->u_ctr.ctr, 0);
/* Number of CTR increments this inbuflen would cause. */
num_ctr_increments = (inbuflen - c->unused) / GCRY_GCM_BLOCK_LEN +
!!((inbuflen - c->unused) % GCRY_GCM_BLOCK_LEN);
if ((u32)(num_ctr_increments + curr_ctr_low) < curr_ctr_low)
{
nblocks_to_overflow = 0xffffffffU - curr_ctr_low + 1;
currlen = nblocks_to_overflow * GCRY_GCM_BLOCK_LEN + c->unused;
if (currlen > inbuflen)
{
currlen = inbuflen;
}
fix_ctr = 1;
cipher_block_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN);
}
}
err = _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, currlen);
if (err != 0)
return err;
if (fix_ctr)
{
/* Lower 32-bits of CTR should now be zero. */
gcry_assert(gcm_add32_be128 (c->u_ctr.ctr, 0) == 0);
/* Restore upper part of CTR. */
buf_cpy(c->u_ctr.ctr, ctr_copy, GCRY_GCM_BLOCK_LEN - sizeof(u32));
wipememory(ctr_copy, sizeof(ctr_copy));
}
inbuflen -= currlen;
inbuf += currlen;
outbuflen -= currlen;
outbuf += currlen;
}
return err;
}
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;
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->u_mode.gcm.ghash_data_finalized
|| !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
_gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
return GPG_ERR_INV_STATE;
if (!c->u_mode.gcm.ghash_aad_finalized)
{
/* Start of encryption marks end of AAD stream. */
do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
c->u_mode.gcm.ghash_aad_finalized = 1;
}
gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen);
if (!gcm_check_datalen(c->u_mode.gcm.datalen))
{
c->u_mode.gcm.datalen_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
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 = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, currlen);
if (err != 0)
return err;
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_decrypt (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;
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->u_mode.gcm.ghash_data_finalized
|| !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
_gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
if (!c->u_mode.gcm.ghash_aad_finalized)
{
/* Start of decryption marks end of AAD stream. */
do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
c->u_mode.gcm.ghash_aad_finalized = 1;
}
gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen);
if (!gcm_check_datalen(c->u_mode.gcm.datalen))
{
c->u_mode.gcm.datalen_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
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;
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)
return err;
outbuf += currlen;
inbuf += currlen;
outbuflen -= currlen;
inbuflen -= currlen;
}
return 0;
}
gcry_err_code_t
_gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
const byte * aadbuf, size_t aadbuflen)
{
static const unsigned char zerobuf[MAX_BLOCKSIZE];
if (c->spec->blocksize != GCRY_GCM_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->u_mode.gcm.ghash_aad_finalized
|| c->u_mode.gcm.ghash_data_finalized
|| !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
_gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
gcm_bytecounter_add(c->u_mode.gcm.aadlen, aadbuflen);
if (!gcm_check_aadlen_or_ivlen(c->u_mode.gcm.aadlen))
{
c->u_mode.gcm.datalen_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen, 0);
return 0;
}
void
_gcry_cipher_gcm_setkey (gcry_cipher_hd_t c)
{
memset (c->u_mode.gcm.u_ghash_key.key, 0, GCRY_GCM_BLOCK_LEN);
c->spec->encrypt (&c->context.c, c->u_mode.gcm.u_ghash_key.key,
c->u_mode.gcm.u_ghash_key.key);
setupM (c);
}
static gcry_err_code_t
_gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
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, GCRY_GCM_BLOCK_LEN);
c->u_mode.gcm.datalen_over_limits = 0;
c->u_mode.gcm.ghash_data_finalized = 0;
c->u_mode.gcm.ghash_aad_finalized = 0;
if (ivlen == 0)
return GPG_ERR_INV_LENGTH;
if (ivlen != GCRY_GCM_BLOCK_LEN - 4)
{
u32 iv_bytes[2] = {0, 0};
u32 bitlengths[2][2];
if (!c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
memset(c->u_ctr.ctr, 0, GCRY_GCM_BLOCK_LEN);
gcm_bytecounter_add(iv_bytes, ivlen);
if (!gcm_check_aadlen_or_ivlen(iv_bytes))
{
c->u_mode.gcm.datalen_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
do_ghash_buf(c, c->u_ctr.ctr, iv, ivlen, 1);
/* iv length, 64-bit */
bitlengths[1][1] = be_bswap32(iv_bytes[0] << 3);
bitlengths[1][0] = be_bswap32((iv_bytes[0] >> 29) |
(iv_bytes[1] << 3));
/* zeros, 64-bit */
bitlengths[0][1] = 0;
bitlengths[0][0] = 0;
do_ghash_buf(c, c->u_ctr.ctr, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN, 1);
wipememory (iv_bytes, sizeof iv_bytes);
wipememory (bitlengths, sizeof bitlengths);
}
else
{
/* 96-bit IV is handled differently. */
memcpy (c->u_ctr.ctr, iv, ivlen);
c->u_ctr.ctr[12] = c->u_ctr.ctr[13] = c->u_ctr.ctr[14] = 0;
c->u_ctr.ctr[15] = 1;
}
c->spec->encrypt (&c->context.c, c->u_mode.gcm.tagiv, c->u_ctr.ctr);
gcm_add32_be128 (c->u_ctr.ctr, 1);
c->unused = 0;
c->marks.iv = 1;
c->marks.tag = 0;
return 0;
}
gcry_err_code_t
_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
c->marks.iv = 0;
c->marks.tag = 0;
c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
if (fips_mode ())
{
/* Direct invocation of GCM setiv in FIPS mode disables encryption. */
c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1;
}
return _gcry_cipher_gcm_initiv (c, iv, ivlen);
}
#if 0 && TODO
void
_gcry_cipher_gcm_geniv (gcry_cipher_hd_t c,
byte *ivout, size_t ivoutlen, const byte *nonce,
size_t noncelen)
{
/* nonce: user provided part (might be null) */
/* noncelen: check if proper length (if nonce not null) */
/* ivout: iv used to initialize gcm, output to user */
/* ivoutlen: check correct size */
byte iv[IVLEN];
if (!ivout)
return GPG_ERR_INV_ARG;
if (ivoutlen != IVLEN)
return GPG_ERR_INV_LENGTH;
if (nonce != NULL && !is_nonce_ok_len(noncelen))
return GPG_ERR_INV_ARG;
gcm_generate_iv(iv, nonce, noncelen);
c->marks.iv = 0;
c->marks.tag = 0;
c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
_gcry_cipher_gcm_initiv (c, iv, IVLEN);
buf_cpy(ivout, iv, IVLEN);
wipememory(iv, sizeof(iv));
}
#endif
static int
is_tag_length_valid(size_t taglen)
{
switch (taglen)
{
/* Allowed tag lengths from NIST SP 800-38D. */
case 128 / 8: /* GCRY_GCM_BLOCK_LEN */
case 120 / 8:
case 112 / 8:
case 104 / 8:
case 96 / 8:
case 64 / 8:
case 32 / 8:
return 1;
default:
return 0;
}
}
static gcry_err_code_t
_gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
byte * outbuf, size_t outbuflen, int check)
{
if (!(is_tag_length_valid (outbuflen) || outbuflen >= GCRY_GCM_BLOCK_LEN))
return GPG_ERR_INV_LENGTH;
if (c->u_mode.gcm.datalen_over_limits)
return GPG_ERR_INV_LENGTH;
if (!c->marks.tag)
{
u32 bitlengths[2][2];
if (!c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
/* aad length */
bitlengths[0][1] = be_bswap32(c->u_mode.gcm.aadlen[0] << 3);
bitlengths[0][0] = be_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
(c->u_mode.gcm.aadlen[1] << 3));
/* data length */
bitlengths[1][1] = be_bswap32(c->u_mode.gcm.datalen[0] << 3);
bitlengths[1][0] = be_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
(c->u_mode.gcm.datalen[1] << 3));
/* Finalize data-stream. */
do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
c->u_mode.gcm.ghash_aad_finalized = 1;
c->u_mode.gcm.ghash_data_finalized = 1;
/* Add bitlengths to tag. */
do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths,
GCRY_GCM_BLOCK_LEN, 1);
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));
wipememory (c->u_mode.gcm.macbuf, GCRY_GCM_BLOCK_LEN);
wipememory (c->u_mode.gcm.tagiv, GCRY_GCM_BLOCK_LEN);
wipememory (c->u_mode.gcm.aadlen, sizeof (c->u_mode.gcm.aadlen));
wipememory (c->u_mode.gcm.datalen, sizeof (c->u_mode.gcm.datalen));
}
if (!check)
{
if (outbuflen > GCRY_GCM_BLOCK_LEN)
outbuflen = GCRY_GCM_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.u_tag.tag, outbuflen);
}
else
{
/* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
* and thus we need to compare its length first. */
if (!is_tag_length_valid (outbuflen)
|| !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen))
return GPG_ERR_CHECKSUM;
}
return 0;
}
gcry_err_code_t
_gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
size_t taglen)
{
/* Outputting authentication tag is part of encryption. */
if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
return GPG_ERR_INV_STATE;
return _gcry_cipher_gcm_tag (c, outtag, taglen, 0);
}
gcry_err_code_t
_gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
size_t taglen)
{
return _gcry_cipher_gcm_tag (c, (unsigned char *) intag, taglen, 1);
}
diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h
index 47b7b6f9..5db82e00 100644
--- a/cipher/cipher-internal.h
+++ b/cipher/cipher-internal.h
@@ -1,795 +1,795 @@
/* cipher-internal.h - Internal defs for cipher.c
* Copyright (C) 2011 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef G10_CIPHER_INTERNAL_H
#define G10_CIPHER_INTERNAL_H
#include "./poly1305-internal.h"
/* The maximum supported size of a block in bytes. */
#define MAX_BLOCKSIZE 16
/* The length for an OCB block. Although OCB supports any block
length it does not make sense to use a 64 bit blocklen (and cipher)
because this reduces the security margin to an unacceptable state.
Thus we require a cipher with 128 bit blocklength. */
#define OCB_BLOCK_LEN (128/8)
/* The size of the pre-computed L table for OCB. This takes the same
size as the table used for GCM and thus we don't save anything by
not using such a table. */
#define OCB_L_TABLE_SIZE 16
/* Check the above constants. */
#if OCB_BLOCK_LEN > MAX_BLOCKSIZE
# error OCB_BLOCKLEN > MAX_BLOCKSIZE
#endif
/* Magic values for the context structure. */
#define CTX_MAGIC_NORMAL 0x24091964
#define CTX_MAGIC_SECURE 0x46919042
/* Try to use 16 byte aligned cipher context for better performance.
We use the aligned attribute, thus it is only possible to implement
this with gcc. */
#undef NEED_16BYTE_ALIGNED_CONTEXT
#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# define NEED_16BYTE_ALIGNED_CONTEXT 1
#endif
/* Undef this symbol to trade GCM speed for 256 bytes of memory per context */
#define GCM_USE_TABLES 1
/* GCM_USE_INTEL_PCLMUL indicates whether to compile GCM with Intel PCLMUL
code. */
#undef GCM_USE_INTEL_PCLMUL
#if defined(ENABLE_PCLMUL_SUPPORT) && defined(GCM_USE_TABLES)
# if ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__))
# if __GNUC__ >= 4
# define GCM_USE_INTEL_PCLMUL 1
# endif
# endif
#endif /* GCM_USE_INTEL_PCLMUL */
/* GCM_USE_ARM_PMULL indicates whether to compile GCM with ARMv8 PMULL code. */
#undef GCM_USE_ARM_PMULL
#if defined(ENABLE_ARM_CRYPTO_SUPPORT) && defined(GCM_USE_TABLES)
# if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
&& defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO)
# define GCM_USE_ARM_PMULL 1
# elif defined(__AARCH64EL__) && \
defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
# define GCM_USE_ARM_PMULL 1
# 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 */
typedef unsigned int (*ghash_fn_t) (gcry_cipher_hd_t c, byte *result,
const byte *buf, size_t nblocks);
/* 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
context, the align attribute as used in rijndael.c does not work on
its own. Thus we need to make sure that the entire context
structure is a aligned on that boundary. We achieve this by
defining a new type and use that instead of our usual alignment
type. */
typedef union
{
PROPERLY_ALIGNED_TYPE foo;
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
char bar[16] __attribute__ ((aligned (16)));
#endif
char c[1];
} 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
{
int magic;
size_t actual_handle_size; /* Allocated size of this handle. */
size_t handle_offset; /* Offset to the malloced block. */
gcry_cipher_spec_t *spec;
/* The algorithm id. This is a hack required because the module
interface does not easily allow to retrieve this value. */
int algo;
/* A structure with function pointers for mode operations. */
struct {
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);
} 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)(void *context, unsigned char *tweak,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks, int encrypt);
} bulk;
int mode;
unsigned int flags;
struct {
unsigned int key:1; /* Set to 1 if a key has been set. */
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. */
} marks;
/* The initialization vector. For best performance we make sure
that it is properly aligned. In particular some implementations
of bulk operations expect an 16 byte aligned IV. IV is also used
to store CBC-MAC in CCM mode; counter IV is stored in U_CTR. For
OCB mode it is used for the offset value. */
union {
cipher_context_alignment_t iv_align;
unsigned char iv[MAX_BLOCKSIZE];
} u_iv;
/* The counter for CTR mode. This field is also used by AESWRAP and
thus we can't use the U_IV union. For OCB mode it is used for
the checksum. */
union {
cipher_context_alignment_t iv_align;
unsigned char ctr[MAX_BLOCKSIZE];
} u_ctr;
/* Space to save an IV or CTR for chaining operations. */
unsigned char lastiv[MAX_BLOCKSIZE];
int unused; /* Number of unused bytes in LASTIV. */
union {
/* Mode specific storage for CCM mode. */
struct {
u64 encryptlen;
u64 aadlen;
unsigned int authlen;
/* Space to save partial input lengths for MAC. */
unsigned char macbuf[GCRY_CCM_BLOCK_LEN];
int mac_unused; /* Number of unprocessed bytes in MACBUF. */
unsigned char s0[GCRY_CCM_BLOCK_LEN];
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;
/* Mode specific storage for Poly1305 mode. */
struct {
/* byte counter for AAD. */
u32 aadcount[2];
/* byte counter for data. */
u32 datacount[2];
unsigned int aad_finalized:1;
unsigned int bytecount_over_limits:1;
poly1305_context_t ctx;
} poly1305;
/* Mode specific storage for CMAC mode. */
gcry_cmac_context_t cmac;
/* Mode specific storage for EAX mode. */
struct {
/* CMAC for header (AAD). */
gcry_cmac_context_t cmac_header;
/* CMAC for ciphertext. */
gcry_cmac_context_t cmac_ciphertext;
} eax;
/* Mode specific storage for GCM mode. */
struct {
/* The interim tag for GCM mode. */
union {
cipher_context_alignment_t iv_align;
unsigned char tag[MAX_BLOCKSIZE];
} u_tag;
/* Space to save partial input lengths for MAC. */
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];
/* encrypted tag counter */
unsigned char tagiv[MAX_BLOCKSIZE];
unsigned int ghash_data_finalized:1;
unsigned int ghash_aad_finalized:1;
unsigned int datalen_over_limits:1;
unsigned int disallow_encryption_because_of_setiv_in_fips_mode:1;
/* --- Following members are not cleared in gcry_cipher_reset --- */
/* GHASH multiplier from key. */
union {
cipher_context_alignment_t iv_align;
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[4 * 16];
#else
#undef GCM_TABLES_USE_U64
u32 gcm_table[8 * 16];
#endif
#endif
} 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 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];
/* A buffer to hold the offset for the AAD processing. */
unsigned char aad_offset[OCB_BLOCK_LEN];
/* A buffer to hold the current sum of AAD processing. We can't
use tag here because tag may already hold the preprocessed
checksum of the data. */
unsigned char aad_sum[OCB_BLOCK_LEN];
/* A buffer to store AAD data not yet processed. */
unsigned char aad_leftover[OCB_BLOCK_LEN];
/* Number of data/aad blocks processed so far. */
u64 data_nblocks;
u64 aad_nblocks;
/* Number of valid bytes in AAD_LEFTOVER. */
unsigned char aad_nleftover;
/* Length of the tag. Fixed for now but may eventually be
specified using a set of gcry_cipher_flags. */
unsigned char taglen;
/* Flags indicating that the final data/aad block has been
processed. */
unsigned int data_finalized:1;
unsigned int aad_finalized:1;
} ocb;
/* Mode specific storage for XTS mode. */
struct {
/* Pointer to tweak cipher context, allocated after actual
* cipher context. */
char *tweak_context;
} xts;
} u_mode;
/* What follows are two contexts of the cipher in use. The first
one needs to be aligned well enough for the cipher operation
whereas the second one is a copy created by cipher_setkey and
used by cipher_reset. That second copy has no need for proper
aligment because it is only accessed by memcpy. */
cipher_context_alignment_t context;
};
/*-- cipher-cbc.c --*/
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);
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
/* */ (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
gcry_err_code_t _gcry_cipher_cfb_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_cfb8_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_cfb8_decrypt
/* */ (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
/*-- cipher-ofb.c --*/
gcry_err_code_t _gcry_cipher_ofb_encrypt
/* */ (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
/*-- cipher-ctr.c --*/
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);
/*-- cipher-aeswrap.c --*/
gcry_err_code_t _gcry_cipher_aeswrap_encrypt
/* */ (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_cipher_hd_t c,
byte *outbuf, size_t outbuflen,
const byte *inbuf, size_t inbuflen);
/*-- cipher-ccm.c --*/
gcry_err_code_t _gcry_cipher_ccm_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_ccm_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_ccm_set_nonce
/* */ (gcry_cipher_hd_t c, const unsigned char *nonce,
size_t noncelen);
gcry_err_code_t _gcry_cipher_ccm_authenticate
/* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen);
gcry_err_code_t _gcry_cipher_ccm_set_lengths
/* */ (gcry_cipher_hd_t c, u64 encryptedlen, u64 aadlen, u64 taglen);
gcry_err_code_t _gcry_cipher_ccm_get_tag
/* */ (gcry_cipher_hd_t c,
unsigned char *outtag, size_t taglen);
gcry_err_code_t _gcry_cipher_ccm_check_tag
/* */ (gcry_cipher_hd_t c,
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,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
gcry_err_code_t _gcry_cipher_gcm_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_setiv
/* */ (gcry_cipher_hd_t c,
const unsigned char *iv, size_t ivlen);
gcry_err_code_t _gcry_cipher_gcm_authenticate
/* */ (gcry_cipher_hd_t c,
const unsigned char *aadbuf, size_t aadbuflen);
gcry_err_code_t _gcry_cipher_gcm_get_tag
/* */ (gcry_cipher_hd_t c,
unsigned char *outtag, size_t taglen);
gcry_err_code_t _gcry_cipher_gcm_check_tag
/* */ (gcry_cipher_hd_t c,
const unsigned char *intag, size_t taglen);
void _gcry_cipher_gcm_setkey
/* */ (gcry_cipher_hd_t c);
/*-- cipher-poly1305.c --*/
gcry_err_code_t _gcry_cipher_poly1305_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_poly1305_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_poly1305_setiv
/* */ (gcry_cipher_hd_t c,
const unsigned char *iv, size_t ivlen);
gcry_err_code_t _gcry_cipher_poly1305_authenticate
/* */ (gcry_cipher_hd_t c,
const unsigned char *aadbuf, size_t aadbuflen);
gcry_err_code_t _gcry_cipher_poly1305_get_tag
/* */ (gcry_cipher_hd_t c,
unsigned char *outtag, size_t taglen);
gcry_err_code_t _gcry_cipher_poly1305_check_tag
/* */ (gcry_cipher_hd_t c,
const unsigned char *intag, size_t taglen);
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,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
gcry_err_code_t _gcry_cipher_ocb_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_ocb_set_nonce
/* */ (gcry_cipher_hd_t c, const unsigned char *nonce,
size_t noncelen);
gcry_err_code_t _gcry_cipher_ocb_authenticate
/* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen);
gcry_err_code_t _gcry_cipher_ocb_get_tag
/* */ (gcry_cipher_hd_t c,
unsigned char *outtag, size_t taglen);
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_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_xts_decrypt
/* */ (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen);
/* Return the L-value for block N. Note: 'cipher_ocb.c' ensures that N
* will never be multiple of 65536 (1 << OCB_L_TABLE_SIZE), thus N can
* be directly passed to _gcry_ctz() function and resulting index will
* never overflow the table. */
static inline const unsigned char *
ocb_get_l (gcry_cipher_hd_t c, u64 n)
{
unsigned long ntz;
#if ((defined(__i386__) || defined(__x86_64__)) && __GNUC__ >= 4)
/* Assumes that N != 0. */
asm ("rep;bsfl %k[low], %k[ntz]\n\t"
: [ntz] "=r" (ntz)
: [low] "r" ((unsigned long)n)
: "cc");
#else
ntz = _gcry_ctz (n);
#endif
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 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*/
diff --git a/cipher/cipher-ocb.c b/cipher/cipher-ocb.c
index b146d058..c1d1bf4f 100644
--- a/cipher/cipher-ocb.c
+++ b/cipher/cipher-ocb.c
@@ -1,760 +1,760 @@
/* cipher-ocb.c - OCB cipher mode
* Copyright (C) 2015, 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*
* OCB is covered by several patents but may be used freely by most
- * software. See http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm .
+ * software. See https://web.cs.ucdavis.edu/~rogaway/ocb/license.htm .
* In particular license 1 is suitable for Libgcrypt: See
- * http://web.cs.ucdavis.edu/~rogaway/ocb/license1.pdf for the full
+ * https://web.cs.ucdavis.edu/~rogaway/ocb/license1.pdf for the full
* license document; it basically says:
*
* License 1 — License for Open-Source Software Implementations of OCB
* (Jan 9, 2013)
*
* Under this license, you are authorized to make, use, and
* distribute open-source software implementations of OCB. This
* license terminates for you if you sue someone over their
* open-source software implementation of OCB claiming that you have
* a patent covering their implementation.
*/
#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"
/* Double the OCB_BLOCK_LEN sized block B in-place. */
static inline void
double_block (u64 b[2])
{
u64 l_0, l, r;
l = b[1];
r = b[0];
l_0 = -(l >> 63);
l = (l + l) ^ (r >> 63);
r = (r + r) ^ (l_0 & 135);
b[1] = l;
b[0] = r;
}
/* 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)
{
u64 s0l, s1l, s1r, s2r;
unsigned int shift;
s += bitoff / 8;
shift = bitoff % 8;
s0l = buf_get_be64 (s + 0);
s1l = buf_get_be64 (s + 8);
s1r = shift ? s1l : 0;
s2r = shift ? buf_get_be64 (s + 16) : 0;
buf_put_be64 (d + 0, (s0l << shift) | (s1r >> ((64 - shift) & 63)));
buf_put_be64 (d + 8, (s1l << shift) | (s2r >> ((64 - shift) & 63)));
}
/* Get L_big value for block N, where N is multiple of 65536. */
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);
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*));
}
/* Set the nonce for OCB. This requires that the key has been set.
Using it again resets start a new encryption cycle using the same
key. */
gcry_err_code_t
_gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
size_t noncelen)
{
unsigned char ktop[OCB_BLOCK_LEN];
unsigned char stretch[OCB_BLOCK_LEN + 8];
unsigned int bottom;
unsigned int burn = 0;
unsigned int nburn;
/* Check args. */
if (!c->marks.key)
return GPG_ERR_INV_STATE; /* Key must have been set first. */
switch (c->u_mode.ocb.taglen)
{
case 8:
case 12:
case 16:
break;
default:
return GPG_ERR_BUG; /* Invalid tag length. */
}
if (c->spec->blocksize != OCB_BLOCK_LEN)
return GPG_ERR_CIPHER_ALGO;
if (!nonce)
return GPG_ERR_INV_ARG;
/* 120 bit is the allowed maximum. In addition we impose a minimum
of 64 bit. */
if (noncelen > (120/8) || noncelen < (64/8) || noncelen >= OCB_BLOCK_LEN)
return GPG_ERR_INV_LENGTH;
/* Prepare the nonce. */
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;
bottom = ktop[OCB_BLOCK_LEN - 1] & 0x3f;
ktop[OCB_BLOCK_LEN - 1] &= 0xc0; /* Zero the bottom bits. */
nburn = c->spec->encrypt (&c->context.c, ktop, ktop);
burn = nburn > burn ? nburn : burn;
/* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
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);
c->marks.iv = 1;
/* Checksum_0 = zeros(128)
(We use the CTR field to store the checksum) */
memset (c->u_ctr.ctr, 0, OCB_BLOCK_LEN);
/* Clear AAD buffer. */
memset (c->u_mode.ocb.aad_offset, 0, OCB_BLOCK_LEN);
memset (c->u_mode.ocb.aad_sum, 0, OCB_BLOCK_LEN);
/* Setup other values. */
memset (c->lastiv, 0, sizeof(c->lastiv));
c->unused = 0;
c->marks.tag = 0;
c->marks.finalize = 0;
c->u_mode.ocb.data_nblocks = 0;
c->u_mode.ocb.aad_nblocks = 0;
c->u_mode.ocb.aad_nleftover = 0;
c->u_mode.ocb.data_finalized = 0;
c->u_mode.ocb.aad_finalized = 0;
/* log_printhex ("L_* ", c->u_mode.ocb.L_star, OCB_BLOCK_LEN); */
/* log_printhex ("L_$ ", c->u_mode.ocb.L_dollar, OCB_BLOCK_LEN); */
/* log_printhex ("L_0 ", c->u_mode.ocb.L[0], OCB_BLOCK_LEN); */
/* log_printhex ("L_1 ", c->u_mode.ocb.L[1], OCB_BLOCK_LEN); */
/* log_debug ( "bottom : %u (decimal)\n", bottom); */
/* log_printhex ("Ktop ", ktop, OCB_BLOCK_LEN); */
/* log_printhex ("Stretch ", stretch, sizeof stretch); */
/* log_printhex ("Offset_0 ", c->u_iv.iv, OCB_BLOCK_LEN); */
/* Cleanup */
wipememory (ktop, sizeof ktop);
wipememory (stretch, sizeof stretch);
if (burn > 0)
_gcry_burn_stack (burn + 4*sizeof(void*));
return 0;
}
/* Process additional authentication data. This implementation allows
to add additional authentication data at any time before the final
gcry_cipher_gettag. */
gcry_err_code_t
_gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
size_t abuflen)
{
const size_t table_maxblks = 1 << OCB_L_TABLE_SIZE;
const u32 table_size_mask = ((1 << OCB_L_TABLE_SIZE) - 1);
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
been finalized (i.e. a short block has been processed). */
if (!c->marks.iv || c->marks.tag || c->u_mode.ocb.aad_finalized)
return GPG_ERR_INV_STATE;
/* Check correct usage and arguments. */
if (c->spec->blocksize != OCB_BLOCK_LEN)
return GPG_ERR_CIPHER_ALGO;
/* Process remaining data from the last call first. */
if (c->u_mode.ocb.aad_nleftover)
{
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)
{
c->u_mode.ocb.aad_nblocks++;
if ((c->u_mode.ocb.aad_nblocks % table_maxblks) == 0)
{
/* Table overflow, L needs to be generated. */
ocb_get_L_big(c, c->u_mode.ocb.aad_nblocks + 1, l_tmp);
}
else
{
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)} */
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) */
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;
cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
c->u_mode.ocb.aad_nleftover = 0;
}
}
if (!abuflen)
{
if (burn > 0)
_gcry_burn_stack (burn + 4*sizeof(void*));
return 0;
}
/* Full blocks handling. */
while (abuflen >= OCB_BLOCK_LEN)
{
size_t nblks = abuflen / OCB_BLOCK_LEN;
size_t nmaxblks;
/* Check how many blocks to process till table overflow. */
nmaxblks = (c->u_mode.ocb.aad_nblocks + 1) % table_maxblks;
nmaxblks = (table_maxblks - nmaxblks) % table_maxblks;
if (nmaxblks == 0)
{
/* Table overflow, generate L and process one block. */
c->u_mode.ocb.aad_nblocks++;
ocb_get_L_big(c, c->u_mode.ocb.aad_nblocks, l_tmp);
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
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) */
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;
cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
abuf += OCB_BLOCK_LEN;
abuflen -= OCB_BLOCK_LEN;
nblks--;
/* With overflow handled, retry loop again. Next overflow will
* happen after 65535 blocks. */
continue;
}
nblks = nblks < nmaxblks ? nblks : nmaxblks;
/* Use a bulk method if available. */
if (nblks && c->bulk.ocb_auth)
{
size_t nleft;
size_t ndone;
nleft = c->bulk.ocb_auth (c, abuf, nblks);
ndone = nblks - nleft;
abuf += ndone * OCB_BLOCK_LEN;
abuflen -= ndone * OCB_BLOCK_LEN;
nblks = nleft;
}
/* Hash all full blocks. */
while (nblks)
{
c->u_mode.ocb.aad_nblocks++;
gcry_assert(c->u_mode.ocb.aad_nblocks & table_size_mask);
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
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) */
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;
cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
abuf += OCB_BLOCK_LEN;
abuflen -= OCB_BLOCK_LEN;
nblks--;
}
}
/* Store away the remaining data. */
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)
_gcry_burn_stack (burn + 4*sizeof(void*));
return 0;
}
/* Hash final partial AAD block. */
static void
ocb_aad_finalize (gcry_cipher_hd_t c)
{
unsigned char l_tmp[OCB_BLOCK_LEN];
unsigned int burn = 0;
unsigned int nburn;
/* Check that a nonce and thus a key has been set and that we have
not yet computed the tag. We also skip this if the aad has been
finalized. */
if (!c->marks.iv || c->marks.tag || c->u_mode.ocb.aad_finalized)
return;
if (c->spec->blocksize != OCB_BLOCK_LEN)
return; /* Ooops. */
/* Hash final partial block if any. */
if (c->u_mode.ocb.aad_nleftover)
{
/* Offset_* = Offset_m xor L_* */
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;
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;
cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
c->u_mode.ocb.aad_nleftover = 0;
}
/* Mark AAD as finalized so that gcry_cipher_ocb_authenticate can
* return an erro when called again. */
c->u_mode.ocb.aad_finalized = 1;
if (burn > 0)
_gcry_burn_stack (burn + 4*sizeof(void*));
}
/* Checksumming for encrypt and decrypt. */
static void
ocb_checksum (unsigned char *chksum, const unsigned char *plainbuf,
size_t nblks)
{
while (nblks > 0)
{
/* Checksum_i = Checksum_{i-1} xor P_i */
cipher_block_xor_1(chksum, plainbuf, OCB_BLOCK_LEN);
plainbuf += OCB_BLOCK_LEN;
nblks--;
}
}
/* Common code for encrypt and decrypt. */
static gcry_err_code_t
ocb_crypt (gcry_cipher_hd_t c, int encrypt,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
const size_t table_maxblks = 1 << OCB_L_TABLE_SIZE;
const u32 table_size_mask = ((1 << OCB_L_TABLE_SIZE) - 1);
unsigned char l_tmp[OCB_BLOCK_LEN];
unsigned int burn = 0;
unsigned int nburn;
gcry_cipher_encrypt_t crypt_fn =
encrypt ? c->spec->encrypt : c->spec->decrypt;
/* Check that a nonce and thus a key has been set and that we are
not yet in end of data state. */
if (!c->marks.iv || c->u_mode.ocb.data_finalized)
return GPG_ERR_INV_STATE;
/* Check correct usage and arguments. */
if (c->spec->blocksize != OCB_BLOCK_LEN)
return GPG_ERR_CIPHER_ALGO;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if (c->marks.finalize)
; /* Allow arbitarty length. */
else if ((inbuflen % OCB_BLOCK_LEN))
return GPG_ERR_INV_LENGTH; /* We support only full blocks for now. */
/* Full blocks handling. */
while (inbuflen >= OCB_BLOCK_LEN)
{
size_t nblks = inbuflen / OCB_BLOCK_LEN;
size_t nmaxblks;
/* Check how many blocks to process till table overflow. */
nmaxblks = (c->u_mode.ocb.data_nblocks + 1) % table_maxblks;
nmaxblks = (table_maxblks - nmaxblks) % table_maxblks;
if (nmaxblks == 0)
{
/* Table overflow, generate L and process one block. */
c->u_mode.ocb.data_nblocks++;
ocb_get_L_big(c, c->u_mode.ocb.data_nblocks, l_tmp);
if (encrypt)
{
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_checksum (c->u_ctr.ctr, inbuf, 1);
}
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
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) */
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;
cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
if (!encrypt)
{
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_checksum (c->u_ctr.ctr, outbuf, 1);
}
inbuf += OCB_BLOCK_LEN;
inbuflen -= OCB_BLOCK_LEN;
outbuf += OCB_BLOCK_LEN;
outbuflen =- OCB_BLOCK_LEN;
nblks--;
/* With overflow handled, retry loop again. Next overflow will
* happen after 65535 blocks. */
continue;
}
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)
{
size_t nleft;
size_t ndone;
nleft = c->bulk.ocb_crypt (c, outbuf, inbuf, nblks, encrypt);
ndone = nblks - nleft;
inbuf += ndone * OCB_BLOCK_LEN;
outbuf += ndone * OCB_BLOCK_LEN;
inbuflen -= ndone * OCB_BLOCK_LEN;
outbuflen -= ndone * OCB_BLOCK_LEN;
nblks = nleft;
}
if (nblks)
{
size_t nblks_chksum = nblks;
if (encrypt)
{
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_checksum (c->u_ctr.ctr, inbuf, nblks_chksum);
}
/* Encrypt all full blocks. */
while (nblks)
{
c->u_mode.ocb.data_nblocks++;
gcry_assert(c->u_mode.ocb.data_nblocks & table_size_mask);
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
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) */
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;
cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
inbuf += OCB_BLOCK_LEN;
inbuflen -= OCB_BLOCK_LEN;
outbuf += OCB_BLOCK_LEN;
outbuflen =- OCB_BLOCK_LEN;
nblks--;
}
if (!encrypt)
{
/* Checksum_i = Checksum_{i-1} xor P_i */
ocb_checksum (c->u_ctr.ctr,
outbuf - nblks_chksum * OCB_BLOCK_LEN,
nblks_chksum);
}
}
}
/* Encrypt final partial block. Note that we expect INBUFLEN to be
shorter than OCB_BLOCK_LEN (see above). */
if (inbuflen)
{
unsigned char pad[OCB_BLOCK_LEN];
/* Offset_* = Offset_m xor L_* */
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;
if (encrypt)
{
/* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
/* Note that INBUFLEN is less than OCB_BLOCK_LEN. */
buf_cpy (l_tmp, inbuf, inbuflen);
memset (l_tmp + inbuflen, 0, OCB_BLOCK_LEN - inbuflen);
l_tmp[inbuflen] = 0x80;
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);
}
else
{
/* P_* = C_* xor Pad[1..bitlen(C_*)] */
/* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
cipher_block_cpy (l_tmp, pad, OCB_BLOCK_LEN);
buf_cpy (l_tmp, inbuf, inbuflen);
cipher_block_xor_1 (l_tmp, pad, OCB_BLOCK_LEN);
l_tmp[inbuflen] = 0x80;
buf_cpy (outbuf, l_tmp, inbuflen);
cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN);
}
}
/* Compute the tag if the finalize flag has been set. */
if (c->marks.finalize)
{
/* Tag = ENCIPHER(K, Checksum xor Offset xor L_$) xor HASH(K,A) */
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;
c->u_mode.ocb.data_finalized = 1;
/* Note that the the final part of the tag computation is done
by _gcry_cipher_ocb_get_tag. */
}
if (burn > 0)
_gcry_burn_stack (burn + 4*sizeof(void*));
return 0;
}
/* Encrypt (INBUF,INBUFLEN) in OCB mode to OUTBUF. OUTBUFLEN gives
the allocated size of OUTBUF. This function accepts only multiples
of a full block unless gcry_cipher_final has been called in which
case the next block may have any length. */
gcry_err_code_t
_gcry_cipher_ocb_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
return ocb_crypt (c, 1, outbuf, outbuflen, inbuf, inbuflen);
}
/* Decrypt (INBUF,INBUFLEN) in OCB mode to OUTBUF. OUTBUFLEN gives
the allocated size of OUTBUF. This function accepts only multiples
of a full block unless gcry_cipher_final has been called in which
case the next block may have any length. */
gcry_err_code_t
_gcry_cipher_ocb_decrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
return ocb_crypt (c, 0, outbuf, outbuflen, inbuf, inbuflen);
}
/* Compute the tag. The last data operation has already done some
part of it. To allow adding AAD even after having done all data,
we finish the tag computation only here. */
static void
compute_tag_if_needed (gcry_cipher_hd_t c)
{
if (!c->marks.tag)
{
ocb_aad_finalize (c);
cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum,
OCB_BLOCK_LEN);
c->marks.tag = 1;
}
}
/* Copy the already computed tag to OUTTAG. OUTTAGSIZE is the
allocated size of OUTTAG; the function returns an error if that is
too short to hold the tag. */
gcry_err_code_t
_gcry_cipher_ocb_get_tag (gcry_cipher_hd_t c,
unsigned char *outtag, size_t outtagsize)
{
if (c->u_mode.ocb.taglen > outtagsize)
return GPG_ERR_BUFFER_TOO_SHORT;
if (!c->u_mode.ocb.data_finalized)
return GPG_ERR_INV_STATE; /* Data has not yet been finalized. */
compute_tag_if_needed (c);
memcpy (outtag, c->u_mode.ocb.tag, c->u_mode.ocb.taglen);
return 0;
}
/* Check that the tag (INTAG,TAGLEN) matches the computed tag for the
handle C. */
gcry_err_code_t
_gcry_cipher_ocb_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
size_t taglen)
{
size_t n;
if (!c->u_mode.ocb.data_finalized)
return GPG_ERR_INV_STATE; /* Data has not yet been finalized. */
compute_tag_if_needed (c);
n = c->u_mode.ocb.taglen;
if (taglen < n)
n = taglen;
if (!buf_eq_const (intag, c->u_mode.ocb.tag, n)
|| c->u_mode.ocb.taglen != taglen)
return GPG_ERR_CHECKSUM;
return 0;
}
diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c
index a3fd2993..ce858b9c 100644
--- a/cipher/cipher-ofb.c
+++ b/cipher/cipher-ofb.c
@@ -1,96 +1,96 @@
/* cipher-ofb.c - Generic OFB mode implementation
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2005, 2007, 2008, 2009, 2011 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/>.
+ * License along with this program; if not, see <https://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_ofb_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
unsigned char *ivp;
gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize_shift = _gcry_blocksize_shift(c);
size_t blocksize = 1 << blocksize_shift;
unsigned int burn, nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if ( inbuflen <= c->unused )
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV */
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor(outbuf, ivp, inbuf, inbuflen);
c->unused -= inbuflen;
return 0;
}
burn = 0;
if( c->unused )
{
inbuflen -= c->unused;
ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor(outbuf, ivp, inbuf, c->unused);
outbuf += c->unused;
inbuf += c->unused;
c->unused = 0;
}
/* Now we can process complete blocks. */
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 );
burn = nburn > burn ? nburn : burn;
c->unused = blocksize;
c->unused -= inbuflen;
buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
outbuf += inbuflen;
inbuf += inbuflen;
inbuflen = 0;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c
index bb475236..51635d08 100644
--- a/cipher/cipher-poly1305.c
+++ b/cipher/cipher-poly1305.c
@@ -1,375 +1,375 @@
/* 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.
*
* 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/>.
+ * License along with this program; if not, see <https://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"
#include "./poly1305-internal.h"
static inline int
poly1305_bytecounter_add (u32 ctr[2], size_t add)
{
int overflow = 0;
if (sizeof(add) > sizeof(u32))
{
u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
ctr[1] += high_add;
if (ctr[1] < high_add)
overflow = 1;
}
ctr[0] += add;
if (ctr[0] >= add)
return overflow;
ctr[1] += 1;
return (ctr[1] < 1) || overflow;
}
static void
poly1305_fill_bytecounts (gcry_cipher_hd_t c)
{
u32 lenbuf[4];
lenbuf[0] = le_bswap32(c->u_mode.poly1305.aadcount[0]);
lenbuf[1] = le_bswap32(c->u_mode.poly1305.aadcount[1]);
lenbuf[2] = le_bswap32(c->u_mode.poly1305.datacount[0]);
lenbuf[3] = le_bswap32(c->u_mode.poly1305.datacount[1]);
_gcry_poly1305_update (&c->u_mode.poly1305.ctx, (byte*)lenbuf,
sizeof(lenbuf));
wipememory(lenbuf, sizeof(lenbuf));
}
static void
poly1305_do_padding (gcry_cipher_hd_t c, u32 ctr[2])
{
static const byte zero_padding_buf[15] = {};
u32 padding_count;
/* Padding to 16 byte boundary. */
if (ctr[0] % 16 > 0)
{
padding_count = 16 - ctr[0] % 16;
_gcry_poly1305_update (&c->u_mode.poly1305.ctx, zero_padding_buf,
padding_count);
}
}
static void
poly1305_aad_finish (gcry_cipher_hd_t c)
{
/* After AAD, feed padding bytes so we get 16 byte alignment. */
poly1305_do_padding (c, c->u_mode.poly1305.aadcount);
/* Start of encryption marks end of AAD stream. */
c->u_mode.poly1305.aad_finalized = 1;
c->u_mode.poly1305.datacount[0] = 0;
c->u_mode.poly1305.datacount[1] = 0;
}
static gcry_err_code_t
poly1305_set_zeroiv (gcry_cipher_hd_t c)
{
byte zero[8] = { 0, };
return _gcry_cipher_poly1305_setiv (c, zero, sizeof(zero));
}
gcry_err_code_t
_gcry_cipher_poly1305_authenticate (gcry_cipher_hd_t c,
const byte * aadbuf, size_t aadbuflen)
{
if (c->u_mode.poly1305.bytecount_over_limits)
return GPG_ERR_INV_LENGTH;
if (c->u_mode.poly1305.aad_finalized)
return GPG_ERR_INV_STATE;
if (c->marks.tag)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
poly1305_set_zeroiv(c);
if (poly1305_bytecounter_add(c->u_mode.poly1305.aadcount, aadbuflen))
{
c->u_mode.poly1305.bytecount_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
_gcry_poly1305_update (&c->u_mode.poly1305.ctx, aadbuf, aadbuflen);
return 0;
}
gcry_err_code_t
_gcry_cipher_poly1305_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->u_mode.poly1305.bytecount_over_limits)
return GPG_ERR_INV_LENGTH;
if (!c->marks.iv)
{
err = poly1305_set_zeroiv(c);
if (err)
return err;
}
if (!c->u_mode.poly1305.aad_finalized)
poly1305_aad_finish(c);
if (poly1305_bytecounter_add(c->u_mode.poly1305.datacount, inbuflen))
{
c->u_mode.poly1305.bytecount_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
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;
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;
}
gcry_err_code_t
_gcry_cipher_poly1305_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->u_mode.poly1305.bytecount_over_limits)
return GPG_ERR_INV_LENGTH;
if (!c->marks.iv)
{
err = poly1305_set_zeroiv(c);
if (err)
return err;
}
if (!c->u_mode.poly1305.aad_finalized)
poly1305_aad_finish(c);
if (poly1305_bytecounter_add(c->u_mode.poly1305.datacount, inbuflen))
{
c->u_mode.poly1305.bytecount_over_limits = 1;
return GPG_ERR_INV_LENGTH;
}
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;
}
return 0;
}
static gcry_err_code_t
_gcry_cipher_poly1305_tag (gcry_cipher_hd_t c,
byte * outbuf, size_t outbuflen, int check)
{
gcry_err_code_t err;
if (outbuflen < POLY1305_TAGLEN)
return GPG_ERR_BUFFER_TOO_SHORT;
if (c->u_mode.poly1305.bytecount_over_limits)
return GPG_ERR_INV_LENGTH;
if (!c->marks.iv)
{
err = poly1305_set_zeroiv(c);
if (err)
return err;
}
if (!c->u_mode.poly1305.aad_finalized)
poly1305_aad_finish(c);
if (!c->marks.tag)
{
/* After data, feed padding bytes so we get 16 byte alignment. */
poly1305_do_padding (c, c->u_mode.poly1305.datacount);
/* Write byte counts to poly1305. */
poly1305_fill_bytecounts(c);
_gcry_poly1305_finish(&c->u_mode.poly1305.ctx, c->u_iv.iv);
c->marks.tag = 1;
}
if (!check)
{
memcpy (outbuf, c->u_iv.iv, POLY1305_TAGLEN);
}
else
{
/* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
* and thus we need to compare its length first. */
if (outbuflen != POLY1305_TAGLEN
|| !buf_eq_const (outbuf, c->u_iv.iv, POLY1305_TAGLEN))
return GPG_ERR_CHECKSUM;
}
return 0;
}
gcry_err_code_t
_gcry_cipher_poly1305_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
size_t taglen)
{
return _gcry_cipher_poly1305_tag (c, outtag, taglen, 0);
}
gcry_err_code_t
_gcry_cipher_poly1305_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
size_t taglen)
{
return _gcry_cipher_poly1305_tag (c, (unsigned char *) intag, taglen, 1);
}
void
_gcry_cipher_poly1305_setkey (gcry_cipher_hd_t c)
{
c->u_mode.poly1305.aadcount[0] = 0;
c->u_mode.poly1305.aadcount[1] = 0;
c->u_mode.poly1305.datacount[0] = 0;
c->u_mode.poly1305.datacount[1] = 0;
c->u_mode.poly1305.bytecount_over_limits = 0;
c->u_mode.poly1305.aad_finalized = 0;
c->marks.tag = 0;
c->marks.iv = 0;
}
gcry_err_code_t
_gcry_cipher_poly1305_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
byte tmpbuf[64]; /* size of ChaCha20 block */
gcry_err_code_t err;
/* IV must be 96-bits */
if (!iv && ivlen != (96 / 8))
return GPG_ERR_INV_ARG;
memset(&c->u_mode.poly1305.ctx, 0, sizeof(c->u_mode.poly1305.ctx));
c->u_mode.poly1305.aadcount[0] = 0;
c->u_mode.poly1305.aadcount[1] = 0;
c->u_mode.poly1305.datacount[0] = 0;
c->u_mode.poly1305.datacount[1] = 0;
c->u_mode.poly1305.bytecount_over_limits = 0;
c->u_mode.poly1305.aad_finalized = 0;
c->marks.tag = 0;
c->marks.iv = 0;
/* Set up IV for stream cipher. */
c->spec->setiv (&c->context.c, iv, ivlen);
/* Get the first block from ChaCha20. */
memset(tmpbuf, 0, sizeof(tmpbuf));
c->spec->stencrypt(&c->context.c, tmpbuf, tmpbuf, sizeof(tmpbuf));
/* Use the first 32-bytes as Poly1305 key. */
err = _gcry_poly1305_init (&c->u_mode.poly1305.ctx, tmpbuf, POLY1305_KEYLEN);
wipememory(tmpbuf, sizeof(tmpbuf));
if (err)
return err;
c->marks.iv = 1;
return 0;
}
diff --git a/cipher/cipher-selftest.c b/cipher/cipher-selftest.c
index eb3614ad..f7131b2e 100644
--- a/cipher/cipher-selftest.c
+++ b/cipher/cipher-selftest.c
@@ -1,511 +1,511 @@
/* cipher-selftest.c - Helper functions for bulk encryption selftests.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /*HAVE_SYSLOG*/
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#include "cipher-selftest.h"
#ifdef HAVE_STDINT_H
# include <stdint.h> /* uintptr_t */
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#else
/* In this case, uintptr_t is provided by config.h. */
#endif
/* Helper macro to force alignment to 16 bytes. */
#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# define ATTR_ALIGNED_16 __attribute__ ((aligned (16)))
#else
# define ATTR_ALIGNED_16
#endif
/* Return an allocated buffers of size CONTEXT_SIZE with an alignment
of 16. The caller must free that buffer using the address returned
at R_MEM. Returns NULL and sets ERRNO on failure. */
void *
_gcry_cipher_selftest_alloc_ctx (const int context_size, unsigned char **r_mem)
{
int offs;
unsigned int ctx_aligned_size, memsize;
ctx_aligned_size = context_size + 15;
ctx_aligned_size -= ctx_aligned_size & 0xf;
memsize = ctx_aligned_size + 16;
*r_mem = xtrycalloc (1, memsize);
if (!*r_mem)
return NULL;
offs = (16 - ((uintptr_t)*r_mem & 15)) & 15;
return (void*)(*r_mem + offs);
}
/* Run the self-tests for <block cipher>-CBC-<block size>, tests bulk CBC
decryption. Returns NULL on success. */
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)
{
int i, offs;
unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
unsigned int ctx_aligned_size, memsize;
static const unsigned char key[16] ATTR_ALIGNED_16 = {
0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22
};
/* Allocate buffers, align first two elements to 16 bytes and latter to
block size. */
ctx_aligned_size = context_size + 15;
ctx_aligned_size -= ctx_aligned_size & 0xf;
memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16;
mem = xtrycalloc (1, memsize);
if (!mem)
return "failed to allocate memory";
offs = (16 - ((uintptr_t)mem & 15)) & 15;
ctx = (void*)(mem + offs);
iv = ctx + ctx_aligned_size;
iv2 = iv + blocksize;
plaintext = iv2 + blocksize;
plaintext2 = plaintext + nblocks * blocksize;
ciphertext = plaintext2 + nblocks * blocksize;
/* Initialize ctx */
if (setkey_func (ctx, key, sizeof(key), NULL) != GPG_ERR_NO_ERROR)
{
xfree(mem);
return "setkey failed";
}
/* Test single block code path */
memset (iv, 0x4e, blocksize);
memset (iv2, 0x4e, blocksize);
for (i = 0; i < blocksize; i++)
plaintext[i] = i;
/* CBC manually. */
buf_xor (ciphertext, iv, plaintext, blocksize);
encrypt_one (ctx, ciphertext, ciphertext);
memcpy (iv, ciphertext, blocksize);
/* CBC decrypt. */
bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, 1);
if (memcmp (plaintext2, plaintext, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CBC-%d test failed (plaintext mismatch)", cipher,
blocksize * 8);
#else
(void)cipher; /* Not used. */
#endif
return "selftest for CBC failed - see syslog for details";
}
if (memcmp (iv2, iv, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CBC-%d test failed (IV mismatch)", cipher, blocksize * 8);
#endif
return "selftest for CBC failed - see syslog for details";
}
/* Test parallelized code paths */
memset (iv, 0x5f, blocksize);
memset (iv2, 0x5f, blocksize);
for (i = 0; i < nblocks * blocksize; i++)
plaintext[i] = i;
/* Create CBC ciphertext manually. */
for (i = 0; i < nblocks * blocksize; i+=blocksize)
{
buf_xor (&ciphertext[i], iv, &plaintext[i], blocksize);
encrypt_one (ctx, &ciphertext[i], &ciphertext[i]);
memcpy (iv, &ciphertext[i], blocksize);
}
/* Decrypt using bulk CBC and compare result. */
bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
if (memcmp (plaintext2, plaintext, nblocks * blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CBC-%d test failed (plaintext mismatch, parallel path)",
cipher, blocksize * 8);
#endif
return "selftest for CBC failed - see syslog for details";
}
if (memcmp (iv2, iv, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CBC-%d test failed (IV mismatch, parallel path)",
cipher, blocksize * 8);
#endif
return "selftest for CBC failed - see syslog for details";
}
xfree (mem);
return NULL;
}
/* Run the self-tests for <block cipher>-CFB-<block size>, tests bulk CFB
decryption. Returns NULL on success. */
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)
{
int i, offs;
unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
unsigned int ctx_aligned_size, memsize;
static const unsigned char key[16] ATTR_ALIGNED_16 = {
0x11,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x33
};
/* Allocate buffers, align first two elements to 16 bytes and latter to
block size. */
ctx_aligned_size = context_size + 15;
ctx_aligned_size -= ctx_aligned_size & 0xf;
memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16;
mem = xtrycalloc (1, memsize);
if (!mem)
return "failed to allocate memory";
offs = (16 - ((uintptr_t)mem & 15)) & 15;
ctx = (void*)(mem + offs);
iv = ctx + ctx_aligned_size;
iv2 = iv + blocksize;
plaintext = iv2 + blocksize;
plaintext2 = plaintext + nblocks * blocksize;
ciphertext = plaintext2 + nblocks * blocksize;
/* Initialize ctx */
if (setkey_func (ctx, key, sizeof(key), NULL) != GPG_ERR_NO_ERROR)
{
xfree(mem);
return "setkey failed";
}
/* Test single block code path */
memset(iv, 0xd3, blocksize);
memset(iv2, 0xd3, blocksize);
for (i = 0; i < blocksize; i++)
plaintext[i] = i;
/* CFB manually. */
encrypt_one (ctx, ciphertext, iv);
buf_xor_2dst (iv, ciphertext, plaintext, blocksize);
/* CFB decrypt. */
bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, 1);
if (memcmp(plaintext2, plaintext, blocksize))
{
xfree(mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CFB-%d test failed (plaintext mismatch)", cipher,
blocksize * 8);
#else
(void)cipher; /* Not used. */
#endif
return "selftest for CFB failed - see syslog for details";
}
if (memcmp(iv2, iv, blocksize))
{
xfree(mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CFB-%d test failed (IV mismatch)", cipher, blocksize * 8);
#endif
return "selftest for CFB failed - see syslog for details";
}
/* Test parallelized code paths */
memset(iv, 0xe6, blocksize);
memset(iv2, 0xe6, blocksize);
for (i = 0; i < nblocks * blocksize; i++)
plaintext[i] = i;
/* Create CFB ciphertext manually. */
for (i = 0; i < nblocks * blocksize; i+=blocksize)
{
encrypt_one (ctx, &ciphertext[i], iv);
buf_xor_2dst (iv, &ciphertext[i], &plaintext[i], blocksize);
}
/* Decrypt using bulk CBC and compare result. */
bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
if (memcmp(plaintext2, plaintext, nblocks * blocksize))
{
xfree(mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CFB-%d test failed (plaintext mismatch, parallel path)",
cipher, blocksize * 8);
#endif
return "selftest for CFB failed - see syslog for details";
}
if (memcmp(iv2, iv, blocksize))
{
xfree(mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CFB-%d test failed (IV mismatch, parallel path)", cipher,
blocksize * 8);
#endif
return "selftest for CFB failed - see syslog for details";
}
xfree(mem);
return NULL;
}
/* Run the self-tests for <block cipher>-CTR-<block size>, tests IV increment
of bulk CTR encryption. Returns NULL on success. */
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)
{
int i, j, offs, diff;
unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *ciphertext2,
*iv, *iv2, *mem;
unsigned int ctx_aligned_size, memsize;
static const unsigned char key[16] ATTR_ALIGNED_16 = {
0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
};
/* Allocate buffers, align first two elements to 16 bytes and latter to
block size. */
ctx_aligned_size = context_size + 15;
ctx_aligned_size -= ctx_aligned_size & 0xf;
memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 4) + 16;
mem = xtrycalloc (1, memsize);
if (!mem)
return "failed to allocate memory";
offs = (16 - ((uintptr_t)mem & 15)) & 15;
ctx = (void*)(mem + offs);
iv = ctx + ctx_aligned_size;
iv2 = iv + blocksize;
plaintext = iv2 + blocksize;
plaintext2 = plaintext + nblocks * blocksize;
ciphertext = plaintext2 + nblocks * blocksize;
ciphertext2 = ciphertext + nblocks * blocksize;
/* Initialize ctx */
if (setkey_func (ctx, key, sizeof(key), NULL) != GPG_ERR_NO_ERROR)
{
xfree(mem);
return "setkey failed";
}
/* Test single block code path */
memset (iv, 0xff, blocksize);
for (i = 0; i < blocksize; i++)
plaintext[i] = i;
/* CTR manually. */
encrypt_one (ctx, ciphertext, iv);
for (i = 0; i < blocksize; i++)
ciphertext[i] ^= plaintext[i];
for (i = blocksize; i > 0; i--)
{
iv[i-1]++;
if (iv[i-1])
break;
}
memset (iv2, 0xff, blocksize);
bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, 1);
if (memcmp (plaintext2, plaintext, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (plaintext mismatch)", cipher,
blocksize * 8);
#else
(void)cipher; /* Not used. */
#endif
return "selftest for CTR failed - see syslog for details";
}
if (memcmp (iv2, iv, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (IV mismatch)", cipher,
blocksize * 8);
#endif
return "selftest for CTR failed - see syslog for details";
}
/* Test bulk encryption with typical IV. */
memset(iv, 0x57, blocksize-4);
iv[blocksize-1] = 1;
iv[blocksize-2] = 0;
iv[blocksize-3] = 0;
iv[blocksize-4] = 0;
memset(iv2, 0x57, blocksize-4);
iv2[blocksize-1] = 1;
iv2[blocksize-2] = 0;
iv2[blocksize-3] = 0;
iv2[blocksize-4] = 0;
for (i = 0; i < blocksize * nblocks; i++)
plaintext2[i] = plaintext[i] = i;
/* Create CTR ciphertext manually. */
for (i = 0; i < blocksize * nblocks; i+=blocksize)
{
encrypt_one (ctx, &ciphertext[i], iv);
for (j = 0; j < blocksize; j++)
ciphertext[i+j] ^= plaintext[i+j];
for (j = blocksize; j > 0; j--)
{
iv[j-1]++;
if (iv[j-1])
break;
}
}
bulk_ctr_enc (ctx, iv2, ciphertext2, plaintext2, nblocks);
if (memcmp (ciphertext2, ciphertext, blocksize * nblocks))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (ciphertext mismatch, bulk)", cipher,
blocksize * 8);
#endif
return "selftest for CTR failed - see syslog for details";
}
if (memcmp(iv2, iv, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (IV mismatch, bulk)", cipher,
blocksize * 8);
#endif
return "selftest for CTR failed - see syslog for details";
}
/* Test parallelized code paths (check counter overflow handling) */
for (diff = 0; diff < nblocks; diff++) {
memset(iv, 0xff, blocksize);
iv[blocksize-1] -= diff;
iv[0] = iv[1] = 0;
iv[2] = 0x07;
for (i = 0; i < blocksize * nblocks; i++)
plaintext[i] = i;
/* Create CTR ciphertext manually. */
for (i = 0; i < blocksize * nblocks; i+=blocksize)
{
encrypt_one (ctx, &ciphertext[i], iv);
for (j = 0; j < blocksize; j++)
ciphertext[i+j] ^= plaintext[i+j];
for (j = blocksize; j > 0; j--)
{
iv[j-1]++;
if (iv[j-1])
break;
}
}
/* Decrypt using bulk CTR and compare result. */
memset(iv2, 0xff, blocksize);
iv2[blocksize-1] -= diff;
iv2[0] = iv2[1] = 0;
iv2[2] = 0x07;
bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, nblocks);
if (memcmp (plaintext2, plaintext, blocksize * nblocks))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (plaintext mismatch, diff: %d)", cipher,
blocksize * 8, diff);
#endif
return "selftest for CTR failed - see syslog for details";
}
if (memcmp(iv2, iv, blocksize))
{
xfree (mem);
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"%s-CTR-%d test failed (IV mismatch, diff: %d)", cipher,
blocksize * 8, diff);
#endif
return "selftest for CTR failed - see syslog for details";
}
}
xfree (mem);
return NULL;
}
diff --git a/cipher/cipher-selftest.h b/cipher/cipher-selftest.h
index a435080f..ad0ab5b7 100644
--- a/cipher/cipher-selftest.h
+++ b/cipher/cipher-selftest.h
@@ -1,72 +1,72 @@
/* cipher-selftest.h - Helper functions for bulk encryption selftests.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef G10_SELFTEST_HELP_H
#define G10_SELFTEST_HELP_H
#include <config.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
typedef void (*gcry_cipher_bulk_cbc_dec_t)(void *context, unsigned char *iv,
void *outbuf_arg,
const void *inbuf_arg,
size_t nblocks);
typedef void (*gcry_cipher_bulk_cfb_dec_t)(void *context, unsigned char *iv,
void *outbuf_arg,
const void *inbuf_arg,
size_t nblocks);
typedef void (*gcry_cipher_bulk_ctr_enc_t)(void *context, unsigned char *iv,
void *outbuf_arg,
const void *inbuf_arg,
size_t nblocks);
/* Helper function to allocate an aligned context for selftests. */
void *_gcry_cipher_selftest_alloc_ctx (const int context_size,
unsigned char **r_mem);
/* Helper function for bulk CBC decryption selftest */
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);
/* Helper function for bulk CFB decryption selftest */
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);
/* Helper function for bulk CTR encryption selftest */
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);
#endif /*G10_SELFTEST_HELP_H*/
diff --git a/cipher/cipher-xts.c b/cipher/cipher-xts.c
index 0522a271..3a00fc23 100644
--- a/cipher/cipher-xts.c
+++ b/cipher/cipher-xts.c
@@ -1,189 +1,189 @@
/* cipher-xts.c - XTS mode implementation
* Copyright (C) 2017 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/>.
+ * License along with this program; if not, see <https://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 xts_gfmul_byA (unsigned char *out, const unsigned char *in)
{
u64 hi = buf_get_le64 (in + 8);
u64 lo = buf_get_le64 (in + 0);
u64 carry = -(hi >> 63) & 0x87;
hi = (hi << 1) + (lo >> 63);
lo = (lo << 1) ^ carry;
buf_put_le64 (out + 8, hi);
buf_put_le64 (out + 0, lo);
}
static inline void xts_inc128 (unsigned char *seqno)
{
u64 lo = buf_get_le64 (seqno + 0);
u64 hi = buf_get_le64 (seqno + 8);
hi += !(++lo);
buf_put_le64 (seqno + 0, lo);
buf_put_le64 (seqno + 8, hi);
}
gcry_err_code_t
_gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen,
int encrypt)
{
gcry_cipher_encrypt_t tweak_fn = c->spec->encrypt;
gcry_cipher_encrypt_t crypt_fn =
encrypt ? c->spec->encrypt : c->spec->decrypt;
union
{
cipher_context_alignment_t xcx;
byte x1[GCRY_XTS_BLOCK_LEN];
u64 x64[GCRY_XTS_BLOCK_LEN / sizeof(u64)];
} tmp;
unsigned int burn, nburn;
size_t nblocks;
if (c->spec->blocksize != GCRY_XTS_BLOCK_LEN)
return GPG_ERR_CIPHER_ALGO;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if (inbuflen < GCRY_XTS_BLOCK_LEN)
return GPG_ERR_BUFFER_TOO_SHORT;
/* Data-unit max length: 2^20 blocks. */
if (inbuflen > GCRY_XTS_BLOCK_LEN << 20)
return GPG_ERR_INV_LENGTH;
nblocks = inbuflen / GCRY_XTS_BLOCK_LEN;
nblocks -= !encrypt && (inbuflen % GCRY_XTS_BLOCK_LEN) != 0;
/* Generate first tweak value. */
burn = tweak_fn (c->u_mode.xts.tweak_context, c->u_ctr.ctr, c->u_iv.iv);
/* Use a bulk method if available. */
if (nblocks && c->bulk.xts_crypt)
{
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;
nblocks = 0;
}
/* If we don't have a bulk method use the standard method. We also
use this method for the a remaining partial block. */
while (nblocks)
{
/* Xor-Encrypt/Decrypt-Xor block. */
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;
cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
outbuf += GCRY_XTS_BLOCK_LEN;
inbuf += GCRY_XTS_BLOCK_LEN;
inbuflen -= GCRY_XTS_BLOCK_LEN;
nblocks--;
/* Generate next tweak. */
xts_gfmul_byA (c->u_ctr.ctr, c->u_ctr.ctr);
}
/* Handle remaining data with ciphertext stealing. */
if (inbuflen)
{
if (!encrypt)
{
gcry_assert (inbuflen > GCRY_XTS_BLOCK_LEN);
gcry_assert (inbuflen < GCRY_XTS_BLOCK_LEN * 2);
/* Generate last tweak. */
xts_gfmul_byA (tmp.x1, c->u_ctr.ctr);
/* Decrypt last block first. */
cipher_block_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
nburn = crypt_fn (&c->context.c, outbuf, outbuf);
burn = nburn > burn ? nburn : burn;
cipher_block_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
inbuflen -= GCRY_XTS_BLOCK_LEN;
inbuf += GCRY_XTS_BLOCK_LEN;
outbuf += GCRY_XTS_BLOCK_LEN;
}
gcry_assert (inbuflen < GCRY_XTS_BLOCK_LEN);
outbuf -= GCRY_XTS_BLOCK_LEN;
/* Steal ciphertext from previous block. */
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. */
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;
cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
}
/* Auto-increment data-unit sequence number */
xts_inc128 (c->u_iv.iv);
wipememory (&tmp, sizeof(tmp));
wipememory (c->u_ctr.ctr, sizeof(c->u_ctr.ctr));
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
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);
}
diff --git a/cipher/cipher.c b/cipher/cipher.c
index ab3e4240..bc48cd69 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1,1819 +1,1819 @@
/* cipher.c - cipher dispatcher
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "g10lib.h"
#include "../src/gcrypt-testapi.h"
#include "cipher.h"
#include "./cipher-internal.h"
/* This is the list of the default ciphers, which are included in
libgcrypt. */
static gcry_cipher_spec_t * const cipher_list[] =
{
#if USE_BLOWFISH
&_gcry_cipher_spec_blowfish,
#endif
#if USE_DES
&_gcry_cipher_spec_des,
&_gcry_cipher_spec_tripledes,
#endif
#if USE_ARCFOUR
&_gcry_cipher_spec_arcfour,
#endif
#if USE_CAST5
&_gcry_cipher_spec_cast5,
#endif
#if USE_AES
&_gcry_cipher_spec_aes,
&_gcry_cipher_spec_aes192,
&_gcry_cipher_spec_aes256,
#endif
#if USE_TWOFISH
&_gcry_cipher_spec_twofish,
&_gcry_cipher_spec_twofish128,
#endif
#if USE_SERPENT
&_gcry_cipher_spec_serpent128,
&_gcry_cipher_spec_serpent192,
&_gcry_cipher_spec_serpent256,
#endif
#if USE_RFC2268
&_gcry_cipher_spec_rfc2268_40,
&_gcry_cipher_spec_rfc2268_128,
#endif
#if USE_SEED
&_gcry_cipher_spec_seed,
#endif
#if USE_CAMELLIA
&_gcry_cipher_spec_camellia128,
&_gcry_cipher_spec_camellia192,
&_gcry_cipher_spec_camellia256,
#endif
#ifdef USE_IDEA
&_gcry_cipher_spec_idea,
#endif
#if USE_SALSA20
&_gcry_cipher_spec_salsa20,
&_gcry_cipher_spec_salsa20r12,
#endif
#if USE_GOST28147
&_gcry_cipher_spec_gost28147,
#endif
#if USE_CHACHA20
&_gcry_cipher_spec_chacha20,
#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 */
#ifdef 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
};
static void _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode);
static int
map_algo (int algo)
{
return algo;
}
/* Return the spec structure for the cipher algorithm ALGO. For
an unknown algorithm NULL is returned. */
static gcry_cipher_spec_t *
spec_from_algo (int algo)
{
gcry_cipher_spec_t *spec = NULL;
algo = map_algo (algo);
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;
}
/* Lookup a cipher's spec by its name. */
static gcry_cipher_spec_t *
spec_from_name (const char *name)
{
gcry_cipher_spec_t *spec;
int idx;
const char **aliases;
for (idx=0; (spec = cipher_list[idx]); idx++)
{
if (!stricmp (name, spec->name))
return spec;
if (spec->aliases)
{
for (aliases = spec->aliases; *aliases; aliases++)
if (!stricmp (name, *aliases))
return spec;
}
}
return NULL;
}
/* Lookup a cipher's spec by its OID. */
static gcry_cipher_spec_t *
spec_from_oid (const char *oid)
{
gcry_cipher_spec_t *spec;
gcry_cipher_oid_spec_t *oid_specs;
int idx, j;
for (idx=0; (spec = cipher_list[idx]); idx++)
{
oid_specs = spec->oids;
if (oid_specs)
{
for (j = 0; oid_specs[j].oid; j++)
if (!stricmp (oid, oid_specs[j].oid))
return spec;
}
}
return NULL;
}
/* Locate the OID in the oid table and return the spec or NULL if not
found. An optional "oid." or "OID." prefix in OID is ignored, the
OID is expected to be in standard IETF dotted notation. A pointer
to the OID specification of the module implementing this algorithm
is return in OID_SPEC unless passed as NULL.*/
static gcry_cipher_spec_t *
search_oid (const char *oid, gcry_cipher_oid_spec_t *oid_spec)
{
gcry_cipher_spec_t *spec;
int i;
if (!oid)
return NULL;
if (!strncmp (oid, "oid.", 4) || !strncmp (oid, "OID.", 4))
oid += 4;
spec = spec_from_oid (oid);
if (spec && spec->oids)
{
for (i = 0; spec->oids[i].oid; i++)
if (!stricmp (oid, spec->oids[i].oid))
{
if (oid_spec)
*oid_spec = spec->oids[i];
return spec;
}
}
return NULL;
}
/* Map STRING to the cipher algorithm identifier. Returns the
algorithm ID of the cipher for the given name or 0 if the name is
not known. It is valid to pass NULL for STRING which results in a
return value of 0. */
int
_gcry_cipher_map_name (const char *string)
{
gcry_cipher_spec_t *spec;
if (!string)
return 0;
/* If the string starts with a digit (optionally prefixed with
either "OID." or "oid."), we first look into our table of ASN.1
object identifiers to figure out the algorithm */
spec = search_oid (string, NULL);
if (spec)
return spec->algo;
spec = spec_from_name (string);
if (spec)
return spec->algo;
return 0;
}
/* Given a STRING with an OID in dotted decimal notation, this
function returns the cipher mode (GCRY_CIPHER_MODE_*) associated
with that OID or 0 if no mode is known. Passing NULL for string
yields a return value of 0. */
int
_gcry_cipher_mode_from_oid (const char *string)
{
gcry_cipher_spec_t *spec;
gcry_cipher_oid_spec_t oid_spec;
if (!string)
return 0;
spec = search_oid (string, &oid_spec);
if (spec)
return oid_spec.mode;
return 0;
}
/* Map the cipher algorithm identifier ALGORITHM to a string
representing this algorithm. This string is the default name as
used by Libgcrypt. A "?" is returned for an unknown algorithm.
NULL is never returned. */
const char *
_gcry_cipher_algo_name (int algorithm)
{
gcry_cipher_spec_t *spec;
spec = spec_from_algo (algorithm);
return spec? spec->name : "?";
}
/* Flag the cipher algorithm with the identifier ALGORITHM as
disabled. There is no error return, the function does nothing for
unknown algorithms. Disabled algorithms are virtually not
available in Libgcrypt. This is not thread safe and should thus be
called early. */
static void
disable_cipher_algo (int algo)
{
gcry_cipher_spec_t *spec = spec_from_algo (algo);
if (spec)
spec->flags.disabled = 1;
}
/* Return 0 if the cipher algorithm with identifier ALGORITHM is
available. Returns a basic error code value if it is not
available. */
static gcry_err_code_t
check_cipher_algo (int algorithm)
{
gcry_cipher_spec_t *spec;
spec = spec_from_algo (algorithm);
if (spec && !spec->flags.disabled)
return 0;
return GPG_ERR_CIPHER_ALGO;
}
/* Return the standard length in bits of the key for the cipher
algorithm with the identifier ALGORITHM. */
static unsigned int
cipher_get_keylen (int algorithm)
{
gcry_cipher_spec_t *spec;
unsigned len = 0;
spec = spec_from_algo (algorithm);
if (spec)
{
len = spec->keylen;
if (!len)
log_bug ("cipher %d w/o key length\n", algorithm);
}
return len;
}
/* Return the block length of the cipher algorithm with the identifier
ALGORITHM. This function return 0 for an invalid algorithm. */
static unsigned int
cipher_get_blocksize (int algorithm)
{
gcry_cipher_spec_t *spec;
unsigned len = 0;
spec = spec_from_algo (algorithm);
if (spec)
{
len = spec->blocksize;
if (!len)
log_bug ("cipher %d w/o blocksize\n", algorithm);
}
return len;
}
/*
Open a cipher handle for use with cipher algorithm ALGORITHM, using
the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a
handle in HANDLE. Put NULL into HANDLE and return an error code if
something goes wrong. FLAGS may be used to modify the
operation. The defined flags are:
GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory.
GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP.
GCRY_CIPHER_CBC_CTS: Enable CTS mode.
GCRY_CIPHER_CBC_MAC: Enable MAC mode.
Values for these flags may be combined using OR.
*/
gcry_err_code_t
_gcry_cipher_open (gcry_cipher_hd_t *handle,
int algo, int mode, unsigned int flags)
{
gcry_err_code_t rc;
gcry_cipher_hd_t h = NULL;
if (mode >= GCRY_CIPHER_MODE_INTERNAL)
rc = GPG_ERR_INV_CIPHER_MODE;
else
rc = _gcry_cipher_open_internal (&h, algo, mode, flags);
*handle = rc ? NULL : h;
return rc;
}
gcry_err_code_t
_gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
int algo, int mode, unsigned int flags)
{
int secure = (flags & GCRY_CIPHER_SECURE);
gcry_cipher_spec_t *spec;
gcry_cipher_hd_t h = NULL;
gcry_err_code_t err;
/* If the application missed to call the random poll function, we do
it here to ensure that it is used once in a while. */
_gcry_fast_random_poll ();
spec = spec_from_algo (algo);
if (!spec)
err = GPG_ERR_CIPHER_ALGO;
else if (spec->flags.disabled)
err = GPG_ERR_CIPHER_ALGO;
else
err = 0;
/* check flags */
if ((! err)
&& ((flags & ~(0
| GCRY_CIPHER_SECURE
| GCRY_CIPHER_ENABLE_SYNC
| GCRY_CIPHER_CBC_CTS
| GCRY_CIPHER_CBC_MAC))
|| ((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)
err = GPG_ERR_INV_CIPHER_MODE;
if (!spec->encrypt || !spec->decrypt)
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;
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_EAX:
case GCRY_CIPHER_MODE_GCM:
if (!spec->encrypt || !spec->decrypt)
err = GPG_ERR_INV_CIPHER_MODE;
break;
case GCRY_CIPHER_MODE_POLY1305:
if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv)
err = GPG_ERR_INV_CIPHER_MODE;
else if (spec->algo != GCRY_CIPHER_CHACHA20)
err = GPG_ERR_INV_CIPHER_MODE;
break;
case GCRY_CIPHER_MODE_OCB:
/* Note that our implementation allows only for 128 bit block
length algorithms. Lower block lengths would be possible
but we do not implement them because they limit the
security too much. */
if (!spec->encrypt || !spec->decrypt)
err = GPG_ERR_INV_CIPHER_MODE;
else if (spec->blocksize != (128/8))
err = GPG_ERR_INV_CIPHER_MODE;
break;
case GCRY_CIPHER_MODE_STREAM:
if (!spec->stencrypt || !spec->stdecrypt)
err = GPG_ERR_INV_CIPHER_MODE;
break;
case GCRY_CIPHER_MODE_NONE:
/* This mode may be used for debugging. It copies the main
text verbatim to the ciphertext. We do not allow this in
fips mode or if no debug flag has been set. */
if (fips_mode () || !_gcry_get_debug_flag (0))
err = GPG_ERR_INV_CIPHER_MODE;
break;
default:
err = GPG_ERR_INV_CIPHER_MODE;
}
/* Perform selftest here and mark this with a flag in cipher_table?
No, we should not do this as it takes too long. Further it does
not make sense to exclude algorithms with failing selftests at
runtime: If a selftest fails there is something seriously wrong
with the system and thus we better die immediately. */
if (! err)
{
size_t size = (sizeof (*h)
+ 2 * spec->contextsize
- sizeof (cipher_context_alignment_t)
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
+ 15 /* Space for leading alignment gap. */
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
);
/* Space needed per mode. */
switch (mode)
{
case GCRY_CIPHER_MODE_XTS:
/* Additional cipher context for tweak. */
size += 2 * spec->contextsize + 15;
break;
default:
break;
}
if (secure)
h = xtrycalloc_secure (1, size);
else
h = xtrycalloc (1, size);
if (! h)
err = gpg_err_code_from_syserror ();
else
{
size_t off = 0;
char *tc;
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
if ( ((uintptr_t)h & 0x0f) )
{
/* The malloced block is not aligned on a 16 byte
boundary. Correct for this. */
off = 16 - ((uintptr_t)h & 0x0f);
h = (void*)((char*)h + off);
}
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
h->actual_handle_size = size - off;
h->handle_offset = off;
h->spec = spec;
h->algo = algo;
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;
h->bulk.xts_crypt = _gcry_aes_xts_crypt;
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)
{
case GCRY_CIPHER_MODE_OCB:
h->u_mode.ocb.taglen = 16; /* Bytes. */
break;
case GCRY_CIPHER_MODE_XTS:
tc = h->context.c + spec->contextsize * 2;
tc += (16 - (uintptr_t)tc % 16) % 16;
h->u_mode.xts.tweak_context = tc;
break;
default:
break;
}
}
}
/* Done. */
*handle = err ? NULL : h;
return err;
}
/* Release all resources associated with the cipher handle H. H may be
NULL in which case this is a no-operation. */
void
_gcry_cipher_close (gcry_cipher_hd_t h)
{
size_t off;
if (!h)
return;
if ((h->magic != CTX_MAGIC_SECURE)
&& (h->magic != CTX_MAGIC_NORMAL))
_gcry_fatal_error(GPG_ERR_INTERNAL,
"gcry_cipher_close: already closed/invalid handle");
else
h->magic = 0;
/* We always want to wipe out the memory even when the context has
been allocated in secure memory. The user might have disabled
secure memory or is using his own implementation which does not
do the wiping. To accomplish this we need to keep track of the
actual size of this structure because we have no way to known
how large the allocated area was when using a standard malloc. */
off = h->handle_offset;
wipememory (h, h->actual_handle_size);
xfree ((char*)h - off);
}
/* Set the key to be used for the encryption context C to KEY with
length KEYLEN. The length should match the required length. */
static gcry_err_code_t
cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
{
gcry_err_code_t rc;
if (c->mode == GCRY_CIPHER_MODE_XTS)
{
/* XTS uses two keys. */
if (keylen % 2)
return GPG_ERR_INV_KEYLEN;
keylen /= 2;
if (fips_mode ())
{
/* Reject key if subkeys Key_1 and Key_2 are equal.
See "Implementation Guidance for FIPS 140-2, A.9 XTS-AES
Key Generation Requirements" for details. */
if (buf_eq_const (key, key + keylen, keylen))
return GPG_ERR_WEAK_KEY;
}
}
rc = c->spec->setkey (&c->context.c, key, keylen, c);
if (!rc)
{
/* Duplicate initial context. */
memcpy ((void *) ((char *) &c->context.c + c->spec->contextsize),
(void *) &c->context.c,
c->spec->contextsize);
c->marks.key = 1;
switch (c->mode)
{
case GCRY_CIPHER_MODE_CMAC:
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_OCB:
_gcry_cipher_ocb_setkey (c);
break;
case GCRY_CIPHER_MODE_POLY1305:
_gcry_cipher_poly1305_setkey (c);
break;
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, c);
if (!rc)
{
/* Duplicate initial tweak context. */
memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize,
c->u_mode.xts.tweak_context, c->spec->contextsize);
}
else
c->marks.key = 0;
break;
default:
break;
};
}
else
c->marks.key = 0;
return rc;
}
/* Set the IV to be used for the encryption context C to IV with
length IVLEN. The length should match the required length. */
static gcry_err_code_t
cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
/* If the cipher has its own IV handler, we use only this one. This
is currently used for stream ciphers requiring a nonce. */
if (c->spec->setiv)
{
c->spec->setiv (&c->context.c, iv, ivlen);
return 0;
}
memset (c->u_iv.iv, 0, c->spec->blocksize);
if (iv)
{
if (ivlen != c->spec->blocksize)
{
log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
(unsigned int)ivlen, (unsigned int)c->spec->blocksize);
fips_signal_error ("IV length does not match blocklength");
}
if (ivlen > c->spec->blocksize)
ivlen = c->spec->blocksize;
memcpy (c->u_iv.iv, iv, ivlen);
c->marks.iv = 1;
}
else
c->marks.iv = 0;
c->unused = 0;
return 0;
}
/* Reset the cipher context to the initial context. This is basically
the same as an release followed by a new. */
static void
cipher_reset (gcry_cipher_hd_t c)
{
unsigned int marks_key;
marks_key = c->marks.key;
memcpy (&c->context.c,
(char *) &c->context.c + c->spec->contextsize,
c->spec->contextsize);
memset (&c->marks, 0, sizeof c->marks);
memset (c->u_iv.iv, 0, c->spec->blocksize);
memset (c->lastiv, 0, c->spec->blocksize);
memset (c->u_ctr.ctr, 0, c->spec->blocksize);
c->unused = 0;
c->marks.key = marks_key;
switch (c->mode)
{
case GCRY_CIPHER_MODE_CMAC:
_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:
/* Only clear head of u_mode, keep ghash_key and gcm_table. */
{
byte *u_mode_pos = (void *)&c->u_mode;
byte *ghash_key_pos = c->u_mode.gcm.u_ghash_key.key;
size_t u_mode_head_length = ghash_key_pos - u_mode_pos;
memset (&c->u_mode, 0, u_mode_head_length);
}
break;
case GCRY_CIPHER_MODE_POLY1305:
memset (&c->u_mode.poly1305, 0, sizeof c->u_mode.poly1305);
break;
case GCRY_CIPHER_MODE_CCM:
memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm);
break;
case GCRY_CIPHER_MODE_OCB:
/* Do not clear precalculated L-values */
{
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;
memset (u_mode_tail_pos, 0, u_mode_tail_length);
/* Setup default taglen. */
c->u_mode.ocb.taglen = 16;
}
break;
case GCRY_CIPHER_MODE_XTS:
memcpy (c->u_mode.xts.tweak_context,
c->u_mode.xts.tweak_context + c->spec->contextsize,
c->spec->contextsize);
break;
default:
break; /* u_mode unused by other modes. */
}
}
static gcry_err_code_t
do_ecb_crypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen,
gcry_cipher_encrypt_t crypt_fn)
{
unsigned int blocksize = c->spec->blocksize;
size_t n, nblocks;
unsigned int burn, nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
if ((inbuflen % blocksize))
return GPG_ERR_INV_LENGTH;
nblocks = inbuflen / blocksize;
burn = 0;
for (n=0; n < nblocks; n++ )
{
nburn = crypt_fn (&c->context.c, outbuf, inbuf);
burn = nburn > burn ? nburn : burn;
inbuf += blocksize;
outbuf += blocksize;
}
if (burn > 0)
_gcry_burn_stack (burn + 4 * sizeof(void *));
return 0;
}
static gcry_err_code_t
do_ecb_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->encrypt);
}
static gcry_err_code_t
do_ecb_decrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, size_t outbuflen,
const unsigned char *inbuf, size_t inbuflen)
{
return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->decrypt);
}
static gcry_err_code_t
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;
(void)outbuflen;
switch (c->mode)
{
case GCRY_CIPHER_MODE_CMAC:
rc = GPG_ERR_INV_CIPHER_MODE;
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_encrypt: invalid mode %d\n", c->mode );
rc = GPG_ERR_INV_CIPHER_MODE;
break;
}
return rc;
}
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;
(void)outbuflen;
switch (c->mode)
{
case GCRY_CIPHER_MODE_CMAC:
rc = GPG_ERR_INV_CIPHER_MODE;
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;
}
/****************
* Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has
* been requested.
*/
gcry_err_code_t
_gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
const void *in, size_t inlen)
{
gcry_err_code_t rc;
if (!in) /* Caller requested in-place encryption. */
{
in = out;
inlen = outsize;
}
if (h->mode != GCRY_CIPHER_MODE_NONE && !h->marks.key)
{
log_error ("cipher_decrypt: 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. */
if (rc && out)
memset (out, 0x42, outsize);
return rc;
}
/****************
* Decrypt IN and write it to OUT. If IN is NULL, in-place encryption has
* been requested.
*/
gcry_err_code_t
_gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
const void *in, size_t inlen)
{
if (!in) /* Caller requested in-place encryption. */
{
in = out;
inlen = outsize;
}
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);
}
/****************
* Used for PGP's somewhat strange CFB mode. Only works if
* the corresponding flag is set.
*/
static void
cipher_sync (gcry_cipher_hd_t c)
{
if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
{
memmove (c->u_iv.iv + c->unused,
c->u_iv.iv, c->spec->blocksize - c->unused);
memcpy (c->u_iv.iv,
c->lastiv + c->spec->blocksize - c->unused, c->unused);
c->unused = 0;
}
}
gcry_err_code_t
_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
{
return cipher_setkey (hd, (void*)key, keylen);
}
gcry_err_code_t
_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
{
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. */
gpg_err_code_t
_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
{
if (ctr && ctrlen == hd->spec->blocksize)
{
memcpy (hd->u_ctr.ctr, ctr, hd->spec->blocksize);
hd->unused = 0;
}
else if (!ctr || !ctrlen)
{
memset (hd->u_ctr.ctr, 0, hd->spec->blocksize);
hd->unused = 0;
}
else
return GPG_ERR_INV_ARG;
return 0;
}
gpg_err_code_t
_gcry_cipher_getctr (gcry_cipher_hd_t hd, void *ctr, size_t ctrlen)
{
if (ctr && ctrlen == hd->spec->blocksize)
memcpy (ctr, hd->u_ctr.ctr, hd->spec->blocksize);
else
return GPG_ERR_INV_ARG;
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;
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.encrypt = _gcry_cipher_aeswrap_encrypt;
c->mode_ops.decrypt = _gcry_cipher_aeswrap_decrypt;
break;
case GCRY_CIPHER_MODE_CCM:
c->mode_ops.encrypt = _gcry_cipher_ccm_encrypt;
c->mode_ops.decrypt = _gcry_cipher_ccm_decrypt;
break;
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:
c->mode_ops.encrypt = _gcry_cipher_gcm_encrypt;
c->mode_ops.decrypt = _gcry_cipher_gcm_decrypt;
break;
case GCRY_CIPHER_MODE_POLY1305:
c->mode_ops.encrypt = _gcry_cipher_poly1305_encrypt;
c->mode_ops.decrypt = _gcry_cipher_poly1305_decrypt;
break;
case GCRY_CIPHER_MODE_OCB:
c->mode_ops.encrypt = _gcry_cipher_ocb_encrypt;
c->mode_ops.decrypt = _gcry_cipher_ocb_decrypt;
break;
case GCRY_CIPHER_MODE_XTS:
c->mode_ops.encrypt = _gcry_cipher_xts_encrypt;
c->mode_ops.decrypt = _gcry_cipher_xts_decrypt;
break;
default:
c->mode_ops.encrypt = do_encrypt_none_unknown;
c->mode_ops.decrypt = do_decrypt_none_unknown;
break;
}
/* Setup IV setting routine. */
switch (mode)
{
case GCRY_CIPHER_MODE_CCM:
c->mode_ops.setiv = _gcry_cipher_ccm_set_nonce;
break;
case GCRY_CIPHER_MODE_EAX:
c->mode_ops.setiv = _gcry_cipher_eax_set_nonce;
break;
case GCRY_CIPHER_MODE_GCM:
c->mode_ops.setiv = _gcry_cipher_gcm_setiv;
break;
case GCRY_CIPHER_MODE_POLY1305:
c->mode_ops.setiv = _gcry_cipher_poly1305_setiv;
break;
case GCRY_CIPHER_MODE_OCB:
c->mode_ops.setiv = _gcry_cipher_ocb_set_nonce;
break;
default:
c->mode_ops.setiv = cipher_setiv;
break;
}
/* Setup authentication routines for AEAD modes. */
switch (mode)
{
case GCRY_CIPHER_MODE_CCM:
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:
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:
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:
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:
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;
default:
c->mode_ops.authenticate = NULL;
c->mode_ops.get_tag = NULL;
c->mode_ops.check_tag = NULL;
break;
}
}
gcry_err_code_t
_gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
{
gcry_err_code_t rc = 0;
switch (cmd)
{
case GCRYCTL_RESET:
cipher_reset (h);
break;
case GCRYCTL_FINALIZE:
if (!h || buffer || buflen)
return GPG_ERR_INV_ARG;
h->marks.finalize = 1;
break;
case GCRYCTL_CFB_SYNC:
cipher_sync( h );
break;
case GCRYCTL_SET_CBC_CTS:
if (buflen)
if (h->flags & GCRY_CIPHER_CBC_MAC)
rc = GPG_ERR_INV_FLAG;
else
h->flags |= GCRY_CIPHER_CBC_CTS;
else
h->flags &= ~GCRY_CIPHER_CBC_CTS;
break;
case GCRYCTL_SET_CBC_MAC:
if (buflen)
if (h->flags & GCRY_CIPHER_CBC_CTS)
rc = GPG_ERR_INV_FLAG;
else
h->flags |= GCRY_CIPHER_CBC_MAC;
else
h->flags &= ~GCRY_CIPHER_CBC_MAC;
break;
case GCRYCTL_SET_CCM_LENGTHS:
{
u64 params[3];
size_t encryptedlen;
size_t aadlen;
size_t authtaglen;
if (h->mode != GCRY_CIPHER_MODE_CCM)
return GPG_ERR_INV_CIPHER_MODE;
if (!buffer || buflen != 3 * sizeof(u64))
return GPG_ERR_INV_ARG;
/* This command is used to pass additional length parameters needed
by CCM mode to initialize CBC-MAC. */
memcpy (params, buffer, sizeof(params));
encryptedlen = params[0];
aadlen = params[1];
authtaglen = params[2];
rc = _gcry_cipher_ccm_set_lengths (h, encryptedlen, aadlen, authtaglen);
}
break;
case GCRYCTL_SET_TAGLEN:
if (!h || !buffer || buflen != sizeof(int) )
return GPG_ERR_INV_ARG;
switch (h->mode)
{
case GCRY_CIPHER_MODE_OCB:
switch (*(int*)buffer)
{
case 8: case 12: case 16:
h->u_mode.ocb.taglen = *(int*)buffer;
break;
default:
rc = GPG_ERR_INV_LENGTH; /* Invalid tag length. */
break;
}
break;
default:
rc =GPG_ERR_INV_CIPHER_MODE;
break;
}
break;
case GCRYCTL_DISABLE_ALGO:
/* This command expects NULL for H and BUFFER to point to an
integer with the algo number. */
if( h || !buffer || buflen != sizeof(int) )
return GPG_ERR_CIPHER_ALGO;
disable_cipher_algo( *(int*)buffer );
break;
case PRIV_CIPHERCTL_DISABLE_WEAK_KEY: /* (private) */
if (h->spec->set_extra_info)
rc = h->spec->set_extra_info
(&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0);
else
rc = GPG_ERR_NOT_SUPPORTED;
break;
case PRIV_CIPHERCTL_GET_INPUT_VECTOR: /* (private) */
/* This is the input block as used in CFB and OFB mode which has
initially been set as IV. The returned format is:
1 byte Actual length of the block in bytes.
n byte The block.
If the provided buffer is too short, an error is returned. */
if (buflen < (1 + h->spec->blocksize))
rc = GPG_ERR_TOO_SHORT;
else
{
unsigned char *ivp;
unsigned char *dst = buffer;
int n = h->unused;
if (!n)
n = h->spec->blocksize;
gcry_assert (n <= h->spec->blocksize);
*dst++ = n;
ivp = h->u_iv.iv + h->spec->blocksize - n;
while (n--)
*dst++ = *ivp++;
}
break;
case GCRYCTL_SET_SBOX:
if (h->spec->set_extra_info)
rc = h->spec->set_extra_info
(&h->context.c, GCRYCTL_SET_SBOX, buffer, buflen);
else
rc = GPG_ERR_NOT_SUPPORTED;
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Return information about the cipher handle H. CMD is the kind of
* information requested.
*
* CMD may be one of:
*
* 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
* at NBYTES. The taglen is returned in bytes.
*
* The function returns 0 on success or an error code.
*/
gcry_err_code_t
_gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
{
gcry_err_code_t rc = 0;
switch (cmd)
{
case GCRYCTL_GET_TAGLEN:
if (!h || buffer || !nbytes)
rc = GPG_ERR_INV_ARG;
else
{
switch (h->mode)
{
case GCRY_CIPHER_MODE_OCB:
*nbytes = h->u_mode.ocb.taglen;
break;
case GCRY_CIPHER_MODE_CCM:
*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;
case GCRY_CIPHER_MODE_POLY1305:
*nbytes = POLY1305_TAGLEN;
break;
default:
rc = GPG_ERR_INV_CIPHER_MODE;
break;
}
}
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Return information about the given cipher algorithm ALGO.
WHAT select the kind of information returned:
GCRYCTL_GET_KEYLEN:
Return the length of the key. If the algorithm ALGO
supports multiple key lengths, the maximum supported key length
is returned. The key length is returned as number of octets.
BUFFER and NBYTES must be zero.
GCRYCTL_GET_BLKLEN:
Return the blocklength of the algorithm ALGO counted in octets.
BUFFER and NBYTES must be zero.
GCRYCTL_TEST_ALGO:
Returns 0 if the specified algorithm ALGO is available for use.
BUFFER and NBYTES must be zero.
Note: Because this function is in most cases used to return an
integer value, we can make it easier for the caller to just look at
the return value. The caller will in all cases consult the value
and thereby detecting whether a error occurred or not (i.e. while
checking the block size)
*/
gcry_err_code_t
_gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
gcry_err_code_t rc = 0;
unsigned int ui;
switch (what)
{
case GCRYCTL_GET_KEYLEN:
if (buffer || (! nbytes))
rc = GPG_ERR_CIPHER_ALGO;
else
{
ui = cipher_get_keylen (algo);
if ((ui > 0) && (ui <= 512))
*nbytes = (size_t) ui / 8;
else
/* The only reason for an error is an invalid algo. */
rc = GPG_ERR_CIPHER_ALGO;
}
break;
case GCRYCTL_GET_BLKLEN:
if (buffer || (! nbytes))
rc = GPG_ERR_CIPHER_ALGO;
else
{
ui = cipher_get_blocksize (algo);
if ((ui > 0) && (ui < 10000))
*nbytes = ui;
else
{
/* The only reason is an invalid algo or a strange
blocksize. */
rc = GPG_ERR_CIPHER_ALGO;
}
}
break;
case GCRYCTL_TEST_ALGO:
if (buffer || nbytes)
rc = GPG_ERR_INV_ARG;
else
rc = check_cipher_algo (algo);
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* 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. */
size_t
_gcry_cipher_get_algo_keylen (int algo)
{
size_t n;
if (_gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n))
n = 0;
return n;
}
/* This functions returns the blocklength 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. */
size_t
_gcry_cipher_get_algo_blklen (int algo)
{
size_t n;
if (_gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n))
n = 0;
return n;
}
/* Explicitly initialize this module. */
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;
}
/* Run the selftests for cipher algorithm ALGO with optional reporting
function REPORT. */
gpg_error_t
_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
{
gcry_err_code_t ec = 0;
gcry_cipher_spec_t *spec;
spec = spec_from_algo (algo);
if (spec && !spec->flags.disabled && spec->selftest)
ec = spec->selftest (algo, extended, report);
else
{
ec = GPG_ERR_CIPHER_ALGO;
if (report)
report ("cipher", algo, "module",
(spec && !spec->flags.disabled)?
"no selftest available" :
spec? "algorithm disabled" : "algorithm not found");
}
return gpg_error (ec);
}
diff --git a/cipher/crc-armv8-aarch64-ce.S b/cipher/crc-armv8-aarch64-ce.S
index 060abdfe..cb2ae9e3 100644
--- a/cipher/crc-armv8-aarch64-ce.S
+++ b/cipher/crc-armv8-aarch64-ce.S
@@ -1,497 +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/>.
+ * License along with this program; if not, see <https://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
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
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
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
CFI_ENDPROC()
ELF(.size _gcry_crc32_armv8_ce_reduction_4,.-_gcry_crc32_armv8_ce_reduction_4;)
#endif
diff --git a/cipher/des-amd64.S b/cipher/des-amd64.S
index a211dac3..f5208700 100644
--- a/cipher/des-amd64.S
+++ b/cipher/des-amd64.S
@@ -1,1111 +1,1111 @@
/* des-amd64.S - AMD64 assembly implementation of 3DES cipher
*
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef __x86_64
#include <config.h>
#if defined(USE_DES) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
#include "asm-common-amd64.h"
.text
#define s1 0
#define s2 ((s1) + (64*8))
#define s3 ((s2) + (64*8))
#define s4 ((s3) + (64*8))
#define s5 ((s4) + (64*8))
#define s6 ((s5) + (64*8))
#define s7 ((s6) + (64*8))
#define s8 ((s7) + (64*8))
/* register macros */
#define CTX %rdi
#define SBOXES %rbp
#define RL0 %r8
#define RL1 %r9
#define RL2 %r10
#define RL0d %r8d
#define RL1d %r9d
#define RL2d %r10d
#define RR0 %r11
#define RR1 %r12
#define RR2 %r13
#define RR0d %r11d
#define RR1d %r12d
#define RR2d %r13d
#define RW0 %rax
#define RW1 %rbx
#define RW2 %rcx
#define RW0d %eax
#define RW1d %ebx
#define RW2d %ecx
#define RW0bl %al
#define RW1bl %bl
#define RW2bl %cl
#define RW0bh %ah
#define RW1bh %bh
#define RW2bh %ch
#define RT0 %r15
#define RT1 %rsi
#define RT2 %r14
#define RT3 %rdx
#define RT0d %r15d
#define RT1d %esi
#define RT2d %r14d
#define RT3d %edx
/***********************************************************************
* 1-way 3DES
***********************************************************************/
#define do_permutation(a, b, offset, mask) \
movl a, RT0d; \
shrl $(offset), RT0d; \
xorl b, RT0d; \
andl $(mask), RT0d; \
xorl RT0d, b; \
shll $(offset), RT0d; \
xorl RT0d, a;
#define expand_to_64bits(val, mask) \
movl val##d, RT0d; \
rorl $4, RT0d; \
shlq $32, RT0; \
orq RT0, val; \
andq mask, val;
#define compress_to_64bits(val) \
movq val, RT0; \
shrq $32, RT0; \
roll $4, RT0d; \
orl RT0d, val##d;
#define initial_permutation(left, right) \
do_permutation(left##d, right##d, 4, 0x0f0f0f0f); \
do_permutation(left##d, right##d, 16, 0x0000ffff); \
do_permutation(right##d, left##d, 2, 0x33333333); \
do_permutation(right##d, left##d, 8, 0x00ff00ff); \
movabs $0x3f3f3f3f3f3f3f3f, RT3; \
movl left##d, RW0d; \
roll $1, right##d; \
xorl right##d, RW0d; \
andl $0xaaaaaaaa, RW0d; \
xorl RW0d, left##d; \
xorl RW0d, right##d; \
roll $1, left##d; \
expand_to_64bits(right, RT3); \
expand_to_64bits(left, RT3);
#define final_permutation(left, right) \
compress_to_64bits(right); \
compress_to_64bits(left); \
movl right##d, RW0d; \
rorl $1, left##d; \
xorl left##d, RW0d; \
andl $0xaaaaaaaa, RW0d; \
xorl RW0d, right##d; \
xorl RW0d, left##d; \
rorl $1, right##d; \
do_permutation(right##d, left##d, 8, 0x00ff00ff); \
do_permutation(right##d, left##d, 2, 0x33333333); \
do_permutation(left##d, right##d, 16, 0x0000ffff); \
do_permutation(left##d, right##d, 4, 0x0f0f0f0f);
#define round1(n, from, to, load_next_key) \
xorq from, RW0; \
\
movzbl RW0bl, RT0d; \
movzbl RW0bh, RT1d; \
shrq $16, RW0; \
movzbl RW0bl, RT2d; \
movzbl RW0bh, RT3d; \
shrq $16, RW0; \
movq s8(SBOXES, RT0, 8), RT0; \
xorq s6(SBOXES, RT1, 8), to; \
movzbl RW0bl, RL1d; \
movzbl RW0bh, RT1d; \
shrl $16, RW0d; \
xorq s4(SBOXES, RT2, 8), RT0; \
xorq s2(SBOXES, RT3, 8), to; \
movzbl RW0bl, RT2d; \
movzbl RW0bh, RT3d; \
xorq s7(SBOXES, RL1, 8), RT0; \
xorq s5(SBOXES, RT1, 8), to; \
xorq s3(SBOXES, RT2, 8), RT0; \
load_next_key(n, RW0); \
xorq RT0, to; \
xorq s1(SBOXES, RT3, 8), to; \
#define load_next_key(n, RWx) \
movq (((n) + 1) * 8)(CTX), RWx;
#define dummy2(a, b) /*_*/
#define read_block(io, left, right) \
movl (io), left##d; \
movl 4(io), right##d; \
bswapl left##d; \
bswapl right##d;
#define write_block(io, left, right) \
bswapl left##d; \
bswapl right##d; \
movl left##d, (io); \
movl right##d, 4(io);
.align 8
.globl _gcry_3des_amd64_crypt_block
ELF(.type _gcry_3des_amd64_crypt_block,@function;)
_gcry_3des_amd64_crypt_block:
/* input:
* %rdi: round keys, CTX
* %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 rRIP, SBOXES;
read_block(%rdx, RL0, RR0);
initial_permutation(RL0, RR0);
movq (CTX), RW0;
round1(0, RR0, RL0, load_next_key);
round1(1, RL0, RR0, load_next_key);
round1(2, RR0, RL0, load_next_key);
round1(3, RL0, RR0, load_next_key);
round1(4, RR0, RL0, load_next_key);
round1(5, RL0, RR0, load_next_key);
round1(6, RR0, RL0, load_next_key);
round1(7, RL0, RR0, load_next_key);
round1(8, RR0, RL0, load_next_key);
round1(9, RL0, RR0, load_next_key);
round1(10, RR0, RL0, load_next_key);
round1(11, RL0, RR0, load_next_key);
round1(12, RR0, RL0, load_next_key);
round1(13, RL0, RR0, load_next_key);
round1(14, RR0, RL0, load_next_key);
round1(15, RL0, RR0, load_next_key);
round1(16+0, RL0, RR0, load_next_key);
round1(16+1, RR0, RL0, load_next_key);
round1(16+2, RL0, RR0, load_next_key);
round1(16+3, RR0, RL0, load_next_key);
round1(16+4, RL0, RR0, load_next_key);
round1(16+5, RR0, RL0, load_next_key);
round1(16+6, RL0, RR0, load_next_key);
round1(16+7, RR0, RL0, load_next_key);
round1(16+8, RL0, RR0, load_next_key);
round1(16+9, RR0, RL0, load_next_key);
round1(16+10, RL0, RR0, load_next_key);
round1(16+11, RR0, RL0, load_next_key);
round1(16+12, RL0, RR0, load_next_key);
round1(16+13, RR0, RL0, load_next_key);
round1(16+14, RL0, RR0, load_next_key);
round1(16+15, RR0, RL0, load_next_key);
round1(32+0, RR0, RL0, load_next_key);
round1(32+1, RL0, RR0, load_next_key);
round1(32+2, RR0, RL0, load_next_key);
round1(32+3, RL0, RR0, load_next_key);
round1(32+4, RR0, RL0, load_next_key);
round1(32+5, RL0, RR0, load_next_key);
round1(32+6, RR0, RL0, load_next_key);
round1(32+7, RL0, RR0, load_next_key);
round1(32+8, RR0, RL0, load_next_key);
round1(32+9, RL0, RR0, load_next_key);
round1(32+10, RR0, RL0, load_next_key);
round1(32+11, RL0, RR0, load_next_key);
round1(32+12, RR0, RL0, load_next_key);
round1(32+13, RL0, RR0, load_next_key);
round1(32+14, RR0, RL0, load_next_key);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block;)
/***********************************************************************
* 3-way 3DES
***********************************************************************/
#define expand_to_64bits(val, mask) \
movl val##d, RT0d; \
rorl $4, RT0d; \
shlq $32, RT0; \
orq RT0, val; \
andq mask, val;
#define compress_to_64bits(val) \
movq val, RT0; \
shrq $32, RT0; \
roll $4, RT0d; \
orl RT0d, val##d;
#define initial_permutation3(left, right) \
do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \
do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \
do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f); \
do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
\
do_permutation(right##0d, left##0d, 2, 0x33333333); \
do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \
do_permutation(right##1d, left##1d, 2, 0x33333333); \
do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \
do_permutation(right##2d, left##2d, 2, 0x33333333); \
do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \
\
movabs $0x3f3f3f3f3f3f3f3f, RT3; \
\
movl left##0d, RW0d; \
roll $1, right##0d; \
xorl right##0d, RW0d; \
andl $0xaaaaaaaa, RW0d; \
xorl RW0d, left##0d; \
xorl RW0d, right##0d; \
roll $1, left##0d; \
expand_to_64bits(right##0, RT3); \
expand_to_64bits(left##0, RT3); \
movl left##1d, RW1d; \
roll $1, right##1d; \
xorl right##1d, RW1d; \
andl $0xaaaaaaaa, RW1d; \
xorl RW1d, left##1d; \
xorl RW1d, right##1d; \
roll $1, left##1d; \
expand_to_64bits(right##1, RT3); \
expand_to_64bits(left##1, RT3); \
movl left##2d, RW2d; \
roll $1, right##2d; \
xorl right##2d, RW2d; \
andl $0xaaaaaaaa, RW2d; \
xorl RW2d, left##2d; \
xorl RW2d, right##2d; \
roll $1, left##2d; \
expand_to_64bits(right##2, RT3); \
expand_to_64bits(left##2, RT3);
#define final_permutation3(left, right) \
compress_to_64bits(right##0); \
compress_to_64bits(left##0); \
movl right##0d, RW0d; \
rorl $1, left##0d; \
xorl left##0d, RW0d; \
andl $0xaaaaaaaa, RW0d; \
xorl RW0d, right##0d; \
xorl RW0d, left##0d; \
rorl $1, right##0d; \
compress_to_64bits(right##1); \
compress_to_64bits(left##1); \
movl right##1d, RW1d; \
rorl $1, left##1d; \
xorl left##1d, RW1d; \
andl $0xaaaaaaaa, RW1d; \
xorl RW1d, right##1d; \
xorl RW1d, left##1d; \
rorl $1, right##1d; \
compress_to_64bits(right##2); \
compress_to_64bits(left##2); \
movl right##2d, RW2d; \
rorl $1, left##2d; \
xorl left##2d, RW2d; \
andl $0xaaaaaaaa, RW2d; \
xorl RW2d, right##2d; \
xorl RW2d, left##2d; \
rorl $1, right##2d; \
\
do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \
do_permutation(right##0d, left##0d, 2, 0x33333333); \
do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \
do_permutation(right##1d, left##1d, 2, 0x33333333); \
do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \
do_permutation(right##2d, left##2d, 2, 0x33333333); \
\
do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \
do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \
do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f);
#define round3(n, from, to, load_next_key, do_movq) \
xorq from##0, RW0; \
movzbl RW0bl, RT3d; \
movzbl RW0bh, RT1d; \
shrq $16, RW0; \
xorq s8(SBOXES, RT3, 8), to##0; \
xorq s6(SBOXES, RT1, 8), to##0; \
movzbl RW0bl, RT3d; \
movzbl RW0bh, RT1d; \
shrq $16, RW0; \
xorq s4(SBOXES, RT3, 8), to##0; \
xorq s2(SBOXES, RT1, 8), to##0; \
movzbl RW0bl, RT3d; \
movzbl RW0bh, RT1d; \
shrl $16, RW0d; \
xorq s7(SBOXES, RT3, 8), to##0; \
xorq s5(SBOXES, RT1, 8), to##0; \
movzbl RW0bl, RT3d; \
movzbl RW0bh, RT1d; \
load_next_key(n, RW0); \
xorq s3(SBOXES, RT3, 8), to##0; \
xorq s1(SBOXES, RT1, 8), to##0; \
xorq from##1, RW1; \
movzbl RW1bl, RT3d; \
movzbl RW1bh, RT1d; \
shrq $16, RW1; \
xorq s8(SBOXES, RT3, 8), to##1; \
xorq s6(SBOXES, RT1, 8), to##1; \
movzbl RW1bl, RT3d; \
movzbl RW1bh, RT1d; \
shrq $16, RW1; \
xorq s4(SBOXES, RT3, 8), to##1; \
xorq s2(SBOXES, RT1, 8), to##1; \
movzbl RW1bl, RT3d; \
movzbl RW1bh, RT1d; \
shrl $16, RW1d; \
xorq s7(SBOXES, RT3, 8), to##1; \
xorq s5(SBOXES, RT1, 8), to##1; \
movzbl RW1bl, RT3d; \
movzbl RW1bh, RT1d; \
do_movq(RW0, RW1); \
xorq s3(SBOXES, RT3, 8), to##1; \
xorq s1(SBOXES, RT1, 8), to##1; \
xorq from##2, RW2; \
movzbl RW2bl, RT3d; \
movzbl RW2bh, RT1d; \
shrq $16, RW2; \
xorq s8(SBOXES, RT3, 8), to##2; \
xorq s6(SBOXES, RT1, 8), to##2; \
movzbl RW2bl, RT3d; \
movzbl RW2bh, RT1d; \
shrq $16, RW2; \
xorq s4(SBOXES, RT3, 8), to##2; \
xorq s2(SBOXES, RT1, 8), to##2; \
movzbl RW2bl, RT3d; \
movzbl RW2bh, RT1d; \
shrl $16, RW2d; \
xorq s7(SBOXES, RT3, 8), to##2; \
xorq s5(SBOXES, RT1, 8), to##2; \
movzbl RW2bl, RT3d; \
movzbl RW2bh, RT1d; \
do_movq(RW0, RW2); \
xorq s3(SBOXES, RT3, 8), to##2; \
xorq s1(SBOXES, RT1, 8), to##2;
#define __movq(src, dst) \
movq src, dst;
#define read_block(io, left, right) \
movl (io), left##d; \
movl 4(io), right##d; \
bswapl left##d; \
bswapl right##d;
#define write_block(io, left, right) \
bswapl left##d; \
bswapl right##d; \
movl left##d, (io); \
movl right##d, 4(io);
.align 8
ELF(.type _gcry_3des_amd64_crypt_blk3,@function;)
_gcry_3des_amd64_crypt_blk3:
/* input:
* %rdi: round keys, CTX
* RL0d, RR0d, RL1d, RR1d, RL2d, RR2d: 3 input blocks
* RR0d, RL0d, RR1d, RL1d, RR2d, RL2d: 3 output blocks
*/
CFI_STARTPROC();
leaq .L_s1 rRIP, SBOXES;
initial_permutation3(RL, RR);
movq 0(CTX), RW0;
movq RW0, RW1;
movq RW0, RW2;
round3(0, RR, RL, load_next_key, __movq);
round3(1, RL, RR, load_next_key, __movq);
round3(2, RR, RL, load_next_key, __movq);
round3(3, RL, RR, load_next_key, __movq);
round3(4, RR, RL, load_next_key, __movq);
round3(5, RL, RR, load_next_key, __movq);
round3(6, RR, RL, load_next_key, __movq);
round3(7, RL, RR, load_next_key, __movq);
round3(8, RR, RL, load_next_key, __movq);
round3(9, RL, RR, load_next_key, __movq);
round3(10, RR, RL, load_next_key, __movq);
round3(11, RL, RR, load_next_key, __movq);
round3(12, RR, RL, load_next_key, __movq);
round3(13, RL, RR, load_next_key, __movq);
round3(14, RR, RL, load_next_key, __movq);
round3(15, RL, RR, load_next_key, __movq);
round3(16+0, RL, RR, load_next_key, __movq);
round3(16+1, RR, RL, load_next_key, __movq);
round3(16+2, RL, RR, load_next_key, __movq);
round3(16+3, RR, RL, load_next_key, __movq);
round3(16+4, RL, RR, load_next_key, __movq);
round3(16+5, RR, RL, load_next_key, __movq);
round3(16+6, RL, RR, load_next_key, __movq);
round3(16+7, RR, RL, load_next_key, __movq);
round3(16+8, RL, RR, load_next_key, __movq);
round3(16+9, RR, RL, load_next_key, __movq);
round3(16+10, RL, RR, load_next_key, __movq);
round3(16+11, RR, RL, load_next_key, __movq);
round3(16+12, RL, RR, load_next_key, __movq);
round3(16+13, RR, RL, load_next_key, __movq);
round3(16+14, RL, RR, load_next_key, __movq);
round3(16+15, RR, RL, load_next_key, __movq);
round3(32+0, RR, RL, load_next_key, __movq);
round3(32+1, RL, RR, load_next_key, __movq);
round3(32+2, RR, RL, load_next_key, __movq);
round3(32+3, RL, RR, load_next_key, __movq);
round3(32+4, RR, RL, load_next_key, __movq);
round3(32+5, RL, RR, load_next_key, __movq);
round3(32+6, RR, RL, load_next_key, __movq);
round3(32+7, RL, RR, load_next_key, __movq);
round3(32+8, RR, RL, load_next_key, __movq);
round3(32+9, RL, RR, load_next_key, __movq);
round3(32+10, RR, RL, load_next_key, __movq);
round3(32+11, RL, RR, load_next_key, __movq);
round3(32+12, RR, RL, load_next_key, __movq);
round3(32+13, RL, RR, load_next_key, __movq);
round3(32+14, RR, RL, load_next_key, __movq);
round3(32+15, RL, RR, dummy2, dummy2);
final_permutation3(RR, RL);
ret;
CFI_ENDPROC();
ELF(.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3;)
.align 8
.globl _gcry_3des_amd64_cbc_dec
ELF(.type _gcry_3des_amd64_cbc_dec,@function;)
_gcry_3des_amd64_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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;
movl 1 * 4(%rdx), RR0d;
movl 2 * 4(%rdx), RL1d;
movl 3 * 4(%rdx), RR1d;
movl 4 * 4(%rdx), RL2d;
movl 5 * 4(%rdx), RR2d;
bswapl RL0d;
bswapl RR0d;
bswapl RL1d;
bswapl RR1d;
bswapl RL2d;
bswapl RR2d;
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;
bswapl RR1d;
bswapl RL1d;
bswapl RR2d;
bswapl RL2d;
movq 2 * 8(%rdx), RT0;
xorl 0 * 4(%rcx), RR0d;
xorl 1 * 4(%rcx), RL0d;
xorl 0 * 4(%rdx), RR1d;
xorl 1 * 4(%rdx), RL1d;
xorl 2 * 4(%rdx), RR2d;
xorl 3 * 4(%rdx), RL2d;
movq RT0, (%rcx); /* store new IV */
movl RR0d, 0 * 4(%rsi);
movl RL0d, 1 * 4(%rsi);
movl RR1d, 2 * 4(%rsi);
movl RL1d, 3 * 4(%rsi);
movl RR2d, 4 * 4(%rsi);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
.align 8
.globl _gcry_3des_amd64_ctr_enc
ELF(.type _gcry_3des_amd64_ctr_enc,@function;)
_gcry_3des_amd64_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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 */
movq (RW2), RT0;
bswapq RT0;
movq RT0, RR0;
/* construct IVs */
leaq 1(RT0), RR1;
leaq 2(RT0), RR2;
leaq 3(RT0), RT0;
movq RR0, RL0;
movq RR1, RL1;
movq RR2, RL2;
bswapq RT0;
shrq $32, RL0;
shrq $32, RL1;
shrq $32, RL2;
/* store new IV */
movq RT0, (RW2);
call _gcry_3des_amd64_crypt_blk3;
popq %rdx; /*src*/
CFI_POP_TMP_REG();
popq %rsi; /*dst*/
CFI_POP_TMP_REG();
bswapl RR0d;
bswapl RL0d;
bswapl RR1d;
bswapl RL1d;
bswapl RR2d;
bswapl RL2d;
xorl 0 * 4(%rdx), RR0d;
xorl 1 * 4(%rdx), RL0d;
xorl 2 * 4(%rdx), RR1d;
xorl 3 * 4(%rdx), RL1d;
xorl 4 * 4(%rdx), RR2d;
xorl 5 * 4(%rdx), RL2d;
movl RR0d, 0 * 4(%rsi);
movl RL0d, 1 * 4(%rsi);
movl RR1d, 2 * 4(%rsi);
movl RL1d, 3 * 4(%rsi);
movl RR2d, 4 * 4(%rsi);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
.align 8
.globl _gcry_3des_amd64_cfb_dec
ELF(.type _gcry_3des_amd64_cfb_dec,@function;)
_gcry_3des_amd64_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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 */
movl 0 * 4(RW2), RL0d;
movl 1 * 4(RW2), RR0d;
movl 0 * 4(%rdx), RL1d;
movl 1 * 4(%rdx), RR1d;
movl 2 * 4(%rdx), RL2d;
movl 3 * 4(%rdx), RR2d;
bswapl RL0d;
bswapl RR0d;
bswapl RL1d;
bswapl RR1d;
bswapl RL2d;
bswapl RR2d;
/* Update IV */
movq 4 * 4(%rdx), RW0;
movq RW0, (RW2);
call _gcry_3des_amd64_crypt_blk3;
popq %rdx; /*src*/
CFI_POP_TMP_REG();
popq %rsi; /*dst*/
CFI_POP_TMP_REG();
bswapl RR0d;
bswapl RL0d;
bswapl RR1d;
bswapl RL1d;
bswapl RR2d;
bswapl RL2d;
xorl 0 * 4(%rdx), RR0d;
xorl 1 * 4(%rdx), RL0d;
xorl 2 * 4(%rdx), RR1d;
xorl 3 * 4(%rdx), RL1d;
xorl 4 * 4(%rdx), RR2d;
xorl 5 * 4(%rdx), RL2d;
movl RR0d, 0 * 4(%rsi);
movl RL0d, 1 * 4(%rsi);
movl RR1d, 2 * 4(%rsi);
movl RL1d, 3 * 4(%rsi);
movl RR2d, 4 * 4(%rsi);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec;)
.align 16
.L_s1:
.quad 0x0010100001010400, 0x0000000000000000
.quad 0x0000100000010000, 0x0010100001010404
.quad 0x0010100001010004, 0x0000100000010404
.quad 0x0000000000000004, 0x0000100000010000
.quad 0x0000000000000400, 0x0010100001010400
.quad 0x0010100001010404, 0x0000000000000400
.quad 0x0010000001000404, 0x0010100001010004
.quad 0x0010000001000000, 0x0000000000000004
.quad 0x0000000000000404, 0x0010000001000400
.quad 0x0010000001000400, 0x0000100000010400
.quad 0x0000100000010400, 0x0010100001010000
.quad 0x0010100001010000, 0x0010000001000404
.quad 0x0000100000010004, 0x0010000001000004
.quad 0x0010000001000004, 0x0000100000010004
.quad 0x0000000000000000, 0x0000000000000404
.quad 0x0000100000010404, 0x0010000001000000
.quad 0x0000100000010000, 0x0010100001010404
.quad 0x0000000000000004, 0x0010100001010000
.quad 0x0010100001010400, 0x0010000001000000
.quad 0x0010000001000000, 0x0000000000000400
.quad 0x0010100001010004, 0x0000100000010000
.quad 0x0000100000010400, 0x0010000001000004
.quad 0x0000000000000400, 0x0000000000000004
.quad 0x0010000001000404, 0x0000100000010404
.quad 0x0010100001010404, 0x0000100000010004
.quad 0x0010100001010000, 0x0010000001000404
.quad 0x0010000001000004, 0x0000000000000404
.quad 0x0000100000010404, 0x0010100001010400
.quad 0x0000000000000404, 0x0010000001000400
.quad 0x0010000001000400, 0x0000000000000000
.quad 0x0000100000010004, 0x0000100000010400
.quad 0x0000000000000000, 0x0010100001010004
.L_s2:
.quad 0x0801080200100020, 0x0800080000000000
.quad 0x0000080000000000, 0x0001080200100020
.quad 0x0001000000100000, 0x0000000200000020
.quad 0x0801000200100020, 0x0800080200000020
.quad 0x0800000200000020, 0x0801080200100020
.quad 0x0801080000100000, 0x0800000000000000
.quad 0x0800080000000000, 0x0001000000100000
.quad 0x0000000200000020, 0x0801000200100020
.quad 0x0001080000100000, 0x0001000200100020
.quad 0x0800080200000020, 0x0000000000000000
.quad 0x0800000000000000, 0x0000080000000000
.quad 0x0001080200100020, 0x0801000000100000
.quad 0x0001000200100020, 0x0800000200000020
.quad 0x0000000000000000, 0x0001080000100000
.quad 0x0000080200000020, 0x0801080000100000
.quad 0x0801000000100000, 0x0000080200000020
.quad 0x0000000000000000, 0x0001080200100020
.quad 0x0801000200100020, 0x0001000000100000
.quad 0x0800080200000020, 0x0801000000100000
.quad 0x0801080000100000, 0x0000080000000000
.quad 0x0801000000100000, 0x0800080000000000
.quad 0x0000000200000020, 0x0801080200100020
.quad 0x0001080200100020, 0x0000000200000020
.quad 0x0000080000000000, 0x0800000000000000
.quad 0x0000080200000020, 0x0801080000100000
.quad 0x0001000000100000, 0x0800000200000020
.quad 0x0001000200100020, 0x0800080200000020
.quad 0x0800000200000020, 0x0001000200100020
.quad 0x0001080000100000, 0x0000000000000000
.quad 0x0800080000000000, 0x0000080200000020
.quad 0x0800000000000000, 0x0801000200100020
.quad 0x0801080200100020, 0x0001080000100000
.L_s3:
.quad 0x0000002000000208, 0x0000202008020200
.quad 0x0000000000000000, 0x0000200008020008
.quad 0x0000002008000200, 0x0000000000000000
.quad 0x0000202000020208, 0x0000002008000200
.quad 0x0000200000020008, 0x0000000008000008
.quad 0x0000000008000008, 0x0000200000020000
.quad 0x0000202008020208, 0x0000200000020008
.quad 0x0000200008020000, 0x0000002000000208
.quad 0x0000000008000000, 0x0000000000000008
.quad 0x0000202008020200, 0x0000002000000200
.quad 0x0000202000020200, 0x0000200008020000
.quad 0x0000200008020008, 0x0000202000020208
.quad 0x0000002008000208, 0x0000202000020200
.quad 0x0000200000020000, 0x0000002008000208
.quad 0x0000000000000008, 0x0000202008020208
.quad 0x0000002000000200, 0x0000000008000000
.quad 0x0000202008020200, 0x0000000008000000
.quad 0x0000200000020008, 0x0000002000000208
.quad 0x0000200000020000, 0x0000202008020200
.quad 0x0000002008000200, 0x0000000000000000
.quad 0x0000002000000200, 0x0000200000020008
.quad 0x0000202008020208, 0x0000002008000200
.quad 0x0000000008000008, 0x0000002000000200
.quad 0x0000000000000000, 0x0000200008020008
.quad 0x0000002008000208, 0x0000200000020000
.quad 0x0000000008000000, 0x0000202008020208
.quad 0x0000000000000008, 0x0000202000020208
.quad 0x0000202000020200, 0x0000000008000008
.quad 0x0000200008020000, 0x0000002008000208
.quad 0x0000002000000208, 0x0000200008020000
.quad 0x0000202000020208, 0x0000000000000008
.quad 0x0000200008020008, 0x0000202000020200
.L_s4:
.quad 0x1008020000002001, 0x1000020800002001
.quad 0x1000020800002001, 0x0000000800000000
.quad 0x0008020800002000, 0x1008000800000001
.quad 0x1008000000000001, 0x1000020000002001
.quad 0x0000000000000000, 0x0008020000002000
.quad 0x0008020000002000, 0x1008020800002001
.quad 0x1000000800000001, 0x0000000000000000
.quad 0x0008000800000000, 0x1008000000000001
.quad 0x1000000000000001, 0x0000020000002000
.quad 0x0008000000000000, 0x1008020000002001
.quad 0x0000000800000000, 0x0008000000000000
.quad 0x1000020000002001, 0x0000020800002000
.quad 0x1008000800000001, 0x1000000000000001
.quad 0x0000020800002000, 0x0008000800000000
.quad 0x0000020000002000, 0x0008020800002000
.quad 0x1008020800002001, 0x1000000800000001
.quad 0x0008000800000000, 0x1008000000000001
.quad 0x0008020000002000, 0x1008020800002001
.quad 0x1000000800000001, 0x0000000000000000
.quad 0x0000000000000000, 0x0008020000002000
.quad 0x0000020800002000, 0x0008000800000000
.quad 0x1008000800000001, 0x1000000000000001
.quad 0x1008020000002001, 0x1000020800002001
.quad 0x1000020800002001, 0x0000000800000000
.quad 0x1008020800002001, 0x1000000800000001
.quad 0x1000000000000001, 0x0000020000002000
.quad 0x1008000000000001, 0x1000020000002001
.quad 0x0008020800002000, 0x1008000800000001
.quad 0x1000020000002001, 0x0000020800002000
.quad 0x0008000000000000, 0x1008020000002001
.quad 0x0000000800000000, 0x0008000000000000
.quad 0x0000020000002000, 0x0008020800002000
.L_s5:
.quad 0x0000001000000100, 0x0020001002080100
.quad 0x0020000002080000, 0x0420001002000100
.quad 0x0000000000080000, 0x0000001000000100
.quad 0x0400000000000000, 0x0020000002080000
.quad 0x0400001000080100, 0x0000000000080000
.quad 0x0020001002000100, 0x0400001000080100
.quad 0x0420001002000100, 0x0420000002080000
.quad 0x0000001000080100, 0x0400000000000000
.quad 0x0020000002000000, 0x0400000000080000
.quad 0x0400000000080000, 0x0000000000000000
.quad 0x0400001000000100, 0x0420001002080100
.quad 0x0420001002080100, 0x0020001002000100
.quad 0x0420000002080000, 0x0400001000000100
.quad 0x0000000000000000, 0x0420000002000000
.quad 0x0020001002080100, 0x0020000002000000
.quad 0x0420000002000000, 0x0000001000080100
.quad 0x0000000000080000, 0x0420001002000100
.quad 0x0000001000000100, 0x0020000002000000
.quad 0x0400000000000000, 0x0020000002080000
.quad 0x0420001002000100, 0x0400001000080100
.quad 0x0020001002000100, 0x0400000000000000
.quad 0x0420000002080000, 0x0020001002080100
.quad 0x0400001000080100, 0x0000001000000100
.quad 0x0020000002000000, 0x0420000002080000
.quad 0x0420001002080100, 0x0000001000080100
.quad 0x0420000002000000, 0x0420001002080100
.quad 0x0020000002080000, 0x0000000000000000
.quad 0x0400000000080000, 0x0420000002000000
.quad 0x0000001000080100, 0x0020001002000100
.quad 0x0400001000000100, 0x0000000000080000
.quad 0x0000000000000000, 0x0400000000080000
.quad 0x0020001002080100, 0x0400001000000100
.L_s6:
.quad 0x0200000120000010, 0x0204000020000000
.quad 0x0000040000000000, 0x0204040120000010
.quad 0x0204000020000000, 0x0000000100000010
.quad 0x0204040120000010, 0x0004000000000000
.quad 0x0200040020000000, 0x0004040100000010
.quad 0x0004000000000000, 0x0200000120000010
.quad 0x0004000100000010, 0x0200040020000000
.quad 0x0200000020000000, 0x0000040100000010
.quad 0x0000000000000000, 0x0004000100000010
.quad 0x0200040120000010, 0x0000040000000000
.quad 0x0004040000000000, 0x0200040120000010
.quad 0x0000000100000010, 0x0204000120000010
.quad 0x0204000120000010, 0x0000000000000000
.quad 0x0004040100000010, 0x0204040020000000
.quad 0x0000040100000010, 0x0004040000000000
.quad 0x0204040020000000, 0x0200000020000000
.quad 0x0200040020000000, 0x0000000100000010
.quad 0x0204000120000010, 0x0004040000000000
.quad 0x0204040120000010, 0x0004000000000000
.quad 0x0000040100000010, 0x0200000120000010
.quad 0x0004000000000000, 0x0200040020000000
.quad 0x0200000020000000, 0x0000040100000010
.quad 0x0200000120000010, 0x0204040120000010
.quad 0x0004040000000000, 0x0204000020000000
.quad 0x0004040100000010, 0x0204040020000000
.quad 0x0000000000000000, 0x0204000120000010
.quad 0x0000000100000010, 0x0000040000000000
.quad 0x0204000020000000, 0x0004040100000010
.quad 0x0000040000000000, 0x0004000100000010
.quad 0x0200040120000010, 0x0000000000000000
.quad 0x0204040020000000, 0x0200000020000000
.quad 0x0004000100000010, 0x0200040120000010
.L_s7:
.quad 0x0002000000200000, 0x2002000004200002
.quad 0x2000000004000802, 0x0000000000000000
.quad 0x0000000000000800, 0x2000000004000802
.quad 0x2002000000200802, 0x0002000004200800
.quad 0x2002000004200802, 0x0002000000200000
.quad 0x0000000000000000, 0x2000000004000002
.quad 0x2000000000000002, 0x0000000004000000
.quad 0x2002000004200002, 0x2000000000000802
.quad 0x0000000004000800, 0x2002000000200802
.quad 0x2002000000200002, 0x0000000004000800
.quad 0x2000000004000002, 0x0002000004200000
.quad 0x0002000004200800, 0x2002000000200002
.quad 0x0002000004200000, 0x0000000000000800
.quad 0x2000000000000802, 0x2002000004200802
.quad 0x0002000000200800, 0x2000000000000002
.quad 0x0000000004000000, 0x0002000000200800
.quad 0x0000000004000000, 0x0002000000200800
.quad 0x0002000000200000, 0x2000000004000802
.quad 0x2000000004000802, 0x2002000004200002
.quad 0x2002000004200002, 0x2000000000000002
.quad 0x2002000000200002, 0x0000000004000000
.quad 0x0000000004000800, 0x0002000000200000
.quad 0x0002000004200800, 0x2000000000000802
.quad 0x2002000000200802, 0x0002000004200800
.quad 0x2000000000000802, 0x2000000004000002
.quad 0x2002000004200802, 0x0002000004200000
.quad 0x0002000000200800, 0x0000000000000000
.quad 0x2000000000000002, 0x2002000004200802
.quad 0x0000000000000000, 0x2002000000200802
.quad 0x0002000004200000, 0x0000000000000800
.quad 0x2000000004000002, 0x0000000004000800
.quad 0x0000000000000800, 0x2002000000200002
.L_s8:
.quad 0x0100010410001000, 0x0000010000001000
.quad 0x0000000000040000, 0x0100010410041000
.quad 0x0100000010000000, 0x0100010410001000
.quad 0x0000000400000000, 0x0100000010000000
.quad 0x0000000400040000, 0x0100000010040000
.quad 0x0100010410041000, 0x0000010000041000
.quad 0x0100010010041000, 0x0000010400041000
.quad 0x0000010000001000, 0x0000000400000000
.quad 0x0100000010040000, 0x0100000410000000
.quad 0x0100010010001000, 0x0000010400001000
.quad 0x0000010000041000, 0x0000000400040000
.quad 0x0100000410040000, 0x0100010010041000
.quad 0x0000010400001000, 0x0000000000000000
.quad 0x0000000000000000, 0x0100000410040000
.quad 0x0100000410000000, 0x0100010010001000
.quad 0x0000010400041000, 0x0000000000040000
.quad 0x0000010400041000, 0x0000000000040000
.quad 0x0100010010041000, 0x0000010000001000
.quad 0x0000000400000000, 0x0100000410040000
.quad 0x0000010000001000, 0x0000010400041000
.quad 0x0100010010001000, 0x0000000400000000
.quad 0x0100000410000000, 0x0100000010040000
.quad 0x0100000410040000, 0x0100000010000000
.quad 0x0000000000040000, 0x0100010410001000
.quad 0x0000000000000000, 0x0100010410041000
.quad 0x0000000400040000, 0x0100000410000000
.quad 0x0100000010040000, 0x0100010010001000
.quad 0x0100010410001000, 0x0000000000000000
.quad 0x0100010410041000, 0x0000010000041000
.quad 0x0000010000041000, 0x0000010400001000
.quad 0x0000010400001000, 0x0000000400040000
.quad 0x0100000010000000, 0x0100010010041000
#endif
#endif
diff --git a/cipher/dsa-common.c b/cipher/dsa-common.c
index 6f2c2f9e..fed338fd 100644
--- a/cipher/dsa-common.c
+++ b/cipher/dsa-common.c
@@ -1,394 +1,394 @@
/* dsa-common.c - Common code for DSA
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "pubkey-internal.h"
/*
* Generate a random secret exponent K less than Q.
* Note that ECDSA uses this code also to generate D.
*/
gcry_mpi_t
_gcry_dsa_gen_k (gcry_mpi_t q, int security_level)
{
gcry_mpi_t k = mpi_alloc_secure (mpi_get_nlimbs (q));
unsigned int nbits = mpi_get_nbits (q);
unsigned int nbytes = (nbits+7)/8;
char *rndbuf = NULL;
/* To learn why we don't use mpi_mod to get the requested bit size,
read the paper: "The Insecurity of the Digital Signature
Algorithm with Partially Known Nonces" by Nguyen and Shparlinski.
Journal of Cryptology, New York. Vol 15, nr 3 (2003) */
if (DBG_CIPHER)
log_debug ("choosing a random k of %u bits at seclevel %d\n",
nbits, security_level);
for (;;)
{
if ( !rndbuf || nbits < 32 )
{
xfree (rndbuf);
rndbuf = _gcry_random_bytes_secure (nbytes, security_level);
}
else
{ /* Change only some of the higher bits. We could improve
this by directly requesting more memory at the first call
to get_random_bytes() and use these extra bytes here.
However the required management code is more complex and
thus we better use this simple method. */
char *pp = _gcry_random_bytes_secure (4, security_level);
memcpy (rndbuf, pp, 4);
xfree (pp);
}
_gcry_mpi_set_buffer (k, rndbuf, nbytes, 0);
/* Make sure we have the requested number of bits. This code
looks a bit funny but it is easy to understand if you
consider that mpi_set_highbit clears all higher bits. We
don't have a clear_highbit, thus we first set the high bit
and then clear it again. */
if (mpi_test_bit (k, nbits-1))
mpi_set_highbit (k, nbits-1);
else
{
mpi_set_highbit (k, nbits-1);
mpi_clear_bit (k, nbits-1);
}
if (!(mpi_cmp (k, q) < 0)) /* check: k < q */
{
if (DBG_CIPHER)
log_debug ("\tk too large - again\n");
continue; /* no */
}
if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */
{
if (DBG_CIPHER)
log_debug ("\tk is zero - again\n");
continue; /* no */
}
break; /* okay */
}
xfree (rndbuf);
return k;
}
/* Turn VALUE into an octet string and store it in an allocated buffer
at R_FRAME. If the resulting octet string is shorter than NBYTES
the result will be left padded with zeroes. If VALUE does not fit
into NBYTES an error code is returned. */
static gpg_err_code_t
int2octets (unsigned char **r_frame, gcry_mpi_t value, size_t nbytes)
{
gpg_err_code_t rc;
size_t nframe, noff, n;
unsigned char *frame;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value);
if (rc)
return rc;
if (nframe > nbytes)
return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */
noff = (nframe < nbytes)? nbytes - nframe : 0;
n = nframe + noff;
frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n);
if (!frame)
return gpg_err_code_from_syserror ();
if (noff)
memset (frame, 0, noff);
nframe += noff;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value);
if (rc)
{
xfree (frame);
return rc;
}
*r_frame = frame;
return 0;
}
/* Connert the bit string BITS of length NBITS into an octet string
with a length of (QBITS+7)/8 bytes. On success store the result at
R_FRAME. */
static gpg_err_code_t
bits2octets (unsigned char **r_frame,
const void *bits, unsigned int nbits,
gcry_mpi_t q, unsigned int qbits)
{
gpg_err_code_t rc;
gcry_mpi_t z1;
/* z1 = bits2int (b) */
rc = _gcry_mpi_scan (&z1, GCRYMPI_FMT_USG, bits, (nbits+7)/8, NULL);
if (rc)
return rc;
if (nbits > qbits)
mpi_rshift (z1, z1, nbits - qbits);
/* z2 - z1 mod q */
if (mpi_cmp (z1, q) >= 0)
mpi_sub (z1, z1, q);
/* Convert to an octet string. */
rc = int2octets (r_frame, z1, (qbits+7)/8);
mpi_free (z1);
return rc;
}
/*
* Generate a deterministic secret exponent K less than DSA_Q. H1 is
* the to be signed digest with a length of HLEN bytes. HALGO is the
* algorithm used to create the hash. On success the value for K is
* stored at R_K.
*/
gpg_err_code_t
_gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
const unsigned char *h1, unsigned int hlen,
int halgo, unsigned int extraloops)
{
gpg_err_code_t rc;
unsigned char *V = NULL;
unsigned char *K = NULL;
unsigned char *x_buf = NULL;
unsigned char *h1_buf = NULL;
gcry_md_hd_t hd = NULL;
unsigned char *t = NULL;
gcry_mpi_t k = NULL;
unsigned int tbits, qbits;
int i;
qbits = mpi_get_nbits (dsa_q);
if (!qbits || !h1 || !hlen)
return GPG_ERR_EINVAL;
if (_gcry_md_get_algo_dlen (halgo) != hlen)
return GPG_ERR_DIGEST_ALGO;
/* Step b: V = 0x01 0x01 0x01 ... 0x01 */
V = xtrymalloc (hlen);
if (!V)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
for (i=0; i < hlen; i++)
V[i] = 1;
/* Step c: K = 0x00 0x00 0x00 ... 0x00 */
K = xtrycalloc (1, hlen);
if (!K)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
rc = int2octets (&x_buf, dsa_x, (qbits+7)/8);
if (rc)
goto leave;
rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits);
if (rc)
goto leave;
/* Create a handle to compute the HMACs. */
rc = _gcry_md_open (&hd, halgo, (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC));
if (rc)
goto leave;
/* Step d: K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
_gcry_md_write (hd, "", 1);
_gcry_md_write (hd, x_buf, (qbits+7)/8);
_gcry_md_write (hd, h1_buf, (qbits+7)/8);
memcpy (K, _gcry_md_read (hd, 0), hlen);
/* Step e: V = HMAC_K(V) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
memcpy (V, _gcry_md_read (hd, 0), hlen);
/* Step f: K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
_gcry_md_write (hd, "\x01", 1);
_gcry_md_write (hd, x_buf, (qbits+7)/8);
_gcry_md_write (hd, h1_buf, (qbits+7)/8);
memcpy (K, _gcry_md_read (hd, 0), hlen);
/* Step g: V = HMAC_K(V) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
memcpy (V, _gcry_md_read (hd, 0), hlen);
/* Step h. */
t = xtrymalloc ((qbits+7)/8+hlen);
if (!t)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
again:
for (tbits = 0; tbits < qbits;)
{
/* V = HMAC_K(V) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
memcpy (V, _gcry_md_read (hd, 0), hlen);
/* T = T || V */
memcpy (t+(tbits+7)/8, V, hlen);
tbits += 8*hlen;
}
/* k = bits2int (T) */
mpi_free (k);
k = NULL;
rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL);
if (rc)
goto leave;
if (tbits > qbits)
mpi_rshift (k, k, tbits - qbits);
/* Check: k < q and k > 1 */
if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
{
/* K = HMAC_K(V || 0x00) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
_gcry_md_write (hd, "", 1);
memcpy (K, _gcry_md_read (hd, 0), hlen);
/* V = HMAC_K(V) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
memcpy (V, _gcry_md_read (hd, 0), hlen);
goto again;
}
/* The caller may have requested that we introduce some extra loops.
This is for example useful if the caller wants another value for
K because the last returned one yielded an R of 0. Because this
is very unlikely we implement it in a straightforward way. */
if (extraloops)
{
extraloops--;
/* K = HMAC_K(V || 0x00) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
_gcry_md_write (hd, "", 1);
memcpy (K, _gcry_md_read (hd, 0), hlen);
/* V = HMAC_K(V) */
rc = _gcry_md_setkey (hd, K, hlen);
if (rc)
goto leave;
_gcry_md_write (hd, V, hlen);
memcpy (V, _gcry_md_read (hd, 0), hlen);
goto again;
}
/* log_mpidump (" k", k); */
leave:
xfree (t);
_gcry_md_close (hd);
xfree (h1_buf);
xfree (x_buf);
xfree (K);
xfree (V);
if (rc)
mpi_free (k);
else
*r_k = k;
return rc;
}
/*
* Truncate opaque hash value to qbits for DSA.
* Non-opaque input is not truncated, in hope that user
* knows what is passed. It is not possible to correctly
* trucate non-opaque inputs.
*/
gpg_err_code_t
_gcry_dsa_normalize_hash (gcry_mpi_t input,
gcry_mpi_t *out,
unsigned int qbits)
{
gpg_err_code_t rc = 0;
const void *abuf;
unsigned int abits;
gcry_mpi_t hash;
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;
*out = hash;
return rc;
}
diff --git a/cipher/dsa.c b/cipher/dsa.c
index 22d8d782..d5a979aa 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -1,1390 +1,1390 @@
/* dsa.c - DSA signature algorithm
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2006, 2008 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "pubkey-internal.h"
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
} DSA_public_key;
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
gcry_mpi_t x; /* secret exponent */
} DSA_secret_key;
/* A structure used to hold domain parameters. */
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t q; /* group order */
gcry_mpi_t g; /* group generator */
} dsa_domain_t;
static const char *dsa_names[] =
{
"dsa",
"openpgp-dsa",
NULL,
};
/* A sample 1024 bit DSA key used for the selftests. Not anymore
* used, kept only for reference. */
#if 0
static const char sample_secret_key_1024[] =
"(private-key"
" (dsa"
" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)"
" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))";
/* A sample 1024 bit DSA key used for the selftests (public only). */
static const char sample_public_key_1024[] =
"(public-key"
" (dsa"
" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)"
" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)"
" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)"
" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))";
#endif /*0*/
/* 2048 DSA key from RFC 6979 A.2.2 */
static const char sample_public_key_2048[] =
"(public-key"
" (dsa"
" (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)"
" (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)"
" (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)"
" (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)))";
static const char sample_secret_key_2048[] =
"(private-key"
" (dsa"
" (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)"
" (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)"
" (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)"
" (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)"
" (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)))";
static int test_keys (DSA_secret_key *sk, unsigned int qbits);
static int check_secret_key (DSA_secret_key *sk);
static gpg_err_code_t generate (DSA_secret_key *sk,
unsigned int nbits,
unsigned int qbits,
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,
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);
static unsigned int dsa_get_nbits (gcry_sexp_t parms);
static void (*progress_cb) (void *,const char *, int, int, int );
static void *progress_cb_data;
void
_gcry_register_pk_dsa_progress (void (*cb) (void *, const char *,
int, int, int),
void *cb_data)
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress (int c)
{
if (progress_cb)
progress_cb (progress_cb_data, "pk_dsa", c, 0, 0);
}
/* Check that a freshly generated key actually works. Returns 0 on success. */
static int
test_keys (DSA_secret_key *sk, unsigned int qbits)
{
int result = -1; /* Default to failure. */
DSA_public_key pk;
gcry_mpi_t data = mpi_new (qbits);
gcry_mpi_t sig_a = mpi_new (qbits);
gcry_mpi_t sig_b = mpi_new (qbits);
/* Put the relevant parameters into a public key structure. */
pk.p = sk->p;
pk.q = sk->q;
pk.g = sk->g;
pk.y = sk->y;
/* Create a random plaintext. */
_gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM);
/* Sign DATA using the secret key. */
sign (sig_a, sig_b, data, sk, 0, 0);
/* Verify the signature using the public key. */
if ( verify (sig_a, sig_b, data, &pk) )
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) )
goto leave; /* Signature matches but should not. */
result = 0; /* The test succeeded. */
leave:
_gcry_mpi_release (sig_b);
_gcry_mpi_release (sig_a);
_gcry_mpi_release (data);
return result;
}
/*
Generate a DSA key pair with a key of size NBITS. If transient_key
is true the key is generated using the standard RNG and not the
very secure one.
Returns: 2 structures filled with all needed values
and an array with the n-1 factors of (p-1)
*/
static gpg_err_code_t
generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
int transient_key, dsa_domain_t *domain, gcry_mpi_t **ret_factors )
{
gpg_err_code_t rc;
gcry_mpi_t p; /* the prime */
gcry_mpi_t q; /* the 160 bit prime factor */
gcry_mpi_t g; /* the generator */
gcry_mpi_t y; /* g^x mod p */
gcry_mpi_t x; /* the secret exponent */
gcry_mpi_t h, e; /* helper */
unsigned char *rndbuf;
gcry_random_level_t random_level;
if (qbits)
; /* Caller supplied qbits. Use this value. */
else if ( nbits >= 512 && nbits <= 1024 )
qbits = 160;
else if ( nbits == 2048 )
qbits = 224;
else if ( nbits == 3072 )
qbits = 256;
else if ( nbits == 7680 )
qbits = 384;
else if ( nbits == 15360 )
qbits = 512;
else
return GPG_ERR_INV_VALUE;
if (qbits < 160 || qbits > 512 || (qbits%8) )
return GPG_ERR_INV_VALUE;
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. */
p = mpi_copy (domain->p);
q = mpi_copy (domain->q);
g = mpi_copy (domain->g);
gcry_assert (mpi_get_nbits (p) == nbits);
gcry_assert (mpi_get_nbits (q) == qbits);
h = mpi_alloc (0);
e = NULL;
}
else
{
/* Generate new domain parameters. */
rc = _gcry_generate_elg_prime (1, nbits, qbits, NULL, &p, ret_factors);
if (rc)
return rc;
/* Get q out of factors. */
q = mpi_copy ((*ret_factors)[0]);
gcry_assert (mpi_get_nbits (q) == qbits);
/* Find a generator g (h and e are helpers).
e = (p-1)/q */
e = mpi_alloc (mpi_get_nlimbs (p));
mpi_sub_ui (e, p, 1);
mpi_fdiv_q (e, e, q);
g = mpi_alloc (mpi_get_nlimbs (p));
h = mpi_alloc_set_ui (1); /* (We start with 2.) */
do
{
mpi_add_ui (h, h, 1);
/* g = h^e mod p */
mpi_powm (g, h, e, p);
}
while (!mpi_cmp_ui (g, 1)); /* Continue until g != 1. */
}
/* Select a random number X with the property:
* 0 < x < q-1
*
* FIXME: Why do we use the requirement x < q-1 ? It should be
* sufficient to test for x < q. FIPS-186-3 check x < q-1 but it
* does not check for 0 < x because it makes sure that Q is unsigned
* and finally adds one to the result so that 0 will never be
* returned. We should replace the code below with _gcry_dsa_gen_k.
*
* This must be a very good random number because this is the secret
* part. The random quality depends on the transient_key flag. */
random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
if (DBG_CIPHER)
log_debug("choosing a random x%s\n", transient_key? " (transient-key)":"");
gcry_assert( qbits >= 160 );
x = mpi_alloc_secure( mpi_get_nlimbs(q) );
mpi_sub_ui( h, q, 1 ); /* put q-1 into h */
rndbuf = NULL;
do
{
if( DBG_CIPHER )
progress('.');
if( !rndbuf )
rndbuf = _gcry_random_bytes_secure ((qbits+7)/8, random_level);
else
{ /* Change only some of the higher bits (= 2 bytes)*/
char *r = _gcry_random_bytes_secure (2, random_level);
memcpy(rndbuf, r, 2 );
xfree(r);
}
_gcry_mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
mpi_clear_highbit( x, qbits+1 );
}
while ( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
xfree(rndbuf);
mpi_free( e );
mpi_free( h );
/* y = g^x mod p */
y = mpi_alloc( mpi_get_nlimbs(p) );
mpi_powm (y, g, x, p);
if( DBG_CIPHER )
{
progress('\n');
log_mpidump("dsa p", p );
log_mpidump("dsa q", q );
log_mpidump("dsa g", g );
log_mpidump("dsa y", y );
log_mpidump("dsa x", x );
}
/* Copy the stuff to the key structures. */
sk->p = p;
sk->q = q;
sk->g = g;
sk->y = y;
sk->x = x;
/* Now we can test our keys (this should never fail!). */
if ( test_keys (sk, qbits) )
{
_gcry_mpi_release (sk->p); sk->p = NULL;
_gcry_mpi_release (sk->q); sk->q = NULL;
_gcry_mpi_release (sk->g); sk->g = NULL;
_gcry_mpi_release (sk->y); sk->y = NULL;
_gcry_mpi_release (sk->x); sk->x = NULL;
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
return 0;
}
/* Generate a DSA key pair with a key of size NBITS using the
algorithm given in FIPS-186-3. If USE_FIPS186_2 is true,
FIPS-186-2 is used and thus the length is restricted to 1024/160.
If DERIVEPARMS is not NULL it may contain a seed value. If domain
parameters are specified in DOMAIN, DERIVEPARMS may not be given
and NBITS and QBITS must match the specified domain parameters. */
static gpg_err_code_t
generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
gcry_sexp_t deriveparms, int use_fips186_2,
dsa_domain_t *domain,
int *r_counter, void **r_seed, size_t *r_seedlen,
gcry_mpi_t *r_h)
{
gpg_err_code_t ec;
struct {
gcry_sexp_t sexp;
const void *seed;
size_t seedlen;
} initial_seed = { NULL, NULL, 0 };
gcry_mpi_t prime_q = NULL;
gcry_mpi_t prime_p = NULL;
gcry_mpi_t value_g = NULL; /* The generator. */
gcry_mpi_t value_y = NULL; /* g^x mod p */
gcry_mpi_t value_x = NULL; /* The secret exponent. */
gcry_mpi_t value_h = NULL; /* Helper. */
gcry_mpi_t value_e = NULL; /* Helper. */
gcry_mpi_t value_c = NULL; /* helper for x */
gcry_mpi_t value_qm2 = NULL; /* q - 2 */
/* Preset return values. */
*r_counter = 0;
*r_seed = NULL;
*r_seedlen = 0;
*r_h = NULL;
/* Derive QBITS from NBITS if requested */
if (!qbits)
{
if (nbits == 1024)
qbits = 160;
else if (nbits == 2048)
qbits = 224;
else if (nbits == 3072)
qbits = 256;
}
/* Check that QBITS and NBITS match the standard. Note that FIPS
186-3 uses N for QBITS and L for NBITS. */
if (nbits == 1024 && qbits == 160 && use_fips186_2)
; /* Allowed in FIPS 186-2 mode. */
else if (nbits == 2048 && qbits == 224)
;
else if (nbits == 2048 && qbits == 256)
;
else if (nbits == 3072 && qbits == 256)
;
else
return GPG_ERR_INV_VALUE;
if (domain->p && domain->q && domain->g)
{
/* Domain parameters are given; use them. */
prime_p = mpi_copy (domain->p);
prime_q = mpi_copy (domain->q);
value_g = mpi_copy (domain->g);
gcry_assert (mpi_get_nbits (prime_p) == nbits);
gcry_assert (mpi_get_nbits (prime_q) == qbits);
gcry_assert (!deriveparms);
ec = 0;
}
else
{
/* Generate new domain parameters. */
/* Get an initial seed value. */
if (deriveparms)
{
initial_seed.sexp = sexp_find_token (deriveparms, "seed", 0);
if (initial_seed.sexp)
initial_seed.seed = sexp_nth_data (initial_seed.sexp, 1,
&initial_seed.seedlen);
}
if (use_fips186_2)
ec = _gcry_generate_fips186_2_prime (nbits, qbits,
initial_seed.seed,
initial_seed.seedlen,
&prime_q, &prime_p,
r_counter,
r_seed, r_seedlen);
else
ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0,
&prime_q, &prime_p,
r_counter,
r_seed, r_seedlen, NULL);
sexp_release (initial_seed.sexp);
if (ec)
goto leave;
/* Find a generator g (h and e are helpers).
* e = (p-1)/q
*/
value_e = mpi_alloc_like (prime_p);
mpi_sub_ui (value_e, prime_p, 1);
mpi_fdiv_q (value_e, value_e, prime_q );
value_g = mpi_alloc_like (prime_p);
value_h = mpi_alloc_set_ui (1);
do
{
mpi_add_ui (value_h, value_h, 1);
/* g = h^e mod p */
mpi_powm (value_g, value_h, value_e, prime_p);
}
while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */
}
value_c = mpi_snew (qbits);
value_x = mpi_snew (qbits);
value_qm2 = mpi_snew (qbits);
mpi_sub_ui (value_qm2, prime_q, 2);
/* FIPS 186-4 B.1.2 steps 4-6 */
do
{
if( DBG_CIPHER )
progress('.');
_gcry_mpi_randomize (value_c, qbits, GCRY_VERY_STRONG_RANDOM);
mpi_clear_highbit (value_c, qbits+1);
}
while (!(mpi_cmp_ui (value_c, 0) > 0 && mpi_cmp (value_c, value_qm2) < 0));
/* while (mpi_cmp (value_c, value_qm2) > 0); */
/* x = c + 1 */
mpi_add_ui(value_x, value_c, 1);
/* y = g^x mod p */
value_y = mpi_alloc_like (prime_p);
mpi_powm (value_y, value_g, value_x, prime_p);
if (DBG_CIPHER)
{
progress('\n');
log_mpidump("dsa p", prime_p );
log_mpidump("dsa q", prime_q );
log_mpidump("dsa g", value_g );
log_mpidump("dsa y", value_y );
log_mpidump("dsa x", value_x );
log_mpidump("dsa h", value_h );
}
/* Copy the stuff to the key structures. */
sk->p = prime_p; prime_p = NULL;
sk->q = prime_q; prime_q = NULL;
sk->g = value_g; value_g = NULL;
sk->y = value_y; value_y = NULL;
sk->x = value_x; value_x = NULL;
*r_h = value_h; value_h = NULL;
leave:
_gcry_mpi_release (prime_p);
_gcry_mpi_release (prime_q);
_gcry_mpi_release (value_g);
_gcry_mpi_release (value_y);
_gcry_mpi_release (value_x);
_gcry_mpi_release (value_h);
_gcry_mpi_release (value_e);
_gcry_mpi_release (value_c);
_gcry_mpi_release (value_qm2);
/* As a last step test this keys (this should never fail of course). */
if (!ec && test_keys (sk, qbits) )
{
_gcry_mpi_release (sk->p); sk->p = NULL;
_gcry_mpi_release (sk->q); sk->q = NULL;
_gcry_mpi_release (sk->g); sk->g = NULL;
_gcry_mpi_release (sk->y); sk->y = NULL;
_gcry_mpi_release (sk->x); sk->x = NULL;
fips_signal_error ("self-test after key generation failed");
ec = GPG_ERR_SELFTEST_FAILED;
}
if (ec)
{
*r_counter = 0;
xfree (*r_seed); *r_seed = NULL;
*r_seedlen = 0;
_gcry_mpi_release (*r_h); *r_h = NULL;
}
return ec;
}
/*
Test whether the secret key is valid.
Returns: if this is a valid key.
*/
static int
check_secret_key( DSA_secret_key *sk )
{
int rc;
gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) );
mpi_powm( y, sk->g, sk->x, sk->p );
rc = !mpi_cmp( y, sk->y );
mpi_free( y );
return rc;
}
/*
Make a DSA signature from INPUT and put it into r and s.
INPUT may either be a plain MPI or an opaque MPI which is then
internally converted to a plain MPI. FLAGS and HASHALGO may both
be 0 for standard operation mode.
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)
{
gpg_err_code_t rc;
gcry_mpi_t hash;
gcry_mpi_t k;
gcry_mpi_t kinv;
gcry_mpi_t tmp;
const void *abuf;
unsigned int abits, qbits;
int extraloops = 0;
qbits = mpi_get_nbits (skey->q);
/* Convert the INPUT into an MPI. */
rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
if (rc)
return rc;
again:
/* Create the K value. */
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, skey->q, skey->x,
abuf, (abits+7)/8, hashalgo, extraloops);
if (rc)
goto leave;
}
else
{
/* Select a random k with 0 < k < q */
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 );
/* 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);
mpi_free(kinv);
mpi_free(tmp);
if (!mpi_cmp_ui (r, 0))
{
/* This is a highly unlikely code path. */
extraloops++;
goto again;
}
rc = 0;
leave:
if (hash != input)
mpi_free (hash);
return rc;
}
/*
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 )
{
gpg_err_code_t rc = 0;
gcry_mpi_t w, u1, u2, v;
gcry_mpi_t base[3];
gcry_mpi_t ex[3];
gcry_mpi_t hash;
unsigned int nbits;
if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */
if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */
nbits = mpi_get_nbits (pkey->q);
rc = _gcry_dsa_normalize_hash (input, &hash, nbits);
if (rc)
return rc;
w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
/* w = s^(-1) mod q */
mpi_invm( w, s, pkey->q );
/* u1 = (hash * w) mod q */
mpi_mulm( u1, hash, w, pkey->q );
/* u2 = r * w mod q */
mpi_mulm( u2, r, w, pkey->q );
/* v = g^u1 * y^u2 mod p mod q */
base[0] = pkey->g; ex[0] = u1;
base[1] = pkey->y; ex[1] = u2;
base[2] = NULL; ex[2] = NULL;
mpi_mulpowm( v, base, ex, pkey->p );
mpi_fdiv_r( v, v, pkey->q );
if (mpi_cmp( v, r ))
{
if (DBG_CIPHER)
{
log_mpidump (" i", input);
log_mpidump (" h", hash);
log_mpidump (" v", v);
log_mpidump (" r", r);
log_mpidump (" s", s);
}
rc = GPG_ERR_BAD_SIGNATURE;
}
mpi_free(w);
mpi_free(u1);
mpi_free(u2);
mpi_free(v);
if (hash != input)
mpi_free (hash);
return rc;
}
/*********************************************
************** interface ******************
*********************************************/
static gcry_err_code_t
dsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
{
gpg_err_code_t rc;
unsigned int nbits;
gcry_sexp_t domainsexp;
DSA_secret_key sk;
gcry_sexp_t l1;
unsigned int qbits = 0;
gcry_sexp_t deriveparms = NULL;
gcry_sexp_t seedinfo = NULL;
gcry_sexp_t misc_info = NULL;
int flags = 0;
dsa_domain_t domain;
gcry_mpi_t *factors = NULL;
memset (&sk, 0, sizeof sk);
memset (&domain, 0, sizeof domain);
rc = _gcry_pk_util_get_nbits (genparms, &nbits);
if (rc)
return rc;
/* 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)
return rc;\
}
/* Parse the optional qbits element. */
l1 = sexp_find_token (genparms, "qbits", 0);
if (l1)
{
char buf[50];
const char *s;
size_t n;
s = sexp_nth_data (l1, 1, &n);
if (!s || n >= DIM (buf) - 1 )
{
sexp_release (l1);
return GPG_ERR_INV_OBJ; /* No value or value too large. */
}
memcpy (buf, s, n);
buf[n] = 0;
qbits = (unsigned int)strtoul (buf, NULL, 0);
sexp_release (l1);
}
/* Parse the optional transient-key flag. */
if (!(flags & PUBKEY_FLAG_TRANSIENT_KEY))
{
l1 = sexp_find_token (genparms, "transient-key", 0);
if (l1)
{
flags |= PUBKEY_FLAG_TRANSIENT_KEY;
sexp_release (l1);
}
}
/* Get the optional derive parameters. */
deriveparms = sexp_find_token (genparms, "derive-parms", 0);
/* Parse the optional "use-fips186" flags. */
if (!(flags & PUBKEY_FLAG_USE_FIPS186))
{
l1 = sexp_find_token (genparms, "use-fips186", 0);
if (l1)
{
flags |= PUBKEY_FLAG_USE_FIPS186;
sexp_release (l1);
}
}
if (!(flags & PUBKEY_FLAG_USE_FIPS186_2))
{
l1 = sexp_find_token (genparms, "use-fips186-2", 0);
if (l1)
{
flags |= PUBKEY_FLAG_USE_FIPS186_2;
sexp_release (l1);
}
}
/* Check whether domain parameters are given. */
domainsexp = sexp_find_token (genparms, "domain", 0);
if (domainsexp)
{
/* DERIVEPARMS can't be used together with domain parameters.
NBITS abnd QBITS may not be specified because there values
are derived from the domain parameters. */
if (deriveparms || qbits || nbits)
{
sexp_release (domainsexp);
sexp_release (deriveparms);
return GPG_ERR_INV_VALUE;
}
/* Put all domain parameters into the domain object. */
l1 = sexp_find_token (domainsexp, "p", 0);
domain.p = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
l1 = sexp_find_token (domainsexp, "q", 0);
domain.q = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
l1 = sexp_find_token (domainsexp, "g", 0);
domain.g = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
sexp_release (domainsexp);
/* Check that all domain parameters are available. */
if (!domain.p || !domain.q || !domain.g)
{
_gcry_mpi_release (domain.p);
_gcry_mpi_release (domain.q);
_gcry_mpi_release (domain.g);
sexp_release (deriveparms);
return GPG_ERR_MISSING_VALUE;
}
/* Get NBITS and QBITS from the domain parameters. */
nbits = mpi_get_nbits (domain.p);
qbits = mpi_get_nbits (domain.q);
}
if (deriveparms
|| (flags & PUBKEY_FLAG_USE_FIPS186)
|| (flags & PUBKEY_FLAG_USE_FIPS186_2)
|| fips_mode ())
{
int counter;
void *seed;
size_t seedlen;
gcry_mpi_t h_value;
rc = generate_fips186 (&sk, nbits, qbits, deriveparms,
!!(flags & PUBKEY_FLAG_USE_FIPS186_2),
&domain,
&counter, &seed, &seedlen, &h_value);
if (!rc && h_value)
{
/* Format the seed-values unless domain parameters are used
for which a H_VALUE of NULL is an indication. */
rc = sexp_build (&seedinfo, NULL,
"(seed-values(counter %d)(seed %b)(h %m))",
counter, (int)seedlen, seed, h_value);
xfree (seed);
_gcry_mpi_release (h_value);
}
}
else
{
rc = generate (&sk, nbits, qbits,
!!(flags & PUBKEY_FLAG_TRANSIENT_KEY),
&domain, &factors);
}
if (!rc)
{
/* Put the factors into MISC_INFO. Note that the factors are
not confidential thus we can store them in standard memory. */
int nfactors, i, j;
char *p;
char *format = NULL;
void **arg_list = NULL;
for (nfactors=0; factors && factors[nfactors]; nfactors++)
;
/* Allocate space for the format string:
"(misc-key-info%S(pm1-factors%m))"
with one "%m" for each factor and construct it. */
format = xtrymalloc (50 + 2*nfactors);
if (!format)
rc = gpg_err_code_from_syserror ();
else
{
p = stpcpy (format, "(misc-key-info");
if (seedinfo)
p = stpcpy (p, "%S");
if (nfactors)
{
p = stpcpy (p, "(pm1-factors");
for (i=0; i < nfactors; i++)
p = stpcpy (p, "%m");
p = stpcpy (p, ")");
}
p = stpcpy (p, ")");
/* Allocate space for the list of factors plus one for the
seedinfo s-exp plus an extra NULL entry for safety and
fill it with the factors. */
arg_list = xtrycalloc (nfactors+1+1, sizeof *arg_list);
if (!arg_list)
rc = gpg_err_code_from_syserror ();
else
{
i = 0;
if (seedinfo)
arg_list[i++] = &seedinfo;
for (j=0; j < nfactors; j++)
arg_list[i++] = factors + j;
arg_list[i] = NULL;
rc = sexp_build_array (&misc_info, NULL, format, arg_list);
}
}
xfree (arg_list);
xfree (format);
}
if (!rc)
rc = sexp_build (r_skey, NULL,
"(key-data"
" (public-key"
" (dsa(p%m)(q%m)(g%m)(y%m)))"
" (private-key"
" (dsa(p%m)(q%m)(g%m)(y%m)(x%m)))"
" %S)",
sk.p, sk.q, sk.g, sk.y,
sk.p, sk.q, sk.g, sk.y, sk.x,
misc_info);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
_gcry_mpi_release (domain.p);
_gcry_mpi_release (domain.q);
_gcry_mpi_release (domain.g);
sexp_release (seedinfo);
sexp_release (misc_info);
sexp_release (deriveparms);
if (factors)
{
gcry_mpi_t *mp;
for (mp = factors; *mp; mp++)
mpi_free (*mp);
xfree (factors);
}
return rc;
}
static gcry_err_code_t
dsa_check_secret_key (gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
DSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL};
rc = _gcry_sexp_extract_param (keyparms, NULL, "pqgyx",
&sk.p, &sk.q, &sk.g, &sk.y, &sk.x,
NULL);
if (rc)
goto leave;
if (!check_secret_key (&sk))
rc = GPG_ERR_BAD_SECKEY;
leave:
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
if (DBG_CIPHER)
log_debug ("dsa_testkey => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
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;
DSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL};
gcry_mpi_t sig_r = NULL;
gcry_mpi_t sig_s = NULL;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
dsa_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("dsa_sign data", data);
/* Extract the key. */
rc = _gcry_sexp_extract_param (keyparms, NULL, "pqgyx",
&sk.p, &sk.q, &sk.g, &sk.y, &sk.x, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_sign p", sk.p);
log_mpidump ("dsa_sign q", sk.q);
log_mpidump ("dsa_sign g", sk.g);
log_mpidump ("dsa_sign y", sk.y);
if (!fips_mode ())
log_mpidump ("dsa_sign x", sk.x);
}
sig_r = mpi_new (0);
sig_s = mpi_new (0);
rc = sign (sig_r, sig_s, data, &sk, ctx.flags, ctx.hash_algo);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_sign sig_r", sig_r);
log_mpidump ("dsa_sign sig_s", sig_s);
}
rc = sexp_build (r_sig, NULL, "(sig-val(dsa(r%M)(s%M)))", sig_r, sig_s);
leave:
_gcry_mpi_release (sig_r);
_gcry_mpi_release (sig_s);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
_gcry_mpi_release (data);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("dsa_sign => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
dsa_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;
gcry_mpi_t sig_r = NULL;
gcry_mpi_t sig_s = NULL;
gcry_mpi_t data = NULL;
DSA_public_key pk = { NULL, NULL, NULL, NULL };
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
dsa_get_nbits (s_keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("dsa_verify data", data);
/* Extract the signature value. */
rc = _gcry_pk_util_preparse_sigval (s_sig, dsa_names, &l1, NULL);
if (rc)
goto leave;
rc = _gcry_sexp_extract_param (l1, NULL, "rs", &sig_r, &sig_s, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_verify s_r", sig_r);
log_mpidump ("dsa_verify s_s", sig_s);
}
/* Extract the key. */
rc = _gcry_sexp_extract_param (s_keyparms, NULL, "pqgy",
&pk.p, &pk.q, &pk.g, &pk.y, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_verify p", pk.p);
log_mpidump ("dsa_verify q", pk.q);
log_mpidump ("dsa_verify g", pk.g);
log_mpidump ("dsa_verify y", pk.y);
}
/* Verify the signature. */
rc = verify (sig_r, sig_s, data, &pk);
leave:
_gcry_mpi_release (pk.p);
_gcry_mpi_release (pk.q);
_gcry_mpi_release (pk.g);
_gcry_mpi_release (pk.y);
_gcry_mpi_release (data);
_gcry_mpi_release (sig_r);
_gcry_mpi_release (sig_s);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("dsa_verify => %s\n", rc?gpg_strerror (rc):"Good");
return rc;
}
/* Return the number of bits for the key described by PARMS. On error
* 0 is returned. The format of PARMS starts with the algorithm name;
* for example:
*
* (dsa
* (p <mpi>)
* (q <mpi>)
* (g <mpi>)
* (y <mpi>))
*
* More parameters may be given but we only need P here.
*/
static unsigned int
dsa_get_nbits (gcry_sexp_t parms)
{
gcry_sexp_t l1;
gcry_mpi_t p;
unsigned int nbits;
l1 = sexp_find_token (parms, "p", 1);
if (!l1)
return 0; /* Parameter P not found. */
p = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
nbits = p? mpi_get_nbits (p) : 0;
_gcry_mpi_release (p);
return nbits;
}
/*
Self-test section.
*/
static const char *
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#))";
static const char sample_data_bad[] =
"(data (flags rfc6979)"
" (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))";
static const char signature_r[] =
"eace8bdbbe353c432a795d9ec556c6d021f7a03f42c36e9bc87e4ac7932cc809";
static const char signature_s[] =
"7081e175455f9247b812b74583e9e94f9ea79bd640dc962533b0680793a38d53";
const char *errtxt = NULL;
gcry_error_t err;
gcry_sexp_t data = NULL;
gcry_sexp_t data_bad = NULL;
gcry_sexp_t sig = NULL;
gcry_sexp_t l1 = NULL;
gcry_sexp_t l2 = NULL;
gcry_mpi_t r = NULL;
gcry_mpi_t s = NULL;
gcry_mpi_t calculated_r = NULL;
gcry_mpi_t calculated_s = NULL;
int cmp;
err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
if (!err)
err = sexp_sscan (&data_bad, NULL,
sample_data_bad, strlen (sample_data_bad));
if (!err)
err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL);
if (!err)
err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL);
if (err)
{
errtxt = "converting data failed";
goto leave;
}
err = _gcry_pk_sign (&sig, data, skey);
if (err)
{
errtxt = "signing failed";
goto leave;
}
/* check against known signature */
errtxt = "signature validity failed";
l1 = _gcry_sexp_find_token (sig, "sig-val", 0);
if (!l1)
goto leave;
l2 = _gcry_sexp_find_token (l1, "dsa", 0);
if (!l2)
goto leave;
sexp_release (l1);
l1 = l2;
l2 = _gcry_sexp_find_token (l1, "r", 0);
if (!l2)
goto leave;
calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!calculated_r)
goto leave;
sexp_release (l2);
l2 = _gcry_sexp_find_token (l1, "s", 0);
if (!l2)
goto leave;
calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!calculated_s)
goto leave;
errtxt = "known sig check failed";
cmp = _gcry_mpi_cmp (r, calculated_r);
if (cmp)
goto leave;
cmp = _gcry_mpi_cmp (s, calculated_s);
if (cmp)
goto leave;
errtxt = NULL;
err = _gcry_pk_verify (sig, data, pkey);
if (err)
{
errtxt = "verify failed";
goto leave;
}
err = _gcry_pk_verify (sig, data_bad, pkey);
if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
{
errtxt = "bad signature not detected";
goto leave;
}
leave:
_gcry_mpi_release (calculated_s);
_gcry_mpi_release (calculated_r);
_gcry_mpi_release (s);
_gcry_mpi_release (r);
sexp_release (l2);
sexp_release (l1);
sexp_release (sig);
sexp_release (data_bad);
sexp_release (data);
return errtxt;
}
static gpg_err_code_t
selftests_dsa_2048 (selftest_report_func_t report)
{
const char *what;
const char *errtxt;
gcry_error_t err;
gcry_sexp_t skey = NULL;
gcry_sexp_t pkey = NULL;
/* Convert the S-expressions into the internal representation. */
what = "convert";
err = sexp_sscan (&skey, NULL, sample_secret_key_2048, strlen (sample_secret_key_2048));
if (!err)
err = sexp_sscan (&pkey, NULL,
sample_public_key_2048, strlen (sample_public_key_2048));
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "key consistency";
err = _gcry_pk_testkey (skey);
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "sign";
errtxt = selftest_sign (pkey, skey);
if (errtxt)
goto failed;
sexp_release (pkey);
sexp_release (skey);
return 0; /* Succeeded. */
failed:
sexp_release (pkey);
sexp_release (skey);
if (report)
report ("pubkey", GCRY_PK_DSA, 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;
(void)extended;
switch (algo)
{
case GCRY_PK_DSA:
ec = selftests_dsa_2048 (report);
break;
default:
ec = GPG_ERR_PUBKEY_ALGO;
break;
}
return ec;
}
gcry_pk_spec_t _gcry_pubkey_spec_dsa =
{
GCRY_PK_DSA, { 0, 1 },
GCRY_PK_USAGE_SIGN,
"DSA", dsa_names,
"pqgy", "pqgyx", "", "rs", "pqgy",
dsa_generate,
dsa_check_secret_key,
NULL,
NULL,
dsa_sign,
dsa_verify,
dsa_get_nbits,
run_selftests
};
diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index 748e6dba..7a9d93e2 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -1,141 +1,141 @@
/* ecc-common.h - Declarations of common ECC code
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_ECC_COMMON_H
#define GCRY_ECC_COMMON_H
/* Definition of a curve. */
typedef struct
{
enum gcry_mpi_ec_models model;/* The model descrinbing this curve. */
enum ecc_dialects dialect; /* The dialect used with the curve. */
gcry_mpi_t p; /* Prime specifying the field GF(p). */
gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */
gcry_mpi_t b; /* Second coefficient of the Weierstrass equation.
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. */
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
point_set (mpi_point_t d, mpi_point_t s)
{
mpi_set (d->x, s->x);
mpi_set (d->y, s->y);
mpi_set (d->z, s->z);
}
#define point_init(a) _gcry_mpi_point_init ((a))
#define point_free(a) _gcry_mpi_point_free_parts ((a))
/*-- ecc-curves.c --*/
gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits,
const char *name,
elliptic_curve_t *curve,
unsigned int *r_nbits);
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);
const char *_gcry_ecc_get_curve (gcry_sexp_t keyparms,
int iterator,
unsigned int *r_nbits);
gcry_sexp_t _gcry_ecc_get_param_sexp (const char *name);
/*-- ecc-misc.c --*/
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);
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);
/*-- ecc.c --*/
/*-- ecc-ecdsa.c --*/
gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
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);
/*-- ecc-eddsa.c --*/
gpg_err_code_t _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign,
mpi_ec_t ec);
gpg_err_code_t _gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ctx,
gcry_mpi_t x, gcry_mpi_t y,
int with_prefix,
unsigned char **r_buffer,
unsigned int *r_buflen);
gpg_err_code_t _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value,
unsigned int nbits);
gpg_err_code_t _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
gcry_mpi_t d, 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_sign (gcry_mpi_t input,
ECC_secret_key *sk,
gcry_mpi_t r_r, gcry_mpi_t s,
int hashalgo, gcry_mpi_t pk);
gpg_err_code_t _gcry_ecc_eddsa_verify (gcry_mpi_t input,
ECC_public_key *pk,
gcry_mpi_t r, gcry_mpi_t s,
int hashalgo, gcry_mpi_t pkmpi);
/*-- ecc-gost.c --*/
gpg_err_code_t _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
gcry_mpi_t r, gcry_mpi_t s);
gpg_err_code_t _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
gcry_mpi_t r, gcry_mpi_t s);
#endif /*GCRY_ECC_COMMON_H*/
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 971afbed..65613d96 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -1,1370 +1,1370 @@
/* ecc-curves.c - Elliptic Curve parameter mangement
* Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "g10lib.h"
#include "mpi.h"
#include "mpi-internal.h"
#include "cipher.h"
#include "context.h"
#include "ec-context.h"
#include "pubkey-internal.h"
#include "ecc-common.h"
/* This tables defines aliases for curve names. */
static const struct
{
const char *name; /* Our name. */
const char *other; /* Other name. */
} curve_aliases[] =
{
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" }, /* OpenPGP */
{ "Ed25519", "1.3.6.1.4.1.11591.15.1" }, /* OpenPGP */
#if 0
/* FIXME: We have a naming issue here. RFC-8032 says that its
* Ed25519 is the pureEdDSA, that is w.o. the SHA512 prehasing we
* use in OpenPGP. */
{ "Ed25519", "1.3.101.112" }, /* rfc8410 */
{ "Ed448", "1.3.101.113" }, /* rfc8410 */
{ "X22519", "1.3.101.110" }, /* rfc8410 */
{ "X448", "1.3.101.111" }, /* rfc8410 */
#endif
{ "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */
{ "NIST P-192", "prime192v1" }, /* X9.62 name. */
{ "NIST P-192", "secp192r1" }, /* SECP name. */
{ "NIST P-192", "nistp192" }, /* rfc5656. */
{ "NIST P-224", "secp224r1" },
{ "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */
{ "NIST P-224", "nistp224" }, /* rfc5656. */
{ "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */
{ "NIST P-256", "prime256v1" },
{ "NIST P-256", "secp256r1" },
{ "NIST P-256", "nistp256" }, /* rfc5656. */
{ "NIST P-384", "secp384r1" },
{ "NIST P-384", "1.3.132.0.34" },
{ "NIST P-384", "nistp384" }, /* rfc5656. */
{ "NIST P-521", "secp521r1" },
{ "NIST P-521", "1.3.132.0.35" },
{ "NIST P-521", "nistp521" }, /* rfc5656. */
{ "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
{ "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
{ "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
{ "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
{ "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
{ "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
{ "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
{ "GOST2001-test", "1.2.643.2.2.35.0" },
{ "GOST2001-CryptoPro-A", "1.2.643.2.2.35.1" },
{ "GOST2001-CryptoPro-B", "1.2.643.2.2.35.2" },
{ "GOST2001-CryptoPro-C", "1.2.643.2.2.35.3" },
{ "GOST2001-CryptoPro-A", "GOST2001-CryptoPro-XchA" },
{ "GOST2001-CryptoPro-C", "GOST2001-CryptoPro-XchB" },
{ "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" },
{ "secp256k1", "1.3.132.0.10" },
{ NULL, NULL}
};
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. */
/* The model describing this curve. This is mainly used to select
the group equation. */
enum gcry_mpi_ec_models model;
/* The actual ECC dialect used. This is used for curve specific
optimizations and to select encodings etc. */
enum ecc_dialects dialect;
const char *p; /* The prime defining the field. */
const char *a, *b; /* The coefficients. For Twisted Edwards
Curves b is used for d. For Montgomery
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. */
} ecc_domain_parms_t;
/* This static table defines all available curves. */
static const ecc_domain_parms_t domain_parms[] =
{
{
/* (-x^2 + y^2 = 1 + dx^2y^2) */
"Ed25519", 256, 0,
MPI_EC_EDWARDS, ECC_DIALECT_ED25519,
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
"-0x01",
"-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
"0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
"0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
"0x6666666666666666666666666666666666666666666666666666666666666658",
"0x08"
},
{
/* (y^2 = x^3 + 486662*x^2 + x) */
"Curve25519", 256, 0,
MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
"0x01DB41",
"0x01",
"0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
"0x0000000000000000000000000000000000000000000000000000000000000009",
"0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
"0x08"
},
#if 0 /* No real specs yet found. */
{
/* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
"Curve3617",
"0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF",
MPI_EC_EDWARDS, 0,
"0x01",
"0x0e21",
"0x07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB3CC92414CF"
"706022B36F1C0338AD63CF181B0E71A5E106AF79",
"0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
"6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
"0x22",
"0x08"
},
#endif /*0*/
{
"NIST P-192", 192, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xfffffffffffffffffffffffffffffffeffffffffffffffff",
"0xfffffffffffffffffffffffffffffffefffffffffffffffc",
"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
"0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
"0x01"
},
{
"NIST P-224", 224, 1,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xffffffffffffffffffffffffffffffff000000000000000000000001",
"0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
"0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
"0x01"
},
{
"NIST P-256", 256, 1,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
"0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
"0x01"
},
{
"NIST P-384", 384, 1,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000ffffffff",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000fffffffc",
"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
"c656398d8a2ed19d2a85c8edd3ec2aef",
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
"581a0db248b0a77aecec196accc52973",
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
"5502f25dbf55296c3a545e3872760ab7",
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
"0a60b1ce1d7e819d7a431d7c90ea0e5f",
"0x01"
},
{
"NIST P-521", 521, 1,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
"0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
"9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
"0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
"3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
"662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"0x01"
},
{ "brainpoolP160r1", 160, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
"0x340e7be2a280eb74e2be61bada745d97e8f7c300",
"0x1e589a8595423412134faa2dbdec95c8d8675e58",
"0xe95e4a5f737059dc60df5991d45029409e60fc09",
"0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
"0x1667cb477a1a8ec338f94741669c976316da6321",
"0x01"
},
{ "brainpoolP192r1", 192, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
"0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
"0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
"0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
"0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
"0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
"0x01"
},
{ "brainpoolP224r1", 224, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
"0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
"0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
"0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
"0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
"0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
"0x01"
},
{ "brainpoolP256r1", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
"0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
"0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
"0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
"0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
"0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
"0x01"
},
{ "brainpoolP320r1", 320, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
"fcd412b1f1b32e27",
"0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
"92f375a97d860eb4",
"0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
"6f5eb4ac8fb1f1a6",
"0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
"8691555b44c59311",
"0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
"10af8d0d39e20611",
"0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
"d35245d1692e8ee1",
"0x01"
},
{ "brainpoolP384r1", 384, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
"acd3a729901d1a71874700133107ec53",
"0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
"8aa5814a503ad4eb04a8c7dd22ce2826",
"0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
"7cb4390295dbc9943ab78696fa504c11",
"0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
"cf3ab6af6b7fc3103b883202e9046565",
"0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
"e826e03436d646aaef87b2e247d4af1e",
"0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
"0e4646217791811142820341263c5315",
"0x01"
},
{ "brainpoolP512r1", 512, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
"7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
"0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
"2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
"0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
"2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
"0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
"553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
"0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
"ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
"0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
"b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
"0x01"
},
{
"GOST2001-test", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x8000000000000000000000000000000000000000000000000000000000000431",
"0x0000000000000000000000000000000000000000000000000000000000000007",
"0x5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e",
"0x8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3",
"0x0000000000000000000000000000000000000000000000000000000000000002",
"0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
"0x01"
},
{
"GOST2001-CryptoPro-A", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd97",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd94",
"0x00000000000000000000000000000000000000000000000000000000000000a6",
"0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
"0x01"
},
{
"GOST2001-CryptoPro-B", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x8000000000000000000000000000000000000000000000000000000000000c99",
"0x8000000000000000000000000000000000000000000000000000000000000c96",
"0x3e1af419a269a5f866a7d3c25c3df80ae979259373ff2b182f49d4ce7e1bbc8b",
"0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
"0x01"
},
{
"GOST2001-CryptoPro-C", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d759b",
"0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d7598",
"0x000000000000000000000000000000000000000000000000000000000000805a",
"0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
"0x01"
},
{
"GOST2012-test", 511, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
"f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373",
"0x0000000000000000000000000000000000000000000000000000000000000007",
"0x1cff0806a31116da29d8cfa54e57eb748bc5f377e49400fdd788b649eca1ac4"
"361834013b2ad7322480a89ca58e0cf74bc9e540c2add6897fad0a3084f302adc",
"0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
"a82f2d7ecb1dbac719905c5eecc423f1d86e25edbe23c595d644aaf187e6e6df",
"0x24d19cc64572ee30f396bf6ebbfd7a6c5213b3b3d7057cc825f91093a68cd762"
"fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
"0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
"c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
"0x01"
},
{
"GOST2012-tc26-A", 512, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc4",
"0xe8c2505dedfc86ddc1bd0b2b6667f1da34b82574761cb0e879bd081cfd0b6265"
"ee3cb090f30d27614cb4574010da90dd862ef9d4ebee4761503190785a71c760",
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"27e69532f48d89116ff22b8d4e0560609b4b38abfad2b85dcacdb1411f10b275",
"0x0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000003",
"0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
"df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
"0x01"
},
{
"GOST2012-tc26-B", 512, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x8000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000000000006f",
"0x8000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000000000000000000000000006c",
"0x687d1b459dc841457e3e06cf6f5e2517b97c7d614af138bcbf85dc806c4b289f"
"3e965d2db1416d217f8b276fad1ab69c50f78bee1fa3106efb8ccbc7c5140116",
"0x8000000000000000000000000000000000000000000000000000000000000001"
"49a1ec142565a545acfdb77bd9d40cfa8b996712101bea0ec6346c54374f25bd",
"0x0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000002",
"0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
"dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
"0x01"
},
{
"secp256k1", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000007",
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
"0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
"0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
"0x01"
},
{ NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
};
/* Return a copy of POINT. */
static gcry_mpi_point_t
point_copy (gcry_mpi_point_t point)
{
gcry_mpi_point_t newpoint;
if (point)
{
newpoint = mpi_point_new (0);
point_set (newpoint, point);
}
else
newpoint = NULL;
return newpoint;
}
/* Helper to scan a hex string. */
static gcry_mpi_t
scanval (const char *string)
{
gpg_err_code_t rc;
gcry_mpi_t val;
rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (rc)
log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
return val;
}
/* Return the index of the domain_parms table for a curve with NAME.
Return -1 if not found. */
static int
find_domain_parms_idx (const char *name)
{
int idx, aliasno;
/* First check our native curves. */
for (idx = 0; domain_parms[idx].desc; idx++)
if (!strcmp (name, domain_parms[idx].desc))
return idx;
/* If not found consult the alias table. */
if (!domain_parms[idx].desc)
{
for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
if (!strcmp (name, curve_aliases[aliasno].other))
break;
if (curve_aliases[aliasno].name)
{
for (idx = 0; domain_parms[idx].desc; idx++)
if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc))
return idx;
}
}
return -1;
}
/* Generate the crypto system setup. This function takes the NAME of
a curve or the desired number of bits and stores at R_CURVE the
parameters of the named curve or those of a suitable curve. If
R_NBITS is not NULL, the chosen number of bits is stored there.
NULL may be given for R_CURVE, if the value is not required and for
example only a quick test for availability is desired. Note that
the curve fields should be initialized to zero because fields which
are not NULL are skipped. */
gpg_err_code_t
_gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
elliptic_curve_t *curve, unsigned int *r_nbits)
{
int idx;
const char *resname = NULL; /* Set to a found curve name. */
if (name)
idx = find_domain_parms_idx (name);
else
{
for (idx = 0; domain_parms[idx].desc; idx++)
if (nbits == domain_parms[idx].nbits
&& domain_parms[idx].model == MPI_EC_WEIERSTRASS)
break;
if (!domain_parms[idx].desc)
idx = -1;
}
if (idx < 0)
return GPG_ERR_UNKNOWN_CURVE;
resname = domain_parms[idx].desc;
/* In fips mode we only support NIST curves. Note that it is
possible to bypass this check by specifying the curve parameters
directly. */
if (fips_mode () && !domain_parms[idx].fips )
return GPG_ERR_NOT_SUPPORTED;
switch (domain_parms[idx].model)
{
case MPI_EC_WEIERSTRASS:
case MPI_EC_EDWARDS:
case MPI_EC_MONTGOMERY:
break;
default:
return GPG_ERR_BUG;
}
if (r_nbits)
*r_nbits = domain_parms[idx].nbits;
if (curve)
{
curve->model = domain_parms[idx].model;
curve->dialect = domain_parms[idx].dialect;
if (!curve->p)
curve->p = scanval (domain_parms[idx].p);
if (!curve->a)
{
curve->a = scanval (domain_parms[idx].a);
if (curve->a->sign)
{
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_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);
if (!curve->G.z)
curve->G.z = mpi_alloc_set_ui (1);
if (!curve->name)
curve->name = resname;
}
return 0;
}
/* 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. */
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)
{
int idx;
idx = find_domain_parms_idx (name);
if (idx < 0)
return GPG_ERR_UNKNOWN_CURVE;
if (g)
{
char *buf;
size_t len;
len = 4;
len += strlen (domain_parms[idx].g_x+2);
len += strlen (domain_parms[idx].g_y+2);
len++;
buf = xtrymalloc (len);
if (!buf)
return gpg_err_code_from_syserror ();
strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
domain_parms[idx].g_y+2);
_gcry_mpi_release (*g);
*g = scanval (buf);
xfree (buf);
}
if (model)
*model = domain_parms[idx].model;
if (dialect)
*dialect = domain_parms[idx].dialect;
if (p)
{
_gcry_mpi_release (*p);
*p = scanval (domain_parms[idx].p);
}
if (a)
{
_gcry_mpi_release (*a);
*a = scanval (domain_parms[idx].a);
}
if (b)
{
_gcry_mpi_release (*b);
*b = scanval (domain_parms[idx].b);
}
if (n)
{
_gcry_mpi_release (*n);
*n = scanval (domain_parms[idx].n);
}
if (h)
{
_gcry_mpi_release (*h);
*h = scanval (domain_parms[idx].h);
}
return 0;
}
/* Return the name matching the parameters in PKEY. This works only
with curves described by the Weierstrass equation. */
const char *
_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_t tmp = NULL;
int idx;
memset (&E, 0, sizeof E);
if (r_nbits)
*r_nbits = 0;
if (!keyparms)
{
idx = iterator;
if (idx >= 0 && idx < DIM (domain_parms))
{
result = domain_parms[idx].desc;
if (r_nbits)
*r_nbits = domain_parms[idx].nbits;
}
return result;
}
/*
* 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));
if (rc == GPG_ERR_NO_OBJ)
{
/* This might be the second use case of checking whether a
specific curve given by name is supported. */
gcry_sexp_t l1;
char *name;
l1 = sexp_find_token (keyparms, "curve", 5);
if (!l1)
goto leave; /* No curve name parameter. */
name = sexp_nth_string (l1, 1);
sexp_release (l1);
if (!name)
goto leave; /* Name missing or out of core. */
idx = find_domain_parms_idx (name);
xfree (name);
if (idx >= 0) /* Curve found. */
{
result = domain_parms[idx].desc;
if (r_nbits)
*r_nbits = domain_parms[idx].nbits;
}
return result;
}
if (rc)
goto leave;
if (mpi_g)
{
_gcry_mpi_point_init (&E.G);
if (_gcry_ecc_os2ec (&E.G, mpi_g))
goto leave;
}
for (idx = 0; domain_parms[idx].desc; idx++)
{
mpi_free (tmp);
tmp = scanval (domain_parms[idx].p);
if (!mpi_cmp (tmp, E.p))
{
mpi_free (tmp);
tmp = scanval (domain_parms[idx].a);
if (!mpi_cmp (tmp, E.a))
{
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;
}
}
}
}
}
}
}
}
leave:
_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)
{
gcry_err_code_t ec = 0;
gcry_sexp_t l1;
l1 = sexp_find_token (keyparam, name, 0);
if (l1)
{
*r_a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
if (!*r_a)
ec = GPG_ERR_INV_OBJ;
}
return ec;
}
/* Helper to extract a point from key parameters. If no parameter
with NAME is found, the functions tries to find a non-encoded point
by appending ".x", ".y" and ".z" to NAME. ".z" is in this case
optional and defaults to 1. EC is the context which at this point
may not be fully initialized. */
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)
{
gcry_err_code_t rc;
gcry_sexp_t l1;
gcry_mpi_point_t point;
l1 = sexp_find_token (keyparam, name, 0);
if (l1)
{
gcry_mpi_t a;
a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
sexp_release (l1);
if (!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);
mpi_free (a);
if (rc)
{
mpi_point_release (point);
return rc;
}
}
else
{
char *tmpname;
gcry_mpi_t x = NULL;
gcry_mpi_t y = NULL;
gcry_mpi_t z = NULL;
tmpname = xtrymalloc (strlen (name) + 2 + 1);
if (!tmpname)
return gpg_err_code_from_syserror ();
strcpy (stpcpy (tmpname, name), ".x");
rc = mpi_from_keyparam (&x, keyparam, tmpname);
if (rc)
{
xfree (tmpname);
return rc;
}
strcpy (stpcpy (tmpname, name), ".y");
rc = mpi_from_keyparam (&y, keyparam, tmpname);
if (rc)
{
mpi_free (x);
xfree (tmpname);
return rc;
}
strcpy (stpcpy (tmpname, name), ".z");
rc = mpi_from_keyparam (&z, keyparam, tmpname);
if (rc)
{
mpi_free (y);
mpi_free (x);
xfree (tmpname);
return rc;
}
if (!z)
z = mpi_set_ui (NULL, 1);
if (x && y)
point = mpi_point_snatch_set (NULL, x, y, z);
else
{
mpi_free (x);
mpi_free (y);
mpi_free (z);
point = NULL;
}
xfree (tmpname);
}
if (point)
*r_a = point;
return 0;
}
/* 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;
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;
gcry_sexp_t l1;
*r_ctx = NULL;
if (keyparam)
{
/* Parse an optional flags list. */
l1 = sexp_find_token (keyparam, "flags", 0);
if (l1)
{
errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
sexp_release (l1);
l1 = NULL;
if (errc)
goto leave;
}
/* Check whether a curve name was given. */
l1 = sexp_find_token (keyparam, "curve", 5);
/* If we don't have a curve name or if override parameters have
explicitly been requested, parse them. */
if (!l1 || (flags & PUBKEY_FLAG_PARAM))
{
errc = mpi_from_keyparam (&p, keyparam, "p");
if (errc)
goto leave;
errc = mpi_from_keyparam (&a, keyparam, "a");
if (errc)
goto leave;
errc = mpi_from_keyparam (&b, keyparam, "b");
if (errc)
goto leave;
errc = point_from_keyparam (&G, keyparam, "g", NULL);
if (errc)
goto leave;
errc = mpi_from_keyparam (&n, keyparam, "n");
if (errc)
goto leave;
errc = mpi_from_keyparam (&h, keyparam, "h");
if (errc)
goto leave;
}
}
else
l1 = NULL; /* No curvename. */
/* Check whether a curve parameter is available and use that to fill
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)
{
char *name;
elliptic_curve_t *E;
if (l1)
{
name = sexp_nth_string (l1, 1);
sexp_release (l1);
if (!name)
{
errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
goto leave;
}
}
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);
xfree (name);
if (errc)
{
xfree (E);
goto leave;
}
model = E->model;
dialect = E->dialect;
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)
{
h = E->h;
E->h = NULL;
}
_gcry_ecc_curve_free (E);
xfree (E);
}
errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
if (!errc)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_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;
}
/* 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)
{
errc = point_from_keyparam (&Q, keyparam, "q", ec);
if (errc)
goto leave;
errc = mpi_from_keyparam (&d, keyparam, "d");
if (errc)
goto leave;
}
if (Q)
{
ec->Q = Q;
Q = NULL;
}
if (d)
{
ec->d = d;
d = NULL;
}
*r_ctx = ctx;
ctx = NULL;
}
leave:
_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;
}
/* Return the parameters of the curve NAME as an S-expression. */
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_sexp_t result;
int i;
memset (&E, 0, sizeof E);
if (_gcry_ecc_fill_in_curve (0, name, &E, &nbits))
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[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]))
result = NULL;
for (i=0; pkey[i]; i++)
_gcry_mpi_release (pkey[i]);
return result;
}
/* Return an MPI (or opaque MPI) described by NAME and the context EC.
If COPY is true a copy is returned, if not a const MPI may be
returned. In any case mpi_free must be used. */
gcry_mpi_t
_gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
{
if (!*name)
return NULL;
if (!strcmp (name, "p") && ec->p)
return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
if (!strcmp (name, "a") && ec->a)
return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
if (!strcmp (name, "b") && ec->b)
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, "d") && ec->d)
return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
/* Return a requested point coordinate. */
if (!strcmp (name, "g.x") && ec->G && ec->G->x)
return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
if (!strcmp (name, "g.y") && ec->G && ec->G->y)
return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
return mpi_is_const (ec->Q->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
/* If the base point has been requested, return it in standard
encoding. */
if (!strcmp (name, "g") && ec->G)
return _gcry_mpi_ec_ec2os (ec->G, ec);
/* If the public key has been requested, return it by default in
standard uncompressed encoding or if requested in other
encodings. */
if (*name == 'q' && (!name[1] || name[1] == '@'))
{
/* If only the private key is given, compute the public key. */
if (!ec->Q)
ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
if (!ec->Q)
return NULL;
if (name[1] != '@')
return _gcry_mpi_ec_ec2os (ec->Q, ec);
if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_EDWARDS)
{
unsigned char *encpk;
unsigned int encpklen;
if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
&encpk, &encpklen))
return mpi_set_opaque (NULL, encpk, encpklen*8);
}
}
return NULL;
}
/* Return a point described by NAME and the context EC. */
gcry_mpi_point_t
_gcry_ecc_get_point (const char *name, mpi_ec_t ec)
{
if (!strcmp (name, "g") && ec->G)
return point_copy (ec->G);
if (!strcmp (name, "q"))
{
/* If only the private key is given, compute the public key. */
if (!ec->Q)
ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
if (ec->Q)
return point_copy (ec->Q);
}
return NULL;
}
/* Store the MPI NEWVALUE into the context EC under NAME. */
gpg_err_code_t
_gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
{
gpg_err_code_t rc = 0;
if (!*name)
;
else if (!strcmp (name, "p"))
{
mpi_free (ec->p);
ec->p = mpi_copy (newvalue);
_gcry_mpi_ec_get_reset (ec);
}
else if (!strcmp (name, "a"))
{
mpi_free (ec->a);
ec->a = mpi_copy (newvalue);
_gcry_mpi_ec_get_reset (ec);
}
else if (!strcmp (name, "b"))
{
mpi_free (ec->b);
ec->b = mpi_copy (newvalue);
}
else if (!strcmp (name, "n"))
{
mpi_free (ec->n);
ec->n = mpi_copy (newvalue);
}
else if (!strcmp (name, "h"))
{
mpi_free (ec->h);
ec->h = mpi_copy (newvalue);
}
else if (*name == 'q' && (!name[1] || name[1] == '@'))
{
if (newvalue)
{
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);
}
if (rc || !newvalue)
{
_gcry_mpi_point_release (ec->Q);
ec->Q = NULL;
}
/* Note: We assume that Q matches d and thus do not reset d. */
}
else if (!strcmp (name, "d"))
{
mpi_free (ec->d);
ec->d = mpi_copy (newvalue);
if (ec->d)
{
/* We need to reset the public key because it may not
anymore match. */
_gcry_mpi_point_release (ec->Q);
ec->Q = NULL;
}
}
else
rc = GPG_ERR_UNKNOWN_NAME;
return rc;
}
/* Store the point NEWVALUE into the context EC under NAME. */
gpg_err_code_t
_gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec)
{
if (!strcmp (name, "g"))
{
_gcry_mpi_point_release (ec->G);
ec->G = point_copy (newvalue);
}
else if (!strcmp (name, "q"))
{
_gcry_mpi_point_release (ec->Q);
ec->Q = point_copy (newvalue);
}
else
return GPG_ERR_UNKNOWN_NAME;
return 0;
}
diff --git a/cipher/ecc-ecdsa.c b/cipher/ecc-ecdsa.c
index 140e8c09..8c03eb30 100644
--- a/cipher/ecc-ecdsa.c
+++ b/cipher/ecc-ecdsa.c
@@ -1,250 +1,250 @@
/* ecc-ecdsa.c - Elliptic Curve ECDSA signatures
* Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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 "pubkey-internal.h"
#include "ecc-common.h"
/* Compute an ECDSA 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_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
gcry_mpi_t r, gcry_mpi_t s,
int flags, int hashalgo)
{
gpg_err_code_t rc = 0;
int extraloops = 0;
gcry_mpi_t k, dr, sum, k_1, x;
mpi_point_struct I;
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. */
if (DBG_CIPHER)
log_mpidump ("ecdsa sign hash ", input );
qbits = mpi_get_nbits (skey->E.n);
/* Convert the INPUT into an MPI if needed. */
rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
if (rc)
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);
}
while (!mpi_invm (bi, b, skey->E.n));
k = NULL;
dr = mpi_alloc (0);
sum = mpi_alloc (0);
k_1 = mpi_alloc (0);
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
{
do
{
mpi_free (k);
k = NULL;
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, skey->E.n, skey->d,
abuf, (abits+7)/8,
hashalgo, extraloops);
if (rc)
goto leave;
extraloops++;
}
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))
{
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 */
}
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)
{
log_mpidump ("ecdsa sign result r ", r);
log_mpidump ("ecdsa sign result s ", s);
}
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 (hash != input)
mpi_free (hash);
return rc;
}
/* Verify an ECDSA signature.
* 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)
{
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;
if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.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) )
return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */
nbits = mpi_get_nbits (pkey->E.n);
err = _gcry_dsa_normalize_hash (input, &hash, nbits);
if (err)
return err;
h = mpi_alloc (0);
h1 = mpi_alloc (0);
h2 = mpi_alloc (0);
x = mpi_alloc (0);
point_init (&Q);
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);
/* h1 = hash * s^(-1) (mod n) */
mpi_mulm (h1, hash, h, pkey->E.n);
/* Q1 = [ hash * s^(-1) ]G */
_gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
/* h2 = r * s^(-1) (mod n) */
mpi_mulm (h2, r, h, pkey->E.n);
/* Q2 = [ r * s^(-1) ]Q */
_gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
/* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
_gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
if (!mpi_cmp_ui (Q.z, 0))
{
if (DBG_CIPHER)
log_debug ("ecc verify: Rejected\n");
err = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
{
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 */
if (mpi_cmp (x, r)) /* x != r */
{
if (DBG_CIPHER)
{
log_mpidump (" x", x);
log_mpidump (" r", r);
log_mpidump (" s", s);
}
err = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
leave:
_gcry_mpi_ec_free (ctx);
point_free (&Q2);
point_free (&Q1);
point_free (&Q);
mpi_free (x);
mpi_free (h2);
mpi_free (h1);
mpi_free (h);
if (hash != input)
mpi_free (hash);
return err;
}
diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 89b708a0..1e80f554 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
@@ -1,864 +1,864 @@
/* ecc-eddsa.c - Elliptic Curve EdDSA signatures
* Copyright (C) 2013, 2014 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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"
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;
}
}
/* Helper to scan a hex string. */
static gcry_mpi_t
scanval (const char *string)
{
gpg_err_code_t rc;
gcry_mpi_t val;
rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (rc)
log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
return val;
}
/* Encode MPI using the EdDSA scheme. MINLEN specifies the required
length of the buffer in bytes. On success 0 is returned an a
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,
unsigned char **r_buffer, unsigned int *r_buflen)
{
unsigned char *rawmpi;
unsigned int rawmpilen;
rawmpi = _gcry_mpi_get_buffer (mpi, minlen, &rawmpilen, NULL);
if (!rawmpi)
return gpg_err_code_from_syserror ();
*r_buffer = rawmpi;
*r_buflen = rawmpilen;
return 0;
}
/* 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
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,
int with_prefix,
unsigned char **r_buffer, unsigned int *r_buflen)
{
unsigned char *rawmpi;
unsigned int rawmpilen;
int off = with_prefix? 1:0;
rawmpi = _gcry_mpi_get_buffer_extra (y, minlen, off?-1:0, &rawmpilen, NULL);
if (!rawmpi)
return gpg_err_code_from_syserror ();
if (mpi_test_bit (x, 0) && rawmpilen)
rawmpi[off + rawmpilen - 1] |= 0x80; /* Set sign bit. */
if (off)
rawmpi[0] = 0x40;
*r_buffer = rawmpi;
*r_buflen = rawmpilen + off;
return 0;
}
/* Encode POINT using the EdDSA scheme. X and Y are either scratch
variables supplied by the caller or NULL. CTX is the usual
context. 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 length of this
buffer is stored at R_BUFLEN. */
gpg_err_code_t
_gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ec,
gcry_mpi_t x_in, gcry_mpi_t y_in,
int with_prefix,
unsigned char **r_buffer, unsigned int *r_buflen)
{
gpg_err_code_t rc;
gcry_mpi_t x, y;
x = x_in? x_in : mpi_new (0);
y = y_in? y_in : mpi_new (0);
if (_gcry_mpi_ec_get_affine (x, y, point, ec))
{
log_error ("eddsa_encodepoint: Failed to get affine coordinates\n");
rc = GPG_ERR_INTERNAL;
}
else
rc = eddsa_encode_x_y (x, y, ec->nbits/8, with_prefix, r_buffer, r_buflen);
if (!x_in)
mpi_free (x);
if (!y_in)
mpi_free (y);
return rc;
}
/* Make sure that the opaque MPI VALUE is in compact EdDSA format.
This function updates MPI if needed. */
gpg_err_code_t
_gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
{
gpg_err_code_t rc;
const unsigned char *buf;
unsigned int rawmpilen;
gcry_mpi_t x, y;
unsigned char *enc;
unsigned int enclen;
if (!mpi_is_opaque (value))
return GPG_ERR_INV_OBJ;
buf = mpi_get_opaque (value, &rawmpilen);
if (!buf)
return GPG_ERR_INV_OBJ;
rawmpilen = (rawmpilen + 7)/8;
if (rawmpilen > 1 && (rawmpilen%2))
{
if (buf[0] == 0x04)
{
/* Buffer is in SEC1 uncompressed format. Extract y and
compress. */
rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
buf+1, (rawmpilen-1)/2, NULL);
if (rc)
return rc;
rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2, NULL);
if (rc)
{
mpi_free (x);
return rc;
}
rc = eddsa_encode_x_y (x, y, nbits/8, 0, &enc, &enclen);
mpi_free (x);
mpi_free (y);
if (rc)
return rc;
mpi_set_opaque (value, enc, 8*enclen);
}
else if (buf[0] == 0x40)
{
/* Buffer is compressed but with our SEC1 alike compression
indicator. Remove that byte. FIXME: We should write and
use a function to manipulate an opaque MPI in place. */
if (!_gcry_mpi_set_opaque_copy (value, buf + 1, (rawmpilen - 1)*8))
return gpg_err_code_from_syserror ();
}
}
return 0;
}
/* 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)
{
gpg_err_code_t rc = 0;
gcry_mpi_t u, v, v3, t;
static gcry_mpi_t p58, seven;
if (ec->dialect != ECC_DIALECT_ED25519)
return GPG_ERR_NOT_IMPLEMENTED;
if (!p58)
p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD");
if (!seven)
seven = mpi_set_ui (NULL, 7);
u = mpi_new (0);
v = 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_add_ui (v, v, 1);
/* Compute sqrt(u/v) */
/* v3 = v^3 */
mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p);
/* t = v3 * v3 * u * v = u * v^7 */
mpi_powm (t, v, seven, ec->p);
mpi_mulm (t, t, u, ec->p);
/* t = t^((p-5)/8) = (u * v^7)^((p-5)/8) */
mpi_powm (t, t, p58, ec->p);
/* x = t * u * v^3 = (u * v^3) * (u * v^7)^((p-5)/8) */
mpi_mulm (t, t, u, ec->p);
mpi_mulm (x, t, v3, ec->p);
/* Adjust if needed. */
/* t = v * x^2 */
mpi_mulm (t, x, x, ec->p);
mpi_mulm (t, t, v, ec->p);
/* -t == u ? x = x * sqrt(-1) */
mpi_sub (t, ec->p, t);
if (!mpi_cmp (t, u))
{
static gcry_mpi_t m1; /* Fixme: this is not thread-safe. */
if (!m1)
m1 = scanval ("2B8324804FC1DF0B2B4D00993DFBD7A7"
"2F431806AD2FE478C4EE1B274A0EA0B0");
mpi_mulm (x, x, m1, ec->p);
/* t = v * x^2 */
mpi_mulm (t, x, x, ec->p);
mpi_mulm (t, t, v, ec->p);
/* -t == u ? x = x * sqrt(-1) */
mpi_sub (t, ec->p, t);
if (!mpi_cmp (t, u))
rc = GPG_ERR_INV_OBJ;
}
/* Choose the desired square root according to parity */
if (mpi_test_bit (x, 0) != !!sign)
mpi_sub (x, ec->p, x);
mpi_free (t);
mpi_free (v3);
mpi_free (v);
mpi_free (u);
return rc;
}
/* Decode the EdDSA style encoded PK and set it into RESULT. CTX is
the usual curve context. If R_ENCPK is not NULL, the encoded PK is
stored at that address; this is a new copy to be released by the
caller. In contrast to the supplied PK, this is not an MPI and
thus guaranteed to be properly padded. R_ENCPKLEN receives the
length of that encoded key. */
gpg_err_code_t
_gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
unsigned char **r_encpk, unsigned int *r_encpklen)
{
gpg_err_code_t rc;
unsigned char *rawmpi;
unsigned int rawmpilen;
int sign;
if (mpi_is_opaque (pk))
{
const unsigned char *buf;
buf = mpi_get_opaque (pk, &rawmpilen);
if (!buf)
return GPG_ERR_INV_OBJ;
rawmpilen = (rawmpilen + 7)/8;
/* Handle compression prefixes. The size of the buffer will be
odd in this case. */
if (rawmpilen > 1 && (rawmpilen%2))
{
/* First check whether the public key has been given in
standard uncompressed format (SEC1). No need to recover
x in this case. */
if (buf[0] == 0x04)
{
gcry_mpi_t x, y;
rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
buf+1, (rawmpilen-1)/2, NULL);
if (rc)
return rc;
rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2,NULL);
if (rc)
{
mpi_free (x);
return rc;
}
if (r_encpk)
{
rc = eddsa_encode_x_y (x, y, ctx->nbits/8, 0,
r_encpk, r_encpklen);
if (rc)
{
mpi_free (x);
mpi_free (y);
return rc;
}
}
mpi_snatch (result->x, x);
mpi_snatch (result->y, y);
mpi_set_ui (result->z, 1);
return 0;
}
/* Check whether the public key has been prefixed with a 0x40
byte to explicitly indicate compressed format using a SEC1
alike prefix byte. This is a Libgcrypt extension. */
if (buf[0] == 0x40)
{
rawmpilen--;
buf++;
}
}
/* EdDSA compressed point. */
rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
if (!rawmpi)
return gpg_err_code_from_syserror ();
memcpy (rawmpi, buf, rawmpilen);
reverse_buffer (rawmpi, rawmpilen);
}
else
{
/* 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);
if (!rawmpi)
return gpg_err_code_from_syserror ();
}
if (rawmpilen)
{
sign = !!(rawmpi[0] & 0x80);
rawmpi[0] &= 0x7f;
}
else
sign = 0;
_gcry_mpi_set_buffer (result->y, rawmpi, rawmpilen, 0);
if (r_encpk)
{
/* Revert to little endian. */
if (sign && rawmpilen)
rawmpi[0] |= 0x80;
reverse_buffer (rawmpi, rawmpilen);
*r_encpk = rawmpi;
if (r_encpklen)
*r_encpklen = rawmpilen;
}
else
xfree (rawmpi);
rc = _gcry_ecc_eddsa_recover_x (result->x, result->y, sign, ctx);
mpi_set_ui (result->z, 1);
return rc;
}
/* Compute the A value as used by EdDSA. The caller needs to provide
the context EC and the actual secret D as an MPI. The function
returns a newly allocated 64 byte buffer at r_digest; the first 32
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)
{
gpg_err_code_t rc;
unsigned char *rawmpi = NULL;
unsigned int rawmpilen;
unsigned char *digest;
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. */
/* Note that we clear DIGEST so we can use it as input to left pad
the key with zeroes for hashing. */
digest = xtrycalloc_secure (2, b);
if (!digest)
return gpg_err_code_from_syserror ();
memset (hvec, 0, sizeof hvec);
rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
if (!rawmpi)
{
xfree (digest);
return gpg_err_code_from_syserror ();
}
hvec[0].data = digest;
hvec[0].off = 0;
hvec[0].len = 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);
xfree (rawmpi);
if (rc)
{
xfree (digest);
return rc;
}
/* Compute the A value. */
reverse_buffer (digest, 32); /* Only the first half of the hash. */
digest[0] = (digest[0] & 0x7f) | 0x40;
digest[31] &= 0xf8;
*r_digest = digest;
return 0;
}
/**
* _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.
* @flags: Flags controlling aspects of the creation.
*
* Return: An error code.
*
* The only @flags bit used by this function is %PUBKEY_FLAG_TRANSIENT
* 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)
{
gpg_err_code_t rc;
int b = 256/8; /* The only size we currently support. */
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;
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);
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;
/* log_printmpi ("ecgen a", a); */
/* Compute Q. */
_gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx);
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);
leave:
point_free (&Q);
_gcry_mpi_release (a);
_gcry_mpi_release (x);
_gcry_mpi_release (y);
xfree (hash_d);
return rc;
}
/* Compute an EdDSA signature. See:
* [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja
* Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security
* signatures. Journal of Cryptographic Engineering 2 (2012), 77-89.
* Document ID: a1a62a2f76d23f65d622484ddd09caf8.
- * URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
+ * URL: https://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
*
* 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.
*
* Return the signature struct (r,s) from the message hash. The caller
* must have allocated R_R and S.
*/
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)
{
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 char *encpk = NULL; /* Encoded public key. */
unsigned int encpklen;
mpi_point_struct I; /* Intermediate value. */
mpi_point_struct Q; /* Public key. */
gcry_mpi_t a, x, y, r;
memset (hvec, 0, sizeof hvec);
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);
if (rc)
goto leave;
_gcry_mpi_set_buffer (a, digest, 32, 0);
/* Compute the public key if it has not been supplied as optional
parameter. */
if (pk)
{
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);
}
/* Compute R. */
mbuf = mpi_get_opaque (input, &tmp);
mlen = (tmp +7)/8;
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);
if (rc)
goto leave;
reverse_buffer (digest, 64);
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);
if (DBG_CIPHER)
log_printpnt (" r", &I, ctx);
/* Convert R into affine coordinates and apply encoding. */
rc = _gcry_ecc_eddsa_encodepoint (&I, ctx, 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);
if (rc)
goto leave;
/* No more need for RAWMPI thus we now transfer it to R_R. */
mpi_set_opaque (r_r, rawmpi, rawmpilen*8);
rawmpi = NULL;
reverse_buffer (digest, 64);
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);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printhex (" e_s", rawmpi, rawmpilen);
mpi_set_opaque (s, rawmpi, rawmpilen*8);
rawmpi = NULL;
rc = 0;
leave:
_gcry_mpi_release (a);
_gcry_mpi_release (x);
_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;
}
/* 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.
*/
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)
{
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;
const void *mbuf, *rbuf;
unsigned char *tbuf = NULL;
size_t mlen, rlen;
unsigned int tlen;
unsigned char digest[64];
gcry_buffer_t hvec[3];
gcry_mpi_t h, s;
mpi_point_struct Ia, Ib;
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);
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);
if (rc)
goto leave;
if (!_gcry_mpi_ec_curve_point (&Q, ctx))
{
rc = GPG_ERR_BROKEN_PUBKEY;
goto leave;
}
if (DBG_CIPHER)
log_printhex (" e_pk", encpk, encpklen);
if (encpklen != b)
{
rc = GPG_ERR_INV_LENGTH;
goto leave;
}
/* Convert the other input parameters. */
mbuf = mpi_get_opaque (input, &tmp);
mlen = (tmp +7)/8;
if (DBG_CIPHER)
log_printhex (" m", mbuf, mlen);
rbuf = mpi_get_opaque (r_in, &tmp);
rlen = (tmp +7)/8;
if (DBG_CIPHER)
log_printhex (" r", rbuf, rlen);
if (rlen != b)
{
rc = GPG_ERR_INV_LENGTH;
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);
if (rc)
goto leave;
reverse_buffer (digest, 64);
if (DBG_CIPHER)
log_printhex (" H(R+)", digest, 64);
_gcry_mpi_set_buffer (h, digest, 64, 0);
/* According to the paper the best way for verification is:
encodepoint(sG - h·Q) = encodepoint(r)
because we don't need to decode R. */
{
void *sbuf;
unsigned int slen;
sbuf = _gcry_mpi_get_opaque_copy (s_in, &tmp);
slen = (tmp +7)/8;
reverse_buffer (sbuf, slen);
if (DBG_CIPHER)
log_printhex (" s", sbuf, slen);
_gcry_mpi_set_buffer (s, sbuf, slen, 0);
xfree (sbuf);
if (slen != b)
{
rc = GPG_ERR_INV_LENGTH;
goto leave;
}
}
_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);
if (rc)
goto leave;
if (tlen != rlen || memcmp (tbuf, rbuf, tlen))
{
rc = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
rc = 0;
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;
}
diff --git a/cipher/ecc-gost.c b/cipher/ecc-gost.c
index a34fa084..41aac2d6 100644
--- a/cipher/ecc-gost.c
+++ b/cipher/ecc-gost.c
@@ -1,233 +1,233 @@
/* ecc-gots.c - Elliptic Curve GOST signatures
* Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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"
#include "pubkey-internal.h"
/* Compute an GOST R 34.10-01/-12 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_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
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;
if (DBG_CIPHER)
log_mpidump ("gost sign hash ", input );
qbits = mpi_get_nbits (skey->E.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;
k = NULL;
dr = mpi_alloc (0);
sum = mpi_alloc (0);
ke = mpi_alloc (0);
e = mpi_alloc (0);
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 */
if (!mpi_cmp_ui (e, 0))
mpi_set_ui (e, 1);
/* 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
{
do
{
mpi_free (k);
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))
{
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 */
}
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 */
}
while (!mpi_cmp_ui (s, 0));
if (DBG_CIPHER)
{
log_mpidump ("gost sign result r ", r);
log_mpidump ("gost sign result s ", s);
}
leave:
_gcry_mpi_ec_free (ctx);
point_free (&I);
mpi_free (x);
mpi_free (e);
mpi_free (ke);
mpi_free (sum);
mpi_free (dr);
mpi_free (k);
if (hash != input)
mpi_free (hash);
return rc;
}
/* Verify a GOST R 34.10-01/-12 signature.
* Check if R and S verifies INPUT.
*/
gpg_err_code_t
_gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
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) )
return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */
if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */
x = mpi_alloc (0);
e = mpi_alloc (0);
z1 = mpi_alloc (0);
z2 = mpi_alloc (0);
v = mpi_alloc (0);
rv = mpi_alloc (0);
zero = mpi_alloc (0);
point_init (&Q);
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 */
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) */
_gcry_mpi_ec_mul_point (&Q1, z1, &pkey->E.G, ctx);
/* 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);
/* 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);
/* log_mpidump (" Q.x", Q.x); */
/* log_mpidump (" Q.y", Q.y); */
/* log_mpidump (" Q.z", Q.z); */
if (!mpi_cmp_ui (Q.z, 0))
{
if (DBG_CIPHER)
log_debug ("ecc verify: Rejected\n");
err = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
{
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 */
if (mpi_cmp (x, r)) /* x != r */
{
if (DBG_CIPHER)
{
log_mpidump (" x", x);
log_mpidump (" r", r);
log_mpidump (" s", s);
log_debug ("ecc verify: Not verified\n");
}
err = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
if (DBG_CIPHER)
log_debug ("ecc verify: Accepted\n");
leave:
_gcry_mpi_ec_free (ctx);
point_free (&Q2);
point_free (&Q1);
point_free (&Q);
mpi_free (zero);
mpi_free (rv);
mpi_free (v);
mpi_free (z2);
mpi_free (z1);
mpi_free (x);
mpi_free (e);
return err;
}
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 41debe40..e0ad77ea 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -1,369 +1,369 @@
/* ecc-misc.c - Elliptic Curve miscellaneous functions
* Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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"
/*
* Release a curve object.
*/
void
_gcry_ecc_curve_free (elliptic_curve_t *E)
{
mpi_free (E->p); E->p = NULL;
mpi_free (E->a); E->a = NULL;
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;
}
/*
* Return a copy of a curve object.
*/
elliptic_curve_t
_gcry_ecc_curve_copy (elliptic_curve_t E)
{
elliptic_curve_t R;
R.model = E.model;
R.dialect = E.dialect;
R.name = E.name;
R.p = mpi_copy (E.p);
R.a = mpi_copy (E.a);
R.b = mpi_copy (E.b);
_gcry_mpi_point_init (&R.G);
point_set (&R.G, &E.G);
R.n = mpi_copy (E.n);
R.h = mpi_copy (E.h);
return R;
}
/*
* Return a description of the curve model.
*/
const char *
_gcry_ecc_model2str (enum gcry_mpi_ec_models model)
{
const char *str = "?";
switch (model)
{
case MPI_EC_WEIERSTRASS: str = "Weierstrass"; break;
case MPI_EC_MONTGOMERY: str = "Montgomery"; break;
case MPI_EC_EDWARDS: str = "Edwards"; break;
}
return str;
}
/*
* Return a description of the curve dialect.
*/
const char *
_gcry_ecc_dialect2str (enum ecc_dialects dialect)
{
const char *str = "?";
switch (dialect)
{
case ECC_DIALECT_STANDARD: str = "Standard"; break;
case ECC_DIALECT_ED25519: str = "Ed25519"; break;
}
return str;
}
gcry_mpi_t
_gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
{
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. */
ptr = buf+1;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
if (rc)
log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc));
if (n < pbytes)
{
memmove (ptr+(pbytes-n), ptr, n);
memset (ptr, 0, (pbytes-n));
}
ptr += pbytes;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
if (rc)
log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc));
if (n < pbytes)
{
memmove (ptr+(pbytes-n), ptr, n);
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;
}
/* 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_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))
result = NULL;
else
result = _gcry_ecc_ec2os (g_x, g_y, ectx->p);
mpi_free (g_x);
mpi_free (g_y);
return result;
}
/* 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)
{
gcry_err_code_t rc;
size_t n;
const unsigned char *buf;
unsigned char *buf_memory;
gcry_mpi_t x, y;
if (mpi_is_opaque (value))
{
unsigned int nbits;
buf = mpi_get_opaque (value, &nbits);
if (!buf)
return GPG_ERR_INV_OBJ;
n = (nbits + 7)/8;
buf_memory = NULL;
}
else
{
n = (mpi_get_nbits (value)+7)/8;
buf_memory = xmalloc (n);
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, buf_memory, n, &n, value);
if (rc)
{
xfree (buf_memory);
return rc;
}
buf = buf_memory;
}
if (n < 1)
{
xfree (buf_memory);
return GPG_ERR_INV_OBJ;
}
if (*buf != 4)
{
xfree (buf_memory);
return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */
}
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);
if (rc)
{
mpi_free (x);
return rc;
}
mpi_set (result->x, x);
mpi_set (result->y, y);
mpi_set_ui (result->z, 1);
mpi_free (x);
mpi_free (y);
return 0;
}
/* Compute the public key from the the context EC. Obviously a
requirement is that the secret key is available in EC. On success
Q is returned; on error NULL. If Q is NULL a newly allocated point
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)
{
if (!G)
G = ec->G;
if (!d)
d = ec->d;
if (!d || !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))
{
gcry_mpi_t a;
unsigned char *digest;
if (_gcry_ecc_eddsa_compute_h_d (&digest, d, ec))
return NULL;
a = mpi_snew (0);
_gcry_mpi_set_buffer (a, digest, 32, 0);
xfree (digest);
/* And finally the public key. */
if (!Q)
Q = mpi_point_new (0);
if (Q)
_gcry_mpi_ec_mul_point (Q, a, G, ec);
mpi_free (a);
}
else
{
if (!Q)
Q = mpi_point_new (0);
if (Q)
_gcry_mpi_ec_mul_point (Q, d, G, ec);
}
return Q;
}
gpg_err_code_t
_gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
{
unsigned char *rawmpi;
unsigned int rawmpilen;
if (mpi_is_opaque (pk))
{
const unsigned char *buf;
unsigned char *p;
buf = mpi_get_opaque (pk, &rawmpilen);
if (!buf)
return GPG_ERR_INV_OBJ;
rawmpilen = (rawmpilen + 7)/8;
if (rawmpilen > 1 && (rawmpilen%2) && buf[0] == 0x40)
{
rawmpilen--;
buf++;
}
rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
if (!rawmpi)
return gpg_err_code_from_syserror ();
p = rawmpi + rawmpilen;
while (p > rawmpi)
*--p = *buf++;
}
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);
}
/*
* 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.
* Just setting RAWMPILEN to NBYTES is enough in this case.
* Othewise, RAWMPILEN is NBYTES already.
*/
rawmpilen = nbytes;
}
rawmpi[0] &= (1 << (ctx->nbits % 8)) - 1;
_gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0);
xfree (rawmpi);
mpi_set_ui (result->z, 1);
return 0;
}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 06010ef2..bafd7c17 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1,2256 +1,2256 @@
/* ecc.c - Elliptic Curve Cryptography
* Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013, 2015 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* This code is originally based on the Patch 0.1.6 for the gnupg
1.4.x branch as retrieved on 2007-03-21 from
- http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
+ https://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2
The original authors are:
Written by
Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>,
Ramiro Moreno Chiral <ramiro at eup.udl.es>
Maintainers
Sergi Blanch i Torne
Ramiro Moreno Chiral
Mikael Mylnikov (mmr)
For use in Libgcrypt the code has been heavily modified and cleaned
up. In fact there is not much left of the originally code except for
some variable names and the text book implementaion of the sign and
verification algorithms. The arithmetic functions have entirely
been rewritten and moved to mpi/ec.c.
ECDH encrypt and decrypt code written by Andrey Jivsov.
*/
/* TODO:
- In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a
special case in mpi_powm or check whether mpi_mulm is faster.
*/
#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 "pubkey-internal.h"
#include "ecc-common.h"
static const char *ecc_names[] =
{
"ecc",
"ecdsa",
"ecdh",
"eddsa",
"gost",
NULL,
};
/* Sample NIST P-256 key from RFC 6979 A.2.5 */
static const char sample_public_key_secp256[] =
"(public-key"
" (ecc"
" (curve secp256r1)"
" (q #04"
/**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
/**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
static const char sample_secret_key_secp256[] =
"(private-key"
" (ecc"
" (curve secp256r1)"
" (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)"
" (q #04"
/**/ "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
/**/ "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
/* Registered progress function and its callback value. */
static void (*progress_cb) (void *, const char*, int, int, int);
static void *progress_cb_data;
/* 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 unsigned int ecc_get_nbits (gcry_sexp_t parms);
void
_gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
int, int, int),
void *cb_data)
{
progress_cb = cb;
progress_cb_data = cb_data;
}
/* static void */
/* progress (int c) */
/* { */
/* if (progress_cb) */
/* progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */
/* } */
/**
* 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.
* @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.
*
* Return: An error code.
*
* The @flags bits used by this function are %PUBKEY_FLAG_TRANSIENT to
* use a faster RNG, and %PUBKEY_FLAG_NO_KEYTEST to skip the assertion
* that the key works as expected.
*
* 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,
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);
point_init (&Q);
if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
random_level = GCRY_STRONG_RANDOM;
else
random_level = GCRY_VERY_STRONG_RANDOM;
/* Generate a secret. */
if (ctx->dialect == ECC_DIALECT_ED25519 || (flags & PUBKEY_FLAG_DJB_TWEAK))
{
char *rndbuf;
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);
}
else
sk->d = _gcry_dsa_gen_k (E->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);
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))
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
- * http://tools.ietf.org/html/draft-jivsov-ecc-compact, which simply
+ * https://tools.ietf.org/html/draft-jivsov-ecc-compact, which simply
* means that we choose either Q=(x,y) or -Q=(x,p-y) such that we
* end up with the min(y,p-y) as the y coordinate. Such a public
* key allows the most efficient compression: y can simply be
* dropped because we know that it's a minimum of the two
* 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);
else
{
gcry_mpi_t negative;
negative = mpi_new (pbits);
if (E->model == MPI_EC_WEIERSTRASS)
mpi_sub (negative, E->p, y); /* negative = p - y */
else
mpi_sub (negative, E->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)
{
mpi_free (y);
y = negative;
}
else
{
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));
if (DBG_CIPHER)
log_debug ("ecgen converted Q to a compliant point\n");
}
else /* p - y >= p */
{
/* No change is needed exactly 50% of the time: just copy. */
mpi_free (negative);
point_set (&sk->Q, &Q);
if (DBG_CIPHER)
log_debug ("ecgen didn't need to convert Q to a compliant point\n");
}
}
*r_x = x;
if (r_y)
*r_y = y;
point_free (&Q);
/* 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
test_ecdh_only_keys (sk, nbits - 64, flags);
return 0;
}
/*
* To verify correct skey it use a random information.
* First, encrypt and decrypt this dummy value,
* test if the information is recuperated.
* Second, test with the sign and verify functions.
*/
static void
test_keys (ECC_secret_key *sk, 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);
gcry_mpi_t out = mpi_new (nbits);
gcry_mpi_t r = mpi_new (nbits);
gcry_mpi_t s = mpi_new (nbits);
if (DBG_CIPHER)
log_debug ("Testing key.\n");
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) )
log_fatal ("ECDSA operation: sign failed\n");
if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
{
log_fatal ("ECDSA operation: sign, verify failed\n");
}
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);
mpi_free (out);
mpi_free (c);
mpi_free (test);
}
static void
test_ecdh_only_keys (ECC_secret_key *sk, 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))
{
char *rndbuf;
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);
}
else
{
test = mpi_new (nbits);
_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);
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);
/* R_ = hdkG */
if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
_gcry_mpi_ec_mul_point (&R_, 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");
if (mpi_cmp (x0, x1))
{
log_fatal ("ECDH test failed.\n");
}
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);
}
/*
* To check the validity of the value, recalculate the correspondence
* between the public value and the secret one.
*/
static int
check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
{
int rc = 1;
mpi_point_struct Q;
gcry_mpi_t x1, y1;
gcry_mpi_t x2 = NULL;
gcry_mpi_t y2 = NULL;
point_init (&Q);
x1 = mpi_new (0);
if (ec->model == MPI_EC_MONTGOMERY)
y1 = NULL;
else
y1 = mpi_new (0);
/* G in E(F_p) */
if (!_gcry_mpi_ec_curve_point (&sk->E.G, ec))
{
if (DBG_CIPHER)
log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
goto leave;
}
/* G != PaI */
if (!mpi_cmp_ui (sk->E.G.z, 0))
{
if (DBG_CIPHER)
log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
goto leave;
}
/* Check order of curve. */
if (sk->E.dialect != ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_DJB_TWEAK))
{
_gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
if (mpi_cmp_ui (Q.z, 0))
{
if (DBG_CIPHER)
log_debug ("check_secret_key: E is not a curve of order n\n");
goto leave;
}
}
/* Pubkey cannot be PaI */
if (!mpi_cmp_ui (sk->Q.z, 0))
{
if (DBG_CIPHER)
log_debug ("Bad check: Q can not be a Point at Infinity!\n");
goto leave;
}
/* pubkey = [d]G over E */
if (!_gcry_ecc_compute_public (&Q, ec, &sk->E.G, sk->d))
{
if (DBG_CIPHER)
log_debug ("Bad check: computation of dG failed\n");
goto leave;
}
if (_gcry_mpi_ec_get_affine (x1, y1, &Q, ec))
{
if (DBG_CIPHER)
log_debug ("Bad check: Q can not be a Point at Infinity!\n");
goto leave;
}
if ((flags & PUBKEY_FLAG_EDDSA))
; /* Fixme: EdDSA is special. */
else if (!mpi_cmp_ui (sk->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 (DBG_CIPHER)
log_debug
("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
goto leave;
}
}
else
{
x2 = mpi_new (0);
y2 = mpi_new (0);
if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ec))
{
if (DBG_CIPHER)
log_debug ("Bad check: Q can not be a Point at Infinity!\n");
goto leave;
}
if (mpi_cmp (x1, x2) || mpi_cmp (y1, y2))
{
if (DBG_CIPHER)
log_debug
("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
goto leave;
}
}
rc = 0; /* Okay. */
leave:
mpi_free (x2);
mpi_free (x1);
mpi_free (y1);
mpi_free (y2);
point_free (&Q);
return rc;
}
/*********************************************
************** interface ******************
*********************************************/
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;
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);
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);
else
rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &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 (_gcry_mpi_ec_get_affine (Gx, Gy, &sk.E.G, ctx))
log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
base = _gcry_ecc_ec2os (Gx, Gy, sk.E.p);
}
if ((sk.E.dialect == ECC_DIALECT_ED25519 || E.model == MPI_EC_MONTGOMERY)
&& !(flags & PUBKEY_FLAG_NOCOMP))
{
unsigned char *encpk;
unsigned int encpklen;
if (E.model != MPI_EC_MONTGOMERY)
/* (Gx and Gy are used as scratch variables) */
rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, Gx, Gy,
!!(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);
mpi_set_opaque (public, encpk, encpklen*8);
}
else
{
if (!Qx)
{
/* This is the case for a key from _gcry_ecc_eddsa_generate
with no compression. */
Qx = mpi_new (0);
Qy = mpi_new (0);
if (_gcry_mpi_ec_get_affine (Qx, Qy, &sk.Q, ctx))
log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
}
public = _gcry_ecc_ec2os (Qx, Qy, sk.E.p);
}
secret = sk.d; sk.d = NULL;
if (E.name)
{
rc = sexp_build (&curve_info, NULL, "(curve %s)", E.name);
if (rc)
goto leave;
}
if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA)
|| (flags & PUBKEY_FLAG_DJB_TWEAK))
{
rc = sexp_build
(&curve_flags, NULL,
((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
"(flags param eddsa)" :
((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
"(flags param djb-tweak)" :
((flags & PUBKEY_FLAG_PARAM))?
"(flags param)" : ((flags & PUBKEY_FLAG_EDDSA))?
"(flags eddsa)" : "(flags djb-tweak)" );
if (rc)
goto leave;
}
if ((flags & PUBKEY_FLAG_PARAM) && E.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)))"
" (private-key"
" (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(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,
curve_info, curve_flags,
sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
secret);
else
rc = sexp_build (r_skey, NULL,
"(key-data"
" (public-key"
" (ecc%S%S(q%m)))"
" (private-key"
" (ecc%S%S(q%m)(d%m)))"
" )",
curve_info, curve_flags,
public,
curve_info, curve_flags,
public, secret);
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 G", base);
log_printmpi ("ecgen result n", sk.E.n);
log_printmpi ("ecgen result h", sk.E.h);
log_printmpi ("ecgen result Q", public);
log_printmpi ("ecgen result d", secret);
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);
sexp_release (curve_flags);
sexp_release (curve_info);
return rc;
}
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);
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 info: %s/%s\n",
_gcry_ecc_model2str (sk.E.model),
_gcry_ecc_dialect2str (sk.E.dialect));
if (sk.E.name)
log_debug ("ecc_testkey name: %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)
{
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))
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));
return rc;
}
static gcry_err_code_t
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 sig_r = NULL;
gcry_mpi_t sig_s = NULL;
memset (&sk, 0, sizeof sk);
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, 0);
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
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 (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)
{
rc = GPG_ERR_NO_OBJ;
goto leave;
}
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);
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);
if (!rc)
rc = sexp_build (r_sig, NULL,
"(sig-val(gost(r%M)(s%M)))", sig_r, sig_s);
}
else
{
rc = _gcry_ecc_ecdsa_sign (data, &sk, 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_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("ecc_sign => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
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;
memset (&pk, 0, sizeof pk);
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
ecc_get_nbits (s_keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("ecc_verify data", data);
/*
* Extract the signature value.
*/
rc = _gcry_pk_util_preparse_sigval (s_sig, ecc_names, &l1, &sigflags);
if (rc)
goto leave;
rc = sexp_extract_param (l1, NULL, (sigflags & PUBKEY_FLAG_EDDSA)? "/rs":"rs",
&sig_r, &sig_s, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("ecc_verify s_r", sig_r);
log_mpidump ("ecc_verify s_s", sig_s);
}
if ((ctx.flags & PUBKEY_FLAG_EDDSA) ^ (sigflags & PUBKEY_FLAG_EDDSA))
{
rc = GPG_ERR_CONFLICT; /* Inconsistent use of flag/algoname. */
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);
}
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);
}
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);
}
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);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("ecc_verify => %s\n", rc?gpg_strerror (rc):"Good");
return rc;
}
/* ecdh raw is classic 2-round DH protocol published in 1976.
*
* Overview of ecc_encrypt_raw and ecc_decrypt_raw.
*
* As with any PK operation, encrypt version uses a public key and
* decrypt -- private.
*
* Symbols used below:
* G - field generator point
* d - private long-term scalar
* dG - public long-term key
* k - ephemeral scalar
* kG - ephemeral public key
* dkG - shared secret
*
* ecc_encrypt_raw description:
* input:
* data[0] : private scalar (k)
* output: A new S-expression with the parameters:
* s : shared point (kdG)
* e : generated ephemeral public key (kG)
*
* ecc_decrypt_raw description:
* input:
* data[0] : a point kG (ephemeral public key)
* output:
* result[0] : shared point (kdG)
*/
static gcry_err_code_t
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;
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.
*/
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/*
* Extract the key.
*/
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);
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.
* It assumes the cofactor is a power of 2.
*/
if ((flags & PUBKEY_FLAG_DJB_TWEAK))
{
int i;
for (i = 0; i < mpi_get_nbits (pk.E.h) - 1; i++)
mpi_clear_bit (data, i);
mpi_set_highbit (data, mpi_get_nbits (pk.E.p) - 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)
{
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)
{
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;
}
/* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
{
mpi_point_struct R; /* Result that we return. */
gcry_mpi_t x, y;
unsigned char *rawmpi;
unsigned int rawmpilen;
rc = 0;
x = mpi_new (0);
if (ec->model == MPI_EC_MONTGOMERY)
y = NULL;
else
y = mpi_new (0);
point_init (&R);
/* R = kQ <=> R = kdG */
_gcry_mpi_ec_mul_point (&R, data, &pk.Q, ec);
if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
{
/*
* Here, X is 0. In the X25519 computation on Curve25519, X0
* function maps infinity to zero. So, when PUBKEY_FLAG_DJB_TWEAK
* is enabled, return the result of 0 not raising an error.
*
* This is a corner case. It never occurs with properly
* generated public keys, but it might happen with blindly
* imported public key which might not follow the key
* generation procedure.
*/
if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
{ /* 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);
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);
}
}
/* R = kG */
_gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec);
if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
{
rc = GPG_ERR_INV_DATA;
goto leave_main;
}
if (y)
mpi_e = _gcry_ecc_ec2os (x, y, pk.E.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_e = mpi_new (0);
mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8);
}
}
leave_main:
mpi_free (x);
mpi_free (y);
point_free (&R);
if (rc)
goto leave;
}
if (!rc)
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)
log_debug ("ecc_encrypt => %s\n", gpg_strerror (rc));
return rc;
}
/* input:
* data[0] : a point kG (ephemeral public key)
* output:
* resaddr[0] : shared point kdG
*
* see ecc_encrypt_raw for details.
*/
static gcry_err_code_t
ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
unsigned int nbits;
gpg_err_code_t rc;
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;
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.
*/
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);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printmpi ("ecc_decrypt d_e", data_e);
if (mpi_is_opaque (data_e))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/*
* Extract the key.
*/
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);
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)
{
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);
}
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)
{
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);
/*
* Compute the plaintext.
*/
if (ec->model == MPI_EC_MONTGOMERY)
rc = _gcry_ecc_mont_decodepoint (data_e, ec, &kG);
else
rc = _gcry_ecc_os2ec (&kG, data_e);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printpnt ("ecc_decrypt kG", &kG, NULL);
if ((flags & PUBKEY_FLAG_DJB_TWEAK))
{
/* For X25519, by its definition, validation should not be done. */
/* (Instead, we do output check.)
*
* However, to mitigate secret key leak from our implementation,
* we also do input validation here. For constant-time
* implementation, we can remove this input validation.
*/
if (_gcry_mpi_ec_bad_point (&kG, ec))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
}
else if (!_gcry_mpi_ec_curve_point (&kG, ec))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* R = dkG */
_gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
/* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */
{
gcry_mpi_t x, y;
x = mpi_new (0);
if (ec->model == MPI_EC_MONTGOMERY)
y = NULL;
else
y = mpi_new (0);
if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
{
rc = GPG_ERR_INV_DATA;
goto leave;
/*
* Note for X25519.
*
* By the definition of X25519, this is the case where X25519
* returns 0, mapping infinity to zero. However, we
* deliberately let it return an error.
*
* 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).
*
* So, it looks like an encrypted message but it can be
* decrypted by anyone, or at least something wrong
* happens. Recipient should not proceed as if it were
* properly encrypted message.
*
* This handling is needed for our major usage of GnuPG,
* where it does the One-Pass Diffie-Hellman method,
* C(1, 1, ECC CDH), with an ephemeral key.
*/
}
if (y)
r = _gcry_ecc_ec2os (x, y, sk.E.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);
}
}
if (!r)
rc = gpg_err_code_from_syserror ();
else
rc = 0;
mpi_free (x);
mpi_free (y);
}
if (DBG_CIPHER)
log_printmpi ("ecc_decrypt res", r);
if (!rc)
rc = sexp_build (r_plain, NULL, "(value %m)", r);
leave:
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);
if (DBG_CIPHER)
log_debug ("ecc_decrypt => %s\n", gpg_strerror (rc));
return rc;
}
/* Return the number of bits for the key described by PARMS. On error
* 0 is returned. The format of PARMS starts with the algorithm name;
* for example:
*
* (ecc
* (curve <name>)
* (p <mpi>)
* (a <mpi>)
* (b <mpi>)
* (g <mpi>)
* (n <mpi>)
* (q <mpi>))
*
* More parameters may be given. Either P or CURVE is needed.
*/
static unsigned int
ecc_get_nbits (gcry_sexp_t parms)
{
gcry_sexp_t l1;
gcry_mpi_t p;
unsigned int nbits = 0;
char *curve;
l1 = sexp_find_token (parms, "p", 1);
if (!l1)
{ /* Parameter P not found - check whether we have "curve". */
l1 = sexp_find_token (parms, "curve", 5);
if (!l1)
return 0; /* Neither P nor CURVE found. */
curve = sexp_nth_string (l1, 1);
sexp_release (l1);
if (!curve)
return 0; /* No curve name given (or out of core). */
if (_gcry_ecc_fill_in_curve (0, curve, NULL, &nbits))
nbits = 0;
xfree (curve);
}
else
{
p = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
if (p)
{
nbits = mpi_get_nbits (p);
_gcry_mpi_release (p);
}
}
return nbits;
}
/* See rsa.c for a description of this function. */
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";
gpg_err_code_t rc;
gcry_sexp_t l1;
gcry_mpi_t values[N_COMPONENTS];
int idx;
char *curvename = NULL;
int flags = 0;
enum gcry_mpi_ec_models model = 0;
enum ecc_dialects dialect = 0;
/* Clear the values first. */
for (idx=0; idx < N_COMPONENTS; idx++)
values[idx] = NULL;
/* 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))
{
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);
}
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);
}
if (rc)
goto leave;
/* Check whether a curve parameter is available and use that to fill
in missing values. */
sexp_release (l1);
l1 = sexp_find_token (keyparms, "curve", 5);
if (l1)
{
curvename = sexp_nth_string (l1, 1);
if (curvename)
{
rc = _gcry_ecc_update_curve_param (curvename,
&model, &dialect,
&values[0], &values[1], &values[2],
&values[3], &values[4], &values[5]);
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)
{
model = ((flags & PUBKEY_FLAG_EDDSA)
? MPI_EC_EDWARDS
: MPI_EC_WEIERSTRASS);
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
should not be required but we use an internal function later and
thus we better make 100% sure that they are normalized). */
for (idx = 0; idx < N_COMPONENTS; idx++)
if (!values[idx])
{
rc = GPG_ERR_NO_OBJ;
goto leave;
}
else
_gcry_mpi_normalize (values[idx]);
/* Uncompress the public key with the exception of EdDSA where
compression is the default and we thus compute the keygrip using
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))
{
rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
if (rc)
goto leave;
}
/* Hash them all. */
for (idx = 0; idx < N_COMPONENTS; idx++)
{
char buf[30];
if (idx == 5)
continue; /* Skip cofactor. */
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);
}
else
{
unsigned char *rawmpi;
unsigned int rawmpilen;
rawmpi = _gcry_mpi_get_buffer (values[idx], 0, &rawmpilen, NULL);
if (!rawmpi)
{
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);
}
}
leave:
xfree (curvename);
sexp_release (l1);
for (idx = 0; idx < N_COMPONENTS; idx++)
_gcry_mpi_release (values[idx]);
return rc;
#undef N_COMPONENTS
}
/*
Low-level API helper functions.
*/
/* This is the worker function for gcry_pubkey_get_sexp for ECC
algorithms. Note that the caller has already stored NULL at
R_SEXP. */
gpg_err_code_t
_gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
{
gpg_err_code_t rc;
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)
return GPG_ERR_BAD_CRYPT_CTX;
if (mode == GCRY_PK_GET_SECKEY && !ec->d)
return GPG_ERR_NO_SECKEY;
/* Compute the public point if it is missing. */
if (!ec->Q && ec->d)
ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
/* Encode G and Q. */
mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
if (!mpi_G)
{
rc = GPG_ERR_BROKEN_PUBKEY;
goto leave;
}
if (!ec->Q)
{
rc = GPG_ERR_BAD_CRYPT_CTX;
goto leave;
}
if (ec->dialect == ECC_DIALECT_ED25519)
{
unsigned char *encpk;
unsigned int encpklen;
rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
&encpk, &encpklen);
if (rc)
goto leave;
mpi_Q = mpi_set_opaque (NULL, encpk, encpklen*8);
encpk = NULL;
}
else
{
mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
}
if (!mpi_Q)
{
rc = GPG_ERR_BROKEN_PUBKEY;
goto leave;
}
/* Fixme: We should return a curve name instead of the parameters if
if know that they match a curve. */
if (ec->d && (!mode || mode == GCRY_PK_GET_SECKEY))
{
/* 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)))",
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)))",
ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q);
}
else
rc = GPG_ERR_BAD_CRYPT_CTX;
leave:
mpi_free (mpi_Q);
mpi_free (mpi_G);
return rc;
}
/*
Self-test section.
*/
static const char *
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#))";
static const char sample_data_bad[] =
"(data (flags rfc6979)"
" (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
/**/ "62113d8a62add1bf#))";
static const char signature_r[] =
"efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716";
static const char signature_s[] =
"f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8";
const char *errtxt = NULL;
gcry_error_t err;
gcry_sexp_t data = NULL;
gcry_sexp_t data_bad = NULL;
gcry_sexp_t sig = NULL;
gcry_sexp_t l1 = NULL;
gcry_sexp_t l2 = NULL;
gcry_mpi_t r = NULL;
gcry_mpi_t s = NULL;
gcry_mpi_t calculated_r = NULL;
gcry_mpi_t calculated_s = NULL;
int cmp;
err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
if (!err)
err = sexp_sscan (&data_bad, NULL,
sample_data_bad, strlen (sample_data_bad));
if (!err)
err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL);
if (!err)
err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL);
if (err)
{
errtxt = "converting data failed";
goto leave;
}
err = _gcry_pk_sign (&sig, data, skey);
if (err)
{
errtxt = "signing failed";
goto leave;
}
/* check against known signature */
errtxt = "signature validity failed";
l1 = _gcry_sexp_find_token (sig, "sig-val", 0);
if (!l1)
goto leave;
l2 = _gcry_sexp_find_token (l1, "ecdsa", 0);
if (!l2)
goto leave;
sexp_release (l1);
l1 = l2;
l2 = _gcry_sexp_find_token (l1, "r", 0);
if (!l2)
goto leave;
calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!calculated_r)
goto leave;
sexp_release (l2);
l2 = _gcry_sexp_find_token (l1, "s", 0);
if (!l2)
goto leave;
calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!calculated_s)
goto leave;
errtxt = "known sig check failed";
cmp = _gcry_mpi_cmp (r, calculated_r);
if (cmp)
goto leave;
cmp = _gcry_mpi_cmp (s, calculated_s);
if (cmp)
goto leave;
errtxt = NULL;
/* verify generated signature */
err = _gcry_pk_verify (sig, data, pkey);
if (err)
{
errtxt = "verify failed";
goto leave;
}
err = _gcry_pk_verify (sig, data_bad, pkey);
if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
{
errtxt = "bad signature not detected";
goto leave;
}
leave:
sexp_release (sig);
sexp_release (data_bad);
sexp_release (data);
sexp_release (l1);
sexp_release (l2);
mpi_release (r);
mpi_release (s);
mpi_release (calculated_r);
mpi_release (calculated_s);
return errtxt;
}
static gpg_err_code_t
selftests_ecdsa (selftest_report_func_t report)
{
const char *what;
const char *errtxt;
gcry_error_t err;
gcry_sexp_t skey = NULL;
gcry_sexp_t pkey = NULL;
what = "convert";
err = sexp_sscan (&skey, NULL, sample_secret_key_secp256,
strlen (sample_secret_key_secp256));
if (!err)
err = sexp_sscan (&pkey, NULL, sample_public_key_secp256,
strlen (sample_public_key_secp256));
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "key consistency";
err = ecc_check_secret_key(skey);
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "sign";
errtxt = selftest_sign (pkey, skey);
if (errtxt)
goto failed;
sexp_release(pkey);
sexp_release(skey);
return 0; /* Succeeded. */
failed:
sexp_release(pkey);
sexp_release(skey);
if (report)
report ("pubkey", GCRY_PK_ECC, 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)
{
(void)extended;
if (algo != GCRY_PK_ECC)
return GPG_ERR_PUBKEY_ALGO;
return selftests_ecdsa (report);
}
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",
ecc_generate,
ecc_check_secret_key,
ecc_encrypt_raw,
ecc_decrypt_raw,
ecc_sign,
ecc_verify,
ecc_get_nbits,
run_selftests,
compute_keygrip,
_gcry_ecc_get_curve,
_gcry_ecc_get_param_sexp
};
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 4eb52d62..da8f7c0e 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -1,1149 +1,1149 @@
/* Elgamal.c - Elgamal Public Key encryption
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2008 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* For a description of the algorithm, see:
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
* ISBN 0-471-11709-9. Pages 476 ff.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "pubkey-internal.h"
/* Blinding is used to mitigate side-channel attacks. You may undef
this to speed up the operation in case the system is secured
against physical and network mounted side-channel attacks. */
#define USE_BLINDING 1
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
} ELG_public_key;
typedef struct
{
gcry_mpi_t p; /* prime */
gcry_mpi_t g; /* group generator */
gcry_mpi_t y; /* g^x mod p */
gcry_mpi_t x; /* secret exponent */
} ELG_secret_key;
static const char *elg_names[] =
{
"elg",
"openpgp-elg",
"openpgp-elg-sig",
NULL,
};
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_err_code_t generate (ELG_secret_key *sk, unsigned nbits,
gcry_mpi_t **factors);
static int check_secret_key (ELG_secret_key *sk);
static void 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);
static void sign (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input,
ELG_secret_key *skey);
static int verify (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input,
ELG_public_key *pkey);
static unsigned int elg_get_nbits (gcry_sexp_t parms);
static void (*progress_cb) (void *, const char *, int, int, int);
static void *progress_cb_data;
void
_gcry_register_pk_elg_progress (void (*cb) (void *, const char *,
int, int, int),
void *cb_data)
{
progress_cb = cb;
progress_cb_data = cb_data;
}
static void
progress (int c)
{
if (progress_cb)
progress_cb (progress_cb_data, "pk_elg", c, 0, 0);
}
/****************
* Michael Wiener's table on subgroup sizes to match field sizes.
* (floating around somewhere, probably based on the paper from
* Eurocrypt 96, page 332)
*/
static unsigned int
wiener_map( unsigned int n )
{
static struct { unsigned int p_n, q_n; } t[] =
{ /* p q attack cost */
{ 512, 119 }, /* 9 x 10^17 */
{ 768, 145 }, /* 6 x 10^21 */
{ 1024, 165 }, /* 7 x 10^24 */
{ 1280, 183 }, /* 3 x 10^27 */
{ 1536, 198 }, /* 7 x 10^29 */
{ 1792, 212 }, /* 9 x 10^31 */
{ 2048, 225 }, /* 8 x 10^33 */
{ 2304, 237 }, /* 5 x 10^35 */
{ 2560, 249 }, /* 3 x 10^37 */
{ 2816, 259 }, /* 1 x 10^39 */
{ 3072, 269 }, /* 3 x 10^40 */
{ 3328, 279 }, /* 8 x 10^41 */
{ 3584, 288 }, /* 2 x 10^43 */
{ 3840, 296 }, /* 4 x 10^44 */
{ 4096, 305 }, /* 7 x 10^45 */
{ 4352, 313 }, /* 1 x 10^47 */
{ 4608, 320 }, /* 2 x 10^48 */
{ 4864, 328 }, /* 2 x 10^49 */
{ 5120, 335 }, /* 3 x 10^50 */
{ 0, 0 }
};
int i;
for(i=0; t[i].p_n; i++ )
{
if( n <= t[i].p_n )
return t[i].q_n;
}
/* Not in table - use an arbitrary high number. */
return n / 8 + 200;
}
static int
test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie )
{
ELG_public_key pk;
gcry_mpi_t test = mpi_new ( 0 );
gcry_mpi_t out1_a = mpi_new ( nbits );
gcry_mpi_t out1_b = mpi_new ( nbits );
gcry_mpi_t out2 = mpi_new ( nbits );
int failed = 0;
pk.p = sk->p;
pk.g = sk->g;
pk.y = sk->y;
_gcry_mpi_randomize ( test, nbits, GCRY_WEAK_RANDOM );
do_encrypt ( out1_a, out1_b, test, &pk );
decrypt ( out2, out1_a, out1_b, sk );
if ( mpi_cmp( test, out2 ) )
failed |= 1;
sign ( out1_a, out1_b, test, sk );
if ( !verify( out1_a, out1_b, test, &pk ) )
failed |= 2;
_gcry_mpi_release ( test );
_gcry_mpi_release ( out1_a );
_gcry_mpi_release ( out1_b );
_gcry_mpi_release ( out2 );
if (failed && !nodie)
log_fatal ("Elgamal test key for %s %s failed\n",
(failed & 1)? "encrypt+decrypt":"",
(failed & 2)? "sign+verify":"");
if (failed && DBG_CIPHER)
log_debug ("Elgamal test key for %s %s failed\n",
(failed & 1)? "encrypt+decrypt":"",
(failed & 2)? "sign+verify":"");
return failed;
}
/****************
* 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!
*/
static gcry_mpi_t
gen_k( gcry_mpi_t p, int small_k )
{
gcry_mpi_t k = mpi_alloc_secure( 0 );
gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) );
gcry_mpi_t p_1 = mpi_copy(p);
unsigned int orig_nbits = mpi_get_nbits(p);
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;
nbytes = (nbits+7)/8;
if( DBG_CIPHER )
log_debug("choosing a random k\n");
mpi_sub_ui( p_1, p, 1);
for(;;)
{
if( !rndbuf || nbits < 32 )
{
xfree(rndbuf);
rndbuf = _gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM );
}
else
{
/* Change only some of the higher bits. We could improve
this by directly requesting more memory at the first call
to get_random_bytes() and use this the here maybe it is
easier to do this directly in random.c Anyway, it is
highly inlikely that we will ever reach this code. */
char *pp = _gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM );
memcpy( rndbuf, pp, 4 );
xfree(pp);
}
_gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 );
for(;;)
{
if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */
{
if( DBG_CIPHER )
progress('+');
break; /* no */
}
if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */
{
if( DBG_CIPHER )
progress('-');
break; /* no */
}
if (mpi_gcd( temp, k, p_1 ))
goto found; /* okay, k is relative prime to (p-1) */
mpi_add_ui( k, k, 1 );
if( DBG_CIPHER )
progress('.');
}
}
found:
xfree (rndbuf);
if( DBG_CIPHER )
progress('\n');
mpi_free(p_1);
mpi_free(temp);
return k;
}
/****************
* Generate a key pair with a key of size NBITS
* Returns: 2 structures filled with all needed values
* and an array with n-1 factors of (p-1)
*/
static gcry_err_code_t
generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors )
{
gcry_err_code_t rc;
gcry_mpi_t p; /* the prime */
gcry_mpi_t p_min1;
gcry_mpi_t g;
gcry_mpi_t x; /* the secret exponent */
gcry_mpi_t y;
unsigned int qbits;
unsigned int xbits;
byte *rndbuf;
p_min1 = mpi_new ( nbits );
qbits = wiener_map( nbits );
if( qbits & 1 ) /* better have a even one */
qbits++;
g = mpi_alloc(1);
rc = _gcry_generate_elg_prime (0, nbits, qbits, g, &p, ret_factors);
if (rc)
{
mpi_free (p_min1);
mpi_free (g);
return rc;
}
mpi_sub_ui(p_min1, p, 1);
/* Select a random number which has these properties:
* 0 < x < p-1
* This must be a very good random number because this is the
* secret part. The prime is public and may be shared anyway,
* so a random generator level of 1 is used for the prime.
*
* I don't see a reason to have a x of about the same size
* as the p. It should be sufficient to have one about the size
* of q or the later used k plus a large safety margin. Decryption
* will be much faster with such an x.
*/
xbits = qbits * 3 / 2;
if( xbits >= nbits )
BUG();
x = mpi_snew ( xbits );
if( DBG_CIPHER )
log_debug("choosing a random x of size %u\n", xbits );
rndbuf = NULL;
do
{
if( DBG_CIPHER )
progress('.');
if( rndbuf )
{ /* Change only some of the higher bits */
if( xbits < 16 ) /* should never happen ... */
{
xfree(rndbuf);
rndbuf = _gcry_random_bytes_secure ((xbits+7)/8,
GCRY_VERY_STRONG_RANDOM);
}
else
{
char *r = _gcry_random_bytes_secure (2, GCRY_VERY_STRONG_RANDOM);
memcpy(rndbuf, r, 2 );
xfree (r);
}
}
else
{
rndbuf = _gcry_random_bytes_secure ((xbits+7)/8,
GCRY_VERY_STRONG_RANDOM );
}
_gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 );
mpi_clear_highbit( x, xbits+1 );
}
while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
xfree(rndbuf);
y = mpi_new (nbits);
mpi_powm( y, g, x, p );
if( DBG_CIPHER )
{
progress ('\n');
log_mpidump ("elg p", p );
log_mpidump ("elg g", g );
log_mpidump ("elg y", y );
log_mpidump ("elg x", x );
}
/* Copy the stuff to the key structures */
sk->p = p;
sk->g = g;
sk->y = y;
sk->x = x;
_gcry_mpi_release ( p_min1 );
/* Now we can test our keys (this should never fail!) */
test_keys ( sk, nbits - 64, 0 );
return 0;
}
/* Generate a key pair with a key of size NBITS not using a random
value for the secret key but the one given as X. This is useful to
implement a passphrase based decryption for a public key based
encryption. It has appliactions in backup systems.
Returns: A structure filled with all needed values and an array
with n-1 factors of (p-1). */
static gcry_err_code_t
generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x,
gcry_mpi_t **ret_factors )
{
gcry_err_code_t rc;
gcry_mpi_t p; /* The prime. */
gcry_mpi_t p_min1; /* The prime minus 1. */
gcry_mpi_t g; /* The generator. */
gcry_mpi_t y; /* g^x mod p. */
unsigned int qbits;
unsigned int xbits;
sk->p = NULL;
sk->g = NULL;
sk->y = NULL;
sk->x = NULL;
/* Do a quick check to see whether X is suitable. */
xbits = mpi_get_nbits (x);
if ( xbits < 64 || xbits >= nbits )
return GPG_ERR_INV_VALUE;
p_min1 = mpi_new ( nbits );
qbits = wiener_map ( nbits );
if ( (qbits & 1) ) /* Better have an even one. */
qbits++;
g = mpi_alloc (1);
rc = _gcry_generate_elg_prime (0, nbits, qbits, g, &p, ret_factors );
if (rc)
{
mpi_free (p_min1);
mpi_free (g);
return rc;
}
mpi_sub_ui (p_min1, p, 1);
if (DBG_CIPHER)
log_debug ("using a supplied x of size %u", xbits );
if ( !(mpi_cmp_ui ( x, 0 ) > 0 && mpi_cmp ( x, p_min1 ) <0 ) )
{
_gcry_mpi_release ( p_min1 );
_gcry_mpi_release ( p );
_gcry_mpi_release ( g );
return GPG_ERR_INV_VALUE;
}
y = mpi_new (nbits);
mpi_powm ( y, g, x, p );
if ( DBG_CIPHER )
{
progress ('\n');
log_mpidump ("elg p", p );
log_mpidump ("elg g", g );
log_mpidump ("elg y", y );
log_mpidump ("elg x", x );
}
/* Copy the stuff to the key structures */
sk->p = p;
sk->g = g;
sk->y = y;
sk->x = mpi_copy (x);
_gcry_mpi_release ( p_min1 );
/* Now we can test our keys. */
if ( test_keys ( sk, nbits - 64, 1 ) )
{
_gcry_mpi_release ( sk->p ); sk->p = NULL;
_gcry_mpi_release ( sk->g ); sk->g = NULL;
_gcry_mpi_release ( sk->y ); sk->y = NULL;
_gcry_mpi_release ( sk->x ); sk->x = NULL;
return GPG_ERR_BAD_SECKEY;
}
return 0;
}
/****************
* Test whether the secret key is valid.
* Returns: if this is a valid key.
*/
static int
check_secret_key( ELG_secret_key *sk )
{
int rc;
gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) );
mpi_powm (y, sk->g, sk->x, sk->p);
rc = !mpi_cmp( y, sk->y );
mpi_free( y );
return rc;
}
static void
do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
{
gcry_mpi_t k;
/* Note: maybe we should change the interface, so that it
* is possible to check that input is < p and return an
* error code.
*/
k = gen_k( pkey->p, 1 );
mpi_powm (a, pkey->g, k, pkey->p);
/* b = (y^k * input) mod p
* = ((y^k mod p) * (input mod p)) mod p
* and because input is < p
* = ((y^k mod p) * input) mod p
*/
mpi_powm (b, pkey->y, k, pkey->p);
mpi_mulm (b, b, input, pkey->p);
#if 0
if( DBG_CIPHER )
{
log_mpidump("elg encrypted y", pkey->y);
log_mpidump("elg encrypted p", pkey->p);
log_mpidump("elg encrypted k", k);
log_mpidump("elg encrypted M", input);
log_mpidump("elg encrypted a", a);
log_mpidump("elg encrypted b", b);
}
#endif
mpi_free(k);
}
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;
unsigned int nbits = mpi_get_nbits (skey->p);
mpi_normalize (a);
mpi_normalize (b);
t1 = mpi_snew (nbits);
#ifdef USE_BLINDING
t2 = mpi_snew (nbits);
r = mpi_new (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);
/* t1 = r^x mod p */
mpi_powm (t1, r, skey->x, skey->p);
/* t2 = (a * r)^-x mod p */
mpi_mulm (t2, a, r, skey->p);
mpi_powm (t2, t2, skey->x, skey->p);
mpi_invm (t2, t2, skey->p);
/* t1 = (t1 * t2) mod p*/
mpi_mulm (t1, t1, t2, skey->p);
mpi_free (r);
mpi_free (t2);
#else /*!USE_BLINDING*/
/* output = b/(a^x) mod p */
mpi_powm (t1, a, skey->x, skey->p);
mpi_invm (t1, t1, skey->p);
#endif /*!USE_BLINDING*/
mpi_mulm (output, b, t1, skey->p);
#if 0
if( DBG_CIPHER )
{
log_mpidump ("elg decrypted x", skey->x);
log_mpidump ("elg decrypted p", skey->p);
log_mpidump ("elg decrypted a", a);
log_mpidump ("elg decrypted b", b);
log_mpidump ("elg decrypted M", output);
}
#endif
mpi_free (t1);
}
/****************
* Make an Elgamal signature out of INPUT
*/
static void
sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey )
{
gcry_mpi_t k;
gcry_mpi_t t = mpi_alloc( mpi_get_nlimbs(a) );
gcry_mpi_t inv = mpi_alloc( mpi_get_nlimbs(a) );
gcry_mpi_t p_1 = mpi_copy(skey->p);
/*
* b = (t * inv) mod (p-1)
* b = (t * inv(k,(p-1),(p-1)) mod (p-1)
* b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1)
*
*/
mpi_sub_ui(p_1, p_1, 1);
k = gen_k( skey->p, 0 /* no small K ! */ );
mpi_powm( a, skey->g, k, skey->p );
mpi_mul(t, skey->x, a );
mpi_subm(t, input, t, p_1 );
mpi_invm(inv, k, p_1 );
mpi_mulm(b, t, inv, p_1 );
#if 0
if( DBG_CIPHER )
{
log_mpidump ("elg sign p", skey->p);
log_mpidump ("elg sign g", skey->g);
log_mpidump ("elg sign y", skey->y);
log_mpidump ("elg sign x", skey->x);
log_mpidump ("elg sign k", k);
log_mpidump ("elg sign M", input);
log_mpidump ("elg sign a", a);
log_mpidump ("elg sign b", b);
}
#endif
mpi_free(k);
mpi_free(t);
mpi_free(inv);
mpi_free(p_1);
}
/****************
* Returns true if the signature composed of A and B is valid.
*/
static int
verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
{
int rc;
gcry_mpi_t t1;
gcry_mpi_t t2;
gcry_mpi_t base[4];
gcry_mpi_t ex[4];
if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) )
return 0; /* assertion 0 < a < p failed */
t1 = mpi_alloc( mpi_get_nlimbs(a) );
t2 = mpi_alloc( mpi_get_nlimbs(a) );
#if 0
/* t1 = (y^a mod p) * (a^b mod p) mod p */
gcry_mpi_powm( t1, pkey->y, a, pkey->p );
gcry_mpi_powm( t2, a, b, pkey->p );
mpi_mulm( t1, t1, t2, pkey->p );
/* t2 = g ^ input mod p */
gcry_mpi_powm( t2, pkey->g, input, pkey->p );
rc = !mpi_cmp( t1, t2 );
#elif 0
/* t1 = (y^a mod p) * (a^b mod p) mod p */
base[0] = pkey->y; ex[0] = a;
base[1] = a; ex[1] = b;
base[2] = NULL; ex[2] = NULL;
mpi_mulpowm( t1, base, ex, pkey->p );
/* t2 = g ^ input mod p */
gcry_mpi_powm( t2, pkey->g, input, pkey->p );
rc = !mpi_cmp( t1, t2 );
#else
/* t1 = g ^ - input * y ^ a * a ^ b mod p */
mpi_invm(t2, pkey->g, pkey->p );
base[0] = t2 ; ex[0] = input;
base[1] = pkey->y; ex[1] = a;
base[2] = a; ex[2] = b;
base[3] = NULL; ex[3] = NULL;
mpi_mulpowm( t1, base, ex, pkey->p );
rc = !mpi_cmp_ui( t1, 1 );
#endif
mpi_free(t1);
mpi_free(t2);
return rc;
}
/*********************************************
************** interface ******************
*********************************************/
static gpg_err_code_t
elg_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
{
gpg_err_code_t rc;
unsigned int nbits;
ELG_secret_key sk;
gcry_mpi_t xvalue = NULL;
gcry_sexp_t l1;
gcry_mpi_t *factors = NULL;
gcry_sexp_t misc_info = NULL;
memset (&sk, 0, sizeof sk);
rc = _gcry_pk_util_get_nbits (genparms, &nbits);
if (rc)
return rc;
/* Parse the optional xvalue element. */
l1 = sexp_find_token (genparms, "xvalue", 0);
if (l1)
{
xvalue = sexp_nth_mpi (l1, 1, 0);
sexp_release (l1);
if (!xvalue)
return GPG_ERR_BAD_MPI;
}
if (xvalue)
{
rc = generate_using_x (&sk, nbits, xvalue, &factors);
mpi_free (xvalue);
}
else
{
rc = generate (&sk, nbits, &factors);
}
if (rc)
goto leave;
if (factors && factors[0])
{
int nfac;
void **arg_list;
char *buffer, *p;
for (nfac = 0; factors[nfac]; nfac++)
;
arg_list = xtrycalloc (nfac+1, sizeof *arg_list);
if (!arg_list)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
buffer = xtrymalloc (30 + nfac*2 + 2 + 1);
if (!buffer)
{
rc = gpg_err_code_from_syserror ();
xfree (arg_list);
goto leave;
}
p = stpcpy (buffer, "(misc-key-info(pm1-factors");
for(nfac = 0; factors[nfac]; nfac++)
{
p = stpcpy (p, "%m");
arg_list[nfac] = factors + nfac;
}
p = stpcpy (p, "))");
rc = sexp_build_array (&misc_info, NULL, buffer, arg_list);
xfree (arg_list);
xfree (buffer);
if (rc)
goto leave;
}
rc = sexp_build (r_skey, NULL,
"(key-data"
" (public-key"
" (elg(p%m)(g%m)(y%m)))"
" (private-key"
" (elg(p%m)(g%m)(y%m)(x%m)))"
" %S)",
sk.p, sk.g, sk.y,
sk.p, sk.g, sk.y, sk.x,
misc_info);
leave:
mpi_free (sk.p);
mpi_free (sk.g);
mpi_free (sk.y);
mpi_free (sk.x);
sexp_release (misc_info);
if (factors)
{
gcry_mpi_t *mp;
for (mp = factors; *mp; mp++)
mpi_free (*mp);
xfree (factors);
}
return rc;
}
static gcry_err_code_t
elg_check_secret_key (gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
ELG_secret_key sk = {NULL, NULL, NULL, NULL};
rc = sexp_extract_param (keyparms, NULL, "pgyx",
&sk.p, &sk.g, &sk.y, &sk.x,
NULL);
if (rc)
goto leave;
if (!check_secret_key (&sk))
rc = GPG_ERR_BAD_SECKEY;
leave:
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
if (DBG_CIPHER)
log_debug ("elg_testkey => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
elg_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_mpi_t mpi_a = NULL;
gcry_mpi_t mpi_b = NULL;
gcry_mpi_t data = NULL;
ELG_public_key pk = { NULL, NULL, NULL };
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
elg_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("elg_encrypt data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "pgy",
&pk.p, &pk.g, &pk.y, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_encrypt p", pk.p);
log_mpidump ("elg_encrypt g", pk.g);
log_mpidump ("elg_encrypt y", pk.y);
}
/* Do Elgamal computation and build result. */
mpi_a = mpi_new (0);
mpi_b = mpi_new (0);
do_encrypt (mpi_a, mpi_b, data, &pk);
rc = sexp_build (r_ciph, NULL, "(enc-val(elg(a%m)(b%m)))", mpi_a, mpi_b);
leave:
_gcry_mpi_release (mpi_a);
_gcry_mpi_release (mpi_b);
_gcry_mpi_release (pk.p);
_gcry_mpi_release (pk.g);
_gcry_mpi_release (pk.y);
_gcry_mpi_release (data);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("elg_encrypt => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
elg_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gpg_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_sexp_t l1 = NULL;
gcry_mpi_t data_a = NULL;
gcry_mpi_t data_b = NULL;
ELG_secret_key sk = {NULL, NULL, NULL, NULL};
gcry_mpi_t plain = NULL;
unsigned char *unpad = NULL;
size_t unpadlen = 0;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
elg_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_preparse_encval (s_data, elg_names, &l1, &ctx);
if (rc)
goto leave;
rc = sexp_extract_param (l1, NULL, "ab", &data_a, &data_b, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_printmpi ("elg_decrypt d_a", data_a);
log_printmpi ("elg_decrypt d_b", data_b);
}
if (mpi_is_opaque (data_a) || mpi_is_opaque (data_b))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "pgyx",
&sk.p, &sk.g, &sk.y, &sk.x,
NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_printmpi ("elg_decrypt p", sk.p);
log_printmpi ("elg_decrypt g", sk.g);
log_printmpi ("elg_decrypt y", sk.y);
if (!fips_mode ())
log_printmpi ("elg_decrypt x", sk.x);
}
plain = mpi_snew (ctx.nbits);
decrypt (plain, data_a, data_b, &sk);
if (DBG_CIPHER)
log_printmpi ("elg_decrypt res", plain);
/* Reverse the encoding and build the s-expression. */
switch (ctx.encoding)
{
case PUBKEY_ENC_PKCS1:
rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
mpi_free (plain); plain = NULL;
if (!rc)
rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
break;
case PUBKEY_ENC_OAEP:
rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
ctx.nbits, ctx.hash_algo, plain,
ctx.label, ctx.labellen);
mpi_free (plain); plain = NULL;
if (!rc)
rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
break;
default:
/* Raw format. For backward compatibility we need to assume a
signed mpi by using the sexp format string "%m". */
rc = sexp_build (r_plain, NULL,
(ctx.flags & PUBKEY_FLAG_LEGACYRESULT)
? "%m" : "(value %m)",
plain);
break;
}
leave:
xfree (unpad);
_gcry_mpi_release (plain);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
_gcry_mpi_release (data_a);
_gcry_mpi_release (data_b);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("elg_decrypt => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
elg_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;
ELG_secret_key sk = {NULL, NULL, NULL, NULL};
gcry_mpi_t sig_r = NULL;
gcry_mpi_t sig_s = NULL;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
elg_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("elg_sign data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "pgyx",
&sk.p, &sk.g, &sk.y, &sk.x, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_sign p", sk.p);
log_mpidump ("elg_sign g", sk.g);
log_mpidump ("elg_sign y", sk.y);
if (!fips_mode ())
log_mpidump ("elg_sign x", sk.x);
}
sig_r = mpi_new (0);
sig_s = mpi_new (0);
sign (sig_r, sig_s, data, &sk);
if (DBG_CIPHER)
{
log_mpidump ("elg_sign sig_r", sig_r);
log_mpidump ("elg_sign sig_s", sig_s);
}
rc = sexp_build (r_sig, NULL, "(sig-val(elg(r%M)(s%M)))", sig_r, sig_s);
leave:
_gcry_mpi_release (sig_r);
_gcry_mpi_release (sig_s);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.g);
_gcry_mpi_release (sk.y);
_gcry_mpi_release (sk.x);
_gcry_mpi_release (data);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("elg_sign => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
elg_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;
gcry_mpi_t sig_r = NULL;
gcry_mpi_t sig_s = NULL;
gcry_mpi_t data = NULL;
ELG_public_key pk = { NULL, NULL, NULL };
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
elg_get_nbits (s_keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("elg_verify data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the signature value. */
rc = _gcry_pk_util_preparse_sigval (s_sig, elg_names, &l1, NULL);
if (rc)
goto leave;
rc = sexp_extract_param (l1, NULL, "rs", &sig_r, &sig_s, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_verify s_r", sig_r);
log_mpidump ("elg_verify s_s", sig_s);
}
/* Extract the key. */
rc = sexp_extract_param (s_keyparms, NULL, "pgy",
&pk.p, &pk.g, &pk.y, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_verify p", pk.p);
log_mpidump ("elg_verify g", pk.g);
log_mpidump ("elg_verify y", pk.y);
}
/* Verify the signature. */
if (!verify (sig_r, sig_s, data, &pk))
rc = GPG_ERR_BAD_SIGNATURE;
leave:
_gcry_mpi_release (pk.p);
_gcry_mpi_release (pk.g);
_gcry_mpi_release (pk.y);
_gcry_mpi_release (data);
_gcry_mpi_release (sig_r);
_gcry_mpi_release (sig_s);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("elg_verify => %s\n", rc?gpg_strerror (rc):"Good");
return rc;
}
/* Return the number of bits for the key described by PARMS. On error
* 0 is returned. The format of PARMS starts with the algorithm name;
* for example:
*
* (dsa
* (p <mpi>)
* (g <mpi>)
* (y <mpi>))
*
* More parameters may be given but we only need P here.
*/
static unsigned int
elg_get_nbits (gcry_sexp_t parms)
{
gcry_sexp_t l1;
gcry_mpi_t p;
unsigned int nbits;
l1 = sexp_find_token (parms, "p", 1);
if (!l1)
return 0; /* Parameter P not found. */
p= sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
nbits = p? mpi_get_nbits (p) : 0;
_gcry_mpi_release (p);
return nbits;
}
gcry_pk_spec_t _gcry_pubkey_spec_elg =
{
GCRY_PK_ELG, { 0, 0 },
(GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
"ELG", elg_names,
"pgy", "pgyx", "ab", "rs", "pgy",
elg_generate,
elg_check_secret_key,
elg_encrypt,
elg_decrypt,
elg_sign,
elg_verify,
elg_get_nbits,
};
diff --git a/cipher/gost-s-box.c b/cipher/gost-s-box.c
index 7aa54447..b63b5b0a 100644
--- a/cipher/gost-s-box.c
+++ b/cipher/gost-s-box.c
@@ -1,257 +1,257 @@
/* gost-s-box.c - GOST 28147-89 S-Box expander
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
struct gost_sbox
{
const char *name;
const char *oid;
unsigned char sbox[16*8];
} gost_sboxes[] = {
{ "test_3411", "1.2.643.2.2.30.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,
0x2, 0xC, 0xD, 0x1, 0x1, 0x0, 0x1, 0x0,
0xD, 0x6, 0xA, 0x0, 0x5, 0x7, 0x3, 0x5,
0x8, 0xD, 0x3, 0x8, 0xF, 0x2, 0xF, 0x7,
0x0, 0xF, 0x4, 0x9, 0xD, 0x1, 0x5, 0xA,
0xE, 0xA, 0x2, 0xF, 0x8, 0xD, 0x9, 0x4,
0x6, 0x2, 0xE, 0xE, 0x4, 0x3, 0x0, 0x9,
0xB, 0x3, 0xF, 0x4, 0xA, 0x6, 0xA, 0x2,
0x1, 0x8, 0xC, 0x6, 0x9, 0x8, 0xE, 0x3,
0xC, 0x1, 0x7, 0xC, 0xE, 0x5, 0x7, 0xE,
0x7, 0x0, 0x6, 0xB, 0x0, 0x9, 0x6, 0x6,
0xF, 0x7, 0x0, 0x2, 0x3, 0xC, 0x8, 0xB,
0x5, 0x5, 0x9, 0x5, 0xB, 0xF, 0x2, 0x8,
0x3, 0x9, 0xB, 0x3, 0x2, 0xE, 0xC, 0xC,
}
},
{ "CryptoPro_3411", "1.2.643.2.2.30.1", {
0xA, 0x5, 0x7, 0x4, 0x7, 0x7, 0xD, 0x1,
0x4, 0xF, 0xF, 0xA, 0x6, 0x6, 0xE, 0x3,
0x5, 0x4, 0xC, 0x7, 0x4, 0x2, 0x4, 0xA,
0x6, 0x0, 0xE, 0xC, 0xB, 0x4, 0x1, 0x9,
0x8, 0x2, 0x9, 0x0, 0x9, 0xD, 0x7, 0x5,
0x1, 0xD, 0x4, 0xF, 0xC, 0x9, 0x0, 0xB,
0x3, 0xB, 0x1, 0x2, 0x2, 0xF, 0x5, 0x4,
0x7, 0x9, 0x0, 0x8, 0xA, 0x0, 0xA, 0xF,
0xD, 0x1, 0x3, 0xE, 0x1, 0xA, 0x3, 0x8,
0xC, 0x7, 0xB, 0x1, 0x8, 0x1, 0xC, 0x6,
0xE, 0x6, 0x5, 0x6, 0x0, 0x5, 0x8, 0x7,
0x0, 0x3, 0x2, 0x5, 0xE, 0xB, 0xF, 0xE,
0x9, 0xC, 0x6, 0xD, 0xF, 0x8, 0x6, 0xD,
0x2, 0xE, 0xA, 0xB, 0xD, 0xE, 0x2, 0x0,
0xB, 0xA, 0x8, 0x9, 0x3, 0xC, 0x9, 0x2,
0xF, 0x8, 0xD, 0x3, 0x5, 0x3, 0xB, 0xC,
}
},
{ "Test_89", "1.2.643.2.2.31.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,
0x5, 0xE, 0xC, 0x2, 0x9, 0xB, 0x0, 0x2,
0x9, 0x8, 0x7, 0x5, 0x6, 0x1, 0x3, 0xB,
0x1, 0x1, 0x3, 0xF, 0x8, 0x9, 0x6, 0x0,
0x0, 0x3, 0x9, 0x7, 0x0, 0xC, 0x7, 0x9,
0x8, 0xA, 0xA, 0x1, 0xD, 0x5, 0x5, 0xD,
0xE, 0x2, 0x1, 0x0, 0xA, 0xD, 0x4, 0x3,
0x3, 0x7, 0x5, 0xD, 0xB, 0x3, 0x8, 0xE,
0xB, 0x4, 0x2, 0xC, 0x7, 0x7, 0xE, 0x7,
0xC, 0xD, 0x4, 0x6, 0xC, 0xA, 0xF, 0xA,
0xD, 0x6, 0x6, 0xA, 0x2, 0x0, 0x1, 0xF,
0x7, 0x0, 0xF, 0x4, 0x1, 0xE, 0xA, 0x4,
0xA, 0xB, 0x0, 0x3, 0xF, 0x2, 0x2, 0x1,
0x6, 0x5, 0xB, 0x8, 0x4, 0x4, 0xD, 0x8,
}
},
{ "CryptoPro_A", "1.2.643.2.2.31.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,
0x2, 0x9, 0x2, 0xC, 0x9, 0xC, 0x9, 0x5,
0x8, 0x8, 0xB, 0xD, 0x8, 0x1, 0x7, 0x0,
0xB, 0xA, 0x3, 0x1, 0xD, 0x2, 0xA, 0xC,
0x1, 0xF, 0xD, 0x3, 0xF, 0x0, 0x6, 0xE,
0x7, 0x0, 0x8, 0x9, 0x0, 0xB, 0x0, 0x8,
0xA, 0x5, 0xC, 0x0, 0xE, 0x7, 0x8, 0x6,
0x4, 0x2, 0xF, 0x2, 0x4, 0x5, 0xC, 0x2,
0xE, 0x6, 0x5, 0xB, 0x2, 0x9, 0x4, 0x3,
0xF, 0xC, 0xA, 0x4, 0x3, 0x4, 0x5, 0x9,
0xC, 0xB, 0x0, 0xF, 0xC, 0x8, 0xF, 0x1,
0x0, 0x4, 0x7, 0x8, 0x7, 0xF, 0x3, 0x7,
0xD, 0xD, 0x1, 0x5, 0xA, 0xE, 0xB, 0xD,
0x5, 0x1, 0x9, 0x6, 0x6, 0x6, 0xE, 0x4,
}
},
{ "CryptoPro_B", "1.2.643.2.2.31.2", {
0x8, 0x0, 0xE, 0x7, 0x2, 0x8, 0x5, 0x0,
0x4, 0x1, 0xC, 0x5, 0x7, 0x3, 0x2, 0x4,
0xB, 0x2, 0x0, 0x0, 0xC, 0x2, 0xA, 0xB,
0x1, 0xA, 0xA, 0xD, 0xF, 0x6, 0xB, 0xE,
0x3, 0x4, 0x9, 0xB, 0x9, 0x4, 0x9, 0x8,
0x5, 0xD, 0x2, 0x6, 0x5, 0xD, 0x1, 0x3,
0x0, 0x5, 0xD, 0x1, 0xA, 0xE, 0xC, 0x7,
0x9, 0xC, 0xB, 0x2, 0xB, 0xB, 0x3, 0x1,
0x2, 0x9, 0x7, 0x3, 0x1, 0xC, 0x7, 0xA,
0xE, 0x7, 0x5, 0xA, 0x4, 0x1, 0x4, 0x2,
0xA, 0x3, 0x8, 0xC, 0x0, 0x7, 0xD, 0x9,
0xC, 0xF, 0xF, 0xF, 0xD, 0xF, 0x0, 0x6,
0xD, 0xB, 0x3, 0x4, 0x6, 0xA, 0x6, 0xF,
0x6, 0x8, 0x6, 0xE, 0x8, 0x0, 0xF, 0xD,
0x7, 0x6, 0x1, 0x9, 0xE, 0x9, 0x8, 0x5,
0xF, 0xE, 0x4, 0x8, 0x3, 0x5, 0xE, 0xC,
}
},
{ "CryptoPro_C", "1.2.643.2.2.31.3", {
0x1, 0x0, 0x8, 0x3, 0x8, 0xC, 0xA, 0x7,
0xB, 0x1, 0x2, 0x6, 0xD, 0x9, 0x9, 0x4,
0xC, 0x7, 0x5, 0x0, 0xB, 0xB, 0x6, 0x0,
0x2, 0xD, 0x0, 0x1, 0x0, 0x1, 0x8, 0x5,
0x9, 0xB, 0x4, 0x5, 0x4, 0x8, 0xD, 0xA,
0xD, 0x4, 0x9, 0xD, 0x5, 0xE, 0xE, 0x2,
0x0, 0x5, 0xF, 0xA, 0x1, 0x2, 0x2, 0xF,
0xF, 0x2, 0xA, 0x8, 0x2, 0x4, 0x0, 0xE,
0x4, 0x8, 0x3, 0xB, 0x9, 0x7, 0xF, 0xC,
0x5, 0xE, 0x7, 0x2, 0x3, 0x3, 0x3, 0x6,
0x8, 0xF, 0xC, 0x9, 0xC, 0x6, 0x5, 0x1,
0xE, 0xC, 0xD, 0x7, 0xE, 0x5, 0xB, 0xB,
0xA, 0x9, 0x6, 0xE, 0x6, 0xA, 0x4, 0xD,
0x7, 0xA, 0xE, 0xF, 0xF, 0x0, 0x1, 0x9,
0x6, 0x6, 0x1, 0xC, 0xA, 0xF, 0xC, 0x3,
0x3, 0x3, 0xB, 0x4, 0x7, 0xD, 0x7, 0x8,
}
},
{ "CryptoPro_D", "1.2.643.2.2.31.4", {
0xF, 0xB, 0x1, 0x1, 0x0, 0x8, 0x3, 0x1,
0xC, 0x6, 0xC, 0x5, 0xC, 0x0, 0x0, 0xA,
0x2, 0x3, 0xB, 0xE, 0x8, 0xF, 0x6, 0x6,
0xA, 0x4, 0x0, 0xC, 0x9, 0x3, 0xF, 0x8,
0x6, 0xC, 0xF, 0xA, 0xD, 0x2, 0x1, 0xF,
0x4, 0xF, 0xE, 0x7, 0x2, 0x5, 0xE, 0xB,
0x5, 0xE, 0x6, 0x0, 0xA, 0xE, 0x9, 0x0,
0x0, 0x2, 0x5, 0xD, 0xB, 0xB, 0x2, 0x4,
0x7, 0x7, 0xA, 0x6, 0x7, 0x1, 0xD, 0xC,
0x9, 0xD, 0xD, 0x2, 0x3, 0xA, 0x8, 0x3,
0xE, 0x8, 0x4, 0xB, 0x6, 0x4, 0xC, 0x5,
0xD, 0x0, 0x8, 0x4, 0x5, 0x7, 0x4, 0x9,
0x1, 0x5, 0x9, 0x9, 0x4, 0xC, 0xB, 0x7,
0xB, 0xA, 0x3, 0x3, 0xE, 0x9, 0xA, 0xD,
0x8, 0x9, 0x7, 0xF, 0xF, 0xD, 0x5, 0x2,
0x3, 0x1, 0x2, 0x8, 0x1, 0x6, 0x7, 0xE,
}
},
{ "TC26_Z", "1.2.643.7.1.2.5.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,
0x2, 0x3, 0x8, 0x1, 0xa, 0x6, 0x5, 0xd,
0xa, 0x9, 0x2, 0xd, 0x8, 0x9, 0x6, 0x0,
0x5, 0xa, 0xf, 0x4, 0x1, 0x2, 0x9, 0x5,
0xb, 0x5, 0xa, 0xf, 0x6, 0xc, 0x1, 0x8,
0x9, 0xc, 0xd, 0x6, 0xd, 0xa, 0xc, 0x3,
0xe, 0x1, 0xe, 0x7, 0x0, 0xb, 0xf, 0x4,
0x8, 0xe, 0x1, 0x0, 0x9, 0x7, 0x4, 0xf,
0xd, 0x4, 0x7, 0xa, 0x3, 0x8, 0xb, 0xa,
0x7, 0x7, 0x4, 0x5, 0xe, 0x1, 0x0, 0x6,
0x0, 0xb, 0xc, 0x3, 0xb, 0x4, 0xd, 0x9,
0x3, 0xd, 0x9, 0xe, 0x4, 0x3, 0xa, 0xc,
0xf, 0x0, 0x6, 0x9, 0x2, 0xe, 0x3, 0xb,
0x1, 0xf, 0x0, 0xb, 0xc, 0x0, 0x7, 0x2,
}
},
};
int main(int argc, char **argv)
{
unsigned int i, j, s;
FILE *f;
if (argc == 1)
f = stdin;
else
f = fopen(argv[1], "w");
if (!f)
{
perror("fopen");
exit(1);
}
for (s = 0; s < DIM(gost_sboxes); s++)
{
unsigned char *sbox = gost_sboxes[s].sbox;
fprintf (f, "static const u32 sbox_%s[4*256] =\n {", gost_sboxes[s].name);
for (i = 0; i < 4; i++) {
fprintf (f, "\n /* %d */\n ", i);
for (j = 0; j < 256; j++) {
unsigned int val;
if (j % 4 == 0 && j != 0)
fprintf (f, "\n ");
val = sbox[ (j & 0xf) * 8 + 2 * i + 0] |
(sbox[ (j >> 4) * 8 + 2 * i + 1] << 4);
val <<= (8*i);
val = (val << 11) | (val >> 21);
fprintf (f, " 0x%08x,", val);
}
}
fprintf (f, "\n };\n\n");
}
fprintf (f, "static struct\n{\n const char *oid;\n const u32 *sbox;\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, " { NULL, NULL }\n};\n");
fclose (f);
return 0;
}
diff --git a/cipher/gost.h b/cipher/gost.h
index 025119c9..545d14f7 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
@@ -1,32 +1,32 @@
/* gost.h - GOST 28147-89 implementation
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _GCRY_GOST_H
#define _GCRY_GOST_H
typedef struct {
u32 key[8];
const u32 *sbox;
} 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,
u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro);
#endif
diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index 1b8ab7ae..c8eff275 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
@@ -1,230 +1,230 @@
/* gost28147.c - GOST 28147-89 implementation for Libgcrypt
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* GOST 28147-89 defines several modes of encryption:
* - ECB which should be used only for key transfer
* - CFB mode
* - OFB-like mode with additional transformation on keystream
* RFC 5830 names this 'counter encryption' mode
* Original GOST text uses the term 'gammirovanie'
* - MAC mode
*
* This implementation handles ECB and CFB modes via usual libgcrypt handling.
* OFB-like and MAC modes are unsupported.
*/
#include <config.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#include "gost.h"
#include "gost-sb.h"
static gcry_err_code_t
gost_setkey (void *c, const byte *key, unsigned keylen,
gcry_cipher_hd_t hd)
{
int i;
GOST28147_context *ctx = c;
(void)hd;
if (keylen != 256 / 8)
return GPG_ERR_INV_KEYLEN;
if (!ctx->sbox)
ctx->sbox = sbox_test_3411;
for (i = 0; i < 8; i++)
{
ctx->key[i] = buf_get_le32(&key[4*i]);
}
return GPG_ERR_NO_ERROR;
}
static u32
gost_val (GOST28147_context *ctx, u32 cm1, int subkey)
{
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)];
return cm1;
}
static unsigned int
_gost_encrypt_data (void *c, 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);
*o1 = n2;
*o2 = n1;
return /* burn_stack */ 4*sizeof(void*) /* func call */ +
3*sizeof(void*) /* stack */ +
4*sizeof(void*) /* gost_val call */;
}
static unsigned int
gost_encrypt_block (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);
burn = _gost_encrypt_data(ctx, &n1, &n2, n1, n2);
buf_put_le32 (outbuf+0, n1);
buf_put_le32 (outbuf+4, n2);
return /* burn_stack */ burn + 6*sizeof(void*) /* func call */;
}
unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro)
{
if (cryptopro)
c->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 *);
}
static unsigned int
gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
{
GOST28147_context *ctx = c;
u32 n1, n2;
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, 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, 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, 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);
buf_put_le32 (outbuf+0, n2);
buf_put_le32 (outbuf+4, n1);
return /* burn_stack */ 4*sizeof(void*) /* func call */ +
3*sizeof(void*) /* stack */ +
4*sizeof(void*) /* gost_val call */;
}
static gpg_err_code_t
gost_set_sbox (GOST28147_context *ctx, const char *oid)
{
int i;
for (i = 0; gost_oid_map[i].oid; i++)
{
if (!strcmp(gost_oid_map[i].oid, oid))
{
ctx->sbox = gost_oid_map[i].sbox;
return 0;
}
}
return GPG_ERR_VALUE_NOT_FOUND;
}
static gpg_err_code_t
gost_set_extra_info (void *c, int what, const void *buffer, size_t buflen)
{
GOST28147_context *ctx = c;
gpg_err_code_t ec = 0;
(void)buffer;
(void)buflen;
switch (what)
{
case GCRYCTL_SET_SBOX:
ec = gost_set_sbox (ctx, buffer);
break;
default:
ec = GPG_ERR_INV_OP;
break;
}
return ec;
}
static gcry_cipher_oid_spec_t oids_gost28147[] =
{
/* { "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 },
{ "1.2.643.2.2.31.3", GCRY_CIPHER_MODE_CFB },
{ "1.2.643.2.2.31.4", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
gcry_cipher_spec_t _gcry_cipher_spec_gost28147 =
{
GCRY_CIPHER_GOST28147, {0, 0},
"GOST28147", NULL, oids_gost28147, 8, 256,
sizeof (GOST28147_context),
gost_setkey,
gost_encrypt_block,
gost_decrypt_block,
NULL, NULL, NULL, gost_set_extra_info,
};
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index d9746275..3601567e 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
@@ -1,357 +1,357 @@
/* gostr3411-94.c - GOST R 34.11-94 hash function
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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"
#include "gost.h"
#define max(a, b) (((a) > (b)) ? (a) : (b))
typedef struct {
gcry_md_block_ctx_t bctx;
GOST28147_context hd;
union {
u32 h[8];
byte result[32];
};
u32 sigma[8];
u32 len;
int cryptopro;
} GOSTR3411_CONTEXT;
static unsigned int
transform (void *c, const unsigned char *data, size_t nblks);
static void
gost3411_init (void *context, unsigned int flags)
{
GOSTR3411_CONTEXT *hd = context;
(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.bwrite = transform;
hd->cryptopro = 0;
}
static void
gost3411_cp_init (void *context, unsigned int flags)
{
GOSTR3411_CONTEXT *hd = context;
gost3411_init (context, flags);
hd->cryptopro = 1;
}
static void
do_p (u32 *p, u32 *u, u32 *v)
{
int k;
u32 t[8];
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;
}
}
static void
do_a (u32 *u)
{
u32 t[2];
int i;
memcpy(t, u, 2*4);
for (i = 0; i < 6; i++)
u[i] = u[i+2];
u[6] = u[0] ^ t[0];
u[7] = u[1] ^ t[1];
}
/* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
static void
do_a2 (u32 *u)
{
u32 t[4];
int i;
memcpy (t, u, 16);
memcpy (u, u + 4, 16);
for (i = 0; i < 2; i++)
{
u[4+i] = t[i] ^ t[i + 2];
u[6+i] = u[i] ^ t[i + 2];
}
}
static void
do_apply_c2 (u32 *u)
{
u[ 0] ^= 0xff00ff00;
u[ 1] ^= 0xff00ff00;
u[ 2] ^= 0x00ff00ff;
u[ 3] ^= 0x00ff00ff;
u[ 4] ^= 0x00ffff00;
u[ 5] ^= 0xff0000ff;
u[ 6] ^= 0x000000ff;
u[ 7] ^= 0xff00ffff;
}
#define do_chi_step12(e) \
e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff;
#define do_chi_step13(e) \
e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16;
#define do_chi_doublestep(e, i) \
e[i] ^= (e[i] >> 16) ^ (e[(i+1)%8] << 16) ^ e[(i+1)%8] ^ (e[(i+1)%8] >> 16) ^ (e[(i+2)%8] << 16) ^ e[(i+6)%8] ^ (e[(i+7)%8] >> 16); \
e[i] ^= (e[i] << 16);
static void
do_chi_submix12 (u32 *e, u32 *x)
{
e[6] ^= x[0];
e[7] ^= x[1];
e[0] ^= x[2];
e[1] ^= x[3];
e[2] ^= x[4];
e[3] ^= x[5];
e[4] ^= x[6];
e[5] ^= x[7];
}
static void
do_chi_submix13 (u32 *e, u32 *x)
{
e[6] ^= (x[0] << 16) | (x[7] >> 16);
e[7] ^= (x[1] << 16) | (x[0] >> 16);
e[0] ^= (x[2] << 16) | (x[1] >> 16);
e[1] ^= (x[3] << 16) | (x[2] >> 16);
e[2] ^= (x[4] << 16) | (x[3] >> 16);
e[3] ^= (x[5] << 16) | (x[4] >> 16);
e[4] ^= (x[6] << 16) | (x[5] >> 16);
e[5] ^= (x[7] << 16) | (x[6] >> 16);
}
static void
do_add (u32 *s, u32 *a)
{
u32 carry = 0;
int i;
for (i = 0; i < 8; i++)
{
u32 op = carry + a[i];
s[i] += op;
carry = (a[i] > op) || (op > s[i]);
}
}
static unsigned int
do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
{
u32 u[8], v[8];
u32 s[8];
u32 k[8];
unsigned int burn;
int i;
memcpy (u, h, 32);
memcpy (v, m, 32);
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);
do_a (u);
if (i == 1)
do_apply_c2 (u);
do_a2 (v);
}
for (i = 0; i < 5; i++)
{
do_chi_doublestep (s, 0);
do_chi_doublestep (s, 1);
do_chi_doublestep (s, 2);
do_chi_doublestep (s, 3);
do_chi_doublestep (s, 4);
/* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
if (i == 4)
break;
do_chi_doublestep (s, 5);
if (i == 0)
do_chi_submix12(s, m);
do_chi_step12 (s);
if (i == 0)
do_chi_submix13(s, h);
do_chi_step13 (s);
do_chi_doublestep (s, 7);
}
memcpy (h, s+5, 12);
memcpy (h+3, s, 20);
return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
4 * 32 + 2 * sizeof(int) /* stack */ +
max(burn /* _gcry_gost_enc_one */,
sizeof(void*) * 2 /* do_a2 call */ +
16 + sizeof(int) /* do_a2 stack */ );
}
static unsigned int
transform_blk (void *ctx, const unsigned char *data)
{
GOSTR3411_CONTEXT *hd = ctx;
u32 m[8];
unsigned int burn;
int i;
for (i = 0; i < 8; i++)
m[i] = buf_get_le32(data + i*4);
burn = do_hash_step (hd, hd->h, m);
do_add (hd->sigma, m);
return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * 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 += 32;
}
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
gost3411_final (void *context)
{
GOSTR3411_CONTEXT *hd = context;
size_t padlen = 0;
u32 l[8];
int i;
MD_NBLOCKS_TYPE nblocks;
if (hd->bctx.count > 0)
{
padlen = 32 - hd->bctx.count;
memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
hd->bctx.count += padlen;
_gcry_md_block_write (hd, NULL, 0); /* flush */;
}
if (hd->bctx.count != 0)
return; /* Something went wrong */
memset (l, 0, 32);
nblocks = hd->bctx.nblocks;
if (padlen)
{
nblocks --;
l[0] = 256 - padlen * 8;
}
l[0] |= nblocks << 8;
nblocks >>= 24;
for (i = 1; i < 8 && nblocks != 0; i++)
{
l[i] = nblocks;
nblocks >>= 24;
}
do_hash_step (hd, hd->h, l);
do_hash_step (hd, hd->h, hd->sigma);
for (i = 0; i < 8; i++)
hd->h[i] = le_bswap32(hd->h[i]);
}
static byte *
gost3411_read (void *context)
{
GOSTR3411_CONTEXT *hd = context;
return hd->result;
}
static 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[] =
{
/* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
{ "1.2.643.2.2.3" },
/* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */
{ "1.2.643.2.2.9" },
{NULL},
};
gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
{
GCRY_MD_GOSTR3411_94, {0, 0},
"GOSTR3411_94", NULL, 0, NULL, 32,
gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
NULL, NULL,
sizeof (GOSTR3411_CONTEXT)
};
gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
{
GCRY_MD_GOSTR3411_CP, {0, 0},
"GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
NULL, NULL,
sizeof (GOSTR3411_CONTEXT)
};
diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index 74675d49..4f3c7789 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -1,185 +1,185 @@
/* hash-common.c - Common code for hash algorithms
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "g10lib.h"
#include "bufhelp.h"
#include "hash-common.h"
/* Run a selftest for hash algorithm ALGO. If the resulting digest
matches EXPECT/EXPECTLEN and everything else is fine as well,
return NULL. If an error occurs, return a static text string
describing the error.
DATAMODE controls what will be hashed according to this table:
0 - Hash the supplied DATA of DATALEN.
1 - Hash one million times a 'a'. DATA and DATALEN are ignored.
*/
const char *
_gcry_hash_selftest_check_one (int algo,
int datamode, const void *data, size_t datalen,
const void *expect, size_t expectlen)
{
const char *result = NULL;
gcry_error_t err = 0;
gcry_md_hd_t hd;
unsigned char *digest;
char aaa[1000];
int xof = 0;
if (_gcry_md_get_algo_dlen (algo) == 0)
xof = 1;
else if (_gcry_md_get_algo_dlen (algo) != expectlen)
return "digest size does not match expected size";
err = _gcry_md_open (&hd, algo, 0);
if (err)
return "gcry_md_open failed";
switch (datamode)
{
case 0:
_gcry_md_write (hd, data, datalen);
break;
case 1: /* Hash one million times an "a". */
{
int i;
/* Write in odd size chunks so that we test the buffering. */
memset (aaa, 'a', 1000);
for (i = 0; i < 1000; i++)
_gcry_md_write (hd, aaa, 1000);
}
break;
default:
result = "invalid DATAMODE";
}
if (!result)
{
if (!xof)
{
digest = _gcry_md_read (hd, algo);
if ( memcmp (digest, expect, expectlen) )
result = "digest mismatch";
}
else
{
gcry_assert(expectlen <= sizeof(aaa));
err = _gcry_md_extract (hd, algo, aaa, expectlen);
if (err)
result = "error extracting output from XOF";
else if ( memcmp (aaa, expect, expectlen) )
result = "digest mismatch";
}
}
_gcry_md_close (hd);
return result;
}
/* Common function to write a chunk of data to the transform function
of a hash algorithm. Note that the use of the term "block" does
not imply a fixed size block. Note that we explicitly allow to use
this function after the context has been finalized; the result does
not have any meaning but writing after finalize is sometimes
helpful to mitigate timing attacks. */
void
_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;
unsigned int nburn;
const unsigned int blocksize = hd->blocksize;
size_t inblocks;
size_t copylen;
if (sizeof(hd->buf) < blocksize)
BUG();
if (!hd->bwrite)
return;
while (hd->count)
{
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;
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;
}
if (inlen)
{
buf_cpy (hd->buf, inbuf, inlen);
hd->count = inlen;
}
if (stack_burn > 0)
_gcry_burn_stack (stack_burn);
}
diff --git a/cipher/hash-common.h b/cipher/hash-common.h
index 0b3ade11..1ea4401a 100644
--- a/cipher/hash-common.h
+++ b/cipher/hash-common.h
@@ -1,62 +1,62 @@
/* hash-common.h - Declarations of common code for hash algorithms.
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_HASH_COMMON_H
#define GCRY_HASH_COMMON_H
#include "types.h"
const char * _gcry_hash_selftest_check_one
/**/ (int algo,
int datamode, const void *data, size_t datalen,
const void *expect, size_t expectlen);
/* Type for the md_write helper function. */
typedef unsigned int (*_gcry_md_block_write_t) (void *c,
const unsigned char *blks,
size_t nblks);
#if (defined(USE_SHA512) || defined(USE_WHIRLPOOL))
/* SHA-512 and Whirlpool needs u64. SHA-512 needs larger buffer. */
# define MD_BLOCK_MAX_BLOCKSIZE 128
# define MD_NBLOCKS_TYPE u64
#else
# define MD_BLOCK_MAX_BLOCKSIZE 64
# 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_CTX_BUFFER_SIZE];
MD_NBLOCKS_TYPE nblocks;
MD_NBLOCKS_TYPE nblocks_high;
int count;
size_t blocksize;
_gcry_md_block_write_t bwrite;
} gcry_md_block_ctx_t;
void
_gcry_md_block_write( void *context, const void *inbuf_arg, size_t inlen);
#endif /*GCRY_HASH_COMMON_H*/
diff --git a/cipher/hmac-tests.c b/cipher/hmac-tests.c
index 78d260a1..12f84ce9 100644
--- a/cipher/hmac-tests.c
+++ b/cipher/hmac-tests.c
@@ -1,1160 +1,1160 @@
/* 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/>.
+ * License along with this program; if not, see <https://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);
}
diff --git a/cipher/kdf-internal.h b/cipher/kdf-internal.h
index 7079860e..8a36ad61 100644
--- a/cipher/kdf-internal.h
+++ b/cipher/kdf-internal.h
@@ -1,40 +1,40 @@
/* kdf-internal.h - Internal defs for kdf.c
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_KDF_INTERNAL_H
#define GCRY_KDF_INTERNAL_H
/*-- kdf.c --*/
gpg_err_code_t
_gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
int hashalgo,
const void *salt, size_t saltlen,
unsigned long iterations,
size_t keysize, void *keybuffer);
/*-- scrypt.c --*/
gcry_err_code_t
_gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
int algo, int subalgo,
const unsigned char *salt, size_t saltlen,
unsigned long iterations,
size_t dklen, unsigned char *dk);
#endif /*GCRY_KDF_INTERNAL_H*/
diff --git a/cipher/kdf.c b/cipher/kdf.c
index 27f57896..d856478b 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -1,307 +1,307 @@
/* kdf.c - Key Derivation Functions
* Copyright (C) 1998, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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 "kdf-internal.h"
/* Transform a passphrase into a suitable key of length KEYSIZE and
store this key in the caller provided buffer KEYBUFFER. The caller
must provide an HASHALGO, a valid ALGO and depending on that algo a
SALT of 8 bytes and the number of ITERATIONS. Code taken from
gnupg/agent/protect.c:hash_passphrase. */
static gpg_err_code_t
openpgp_s2k (const void *passphrase, size_t passphraselen,
int algo, int hashalgo,
const void *salt, size_t saltlen,
unsigned long iterations,
size_t keysize, void *keybuffer)
{
gpg_err_code_t ec;
gcry_md_hd_t md;
char *key = keybuffer;
int pass, i;
int used = 0;
int secmode;
if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
&& (!salt || saltlen != 8))
return GPG_ERR_INV_VALUE;
secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
ec = _gcry_md_open (&md, hashalgo, secmode? GCRY_MD_FLAG_SECURE : 0);
if (ec)
return ec;
for (pass=0; used < keysize; pass++)
{
if (pass)
{
_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)
{
int len2 = passphraselen + 8;
unsigned long count = len2;
if (algo == GCRY_KDF_ITERSALTED_S2K)
{
count = iterations;
if (count < len2)
count = len2;
}
while (count > len2)
{
_gcry_md_write (md, salt, saltlen);
_gcry_md_write (md, passphrase, passphraselen);
count -= len2;
}
if (count < saltlen)
_gcry_md_write (md, salt, count);
else
{
_gcry_md_write (md, salt, saltlen);
count -= saltlen;
_gcry_md_write (md, passphrase, count);
}
}
else
_gcry_md_write (md, passphrase, passphraselen);
_gcry_md_final (md);
i = _gcry_md_get_algo_dlen (hashalgo);
if (i > keysize - used)
i = keysize - used;
memcpy (key+used, _gcry_md_read (md, hashalgo), i);
used += i;
}
_gcry_md_close (md);
return 0;
}
/* Transform a passphrase into a suitable key of length KEYSIZE and
store this key in the caller provided buffer KEYBUFFER. The caller
must provide PRFALGO which indicates the pseudorandom function to
use: This shall be the algorithms id of a hash algorithm; it is
used in HMAC mode. SALT is a salt of length SALTLEN and ITERATIONS
gives the number of iterations. */
gpg_err_code_t
_gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
int hashalgo,
const void *salt, size_t saltlen,
unsigned long iterations,
size_t keysize, void *keybuffer)
{
gpg_err_code_t ec;
gcry_md_hd_t md;
int secmode;
unsigned long dklen = keysize;
char *dk = keybuffer;
unsigned int hlen; /* Output length of the digest function. */
unsigned int l; /* Rounded up number of blocks. */
unsigned int r; /* Number of octets in the last block. */
char *sbuf; /* Malloced buffer to concatenate salt and iter
as well as space to hold TBUF and UBUF. */
char *tbuf; /* Buffer for T; ptr into SBUF, size is HLEN. */
char *ubuf; /* Buffer for U; ptr into SBUF, size is HLEN. */
unsigned int lidx; /* Current block number. */
unsigned long iter; /* Current iteration number. */
unsigned int i;
/* We allow for a saltlen of 0 here to support scrypt. It is not
clear whether rfc2898 allows for this this, thus we do a test on
saltlen > 0 only in gcry_kdf_derive. */
if (!salt || !iterations || !dklen)
return GPG_ERR_INV_VALUE;
hlen = _gcry_md_get_algo_dlen (hashalgo);
if (!hlen)
return GPG_ERR_DIGEST_ALGO;
secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
/* Step 1 */
/* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
* stop. We use a stronger inequality but only if our type can hold
* a larger value. */
#if SIZEOF_UNSIGNED_LONG > 4
if (dklen > 0xffffffffU)
return GPG_ERR_INV_VALUE;
#endif
/* Step 2 */
l = ((dklen - 1)/ hlen) + 1;
r = dklen - (l - 1) * hlen;
/* Setup buffers and prepare a hash context. */
sbuf = (secmode
? xtrymalloc_secure (saltlen + 4 + hlen + hlen)
: xtrymalloc (saltlen + 4 + hlen + hlen));
if (!sbuf)
return gpg_err_code_from_syserror ();
tbuf = sbuf + saltlen + 4;
ubuf = tbuf + hlen;
ec = _gcry_md_open (&md, hashalgo, (GCRY_MD_FLAG_HMAC
| (secmode?GCRY_MD_FLAG_SECURE:0)));
if (ec)
{
xfree (sbuf);
return ec;
}
ec = _gcry_md_setkey (md, passphrase, passphraselen);
if (ec)
{
_gcry_md_close (md);
xfree (sbuf);
return ec;
}
/* Step 3 and 4. */
memcpy (sbuf, salt, saltlen);
for (lidx = 1; lidx <= l; lidx++)
{
for (iter = 0; iter < iterations; iter++)
{
_gcry_md_reset (md);
if (!iter) /* Compute U_1: */
{
sbuf[saltlen] = (lidx >> 24);
sbuf[saltlen + 1] = (lidx >> 16);
sbuf[saltlen + 2] = (lidx >> 8);
sbuf[saltlen + 3] = lidx;
_gcry_md_write (md, sbuf, saltlen + 4);
memcpy (ubuf, _gcry_md_read (md, 0), hlen);
memcpy (tbuf, ubuf, hlen);
}
else /* Compute U_(2..c): */
{
_gcry_md_write (md, ubuf, hlen);
memcpy (ubuf, _gcry_md_read (md, 0), hlen);
for (i=0; i < hlen; i++)
tbuf[i] ^= ubuf[i];
}
}
if (lidx == l) /* Last block. */
memcpy (dk, tbuf, r);
else
{
memcpy (dk, tbuf, hlen);
dk += hlen;
}
}
_gcry_md_close (md);
xfree (sbuf);
return 0;
}
/* 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,PASSPHRASELEN) which is an arbitrary memory
buffer. ALGO specifies the KDF algorithm to use; these are the
constants GCRY_KDF_*. SUBALGO specifies an algorithm used
internally by the KDF algorithms; this is usually a hash algorithm
but certain KDF algorithm may use it differently. {SALT,SALTLEN}
is a salt as needed by most KDF algorithms. ITERATIONS is a
positive integer parameter to most KDFs. 0 is returned on success,
or an error code on failure. */
gpg_err_code_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)
{
gpg_err_code_t ec;
if (!passphrase)
{
ec = GPG_ERR_INV_DATA;
goto leave;
}
if (!keybuffer || !keysize)
{
ec = GPG_ERR_INV_VALUE;
goto leave;
}
switch (algo)
{
case GCRY_KDF_SIMPLE_S2K:
case GCRY_KDF_SALTED_S2K:
case GCRY_KDF_ITERSALTED_S2K:
if (!passphraselen)
ec = GPG_ERR_INV_DATA;
else
ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo,
salt, saltlen, iterations, keysize, keybuffer);
break;
case GCRY_KDF_PBKDF1:
ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
break;
case GCRY_KDF_PBKDF2:
if (!saltlen)
ec = GPG_ERR_INV_VALUE;
else
ec = _gcry_kdf_pkdf2 (passphrase, passphraselen, subalgo,
salt, saltlen, iterations, keysize, keybuffer);
break;
case 41:
case GCRY_KDF_SCRYPT:
#if USE_SCRYPT
ec = _gcry_kdf_scrypt (passphrase, passphraselen, algo, subalgo,
salt, saltlen, iterations, keysize, keybuffer);
#else
ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
#endif /*USE_SCRYPT*/
break;
default:
ec = GPG_ERR_UNKNOWN_ALGORITHM;
break;
}
leave:
return ec;
}
diff --git a/cipher/keccak-armv7-neon.S b/cipher/keccak-armv7-neon.S
index 0bec8d50..9081a4f6 100644
--- a/cipher/keccak-armv7-neon.S
+++ b/cipher/keccak-armv7-neon.S
@@ -1,945 +1,945 @@
/* keccak-armv7-neon.S - ARMv7/NEON implementation of Keccak
*
* Copyright (C) 2015 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/>.
+ * License along with this program; if not, see <https://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)
/* Based on public-domain/CC0 implementation from SUPERCOP package
* (keccakc1024/inplace-armv7a-neon/keccak2.s)
*
* Original copyright header follows:
*/
@ The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
@ Michaël Peeters and Gilles Van Assche. For more information, feedback or
@ questions, please refer to our website: http://keccak.noekeon.org/
@
@ Implementation by Ronny Van Keer, hereby denoted as "the implementer".
@
@ To the extent possible under law, the implementer has waived all copyright
@ and related or neighboring rights to the source code in this file.
-@ http://creativecommons.org/publicdomain/zero/1.0/
+@ https://creativecommons.org/publicdomain/zero/1.0/
.text
.syntax unified
.fpu neon
.arm
.extern _gcry_keccak_round_consts_64bit;
#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
@// --- offsets in state
.equ Aba, 0*8
.equ Aga, 1*8
.equ Aka, 2*8
.equ Ama, 3*8
.equ Asa, 4*8
@// --- macros
.macro KeccakThetaRhoPiChiIota argA1, argA2, argA3, argA4, argA5
@Prepare Theta
@Ca = Aba^Aga^Aka^Ama^Asa@
@Ce = Abe^Age^Ake^Ame^Ase@
@Ci = Abi^Agi^Aki^Ami^Asi@
@Co = Abo^Ago^Ako^Amo^Aso@
@Cu = Abu^Agu^Aku^Amu^Asu@
@De = Ca^ROL64(Ci, 1)@
@Di = Ce^ROL64(Co, 1)@
@Do = Ci^ROL64(Cu, 1)@
@Du = Co^ROL64(Ca, 1)@
@Da = Cu^ROL64(Ce, 1)@
veor.64 q4, q6, q7
veor.64 q5, q9, q10
veor.64 d8, d8, d9
veor.64 d10, d10, d11
veor.64 d1, d8, d16
veor.64 d2, d10, d17
veor.64 q4, q11, q12
veor.64 q5, q14, q15
veor.64 d8, d8, d9
veor.64 d10, d10, d11
veor.64 d3, d8, d26
vadd.u64 q4, q1, q1
veor.64 d4, d10, d27
vmov.64 d0, d5
vsri.64 q4, q1, #63
vadd.u64 q5, q2, q2
veor.64 q4, q4, q0
vsri.64 q5, q2, #63
vadd.u64 d7, d1, d1
veor.64 \argA2, \argA2, d8
veor.64 q5, q5, q1
vsri.64 d7, d1, #63
vshl.u64 d1, \argA2, #44
veor.64 \argA3, \argA3, d9
veor.64 d7, d7, d4
@Ba = argA1^Da@
@Be = ROL64((argA2^De), 44)@
@Bi = ROL64((argA3^Di), 43)@
@Bo = ROL64((argA4^Do), 21)@
@Bu = ROL64((argA5^Du), 14)@
@argA2 = Be ^((~Bi)& Bo )@
@argA3 = Bi ^((~Bo)& Bu )@
@argA4 = Bo ^((~Bu)& Ba )@
@argA5 = Bu ^((~Ba)& Be )@
@argA1 = Ba ^((~Be)& Bi )@ argA1 ^= KeccakF1600RoundConstants[i+round]@
vsri.64 d1, \argA2, #64-44
vshl.u64 d2, \argA3, #43
vldr.64 d0, [sp, #\argA1]
veor.64 \argA4, \argA4, d10
vsri.64 d2, \argA3, #64-43
vshl.u64 d3, \argA4, #21
veor.64 \argA5, \argA5, d11
veor.64 d0, d0, d7
vsri.64 d3, \argA4, #64-21
vbic.64 d5, d2, d1
vshl.u64 d4, \argA5, #14
vbic.64 \argA2, d3, d2
vld1.64 d6, [ip]!
veor.64 d5, d0
vsri.64 d4, \argA5, #64-14
veor.64 d5, d6
vbic.64 \argA5, d1, d0
vbic.64 \argA3, d4, d3
vbic.64 \argA4, d0, d4
veor.64 \argA2, d1
vstr.64 d5, [sp, #\argA1]
veor.64 \argA3, d2
veor.64 \argA4, d3
veor.64 \argA5, d4
.endm
.macro KeccakThetaRhoPiChi1 argA1, argA2, argA3, argA4, argA5
@d2 = ROL64((argA1^Da), 3)@
@d3 = ROL64((argA2^De), 45)@
@d4 = ROL64((argA3^Di), 61)@
@d0 = ROL64((argA4^Do), 28)@
@d1 = ROL64((argA5^Du), 20)@
@argA1 = Ba ^((~Be)& Bi )@ Ca ^= argA1@
@argA2 = Be ^((~Bi)& Bo )@
@argA3 = Bi ^((~Bo)& Bu )@
@argA4 = Bo ^((~Bu)& Ba )@
@argA5 = Bu ^((~Ba)& Be )@
veor.64 \argA2, \argA2, d8
veor.64 \argA3, \argA3, d9
vshl.u64 d3, \argA2, #45
vldr.64 d6, [sp, #\argA1]
vshl.u64 d4, \argA3, #61
veor.64 \argA4, \argA4, d10
vsri.64 d3, \argA2, #64-45
veor.64 \argA5, \argA5, d11
vsri.64 d4, \argA3, #64-61
vshl.u64 d0, \argA4, #28
veor.64 d6, d6, d7
vshl.u64 d1, \argA5, #20
vbic.64 \argA3, d4, d3
vsri.64 d0, \argA4, #64-28
vbic.64 \argA4, d0, d4
vshl.u64 d2, d6, #3
vsri.64 d1, \argA5, #64-20
veor.64 \argA4, d3
vsri.64 d2, d6, #64-3
vbic.64 \argA5, d1, d0
vbic.64 d6, d2, d1
vbic.64 \argA2, d3, d2
veor.64 d6, d0
veor.64 \argA2, d1
vstr.64 d6, [sp, #\argA1]
veor.64 \argA3, d2
veor.64 d5, d6
veor.64 \argA5, d4
.endm
.macro KeccakThetaRhoPiChi2 argA1, argA2, argA3, argA4, argA5
@d4 = ROL64((argA1^Da), 18)@
@d0 = ROL64((argA2^De), 1)@
@d1 = ROL64((argA3^Di), 6)@
@d2 = ROL64((argA4^Do), 25)@
@d3 = ROL64((argA5^Du), 8)@
@argA1 = Ba ^((~Be)& Bi )@ Ca ^= argA1@
@argA2 = Be ^((~Bi)& Bo )@
@argA3 = Bi ^((~Bo)& Bu )@
@argA4 = Bo ^((~Bu)& Ba )@
@argA5 = Bu ^((~Ba)& Be )@
veor.64 \argA3, \argA3, d9
veor.64 \argA4, \argA4, d10
vshl.u64 d1, \argA3, #6
vldr.64 d6, [sp, #\argA1]
vshl.u64 d2, \argA4, #25
veor.64 \argA5, \argA5, d11
vsri.64 d1, \argA3, #64-6
veor.64 \argA2, \argA2, d8
vsri.64 d2, \argA4, #64-25
vext.8 d3, \argA5, \argA5, #7
veor.64 d6, d6, d7
vbic.64 \argA3, d2, d1
vadd.u64 d0, \argA2, \argA2
vbic.64 \argA4, d3, d2
vsri.64 d0, \argA2, #64-1
vshl.u64 d4, d6, #18
veor.64 \argA2, d1, \argA4
veor.64 \argA3, d0
vsri.64 d4, d6, #64-18
vstr.64 \argA3, [sp, #\argA1]
veor.64 d5, \argA3
vbic.64 \argA5, d1, d0
vbic.64 \argA3, d4, d3
vbic.64 \argA4, d0, d4
veor.64 \argA3, d2
veor.64 \argA4, d3
veor.64 \argA5, d4
.endm
.macro KeccakThetaRhoPiChi3 argA1, argA2, argA3, argA4, argA5
@d1 = ROL64((argA1^Da), 36)@
@d2 = ROL64((argA2^De), 10)@
@d3 = ROL64((argA3^Di), 15)@
@d4 = ROL64((argA4^Do), 56)@
@d0 = ROL64((argA5^Du), 27)@
@argA1 = Ba ^((~Be)& Bi )@ Ca ^= argA1@
@argA2 = Be ^((~Bi)& Bo )@
@argA3 = Bi ^((~Bo)& Bu )@
@argA4 = Bo ^((~Bu)& Ba )@
@argA5 = Bu ^((~Ba)& Be )@
veor.64 \argA2, \argA2, d8
veor.64 \argA3, \argA3, d9
vshl.u64 d2, \argA2, #10
vldr.64 d6, [sp, #\argA1]
vshl.u64 d3, \argA3, #15
veor.64 \argA4, \argA4, d10
vsri.64 d2, \argA2, #64-10
vsri.64 d3, \argA3, #64-15
veor.64 \argA5, \argA5, d11
vext.8 d4, \argA4, \argA4, #1
vbic.64 \argA2, d3, d2
vshl.u64 d0, \argA5, #27
veor.64 d6, d6, d7
vbic.64 \argA3, d4, d3
vsri.64 d0, \argA5, #64-27
vshl.u64 d1, d6, #36
veor.64 \argA3, d2
vbic.64 \argA4, d0, d4
vsri.64 d1, d6, #64-36
veor.64 \argA4, d3
vbic.64 d6, d2, d1
vbic.64 \argA5, d1, d0
veor.64 d6, d0
veor.64 \argA2, d1
vstr.64 d6, [sp, #\argA1]
veor.64 d5, d6
veor.64 \argA5, d4
.endm
.macro KeccakThetaRhoPiChi4 argA1, argA2, argA3, argA4, argA5
@d3 = ROL64((argA1^Da), 41)@
@d4 = ROL64((argA2^De), 2)@
@d0 = ROL64((argA3^Di), 62)@
@d1 = ROL64((argA4^Do), 55)@
@d2 = ROL64((argA5^Du), 39)@
@argA1 = Ba ^((~Be)& Bi )@ Ca ^= argA1@
@argA2 = Be ^((~Bi)& Bo )@
@argA3 = Bi ^((~Bo)& Bu )@
@argA4 = Bo ^((~Bu)& Ba )@
@argA5 = Bu ^((~Ba)& Be )@
veor.64 \argA2, \argA2, d8
veor.64 \argA3, \argA3, d9
vshl.u64 d4, \argA2, #2
veor.64 \argA5, \argA5, d11
vshl.u64 d0, \argA3, #62
vldr.64 d6, [sp, #\argA1]
vsri.64 d4, \argA2, #64-2
veor.64 \argA4, \argA4, d10
vsri.64 d0, \argA3, #64-62
vshl.u64 d1, \argA4, #55
veor.64 d6, d6, d7
vshl.u64 d2, \argA5, #39
vsri.64 d1, \argA4, #64-55
vbic.64 \argA4, d0, d4
vsri.64 d2, \argA5, #64-39
vbic.64 \argA2, d1, d0
vshl.u64 d3, d6, #41
veor.64 \argA5, d4, \argA2
vbic.64 \argA2, d2, d1
vsri.64 d3, d6, #64-41
veor.64 d6, d0, \argA2
vbic.64 \argA2, d3, d2
vbic.64 \argA3, d4, d3
veor.64 \argA2, d1
vstr.64 d6, [sp, #\argA1]
veor.64 d5, d6
veor.64 \argA3, d2
veor.64 \argA4, d3
.endm
@// --- code
@not callable from C!
.p2align 3
.type KeccakF_armv7a_neon_asm,%function;
KeccakF_armv7a_neon_asm: @
.LroundLoop:
KeccakThetaRhoPiChiIota Aba, d13, d19, d25, d31
KeccakThetaRhoPiChi1 Aka, d15, d21, d22, d28
KeccakThetaRhoPiChi2 Asa, d12, d18, d24, d30
KeccakThetaRhoPiChi3 Aga, d14, d20, d26, d27
KeccakThetaRhoPiChi4 Ama, d16, d17, d23, d29
KeccakThetaRhoPiChiIota Aba, d15, d18, d26, d29
KeccakThetaRhoPiChi1 Asa, d14, d17, d25, d28
KeccakThetaRhoPiChi2 Ama, d13, d21, d24, d27
KeccakThetaRhoPiChi3 Aka, d12, d20, d23, d31
KeccakThetaRhoPiChi4 Aga, d16, d19, d22, d30
KeccakThetaRhoPiChiIota Aba, d14, d21, d23, d30
KeccakThetaRhoPiChi1 Ama, d12, d19, d26, d28
KeccakThetaRhoPiChi2 Aga, d15, d17, d24, d31
KeccakThetaRhoPiChi3 Asa, d13, d20, d22, d29
KeccakThetaRhoPiChi4 Aka, d16, d18, d25, d27
KeccakThetaRhoPiChiIota Aba, d12, d17, d22, d27
KeccakThetaRhoPiChi1 Aga, d13, d18, d23, d28
KeccakThetaRhoPiChi2 Aka, d14, d19, d24, d29
ldr r0, [ip]
KeccakThetaRhoPiChi3 Ama, d15, d20, d25, d30
cmp r0, #0xFFFFFFFF
KeccakThetaRhoPiChi4 Asa, d16, d21, d26, d31
bne .LroundLoop
sub ip, #(8*24)
bx lr
.p2align 2
.ltorg
.size KeccakF_armv7a_neon_asm,.-KeccakF_armv7a_neon_asm;
@//unsigned _gcry_keccak_permute_armv7_neon(u64 *state) callable from C
.p2align 3
.global _gcry_keccak_permute_armv7_neon
.type _gcry_keccak_permute_armv7_neon,%function;
_gcry_keccak_permute_armv7_neon:
push {ip, lr}
vpush {q4-q7}
sub sp,sp, #5*8
vldr.64 d0, [r0, #0*8]
vldr.64 d12, [r0, #1*8]
vldr.64 d17, [r0, #2*8]
vldr.64 d22, [r0, #3*8]
vldr.64 d27, [r0, #4*8]
GET_DATA_POINTER(ip, _gcry_keccak_round_consts_64bit, lr);
vldr.64 d1, [r0, #5*8]
vldr.64 d13, [r0, #6*8]
vldr.64 d18, [r0, #7*8]
vldr.64 d23, [r0, #8*8]
vldr.64 d28, [r0, #9*8]
vldr.64 d2, [r0, #10*8]
vldr.64 d14, [r0, #11*8]
vldr.64 d19, [r0, #12*8]
vldr.64 d24, [r0, #13*8]
vldr.64 d29, [r0, #14*8]
vldr.64 d3, [r0, #15*8]
vldr.64 d15, [r0, #16*8]
vldr.64 d20, [r0, #17*8]
vldr.64 d25, [r0, #18*8]
vldr.64 d30, [r0, #19*8]
vldr.64 d4, [r0, #20*8]
vldr.64 d16, [r0, #21*8]
vldr.64 d21, [r0, #22*8]
vldr.64 d26, [r0, #23*8]
vldr.64 d31, [r0, #24*8]
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
mov r1, r0
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
vpop.64 { d0- d4 }
vstr.64 d0, [r1, #0*8]
vstr.64 d12, [r1, #1*8]
vstr.64 d17, [r1, #2*8]
vstr.64 d22, [r1, #3*8]
vstr.64 d27, [r1, #4*8]
vstr.64 d1, [r1, #5*8]
vstr.64 d13, [r1, #6*8]
vstr.64 d18, [r1, #7*8]
vstr.64 d23, [r1, #8*8]
vstr.64 d28, [r1, #9*8]
vstr.64 d2, [r1, #10*8]
vstr.64 d14, [r1, #11*8]
vstr.64 d19, [r1, #12*8]
vstr.64 d24, [r1, #13*8]
vstr.64 d29, [r1, #14*8]
vstr.64 d3, [r1, #15*8]
vstr.64 d15, [r1, #16*8]
vstr.64 d20, [r1, #17*8]
vstr.64 d25, [r1, #18*8]
vstr.64 d30, [r1, #19*8]
vstr.64 d4, [r1, #20*8]
vstr.64 d16, [r1, #21*8]
vstr.64 d21, [r1, #22*8]
vstr.64 d26, [r1, #23*8]
vstr.64 d31, [r1, #24*8]
mov r0, #112
vpop {q4-q7}
pop {ip, pc}
.p2align 2
.ltorg
.size _gcry_keccak_permute_armv7_neon,.-_gcry_keccak_permute_armv7_neon;
@//unsigned _gcry_keccak_permute_armv7_neon(u64 *state, @r4
@ int pos, @r1
@ const byte *lanes, @r2
@ unsigned int nlanes, @r3
@ int blocklanes) @ r5 callable from C
.p2align 3
.global _gcry_keccak_absorb_lanes64_armv7_neon
.type _gcry_keccak_absorb_lanes64_armv7_neon,%function;
_gcry_keccak_absorb_lanes64_armv7_neon:
cmp r3, #0 @ nlanes == 0
itt eq
moveq r0, #0
bxeq lr
push {r4-r5, ip, lr}
beq .Lout
mov r4, r0
ldr r5, [sp, #(4*4)]
vpush {q4-q7}
@ load state
vldr.64 d0, [r4, #0*8]
vldr.64 d12, [r4, #1*8]
vldr.64 d17, [r4, #2*8]
vldr.64 d22, [r4, #3*8]
vldr.64 d27, [r4, #4*8]
GET_DATA_POINTER(ip, _gcry_keccak_round_consts_64bit, lr);
vldr.64 d1, [r4, #5*8]
vldr.64 d13, [r4, #6*8]
vldr.64 d18, [r4, #7*8]
vldr.64 d23, [r4, #8*8]
vldr.64 d28, [r4, #9*8]
vldr.64 d2, [r4, #10*8]
vldr.64 d14, [r4, #11*8]
vldr.64 d19, [r4, #12*8]
vldr.64 d24, [r4, #13*8]
vldr.64 d29, [r4, #14*8]
vldr.64 d3, [r4, #15*8]
vldr.64 d15, [r4, #16*8]
vldr.64 d20, [r4, #17*8]
vldr.64 d25, [r4, #18*8]
vldr.64 d30, [r4, #19*8]
vldr.64 d4, [r4, #20*8]
vldr.64 d16, [r4, #21*8]
vldr.64 d21, [r4, #22*8]
vldr.64 d26, [r4, #23*8]
vldr.64 d31, [r4, #24*8]
.Lmain_loop:
@ detect absorb mode (full blocks vs lanes)
cmp r1, #0 @ pos != 0
bne .Llanes_loop
.Lmain_loop_pos0:
@ full blocks mode
@ switch (blocksize)
cmp r5, #21
beq .Lfull_block_21
cmp r5, #18
beq .Lfull_block_18
cmp r5, #17
beq .Lfull_block_17
cmp r5, #13
beq .Lfull_block_13
cmp r5, #9
beq .Lfull_block_9
@ unknown blocksize
b .Llanes_loop
.Lfull_block_21:
@ SHAKE128
cmp r3, #21 @ nlanes < blocklanes
blo .Llanes_loop
sub sp,sp, #5*8
vld1.64 {d5-d8}, [r2]!
veor d0, d5
vld1.64 {d9-d11}, [r2]!
veor d12, d6
veor d17, d7
veor d22, d8
vld1.64 {d5-d8}, [r2]!
veor d27, d9
veor d1, d10
veor d13, d11
vld1.64 {d9-d11}, [r2]!
veor d18, d5
veor d23, d6
veor d28, d7
veor d2, d8
vld1.64 {d5-d8}, [r2]!
veor d14, d9
veor d19, d10
veor d24, d11
vld1.64 {d9-d11}, [r2]!
veor d29, d5
veor d3, d6
veor d15, d7
veor d20, d8
veor d25, d9
veor d30, d10
veor d4, d11
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
subs r3, #21 @ nlanes -= 21
vpop.64 { d0-d4 }
beq .Ldone
b .Lfull_block_21
.Lfull_block_18:
@ SHA3-224
cmp r3, #18 @ nlanes < blocklanes
blo .Llanes_loop
sub sp,sp, #5*8
vld1.64 {d5-d8}, [r2]!
veor d0, d5
vld1.64 {d9-d11}, [r2]!
veor d12, d6
veor d17, d7
veor d22, d8
vld1.64 {d5-d8}, [r2]!
veor d27, d9
veor d1, d10
veor d13, d11
vld1.64 {d9-d11}, [r2]!
veor d18, d5
veor d23, d6
veor d28, d7
veor d2, d8
vld1.64 {d5-d8}, [r2]!
veor d14, d9
veor d19, d10
veor d24, d11
veor d29, d5
veor d3, d6
veor d15, d7
veor d20, d8
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
subs r3, #18 @ nlanes -= 18
vpop.64 { d0-d4 }
beq .Ldone
b .Lfull_block_18
.Lfull_block_17:
@ SHA3-256 & SHAKE256
cmp r3, #17 @ nlanes < blocklanes
blo .Llanes_loop
sub sp,sp, #5*8
vld1.64 {d5-d8}, [r2]!
veor d0, d5
vld1.64 {d9-d11}, [r2]!
veor d12, d6
veor d17, d7
veor d22, d8
vld1.64 {d5-d8}, [r2]!
veor d27, d9
veor d1, d10
veor d13, d11
vld1.64 {d9-d11}, [r2]!
veor d18, d5
veor d23, d6
veor d28, d7
veor d2, d8
vld1.64 {d5-d7}, [r2]!
veor d14, d9
veor d19, d10
veor d24, d11
veor d29, d5
veor d3, d6
veor d15, d7
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
subs r3, #17 @ nlanes -= 17
vpop.64 { d0-d4 }
beq .Ldone
b .Lfull_block_17
.Lfull_block_13:
@ SHA3-384
cmp r3, #13 @ nlanes < blocklanes
blo .Llanes_loop
sub sp,sp, #5*8
vld1.64 {d5-d8}, [r2]!
veor d0, d5
vld1.64 {d9-d11}, [r2]!
veor d12, d6
veor d17, d7
veor d22, d8
vld1.64 {d5-d8}, [r2]!
veor d27, d9
veor d1, d10
veor d13, d11
vld1.64 {d9-d10}, [r2]!
veor d18, d5
veor d23, d6
veor d28, d7
veor d2, d8
veor d14, d9
veor d19, d10
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
subs r3, #13 @ nlanes -= 13
vpop.64 { d0-d4 }
beq .Ldone
b .Lfull_block_13
.Lfull_block_9:
@ SHA3-512
cmp r3, #9 @ nlanes < blocklanes
blo .Llanes_loop
sub sp,sp, #5*8
vld1.64 {d5-d8}, [r2]!
veor d0, d5
vld1.64 {d9-d11}, [r2]!
veor d12, d6
veor d17, d7
veor d22, d8
vld1.64 {d5-d6}, [r2]!
veor d27, d9
veor d1, d10
veor d13, d11
veor d18, d5
veor d23, d6
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
subs r3, #9 @ nlanes -= 9
vpop.64 { d0-d4 }
beq .Ldone
b .Lfull_block_9
.Llanes_loop:
@ per-lane mode
@ switch (pos)
ldrb r0, [pc, r1]
add pc, pc, r0, lsl #2
.Lswitch_table:
.byte (.Llane0-.Lswitch_table-4)/4
.byte (.Llane1-.Lswitch_table-4)/4
.byte (.Llane2-.Lswitch_table-4)/4
.byte (.Llane3-.Lswitch_table-4)/4
.byte (.Llane4-.Lswitch_table-4)/4
.byte (.Llane5-.Lswitch_table-4)/4
.byte (.Llane6-.Lswitch_table-4)/4
.byte (.Llane7-.Lswitch_table-4)/4
.byte (.Llane8-.Lswitch_table-4)/4
.byte (.Llane9-.Lswitch_table-4)/4
.byte (.Llane10-.Lswitch_table-4)/4
.byte (.Llane11-.Lswitch_table-4)/4
.byte (.Llane12-.Lswitch_table-4)/4
.byte (.Llane13-.Lswitch_table-4)/4
.byte (.Llane14-.Lswitch_table-4)/4
.byte (.Llane15-.Lswitch_table-4)/4
.byte (.Llane16-.Lswitch_table-4)/4
.byte (.Llane17-.Lswitch_table-4)/4
.byte (.Llane18-.Lswitch_table-4)/4
.byte (.Llane19-.Lswitch_table-4)/4
.byte (.Llane20-.Lswitch_table-4)/4
.byte (.Llane21-.Lswitch_table-4)/4
.byte (.Llane22-.Lswitch_table-4)/4
.byte (.Llane23-.Lswitch_table-4)/4
.byte (.Llane24-.Lswitch_table-4)/4
.p2align 2
#define ABSORB_LANE(label, vreg) \
label: \
add r1, #1; \
vld1.64 d5, [r2]!; \
cmp r1, r5; /* pos == blocklanes */ \
veor vreg, vreg, d5; \
beq .Llanes_permute; \
subs r3, #1; \
beq .Ldone;
ABSORB_LANE(.Llane0, d0)
ABSORB_LANE(.Llane1, d12)
ABSORB_LANE(.Llane2, d17)
ABSORB_LANE(.Llane3, d22)
ABSORB_LANE(.Llane4, d27)
ABSORB_LANE(.Llane5, d1)
ABSORB_LANE(.Llane6, d13)
ABSORB_LANE(.Llane7, d18)
ABSORB_LANE(.Llane8, d23)
ABSORB_LANE(.Llane9, d28)
ABSORB_LANE(.Llane10, d2)
ABSORB_LANE(.Llane11, d14)
ABSORB_LANE(.Llane12, d19)
ABSORB_LANE(.Llane13, d24)
ABSORB_LANE(.Llane14, d29)
ABSORB_LANE(.Llane15, d3)
ABSORB_LANE(.Llane16, d15)
ABSORB_LANE(.Llane17, d20)
ABSORB_LANE(.Llane18, d25)
ABSORB_LANE(.Llane19, d30)
ABSORB_LANE(.Llane20, d4)
ABSORB_LANE(.Llane21, d16)
ABSORB_LANE(.Llane22, d21)
ABSORB_LANE(.Llane23, d26)
ABSORB_LANE(.Llane24, d31)
b .Llanes_loop
.Llanes_permute:
sub sp,sp, #5*8
vstr.64 d0, [sp, #Aba]
vstr.64 d1, [sp, #Aga]
veor.64 q0, q0, q1
vstr.64 d2, [sp, #Aka]
veor.64 d5, d0, d1
vstr.64 d3, [sp, #Ama]
vstr.64 d4, [sp, #Asa]
veor.64 d5, d5, d4
bl KeccakF_armv7a_neon_asm
mov r1, #0 @ pos <= 0
subs r3, #1
vpop.64 { d0-d4 }
beq .Ldone
b .Lmain_loop_pos0
.Ldone:
@ save state
vstr.64 d0, [r4, #0*8]
vstr.64 d12, [r4, #1*8]
vstr.64 d17, [r4, #2*8]
vstr.64 d22, [r4, #3*8]
vstr.64 d27, [r4, #4*8]
vstr.64 d1, [r4, #5*8]
vstr.64 d13, [r4, #6*8]
vstr.64 d18, [r4, #7*8]
vstr.64 d23, [r4, #8*8]
vstr.64 d28, [r4, #9*8]
vstr.64 d2, [r4, #10*8]
vstr.64 d14, [r4, #11*8]
vstr.64 d19, [r4, #12*8]
vstr.64 d24, [r4, #13*8]
vstr.64 d29, [r4, #14*8]
vstr.64 d3, [r4, #15*8]
vstr.64 d15, [r4, #16*8]
vstr.64 d20, [r4, #17*8]
vstr.64 d25, [r4, #18*8]
vstr.64 d30, [r4, #19*8]
vstr.64 d4, [r4, #20*8]
vstr.64 d16, [r4, #21*8]
vstr.64 d21, [r4, #22*8]
vstr.64 d26, [r4, #23*8]
vstr.64 d31, [r4, #24*8]
mov r0, #120
vpop {q4-q7}
.Lout:
pop {r4-r5, ip, pc}
.p2align 2
.ltorg
.size _gcry_keccak_absorb_lanes64_armv7_neon,.-_gcry_keccak_absorb_lanes64_armv7_neon;
#endif
diff --git a/cipher/keccak.c b/cipher/keccak.c
index 24963f12..258419ae 100644
--- a/cipher/keccak.c
+++ b/cipher/keccak.c
@@ -1,1354 +1,1354 @@
/* keccak.c - SHA3 hash functions
* Copyright (C) 2015 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <string.h>
#include "g10lib.h"
#include "bithelp.h"
#include "bufhelp.h"
#include "cipher.h"
#include "hash-common.h"
/* USE_64BIT indicates whether to use 64-bit generic implementation.
* USE_32BIT indicates whether to use 32-bit generic implementation. */
#undef USE_64BIT
#if defined(__x86_64__) || SIZEOF_UNSIGNED_LONG == 8
# define USE_64BIT 1
#else
# define USE_32BIT 1
#endif
/* 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)
# 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__)
# 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)
# define USE_32BIT_BMI2 1
#endif
/* USE_64BIT_ARM_NEON indicates whether to enable 64-bit ARM/NEON assembly
* code. */
#undef USE_64BIT_ARM_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_64BIT_ARM_NEON 1
# endif
#endif /*ENABLE_NEON_SUPPORT*/
#if defined(USE_64BIT) || defined(USE_64BIT_ARM_NEON)
# define NEED_COMMON64 1
#endif
#ifdef USE_32BIT
# define NEED_COMMON32BI 1
#endif
#define SHA3_DELIMITED_SUFFIX 0x06
#define SHAKE_DELIMITED_SUFFIX 0x1F
typedef struct
{
union {
#ifdef NEED_COMMON64
u64 state64[25];
#endif
#ifdef NEED_COMMON32BI
u32 state32bi[50];
#endif
} u;
} KECCAK_STATE;
typedef struct
{
unsigned int (*permute)(KECCAK_STATE *hd);
unsigned int (*absorb)(KECCAK_STATE *hd, int pos, const byte *lanes,
unsigned int nlanes, int blocklanes);
unsigned int (*extract) (KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
unsigned int outlen);
} keccak_ops_t;
typedef struct KECCAK_CONTEXT_S
{
KECCAK_STATE state;
unsigned int outlen;
unsigned int blocksize;
unsigned int count;
unsigned int suffix;
const keccak_ops_t *ops;
} KECCAK_CONTEXT;
#ifdef NEED_COMMON64
const u64 _gcry_keccak_round_consts_64bit[24 + 1] =
{
U64_C(0x0000000000000001), U64_C(0x0000000000008082),
U64_C(0x800000000000808A), U64_C(0x8000000080008000),
U64_C(0x000000000000808B), U64_C(0x0000000080000001),
U64_C(0x8000000080008081), U64_C(0x8000000000008009),
U64_C(0x000000000000008A), U64_C(0x0000000000000088),
U64_C(0x0000000080008009), U64_C(0x000000008000000A),
U64_C(0x000000008000808B), U64_C(0x800000000000008B),
U64_C(0x8000000000008089), U64_C(0x8000000000008003),
U64_C(0x8000000000008002), U64_C(0x8000000000000080),
U64_C(0x000000000000800A), U64_C(0x800000008000000A),
U64_C(0x8000000080008081), U64_C(0x8000000000008080),
U64_C(0x0000000080000001), U64_C(0x8000000080008008),
U64_C(0xFFFFFFFFFFFFFFFF)
};
static unsigned int
keccak_extract64(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
unsigned int outlen)
{
unsigned int i;
/* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
{
u64 tmp = hd->u.state64[i];
buf_put_le64(outbuf, tmp);
outbuf += 8;
}
return 0;
}
#endif /* NEED_COMMON64 */
#ifdef NEED_COMMON32BI
static const u32 round_consts_32bit[2 * 24] =
{
0x00000001UL, 0x00000000UL, 0x00000000UL, 0x00000089UL,
0x00000000UL, 0x8000008bUL, 0x00000000UL, 0x80008080UL,
0x00000001UL, 0x0000008bUL, 0x00000001UL, 0x00008000UL,
0x00000001UL, 0x80008088UL, 0x00000001UL, 0x80000082UL,
0x00000000UL, 0x0000000bUL, 0x00000000UL, 0x0000000aUL,
0x00000001UL, 0x00008082UL, 0x00000000UL, 0x00008003UL,
0x00000001UL, 0x0000808bUL, 0x00000001UL, 0x8000000bUL,
0x00000001UL, 0x8000008aUL, 0x00000001UL, 0x80000081UL,
0x00000000UL, 0x80000081UL, 0x00000000UL, 0x80000008UL,
0x00000000UL, 0x00000083UL, 0x00000000UL, 0x80008003UL,
0x00000001UL, 0x80008088UL, 0x00000000UL, 0x80000088UL,
0x00000001UL, 0x00008000UL, 0x00000000UL, 0x80008082UL
};
static unsigned int
keccak_extract32bi(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
unsigned int outlen)
{
unsigned int i;
u32 x0;
u32 x1;
u32 t;
/* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
{
x0 = hd->u.state32bi[i * 2 + 0];
x1 = hd->u.state32bi[i * 2 + 1];
t = (x0 & 0x0000FFFFUL) + (x1 << 16);
x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL);
x0 = t;
t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8);
t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4);
t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2);
t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1);
t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8);
t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4);
t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2);
t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1);
buf_put_le32(&outbuf[0], x0);
buf_put_le32(&outbuf[4], x1);
outbuf += 8;
}
return 0;
}
static inline void
keccak_absorb_lane32bi(u32 *lane, u32 x0, u32 x1)
{
u32 t;
t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1);
t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2);
t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4);
t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8);
t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1);
t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2);
t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4);
t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8);
lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16);
lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL);
}
#endif /* NEED_COMMON32BI */
/* Construct generic 64-bit implementation. */
#ifdef USE_64BIT
#if __GNUC__ >= 4 && defined(__x86_64__)
static inline void absorb_lanes64_8(u64 *dst, const byte *in)
{
asm ("movdqu 0*16(%[dst]), %%xmm0\n\t"
"movdqu 0*16(%[in]), %%xmm4\n\t"
"movdqu 1*16(%[dst]), %%xmm1\n\t"
"movdqu 1*16(%[in]), %%xmm5\n\t"
"movdqu 2*16(%[dst]), %%xmm2\n\t"
"movdqu 3*16(%[dst]), %%xmm3\n\t"
"pxor %%xmm4, %%xmm0\n\t"
"pxor %%xmm5, %%xmm1\n\t"
"movdqu 2*16(%[in]), %%xmm4\n\t"
"movdqu 3*16(%[in]), %%xmm5\n\t"
"movdqu %%xmm0, 0*16(%[dst])\n\t"
"pxor %%xmm4, %%xmm2\n\t"
"movdqu %%xmm1, 1*16(%[dst])\n\t"
"pxor %%xmm5, %%xmm3\n\t"
"movdqu %%xmm2, 2*16(%[dst])\n\t"
"movdqu %%xmm3, 3*16(%[dst])\n\t"
:
: [dst] "r" (dst), [in] "r" (in)
: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "memory");
}
static inline void absorb_lanes64_4(u64 *dst, const byte *in)
{
asm ("movdqu 0*16(%[dst]), %%xmm0\n\t"
"movdqu 0*16(%[in]), %%xmm4\n\t"
"movdqu 1*16(%[dst]), %%xmm1\n\t"
"movdqu 1*16(%[in]), %%xmm5\n\t"
"pxor %%xmm4, %%xmm0\n\t"
"pxor %%xmm5, %%xmm1\n\t"
"movdqu %%xmm0, 0*16(%[dst])\n\t"
"movdqu %%xmm1, 1*16(%[dst])\n\t"
:
: [dst] "r" (dst), [in] "r" (in)
: "xmm0", "xmm1", "xmm4", "xmm5", "memory");
}
static inline void absorb_lanes64_2(u64 *dst, const byte *in)
{
asm ("movdqu 0*16(%[dst]), %%xmm0\n\t"
"movdqu 0*16(%[in]), %%xmm4\n\t"
"pxor %%xmm4, %%xmm0\n\t"
"movdqu %%xmm0, 0*16(%[dst])\n\t"
:
: [dst] "r" (dst), [in] "r" (in)
: "xmm0", "xmm4", "memory");
}
#else /* __x86_64__ */
static inline void absorb_lanes64_8(u64 *dst, const byte *in)
{
dst[0] ^= buf_get_le64(in + 8 * 0);
dst[1] ^= buf_get_le64(in + 8 * 1);
dst[2] ^= buf_get_le64(in + 8 * 2);
dst[3] ^= buf_get_le64(in + 8 * 3);
dst[4] ^= buf_get_le64(in + 8 * 4);
dst[5] ^= buf_get_le64(in + 8 * 5);
dst[6] ^= buf_get_le64(in + 8 * 6);
dst[7] ^= buf_get_le64(in + 8 * 7);
}
static inline void absorb_lanes64_4(u64 *dst, const byte *in)
{
dst[0] ^= buf_get_le64(in + 8 * 0);
dst[1] ^= buf_get_le64(in + 8 * 1);
dst[2] ^= buf_get_le64(in + 8 * 2);
dst[3] ^= buf_get_le64(in + 8 * 3);
}
static inline void absorb_lanes64_2(u64 *dst, const byte *in)
{
dst[0] ^= buf_get_le64(in + 8 * 0);
dst[1] ^= buf_get_le64(in + 8 * 1);
}
#endif /* !__x86_64__ */
static inline void absorb_lanes64_1(u64 *dst, const byte *in)
{
dst[0] ^= buf_get_le64(in + 8 * 0);
}
# define ANDN64(x, y) (~(x) & (y))
# define ROL64(x, n) (((x) << ((unsigned int)n & 63)) | \
((x) >> ((64 - (unsigned int)(n)) & 63)))
# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64
# define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64
# include "keccak_permute_64.h"
# undef ANDN64
# undef ROL64
# undef KECCAK_F1600_PERMUTE_FUNC_NAME
# undef KECCAK_F1600_ABSORB_FUNC_NAME
static const keccak_ops_t keccak_generic64_ops =
{
.permute = keccak_f1600_state_permute64,
.absorb = keccak_absorb_lanes64,
.extract = keccak_extract64,
};
#endif /* USE_64BIT */
/* Construct 64-bit Intel SHLD implementation. */
#ifdef USE_64BIT_SHLD
# define ANDN64(x, y) (~(x) & (y))
# define ROL64(x, n) ({ \
u64 tmp = (x); \
asm ("shldq %1, %0, %0" \
: "+r" (tmp) \
: "J" ((n) & 63) \
: "cc"); \
tmp; })
# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_shld
# define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_shld
# include "keccak_permute_64.h"
# undef ANDN64
# undef ROL64
# undef KECCAK_F1600_PERMUTE_FUNC_NAME
# undef KECCAK_F1600_ABSORB_FUNC_NAME
static const keccak_ops_t keccak_shld_64_ops =
{
.permute = keccak_f1600_state_permute64_shld,
.absorb = keccak_absorb_lanes64_shld,
.extract = keccak_extract64,
};
#endif /* USE_64BIT_SHLD */
/* Construct 64-bit Intel BMI2 implementation. */
#ifdef USE_64BIT_BMI2
# define ANDN64(x, y) ({ \
u64 tmp; \
asm ("andnq %2, %1, %0" \
: "=r" (tmp) \
: "r0" (x), "rm" (y)); \
tmp; })
# define ROL64(x, n) ({ \
u64 tmp; \
asm ("rorxq %2, %1, %0" \
: "=r" (tmp) \
: "rm0" (x), "J" (64 - ((n) & 63))); \
tmp; })
# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_bmi2
# define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_bmi2
# include "keccak_permute_64.h"
# undef ANDN64
# undef ROL64
# undef KECCAK_F1600_PERMUTE_FUNC_NAME
# undef KECCAK_F1600_ABSORB_FUNC_NAME
static const keccak_ops_t keccak_bmi2_64_ops =
{
.permute = keccak_f1600_state_permute64_bmi2,
.absorb = keccak_absorb_lanes64_bmi2,
.extract = keccak_extract64,
};
#endif /* USE_64BIT_BMI2 */
/* 64-bit ARMv7/NEON implementation. */
#ifdef USE_64BIT_ARM_NEON
unsigned int _gcry_keccak_permute_armv7_neon(u64 *state);
unsigned int _gcry_keccak_absorb_lanes64_armv7_neon(u64 *state, int pos,
const byte *lanes,
unsigned int nlanes,
int blocklanes);
static unsigned int keccak_permute64_armv7_neon(KECCAK_STATE *hd)
{
return _gcry_keccak_permute_armv7_neon(hd->u.state64);
}
static unsigned int
keccak_absorb_lanes64_armv7_neon(KECCAK_STATE *hd, int pos, const byte *lanes,
unsigned int nlanes, int blocklanes)
{
if (blocklanes < 0)
{
/* blocklanes == -1, permutationless absorb from keccak_final. */
while (nlanes)
{
hd->u.state64[pos] ^= buf_get_le64(lanes);
lanes += 8;
nlanes--;
}
return 0;
}
else
{
return _gcry_keccak_absorb_lanes64_armv7_neon(hd->u.state64, pos, lanes,
nlanes, blocklanes);
}
}
static const keccak_ops_t keccak_armv7_neon_64_ops =
{
.permute = keccak_permute64_armv7_neon,
.absorb = keccak_absorb_lanes64_armv7_neon,
.extract = keccak_extract64,
};
#endif /* USE_64BIT_ARM_NEON */
/* Construct generic 32-bit implementation. */
#ifdef USE_32BIT
# define ANDN32(x, y) (~(x) & (y))
# define ROL32(x, n) (((x) << ((unsigned int)n & 31)) | \
((x) >> ((32 - (unsigned int)(n)) & 31)))
# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi
# include "keccak_permute_32.h"
# undef ANDN32
# undef ROL32
# undef KECCAK_F1600_PERMUTE_FUNC_NAME
static unsigned int
keccak_absorb_lanes32bi(KECCAK_STATE *hd, int pos, const byte *lanes,
unsigned int nlanes, int blocklanes)
{
unsigned int burn = 0;
while (nlanes)
{
keccak_absorb_lane32bi(&hd->u.state32bi[pos * 2],
buf_get_le32(lanes + 0),
buf_get_le32(lanes + 4));
lanes += 8;
nlanes--;
if (++pos == blocklanes)
{
burn = keccak_f1600_state_permute32bi(hd);
pos = 0;
}
}
return burn;
}
static const keccak_ops_t keccak_generic32bi_ops =
{
.permute = keccak_f1600_state_permute32bi,
.absorb = keccak_absorb_lanes32bi,
.extract = keccak_extract32bi,
};
#endif /* USE_32BIT */
/* Construct 32-bit Intel BMI2 implementation. */
#ifdef USE_32BIT_BMI2
# define ANDN32(x, y) ({ \
u32 tmp; \
asm ("andnl %2, %1, %0" \
: "=r" (tmp) \
: "r0" (x), "rm" (y)); \
tmp; })
# define ROL32(x, n) ({ \
u32 tmp; \
asm ("rorxl %2, %1, %0" \
: "=r" (tmp) \
: "rm0" (x), "J" (32 - ((n) & 31))); \
tmp; })
# define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi_bmi2
# include "keccak_permute_32.h"
# undef ANDN32
# undef ROL32
# undef KECCAK_F1600_PERMUTE_FUNC_NAME
static inline u32 pext(u32 x, u32 mask)
{
u32 tmp;
asm ("pextl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask));
return tmp;
}
static inline u32 pdep(u32 x, u32 mask)
{
u32 tmp;
asm ("pdepl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask));
return tmp;
}
static inline void
keccak_absorb_lane32bi_bmi2(u32 *lane, u32 x0, u32 x1)
{
x0 = pdep(pext(x0, 0x55555555), 0x0000ffff) | (pext(x0, 0xaaaaaaaa) << 16);
x1 = pdep(pext(x1, 0x55555555), 0x0000ffff) | (pext(x1, 0xaaaaaaaa) << 16);
lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16);
lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL);
}
static unsigned int
keccak_absorb_lanes32bi_bmi2(KECCAK_STATE *hd, int pos, const byte *lanes,
unsigned int nlanes, int blocklanes)
{
unsigned int burn = 0;
while (nlanes)
{
keccak_absorb_lane32bi_bmi2(&hd->u.state32bi[pos * 2],
buf_get_le32(lanes + 0),
buf_get_le32(lanes + 4));
lanes += 8;
nlanes--;
if (++pos == blocklanes)
{
burn = keccak_f1600_state_permute32bi_bmi2(hd);
pos = 0;
}
}
return burn;
}
static unsigned int
keccak_extract32bi_bmi2(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
unsigned int outlen)
{
unsigned int i;
u32 x0;
u32 x1;
u32 t;
/* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
{
x0 = hd->u.state32bi[i * 2 + 0];
x1 = hd->u.state32bi[i * 2 + 1];
t = (x0 & 0x0000FFFFUL) + (x1 << 16);
x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL);
x0 = t;
x0 = pdep(pext(x0, 0xffff0001), 0xaaaaaaab) | pdep(x0 >> 1, 0x55555554);
x1 = pdep(pext(x1, 0xffff0001), 0xaaaaaaab) | pdep(x1 >> 1, 0x55555554);
buf_put_le32(&outbuf[0], x0);
buf_put_le32(&outbuf[4], x1);
outbuf += 8;
}
return 0;
}
static const keccak_ops_t keccak_bmi2_32bi_ops =
{
.permute = keccak_f1600_state_permute32bi_bmi2,
.absorb = keccak_absorb_lanes32bi_bmi2,
.extract = keccak_extract32bi_bmi2,
};
#endif /* USE_32BIT */
static void
keccak_write (void *context, const void *inbuf_arg, size_t inlen)
{
KECCAK_CONTEXT *ctx = context;
const size_t bsize = ctx->blocksize;
const size_t blocklanes = bsize / 8;
const byte *inbuf = inbuf_arg;
unsigned int nburn, burn = 0;
unsigned int count, i;
unsigned int pos, nlanes;
count = ctx->count;
if (inlen && (count % 8))
{
byte lane[8] = { 0, };
/* Complete absorbing partial input lane. */
pos = count / 8;
for (i = count % 8; inlen && i < 8; i++)
{
lane[i] = *inbuf++;
inlen--;
count++;
}
if (count == bsize)
count = 0;
nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1,
(count % 8) ? -1 : blocklanes);
burn = nburn > burn ? nburn : burn;
}
/* Absorb full input lanes. */
pos = count / 8;
nlanes = inlen / 8;
if (nlanes > 0)
{
nburn = ctx->ops->absorb(&ctx->state, pos, inbuf, nlanes, blocklanes);
burn = nburn > burn ? nburn : burn;
inlen -= nlanes * 8;
inbuf += nlanes * 8;
count += nlanes * 8;
count = count % bsize;
}
if (inlen)
{
byte lane[8] = { 0, };
/* Absorb remaining partial input lane. */
pos = count / 8;
for (i = count % 8; inlen && i < 8; i++)
{
lane[i] = *inbuf++;
inlen--;
count++;
}
nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1, -1);
burn = nburn > burn ? nburn : burn;
gcry_assert(count < bsize);
}
ctx->count = count;
if (burn)
_gcry_burn_stack (burn);
}
static void
keccak_init (int algo, void *context, unsigned int flags)
{
KECCAK_CONTEXT *ctx = context;
KECCAK_STATE *hd = &ctx->state;
unsigned int features = _gcry_get_hw_features ();
(void)flags;
(void)features;
memset (hd, 0, sizeof *hd);
ctx->count = 0;
/* Select generic implementation. */
#ifdef USE_64BIT
ctx->ops = &keccak_generic64_ops;
#elif defined USE_32BIT
ctx->ops = &keccak_generic32bi_ops;
#endif
/* Select optimized implementation based in hw features. */
if (0) {}
#ifdef USE_64BIT_ARM_NEON
else if (features & HWF_ARM_NEON)
ctx->ops = &keccak_armv7_neon_64_ops;
#endif
#ifdef USE_64BIT_BMI2
else if (features & HWF_INTEL_BMI2)
ctx->ops = &keccak_bmi2_64_ops;
#endif
#ifdef USE_32BIT_BMI2
else if (features & HWF_INTEL_BMI2)
ctx->ops = &keccak_bmi2_32bi_ops;
#endif
#ifdef USE_64BIT_SHLD
else if (features & HWF_INTEL_FAST_SHLD)
ctx->ops = &keccak_shld_64_ops;
#endif
/* Set input block size, in Keccak terms this is called 'rate'. */
switch (algo)
{
case GCRY_MD_SHA3_224:
ctx->suffix = SHA3_DELIMITED_SUFFIX;
ctx->blocksize = 1152 / 8;
ctx->outlen = 224 / 8;
break;
case GCRY_MD_SHA3_256:
ctx->suffix = SHA3_DELIMITED_SUFFIX;
ctx->blocksize = 1088 / 8;
ctx->outlen = 256 / 8;
break;
case GCRY_MD_SHA3_384:
ctx->suffix = SHA3_DELIMITED_SUFFIX;
ctx->blocksize = 832 / 8;
ctx->outlen = 384 / 8;
break;
case GCRY_MD_SHA3_512:
ctx->suffix = SHA3_DELIMITED_SUFFIX;
ctx->blocksize = 576 / 8;
ctx->outlen = 512 / 8;
break;
case GCRY_MD_SHAKE128:
ctx->suffix = SHAKE_DELIMITED_SUFFIX;
ctx->blocksize = 1344 / 8;
ctx->outlen = 0;
break;
case GCRY_MD_SHAKE256:
ctx->suffix = SHAKE_DELIMITED_SUFFIX;
ctx->blocksize = 1088 / 8;
ctx->outlen = 0;
break;
default:
BUG();
}
}
static void
sha3_224_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHA3_224, context, flags);
}
static void
sha3_256_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHA3_256, context, flags);
}
static void
sha3_384_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHA3_384, context, flags);
}
static void
sha3_512_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHA3_512, context, flags);
}
static void
shake128_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHAKE128, context, flags);
}
static void
shake256_init (void *context, unsigned int flags)
{
keccak_init (GCRY_MD_SHAKE256, context, flags);
}
/* The routine final 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: 64 bytes representing the digest. When used for sha384,
* we take the leftmost 48 of those bytes.
*/
static void
keccak_final (void *context)
{
KECCAK_CONTEXT *ctx = context;
KECCAK_STATE *hd = &ctx->state;
const size_t bsize = ctx->blocksize;
const byte suffix = ctx->suffix;
unsigned int nburn, burn = 0;
unsigned int lastbytes;
byte lane[8];
lastbytes = ctx->count;
/* Do the padding and switch to the squeezing phase */
/* Absorb the last few bits and add the first bit of padding (which
coincides with the delimiter in delimited suffix) */
buf_put_le64(lane, (u64)suffix << ((lastbytes % 8) * 8));
nburn = ctx->ops->absorb(&ctx->state, lastbytes / 8, lane, 1, -1);
burn = nburn > burn ? nburn : burn;
/* Add the second bit of padding. */
buf_put_le64(lane, (u64)0x80 << (((bsize - 1) % 8) * 8));
nburn = ctx->ops->absorb(&ctx->state, (bsize - 1) / 8, lane, 1, -1);
burn = nburn > burn ? nburn : burn;
if (suffix == SHA3_DELIMITED_SUFFIX)
{
/* Switch to the squeezing phase. */
nburn = ctx->ops->permute(hd);
burn = nburn > burn ? nburn : burn;
/* Squeeze out the SHA3 digest. */
nburn = ctx->ops->extract(hd, 0, (void *)hd, ctx->outlen);
burn = nburn > burn ? nburn : burn;
}
else
{
/* Output for SHAKE can now be read with md_extract(). */
ctx->count = 0;
}
wipememory(lane, sizeof(lane));
if (burn)
_gcry_burn_stack (burn);
}
static byte *
keccak_read (void *context)
{
KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context;
KECCAK_STATE *hd = &ctx->state;
return (byte *)&hd->u;
}
static void
keccak_extract (void *context, void *out, size_t outlen)
{
KECCAK_CONTEXT *ctx = context;
KECCAK_STATE *hd = &ctx->state;
const size_t bsize = ctx->blocksize;
unsigned int nburn, burn = 0;
byte *outbuf = out;
unsigned int nlanes;
unsigned int nleft;
unsigned int count;
unsigned int i;
byte lane[8];
count = ctx->count;
while (count && outlen && (outlen < 8 || count % 8))
{
/* Extract partial lane. */
nburn = ctx->ops->extract(hd, count / 8, lane, 8);
burn = nburn > burn ? nburn : burn;
for (i = count % 8; outlen && i < 8; i++)
{
*outbuf++ = lane[i];
outlen--;
count++;
}
gcry_assert(count <= bsize);
if (count == bsize)
count = 0;
}
if (outlen >= 8 && count)
{
/* Extract tail of partial block. */
nlanes = outlen / 8;
nleft = (bsize - count) / 8;
nlanes = nlanes < nleft ? nlanes : nleft;
nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8);
burn = nburn > burn ? nburn : burn;
outlen -= nlanes * 8;
outbuf += nlanes * 8;
count += nlanes * 8;
gcry_assert(count <= bsize);
if (count == bsize)
count = 0;
}
while (outlen >= bsize)
{
gcry_assert(count == 0);
/* Squeeze more. */
nburn = ctx->ops->permute(hd);
burn = nburn > burn ? nburn : burn;
/* Extract full block. */
nburn = ctx->ops->extract(hd, 0, outbuf, bsize);
burn = nburn > burn ? nburn : burn;
outlen -= bsize;
outbuf += bsize;
}
if (outlen)
{
gcry_assert(outlen < bsize);
if (count == 0)
{
/* Squeeze more. */
nburn = ctx->ops->permute(hd);
burn = nburn > burn ? nburn : burn;
}
if (outlen >= 8)
{
/* Extract head of partial block. */
nlanes = outlen / 8;
nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8);
burn = nburn > burn ? nburn : burn;
outlen -= nlanes * 8;
outbuf += nlanes * 8;
count += nlanes * 8;
gcry_assert(count < bsize);
}
if (outlen)
{
/* Extract head of partial lane. */
nburn = ctx->ops->extract(hd, count / 8, lane, 8);
burn = nburn > burn ? nburn : burn;
for (i = count % 8; outlen && i < 8; i++)
{
*outbuf++ = lane[i];
outlen--;
count++;
}
gcry_assert(count < bsize);
}
}
ctx->count = count;
if (burn)
_gcry_burn_stack (burn);
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 'spec->mdlen' bytes. */
static void
_gcry_sha3_hash_buffer (void *outbuf, const void *buffer, size_t length,
const gcry_md_spec_t *spec)
{
KECCAK_CONTEXT hd;
spec->init (&hd, 0);
keccak_write (&hd, buffer, length);
keccak_final (&hd);
memcpy (outbuf, keccak_read (&hd), spec->mdlen);
}
/* Variant of the above shortcut function using multiple buffers. */
static void
_gcry_sha3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt,
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);
memcpy (outbuf, keccak_read (&hd), spec->mdlen);
}
static void
_gcry_sha3_224_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
_gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_224);
}
static void
_gcry_sha3_256_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
_gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_256);
}
static void
_gcry_sha3_384_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
_gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_384);
}
static void
_gcry_sha3_512_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
_gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_512);
}
static void
_gcry_sha3_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
_gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_224);
}
static void
_gcry_sha3_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
_gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_256);
}
static void
_gcry_sha3_384_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
_gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_384);
}
static void
_gcry_sha3_512_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
_gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_512);
}
/*
Self-test section.
*/
static gpg_err_code_t
selftests_keccak (int algo, int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
const char *short_hash;
const char *long_hash;
const char *one_million_a_hash;
int hash_len;
switch (algo)
{
default:
BUG();
case GCRY_MD_SHA3_224:
short_hash =
"\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";
long_hash =
"\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5"
"\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc";
one_million_a_hash =
"\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c"
"\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c";
hash_len = 28;
break;
case GCRY_MD_SHA3_256:
short_hash =
"\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd"
"\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32";
long_hash =
"\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb"
"\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18";
one_million_a_hash =
"\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6"
"\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1";
hash_len = 32;
break;
case GCRY_MD_SHA3_384:
short_hash =
"\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d"
"\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2"
"\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25";
long_hash =
"\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91"
"\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc"
"\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7";
one_million_a_hash =
"\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad"
"\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84"
"\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40";
hash_len = 48;
break;
case GCRY_MD_SHA3_512:
short_hash =
"\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e"
"\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e"
"\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40"
"\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0";
long_hash =
"\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9"
"\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa"
"\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89"
"\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85";
one_million_a_hash =
"\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e"
"\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59"
"\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66"
"\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87";
hash_len = 64;
break;
case GCRY_MD_SHAKE128:
short_hash =
"\x58\x81\x09\x2d\xd8\x18\xbf\x5c\xf8\xa3\xdd\xb7\x93\xfb\xcb\xa7"
"\x40\x97\xd5\xc5\x26\xa6\xd3\x5f\x97\xb8\x33\x51\x94\x0f\x2c\xc8";
long_hash =
"\x7b\x6d\xf6\xff\x18\x11\x73\xb6\xd7\x89\x8d\x7f\xf6\x3f\xb0\x7b"
"\x7c\x23\x7d\xaf\x47\x1a\x5a\xe5\x60\x2a\xdb\xcc\xef\x9c\xcf\x4b";
one_million_a_hash =
"\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11"
"\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58";
hash_len = 32;
break;
case GCRY_MD_SHAKE256:
short_hash =
"\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11\x4d"
"\x8d\xb4\x45\x30\xf8\xf1\xe1\xee\x4f\x94\xea\x37\xe7\x8b\x57\x39";
long_hash =
"\x98\xbe\x04\x51\x6c\x04\xcc\x73\x59\x3f\xef\x3e\xd0\x35\x2e\xa9"
"\xf6\x44\x39\x42\xd6\x95\x0e\x29\xa3\x72\xa6\x81\xc3\xde\xaf\x45";
one_million_a_hash =
"\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb"
"\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a";
hash_len = 32;
break;
}
what = "short string";
errtxt = _gcry_hash_selftest_check_one (algo, 0, "abc", 3, short_hash,
hash_len);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(algo, 0,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
long_hash, hash_len);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one (algo, 1, NULL, 0,
one_million_a_hash, hash_len);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", algo, 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_SHA3_224:
case GCRY_MD_SHA3_256:
case GCRY_MD_SHA3_384:
case GCRY_MD_SHA3_512:
case GCRY_MD_SHAKE128:
case GCRY_MD_SHAKE256:
ec = selftests_keccak (algo, extended, report);
break;
default:
ec = GPG_ERR_DIGEST_ALGO;
break;
}
return ec;
}
static byte sha3_224_asn[] = { 0x30 };
static 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[] =
{
{ "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[] =
{
{ "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[] =
{
{ "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[] =
{
{ "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[] =
{
{ "2.16.840.1.101.3.4.2.12" },
/* PKCS#1 shake256WithRSAEncryption */
{ "?" },
{ NULL }
};
gcry_md_spec_t _gcry_digest_spec_sha3_224 =
{
GCRY_MD_SHA3_224, {0, 1},
"SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28,
sha3_224_init, keccak_write, keccak_final, keccak_read, NULL,
_gcry_sha3_224_hash_buffer, _gcry_sha3_224_hash_buffers,
sizeof (KECCAK_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_sha3_256 =
{
GCRY_MD_SHA3_256, {0, 1},
"SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32,
sha3_256_init, keccak_write, keccak_final, keccak_read, NULL,
_gcry_sha3_256_hash_buffer, _gcry_sha3_256_hash_buffers,
sizeof (KECCAK_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_sha3_384 =
{
GCRY_MD_SHA3_384, {0, 1},
"SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48,
sha3_384_init, keccak_write, keccak_final, keccak_read, NULL,
_gcry_sha3_384_hash_buffer, _gcry_sha3_384_hash_buffers,
sizeof (KECCAK_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_sha3_512 =
{
GCRY_MD_SHA3_512, {0, 1},
"SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64,
sha3_512_init, keccak_write, keccak_final, keccak_read, NULL,
_gcry_sha3_512_hash_buffer, _gcry_sha3_512_hash_buffers,
sizeof (KECCAK_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_shake128 =
{
GCRY_MD_SHAKE128, {0, 1},
"SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0,
shake128_init, keccak_write, keccak_final, NULL, keccak_extract,
NULL, NULL,
sizeof (KECCAK_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_shake256 =
{
GCRY_MD_SHAKE256, {0, 1},
"SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0,
shake256_init, keccak_write, keccak_final, NULL, keccak_extract,
NULL, NULL,
sizeof (KECCAK_CONTEXT),
run_selftests
};
diff --git a/cipher/keccak_permute_32.h b/cipher/keccak_permute_32.h
index 1ce42a42..a541699f 100644
--- a/cipher/keccak_permute_32.h
+++ b/cipher/keccak_permute_32.h
@@ -1,536 +1,536 @@
/* keccak_permute_32.h - Keccak permute function (simple 32bit bit-interleaved)
* Copyright (C) 2015 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* The code is based on public-domain/CC0 "keccakc1024/simple32bi/
* Keccak-simple32BI.c" implementation by Ronny Van Keer from SUPERCOP toolkit
* package.
*/
/* Function that computes the Keccak-f[1600] permutation on the given state. */
static unsigned int
KECCAK_F1600_PERMUTE_FUNC_NAME(KECCAK_STATE *hd)
{
const u32 *round_consts = round_consts_32bit;
const u32 *round_consts_end = round_consts_32bit + 2 * 24;
u32 Aba0, Abe0, Abi0, Abo0, Abu0;
u32 Aba1, Abe1, Abi1, Abo1, Abu1;
u32 Aga0, Age0, Agi0, Ago0, Agu0;
u32 Aga1, Age1, Agi1, Ago1, Agu1;
u32 Aka0, Ake0, Aki0, Ako0, Aku0;
u32 Aka1, Ake1, Aki1, Ako1, Aku1;
u32 Ama0, Ame0, Ami0, Amo0, Amu0;
u32 Ama1, Ame1, Ami1, Amo1, Amu1;
u32 Asa0, Ase0, Asi0, Aso0, Asu0;
u32 Asa1, Ase1, Asi1, Aso1, Asu1;
u32 BCa0, BCe0, BCi0, BCo0, BCu0;
u32 BCa1, BCe1, BCi1, BCo1, BCu1;
u32 Da0, De0, Di0, Do0, Du0;
u32 Da1, De1, Di1, Do1, Du1;
u32 Eba0, Ebe0, Ebi0, Ebo0, Ebu0;
u32 Eba1, Ebe1, Ebi1, Ebo1, Ebu1;
u32 Ega0, Ege0, Egi0, Ego0, Egu0;
u32 Ega1, Ege1, Egi1, Ego1, Egu1;
u32 Eka0, Eke0, Eki0, Eko0, Eku0;
u32 Eka1, Eke1, Eki1, Eko1, Eku1;
u32 Ema0, Eme0, Emi0, Emo0, Emu0;
u32 Ema1, Eme1, Emi1, Emo1, Emu1;
u32 Esa0, Ese0, Esi0, Eso0, Esu0;
u32 Esa1, Ese1, Esi1, Eso1, Esu1;
u32 *state = hd->u.state32bi;
Aba0 = state[0];
Aba1 = state[1];
Abe0 = state[2];
Abe1 = state[3];
Abi0 = state[4];
Abi1 = state[5];
Abo0 = state[6];
Abo1 = state[7];
Abu0 = state[8];
Abu1 = state[9];
Aga0 = state[10];
Aga1 = state[11];
Age0 = state[12];
Age1 = state[13];
Agi0 = state[14];
Agi1 = state[15];
Ago0 = state[16];
Ago1 = state[17];
Agu0 = state[18];
Agu1 = state[19];
Aka0 = state[20];
Aka1 = state[21];
Ake0 = state[22];
Ake1 = state[23];
Aki0 = state[24];
Aki1 = state[25];
Ako0 = state[26];
Ako1 = state[27];
Aku0 = state[28];
Aku1 = state[29];
Ama0 = state[30];
Ama1 = state[31];
Ame0 = state[32];
Ame1 = state[33];
Ami0 = state[34];
Ami1 = state[35];
Amo0 = state[36];
Amo1 = state[37];
Amu0 = state[38];
Amu1 = state[39];
Asa0 = state[40];
Asa1 = state[41];
Ase0 = state[42];
Ase1 = state[43];
Asi0 = state[44];
Asi1 = state[45];
Aso0 = state[46];
Aso1 = state[47];
Asu0 = state[48];
Asu1 = state[49];
do
{
/* prepareTheta */
BCa0 = Aba0 ^ Aga0 ^ Aka0 ^ Ama0 ^ Asa0;
BCa1 = Aba1 ^ Aga1 ^ Aka1 ^ Ama1 ^ Asa1;
BCe0 = Abe0 ^ Age0 ^ Ake0 ^ Ame0 ^ Ase0;
BCe1 = Abe1 ^ Age1 ^ Ake1 ^ Ame1 ^ Ase1;
BCi0 = Abi0 ^ Agi0 ^ Aki0 ^ Ami0 ^ Asi0;
BCi1 = Abi1 ^ Agi1 ^ Aki1 ^ Ami1 ^ Asi1;
BCo0 = Abo0 ^ Ago0 ^ Ako0 ^ Amo0 ^ Aso0;
BCo1 = Abo1 ^ Ago1 ^ Ako1 ^ Amo1 ^ Aso1;
BCu0 = Abu0 ^ Agu0 ^ Aku0 ^ Amu0 ^ Asu0;
BCu1 = Abu1 ^ Agu1 ^ Aku1 ^ Amu1 ^ Asu1;
/* thetaRhoPiChiIota(round , A, E) */
Da0 = BCu0 ^ ROL32(BCe1, 1);
Da1 = BCu1 ^ BCe0;
De0 = BCa0 ^ ROL32(BCi1, 1);
De1 = BCa1 ^ BCi0;
Di0 = BCe0 ^ ROL32(BCo1, 1);
Di1 = BCe1 ^ BCo0;
Do0 = BCi0 ^ ROL32(BCu1, 1);
Do1 = BCi1 ^ BCu0;
Du0 = BCo0 ^ ROL32(BCa1, 1);
Du1 = BCo1 ^ BCa0;
Aba0 ^= Da0;
BCa0 = Aba0;
Age0 ^= De0;
BCe0 = ROL32(Age0, 22);
Aki1 ^= Di1;
BCi0 = ROL32(Aki1, 22);
Amo1 ^= Do1;
BCo0 = ROL32(Amo1, 11);
Asu0 ^= Du0;
BCu0 = ROL32(Asu0, 7);
Eba0 = BCa0 ^ ANDN32(BCe0, BCi0);
Eba0 ^= *(round_consts++);
Ebe0 = BCe0 ^ ANDN32(BCi0, BCo0);
Ebi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Ebo0 = BCo0 ^ ANDN32(BCu0, BCa0);
Ebu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Aba1 ^= Da1;
BCa1 = Aba1;
Age1 ^= De1;
BCe1 = ROL32(Age1, 22);
Aki0 ^= Di0;
BCi1 = ROL32(Aki0, 21);
Amo0 ^= Do0;
BCo1 = ROL32(Amo0, 10);
Asu1 ^= Du1;
BCu1 = ROL32(Asu1, 7);
Eba1 = BCa1 ^ ANDN32(BCe1, BCi1);
Eba1 ^= *(round_consts++);
Ebe1 = BCe1 ^ ANDN32(BCi1, BCo1);
Ebi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Ebo1 = BCo1 ^ ANDN32(BCu1, BCa1);
Ebu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Abo0 ^= Do0;
BCa0 = ROL32(Abo0, 14);
Agu0 ^= Du0;
BCe0 = ROL32(Agu0, 10);
Aka1 ^= Da1;
BCi0 = ROL32(Aka1, 2);
Ame1 ^= De1;
BCo0 = ROL32(Ame1, 23);
Asi1 ^= Di1;
BCu0 = ROL32(Asi1, 31);
Ega0 = BCa0 ^ ANDN32(BCe0, BCi0);
Ege0 = BCe0 ^ ANDN32(BCi0, BCo0);
Egi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Ego0 = BCo0 ^ ANDN32(BCu0, BCa0);
Egu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Abo1 ^= Do1;
BCa1 = ROL32(Abo1, 14);
Agu1 ^= Du1;
BCe1 = ROL32(Agu1, 10);
Aka0 ^= Da0;
BCi1 = ROL32(Aka0, 1);
Ame0 ^= De0;
BCo1 = ROL32(Ame0, 22);
Asi0 ^= Di0;
BCu1 = ROL32(Asi0, 30);
Ega1 = BCa1 ^ ANDN32(BCe1, BCi1);
Ege1 = BCe1 ^ ANDN32(BCi1, BCo1);
Egi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Ego1 = BCo1 ^ ANDN32(BCu1, BCa1);
Egu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Abe1 ^= De1;
BCa0 = ROL32(Abe1, 1);
Agi0 ^= Di0;
BCe0 = ROL32(Agi0, 3);
Ako1 ^= Do1;
BCi0 = ROL32(Ako1, 13);
Amu0 ^= Du0;
BCo0 = ROL32(Amu0, 4);
Asa0 ^= Da0;
BCu0 = ROL32(Asa0, 9);
Eka0 = BCa0 ^ ANDN32(BCe0, BCi0);
Eke0 = BCe0 ^ ANDN32(BCi0, BCo0);
Eki0 = BCi0 ^ ANDN32(BCo0, BCu0);
Eko0 = BCo0 ^ ANDN32(BCu0, BCa0);
Eku0 = BCu0 ^ ANDN32(BCa0, BCe0);
Abe0 ^= De0;
BCa1 = Abe0;
Agi1 ^= Di1;
BCe1 = ROL32(Agi1, 3);
Ako0 ^= Do0;
BCi1 = ROL32(Ako0, 12);
Amu1 ^= Du1;
BCo1 = ROL32(Amu1, 4);
Asa1 ^= Da1;
BCu1 = ROL32(Asa1, 9);
Eka1 = BCa1 ^ ANDN32(BCe1, BCi1);
Eke1 = BCe1 ^ ANDN32(BCi1, BCo1);
Eki1 = BCi1 ^ ANDN32(BCo1, BCu1);
Eko1 = BCo1 ^ ANDN32(BCu1, BCa1);
Eku1 = BCu1 ^ ANDN32(BCa1, BCe1);
Abu1 ^= Du1;
BCa0 = ROL32(Abu1, 14);
Aga0 ^= Da0;
BCe0 = ROL32(Aga0, 18);
Ake0 ^= De0;
BCi0 = ROL32(Ake0, 5);
Ami1 ^= Di1;
BCo0 = ROL32(Ami1, 8);
Aso0 ^= Do0;
BCu0 = ROL32(Aso0, 28);
Ema0 = BCa0 ^ ANDN32(BCe0, BCi0);
Eme0 = BCe0 ^ ANDN32(BCi0, BCo0);
Emi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Emo0 = BCo0 ^ ANDN32(BCu0, BCa0);
Emu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Abu0 ^= Du0;
BCa1 = ROL32(Abu0, 13);
Aga1 ^= Da1;
BCe1 = ROL32(Aga1, 18);
Ake1 ^= De1;
BCi1 = ROL32(Ake1, 5);
Ami0 ^= Di0;
BCo1 = ROL32(Ami0, 7);
Aso1 ^= Do1;
BCu1 = ROL32(Aso1, 28);
Ema1 = BCa1 ^ ANDN32(BCe1, BCi1);
Eme1 = BCe1 ^ ANDN32(BCi1, BCo1);
Emi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Emo1 = BCo1 ^ ANDN32(BCu1, BCa1);
Emu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Abi0 ^= Di0;
BCa0 = ROL32(Abi0, 31);
Ago1 ^= Do1;
BCe0 = ROL32(Ago1, 28);
Aku1 ^= Du1;
BCi0 = ROL32(Aku1, 20);
Ama1 ^= Da1;
BCo0 = ROL32(Ama1, 21);
Ase0 ^= De0;
BCu0 = ROL32(Ase0, 1);
Esa0 = BCa0 ^ ANDN32(BCe0, BCi0);
Ese0 = BCe0 ^ ANDN32(BCi0, BCo0);
Esi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Eso0 = BCo0 ^ ANDN32(BCu0, BCa0);
Esu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Abi1 ^= Di1;
BCa1 = ROL32(Abi1, 31);
Ago0 ^= Do0;
BCe1 = ROL32(Ago0, 27);
Aku0 ^= Du0;
BCi1 = ROL32(Aku0, 19);
Ama0 ^= Da0;
BCo1 = ROL32(Ama0, 20);
Ase1 ^= De1;
BCu1 = ROL32(Ase1, 1);
Esa1 = BCa1 ^ ANDN32(BCe1, BCi1);
Ese1 = BCe1 ^ ANDN32(BCi1, BCo1);
Esi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Eso1 = BCo1 ^ ANDN32(BCu1, BCa1);
Esu1 = BCu1 ^ ANDN32(BCa1, BCe1);
/* prepareTheta */
BCa0 = Eba0 ^ Ega0 ^ Eka0 ^ Ema0 ^ Esa0;
BCa1 = Eba1 ^ Ega1 ^ Eka1 ^ Ema1 ^ Esa1;
BCe0 = Ebe0 ^ Ege0 ^ Eke0 ^ Eme0 ^ Ese0;
BCe1 = Ebe1 ^ Ege1 ^ Eke1 ^ Eme1 ^ Ese1;
BCi0 = Ebi0 ^ Egi0 ^ Eki0 ^ Emi0 ^ Esi0;
BCi1 = Ebi1 ^ Egi1 ^ Eki1 ^ Emi1 ^ Esi1;
BCo0 = Ebo0 ^ Ego0 ^ Eko0 ^ Emo0 ^ Eso0;
BCo1 = Ebo1 ^ Ego1 ^ Eko1 ^ Emo1 ^ Eso1;
BCu0 = Ebu0 ^ Egu0 ^ Eku0 ^ Emu0 ^ Esu0;
BCu1 = Ebu1 ^ Egu1 ^ Eku1 ^ Emu1 ^ Esu1;
/* thetaRhoPiChiIota(round+1, E, A) */
Da0 = BCu0 ^ ROL32(BCe1, 1);
Da1 = BCu1 ^ BCe0;
De0 = BCa0 ^ ROL32(BCi1, 1);
De1 = BCa1 ^ BCi0;
Di0 = BCe0 ^ ROL32(BCo1, 1);
Di1 = BCe1 ^ BCo0;
Do0 = BCi0 ^ ROL32(BCu1, 1);
Do1 = BCi1 ^ BCu0;
Du0 = BCo0 ^ ROL32(BCa1, 1);
Du1 = BCo1 ^ BCa0;
Eba0 ^= Da0;
BCa0 = Eba0;
Ege0 ^= De0;
BCe0 = ROL32(Ege0, 22);
Eki1 ^= Di1;
BCi0 = ROL32(Eki1, 22);
Emo1 ^= Do1;
BCo0 = ROL32(Emo1, 11);
Esu0 ^= Du0;
BCu0 = ROL32(Esu0, 7);
Aba0 = BCa0 ^ ANDN32(BCe0, BCi0);
Aba0 ^= *(round_consts++);
Abe0 = BCe0 ^ ANDN32(BCi0, BCo0);
Abi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Abo0 = BCo0 ^ ANDN32(BCu0, BCa0);
Abu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Eba1 ^= Da1;
BCa1 = Eba1;
Ege1 ^= De1;
BCe1 = ROL32(Ege1, 22);
Eki0 ^= Di0;
BCi1 = ROL32(Eki0, 21);
Emo0 ^= Do0;
BCo1 = ROL32(Emo0, 10);
Esu1 ^= Du1;
BCu1 = ROL32(Esu1, 7);
Aba1 = BCa1 ^ ANDN32(BCe1, BCi1);
Aba1 ^= *(round_consts++);
Abe1 = BCe1 ^ ANDN32(BCi1, BCo1);
Abi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Abo1 = BCo1 ^ ANDN32(BCu1, BCa1);
Abu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Ebo0 ^= Do0;
BCa0 = ROL32(Ebo0, 14);
Egu0 ^= Du0;
BCe0 = ROL32(Egu0, 10);
Eka1 ^= Da1;
BCi0 = ROL32(Eka1, 2);
Eme1 ^= De1;
BCo0 = ROL32(Eme1, 23);
Esi1 ^= Di1;
BCu0 = ROL32(Esi1, 31);
Aga0 = BCa0 ^ ANDN32(BCe0, BCi0);
Age0 = BCe0 ^ ANDN32(BCi0, BCo0);
Agi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Ago0 = BCo0 ^ ANDN32(BCu0, BCa0);
Agu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Ebo1 ^= Do1;
BCa1 = ROL32(Ebo1, 14);
Egu1 ^= Du1;
BCe1 = ROL32(Egu1, 10);
Eka0 ^= Da0;
BCi1 = ROL32(Eka0, 1);
Eme0 ^= De0;
BCo1 = ROL32(Eme0, 22);
Esi0 ^= Di0;
BCu1 = ROL32(Esi0, 30);
Aga1 = BCa1 ^ ANDN32(BCe1, BCi1);
Age1 = BCe1 ^ ANDN32(BCi1, BCo1);
Agi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Ago1 = BCo1 ^ ANDN32(BCu1, BCa1);
Agu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Ebe1 ^= De1;
BCa0 = ROL32(Ebe1, 1);
Egi0 ^= Di0;
BCe0 = ROL32(Egi0, 3);
Eko1 ^= Do1;
BCi0 = ROL32(Eko1, 13);
Emu0 ^= Du0;
BCo0 = ROL32(Emu0, 4);
Esa0 ^= Da0;
BCu0 = ROL32(Esa0, 9);
Aka0 = BCa0 ^ ANDN32(BCe0, BCi0);
Ake0 = BCe0 ^ ANDN32(BCi0, BCo0);
Aki0 = BCi0 ^ ANDN32(BCo0, BCu0);
Ako0 = BCo0 ^ ANDN32(BCu0, BCa0);
Aku0 = BCu0 ^ ANDN32(BCa0, BCe0);
Ebe0 ^= De0;
BCa1 = Ebe0;
Egi1 ^= Di1;
BCe1 = ROL32(Egi1, 3);
Eko0 ^= Do0;
BCi1 = ROL32(Eko0, 12);
Emu1 ^= Du1;
BCo1 = ROL32(Emu1, 4);
Esa1 ^= Da1;
BCu1 = ROL32(Esa1, 9);
Aka1 = BCa1 ^ ANDN32(BCe1, BCi1);
Ake1 = BCe1 ^ ANDN32(BCi1, BCo1);
Aki1 = BCi1 ^ ANDN32(BCo1, BCu1);
Ako1 = BCo1 ^ ANDN32(BCu1, BCa1);
Aku1 = BCu1 ^ ANDN32(BCa1, BCe1);
Ebu1 ^= Du1;
BCa0 = ROL32(Ebu1, 14);
Ega0 ^= Da0;
BCe0 = ROL32(Ega0, 18);
Eke0 ^= De0;
BCi0 = ROL32(Eke0, 5);
Emi1 ^= Di1;
BCo0 = ROL32(Emi1, 8);
Eso0 ^= Do0;
BCu0 = ROL32(Eso0, 28);
Ama0 = BCa0 ^ ANDN32(BCe0, BCi0);
Ame0 = BCe0 ^ ANDN32(BCi0, BCo0);
Ami0 = BCi0 ^ ANDN32(BCo0, BCu0);
Amo0 = BCo0 ^ ANDN32(BCu0, BCa0);
Amu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Ebu0 ^= Du0;
BCa1 = ROL32(Ebu0, 13);
Ega1 ^= Da1;
BCe1 = ROL32(Ega1, 18);
Eke1 ^= De1;
BCi1 = ROL32(Eke1, 5);
Emi0 ^= Di0;
BCo1 = ROL32(Emi0, 7);
Eso1 ^= Do1;
BCu1 = ROL32(Eso1, 28);
Ama1 = BCa1 ^ ANDN32(BCe1, BCi1);
Ame1 = BCe1 ^ ANDN32(BCi1, BCo1);
Ami1 = BCi1 ^ ANDN32(BCo1, BCu1);
Amo1 = BCo1 ^ ANDN32(BCu1, BCa1);
Amu1 = BCu1 ^ ANDN32(BCa1, BCe1);
Ebi0 ^= Di0;
BCa0 = ROL32(Ebi0, 31);
Ego1 ^= Do1;
BCe0 = ROL32(Ego1, 28);
Eku1 ^= Du1;
BCi0 = ROL32(Eku1, 20);
Ema1 ^= Da1;
BCo0 = ROL32(Ema1, 21);
Ese0 ^= De0;
BCu0 = ROL32(Ese0, 1);
Asa0 = BCa0 ^ ANDN32(BCe0, BCi0);
Ase0 = BCe0 ^ ANDN32(BCi0, BCo0);
Asi0 = BCi0 ^ ANDN32(BCo0, BCu0);
Aso0 = BCo0 ^ ANDN32(BCu0, BCa0);
Asu0 = BCu0 ^ ANDN32(BCa0, BCe0);
Ebi1 ^= Di1;
BCa1 = ROL32(Ebi1, 31);
Ego0 ^= Do0;
BCe1 = ROL32(Ego0, 27);
Eku0 ^= Du0;
BCi1 = ROL32(Eku0, 19);
Ema0 ^= Da0;
BCo1 = ROL32(Ema0, 20);
Ese1 ^= De1;
BCu1 = ROL32(Ese1, 1);
Asa1 = BCa1 ^ ANDN32(BCe1, BCi1);
Ase1 = BCe1 ^ ANDN32(BCi1, BCo1);
Asi1 = BCi1 ^ ANDN32(BCo1, BCu1);
Aso1 = BCo1 ^ ANDN32(BCu1, BCa1);
Asu1 = BCu1 ^ ANDN32(BCa1, BCe1);
}
while (round_consts < round_consts_end);
state[0] = Aba0;
state[1] = Aba1;
state[2] = Abe0;
state[3] = Abe1;
state[4] = Abi0;
state[5] = Abi1;
state[6] = Abo0;
state[7] = Abo1;
state[8] = Abu0;
state[9] = Abu1;
state[10] = Aga0;
state[11] = Aga1;
state[12] = Age0;
state[13] = Age1;
state[14] = Agi0;
state[15] = Agi1;
state[16] = Ago0;
state[17] = Ago1;
state[18] = Agu0;
state[19] = Agu1;
state[20] = Aka0;
state[21] = Aka1;
state[22] = Ake0;
state[23] = Ake1;
state[24] = Aki0;
state[25] = Aki1;
state[26] = Ako0;
state[27] = Ako1;
state[28] = Aku0;
state[29] = Aku1;
state[30] = Ama0;
state[31] = Ama1;
state[32] = Ame0;
state[33] = Ame1;
state[34] = Ami0;
state[35] = Ami1;
state[36] = Amo0;
state[37] = Amo1;
state[38] = Amu0;
state[39] = Amu1;
state[40] = Asa0;
state[41] = Asa1;
state[42] = Ase0;
state[43] = Ase1;
state[44] = Asi0;
state[45] = Asi1;
state[46] = Aso0;
state[47] = Aso1;
state[48] = Asu0;
state[49] = Asu1;
return sizeof(void *) * 4 + sizeof(u32) * 12 * 5 * 2;
}
diff --git a/cipher/keccak_permute_64.h b/cipher/keccak_permute_64.h
index b28c871e..cd6ac66a 100644
--- a/cipher/keccak_permute_64.h
+++ b/cipher/keccak_permute_64.h
@@ -1,385 +1,385 @@
/* keccak_permute_64.h - Keccak permute function (simple 64bit)
* Copyright (C) 2015 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* The code is based on public-domain/CC0 "keccakc1024/simple/Keccak-simple.c"
* implementation by Ronny Van Keer from SUPERCOP toolkit package.
*/
/* Function that computes the Keccak-f[1600] permutation on the given state. */
static unsigned int
KECCAK_F1600_PERMUTE_FUNC_NAME(KECCAK_STATE *hd)
{
const u64 *round_consts = _gcry_keccak_round_consts_64bit;
const u64 *round_consts_end = _gcry_keccak_round_consts_64bit + 24;
u64 Aba, Abe, Abi, Abo, Abu;
u64 Aga, Age, Agi, Ago, Agu;
u64 Aka, Ake, Aki, Ako, Aku;
u64 Ama, Ame, Ami, Amo, Amu;
u64 Asa, Ase, Asi, Aso, Asu;
u64 BCa, BCe, BCi, BCo, BCu;
u64 Da, De, Di, Do, Du;
u64 Eba, Ebe, Ebi, Ebo, Ebu;
u64 Ega, Ege, Egi, Ego, Egu;
u64 Eka, Eke, Eki, Eko, Eku;
u64 Ema, Eme, Emi, Emo, Emu;
u64 Esa, Ese, Esi, Eso, Esu;
u64 *state = hd->u.state64;
Aba = state[0];
Abe = state[1];
Abi = state[2];
Abo = state[3];
Abu = state[4];
Aga = state[5];
Age = state[6];
Agi = state[7];
Ago = state[8];
Agu = state[9];
Aka = state[10];
Ake = state[11];
Aki = state[12];
Ako = state[13];
Aku = state[14];
Ama = state[15];
Ame = state[16];
Ami = state[17];
Amo = state[18];
Amu = state[19];
Asa = state[20];
Ase = state[21];
Asi = state[22];
Aso = state[23];
Asu = state[24];
do
{
/* prepareTheta */
BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa;
BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase;
BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi;
BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso;
BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu;
/* thetaRhoPiChiIotaPrepareTheta(round , A, E) */
Da = BCu ^ ROL64(BCe, 1);
De = BCa ^ ROL64(BCi, 1);
Di = BCe ^ ROL64(BCo, 1);
Do = BCi ^ ROL64(BCu, 1);
Du = BCo ^ ROL64(BCa, 1);
Aba ^= Da;
BCa = Aba;
Age ^= De;
BCe = ROL64(Age, 44);
Aki ^= Di;
BCi = ROL64(Aki, 43);
Amo ^= Do;
BCo = ROL64(Amo, 21);
Asu ^= Du;
BCu = ROL64(Asu, 14);
Eba = BCa ^ ANDN64(BCe, BCi);
Eba ^= *(round_consts++);
Ebe = BCe ^ ANDN64(BCi, BCo);
Ebi = BCi ^ ANDN64(BCo, BCu);
Ebo = BCo ^ ANDN64(BCu, BCa);
Ebu = BCu ^ ANDN64(BCa, BCe);
Abo ^= Do;
BCa = ROL64(Abo, 28);
Agu ^= Du;
BCe = ROL64(Agu, 20);
Aka ^= Da;
BCi = ROL64(Aka, 3);
Ame ^= De;
BCo = ROL64(Ame, 45);
Asi ^= Di;
BCu = ROL64(Asi, 61);
Ega = BCa ^ ANDN64(BCe, BCi);
Ege = BCe ^ ANDN64(BCi, BCo);
Egi = BCi ^ ANDN64(BCo, BCu);
Ego = BCo ^ ANDN64(BCu, BCa);
Egu = BCu ^ ANDN64(BCa, BCe);
Abe ^= De;
BCa = ROL64(Abe, 1);
Agi ^= Di;
BCe = ROL64(Agi, 6);
Ako ^= Do;
BCi = ROL64(Ako, 25);
Amu ^= Du;
BCo = ROL64(Amu, 8);
Asa ^= Da;
BCu = ROL64(Asa, 18);
Eka = BCa ^ ANDN64(BCe, BCi);
Eke = BCe ^ ANDN64(BCi, BCo);
Eki = BCi ^ ANDN64(BCo, BCu);
Eko = BCo ^ ANDN64(BCu, BCa);
Eku = BCu ^ ANDN64(BCa, BCe);
Abu ^= Du;
BCa = ROL64(Abu, 27);
Aga ^= Da;
BCe = ROL64(Aga, 36);
Ake ^= De;
BCi = ROL64(Ake, 10);
Ami ^= Di;
BCo = ROL64(Ami, 15);
Aso ^= Do;
BCu = ROL64(Aso, 56);
Ema = BCa ^ ANDN64(BCe, BCi);
Eme = BCe ^ ANDN64(BCi, BCo);
Emi = BCi ^ ANDN64(BCo, BCu);
Emo = BCo ^ ANDN64(BCu, BCa);
Emu = BCu ^ ANDN64(BCa, BCe);
Abi ^= Di;
BCa = ROL64(Abi, 62);
Ago ^= Do;
BCe = ROL64(Ago, 55);
Aku ^= Du;
BCi = ROL64(Aku, 39);
Ama ^= Da;
BCo = ROL64(Ama, 41);
Ase ^= De;
BCu = ROL64(Ase, 2);
Esa = BCa ^ ANDN64(BCe, BCi);
Ese = BCe ^ ANDN64(BCi, BCo);
Esi = BCi ^ ANDN64(BCo, BCu);
Eso = BCo ^ ANDN64(BCu, BCa);
Esu = BCu ^ ANDN64(BCa, BCe);
/* prepareTheta */
BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa;
BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese;
BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi;
BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso;
BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu;
/* thetaRhoPiChiIotaPrepareTheta(round+1, E, A) */
Da = BCu ^ ROL64(BCe, 1);
De = BCa ^ ROL64(BCi, 1);
Di = BCe ^ ROL64(BCo, 1);
Do = BCi ^ ROL64(BCu, 1);
Du = BCo ^ ROL64(BCa, 1);
Eba ^= Da;
BCa = Eba;
Ege ^= De;
BCe = ROL64(Ege, 44);
Eki ^= Di;
BCi = ROL64(Eki, 43);
Emo ^= Do;
BCo = ROL64(Emo, 21);
Esu ^= Du;
BCu = ROL64(Esu, 14);
Aba = BCa ^ ANDN64(BCe, BCi);
Aba ^= *(round_consts++);
Abe = BCe ^ ANDN64(BCi, BCo);
Abi = BCi ^ ANDN64(BCo, BCu);
Abo = BCo ^ ANDN64(BCu, BCa);
Abu = BCu ^ ANDN64(BCa, BCe);
Ebo ^= Do;
BCa = ROL64(Ebo, 28);
Egu ^= Du;
BCe = ROL64(Egu, 20);
Eka ^= Da;
BCi = ROL64(Eka, 3);
Eme ^= De;
BCo = ROL64(Eme, 45);
Esi ^= Di;
BCu = ROL64(Esi, 61);
Aga = BCa ^ ANDN64(BCe, BCi);
Age = BCe ^ ANDN64(BCi, BCo);
Agi = BCi ^ ANDN64(BCo, BCu);
Ago = BCo ^ ANDN64(BCu, BCa);
Agu = BCu ^ ANDN64(BCa, BCe);
Ebe ^= De;
BCa = ROL64(Ebe, 1);
Egi ^= Di;
BCe = ROL64(Egi, 6);
Eko ^= Do;
BCi = ROL64(Eko, 25);
Emu ^= Du;
BCo = ROL64(Emu, 8);
Esa ^= Da;
BCu = ROL64(Esa, 18);
Aka = BCa ^ ANDN64(BCe, BCi);
Ake = BCe ^ ANDN64(BCi, BCo);
Aki = BCi ^ ANDN64(BCo, BCu);
Ako = BCo ^ ANDN64(BCu, BCa);
Aku = BCu ^ ANDN64(BCa, BCe);
Ebu ^= Du;
BCa = ROL64(Ebu, 27);
Ega ^= Da;
BCe = ROL64(Ega, 36);
Eke ^= De;
BCi = ROL64(Eke, 10);
Emi ^= Di;
BCo = ROL64(Emi, 15);
Eso ^= Do;
BCu = ROL64(Eso, 56);
Ama = BCa ^ ANDN64(BCe, BCi);
Ame = BCe ^ ANDN64(BCi, BCo);
Ami = BCi ^ ANDN64(BCo, BCu);
Amo = BCo ^ ANDN64(BCu, BCa);
Amu = BCu ^ ANDN64(BCa, BCe);
Ebi ^= Di;
BCa = ROL64(Ebi, 62);
Ego ^= Do;
BCe = ROL64(Ego, 55);
Eku ^= Du;
BCi = ROL64(Eku, 39);
Ema ^= Da;
BCo = ROL64(Ema, 41);
Ese ^= De;
BCu = ROL64(Ese, 2);
Asa = BCa ^ ANDN64(BCe, BCi);
Ase = BCe ^ ANDN64(BCi, BCo);
Asi = BCi ^ ANDN64(BCo, BCu);
Aso = BCo ^ ANDN64(BCu, BCa);
Asu = BCu ^ ANDN64(BCa, BCe);
}
while (round_consts < round_consts_end);
state[0] = Aba;
state[1] = Abe;
state[2] = Abi;
state[3] = Abo;
state[4] = Abu;
state[5] = Aga;
state[6] = Age;
state[7] = Agi;
state[8] = Ago;
state[9] = Agu;
state[10] = Aka;
state[11] = Ake;
state[12] = Aki;
state[13] = Ako;
state[14] = Aku;
state[15] = Ama;
state[16] = Ame;
state[17] = Ami;
state[18] = Amo;
state[19] = Amu;
state[20] = Asa;
state[21] = Ase;
state[22] = Asi;
state[23] = Aso;
state[24] = Asu;
return sizeof(void *) * 4 + sizeof(u64) * 12 * 5;
}
static unsigned int
KECCAK_F1600_ABSORB_FUNC_NAME(KECCAK_STATE *hd, int pos, const byte *lanes,
unsigned int nlanes, int blocklanes)
{
unsigned int burn = 0;
while (nlanes)
{
switch (blocklanes)
{
case 21:
/* SHAKE128 */
while (pos == 0 && nlanes >= 21)
{
nlanes -= 21;
absorb_lanes64_8(&hd->u.state64[0], lanes); lanes += 8 * 8;
absorb_lanes64_8(&hd->u.state64[8], lanes); lanes += 8 * 8;
absorb_lanes64_4(&hd->u.state64[16], lanes); lanes += 8 * 4;
absorb_lanes64_1(&hd->u.state64[20], lanes); lanes += 8 * 1;
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
}
break;
case 18:
/* SHA3-224 */
while (pos == 0 && nlanes >= 18)
{
nlanes -= 18;
absorb_lanes64_8(&hd->u.state64[0], lanes); lanes += 8 * 8;
absorb_lanes64_8(&hd->u.state64[8], lanes); lanes += 8 * 8;
absorb_lanes64_2(&hd->u.state64[16], lanes); lanes += 8 * 2;
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
}
break;
case 17:
/* SHA3-256 & SHAKE256 */
while (pos == 0 && nlanes >= 17)
{
nlanes -= 17;
absorb_lanes64_8(&hd->u.state64[0], lanes); lanes += 8 * 8;
absorb_lanes64_8(&hd->u.state64[8], lanes); lanes += 8 * 8;
absorb_lanes64_1(&hd->u.state64[16], lanes); lanes += 8 * 1;
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
}
break;
case 13:
/* SHA3-384 */
while (pos == 0 && nlanes >= 13)
{
nlanes -= 13;
absorb_lanes64_8(&hd->u.state64[0], lanes); lanes += 8 * 8;
absorb_lanes64_4(&hd->u.state64[8], lanes); lanes += 8 * 4;
absorb_lanes64_1(&hd->u.state64[12], lanes); lanes += 8 * 1;
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
}
break;
case 9:
/* SHA3-512 */
while (pos == 0 && nlanes >= 9)
{
nlanes -= 9;
absorb_lanes64_8(&hd->u.state64[0], lanes); lanes += 8 * 8;
absorb_lanes64_1(&hd->u.state64[8], lanes); lanes += 8 * 1;
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
}
break;
}
while (nlanes)
{
hd->u.state64[pos] ^= buf_get_le64(lanes);
lanes += 8;
nlanes--;
if (++pos == blocklanes)
{
burn = KECCAK_F1600_PERMUTE_FUNC_NAME(hd);
pos = 0;
break;
}
}
}
return burn;
}
diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c
index e42a764d..9b14e832 100644
--- a/cipher/mac-cmac.c
+++ b/cipher/mac-cmac.c
@@ -1,226 +1,226 @@
/* mac-cmac.c - CMAC glue for MAC API
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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 "./mac-internal.h"
static int
map_mac_algo_to_cipher (int mac_algo)
{
switch (mac_algo)
{
default:
return GCRY_CIPHER_NONE;
case GCRY_MAC_CMAC_AES:
return GCRY_CIPHER_AES;
case GCRY_MAC_CMAC_3DES:
return GCRY_CIPHER_3DES;
case GCRY_MAC_CMAC_CAMELLIA:
return GCRY_CIPHER_CAMELLIA128;
case GCRY_MAC_CMAC_IDEA:
return GCRY_CIPHER_IDEA;
case GCRY_MAC_CMAC_CAST5:
return GCRY_CIPHER_CAST5;
case GCRY_MAC_CMAC_BLOWFISH:
return GCRY_CIPHER_BLOWFISH;
case GCRY_MAC_CMAC_TWOFISH:
return GCRY_CIPHER_TWOFISH;
case GCRY_MAC_CMAC_SERPENT:
return GCRY_CIPHER_SERPENT128;
case GCRY_MAC_CMAC_SEED:
return GCRY_CIPHER_SEED;
case GCRY_MAC_CMAC_RFC2268:
return GCRY_CIPHER_RFC2268_128;
case GCRY_MAC_CMAC_GOST28147:
return GCRY_CIPHER_GOST28147;
}
}
static gcry_err_code_t
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 cipher_algo;
unsigned int flags;
cipher_algo = map_mac_algo_to_cipher (h->spec->algo);
flags = (secure ? GCRY_CIPHER_SECURE : 0);
err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC,
flags);
if (err)
return err;
h->u.cmac.cipher_algo = cipher_algo;
h->u.cmac.ctx = hd;
h->u.cmac.blklen = _gcry_cipher_get_algo_blklen (cipher_algo);
return 0;
}
static void
cmac_close (gcry_mac_hd_t h)
{
_gcry_cipher_close (h->u.cmac.ctx);
h->u.cmac.ctx = NULL;
}
static gcry_err_code_t
cmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
{
return _gcry_cipher_setkey (h->u.cmac.ctx, key, keylen);
}
static gcry_err_code_t
cmac_reset (gcry_mac_hd_t h)
{
return _gcry_cipher_reset (h->u.cmac.ctx);
}
static gcry_err_code_t
cmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
return _gcry_cipher_cmac_authenticate (h->u.cmac.ctx, buf, buflen);
}
static gcry_err_code_t
cmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen)
{
if (*outlen > h->u.cmac.blklen)
*outlen = h->u.cmac.blklen;
return _gcry_cipher_cmac_get_tag (h->u.cmac.ctx, outbuf, *outlen);
}
static gcry_err_code_t
cmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
return _gcry_cipher_cmac_check_tag (h->u.cmac.ctx, buf, buflen);
}
static unsigned int
cmac_get_maclen (int algo)
{
return _gcry_cipher_get_algo_blklen (map_mac_algo_to_cipher (algo));
}
static unsigned int
cmac_get_keylen (int algo)
{
return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo));
}
static gcry_mac_spec_ops_t cmac_ops = {
cmac_open,
cmac_close,
cmac_setkey,
NULL,
cmac_reset,
cmac_write,
cmac_read,
cmac_verify,
cmac_get_maclen,
cmac_get_keylen
};
#if USE_BLOWFISH
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",
&cmac_ops
};
#endif
#if USE_CAST5
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 = {
GCRY_MAC_CMAC_AES, {0, 1}, "CMAC_AES",
&cmac_ops
};
#endif
#if USE_TWOFISH
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 = {
GCRY_MAC_CMAC_SERPENT, {0, 0}, "CMAC_SERPENT",
&cmac_ops
};
#endif
#if USE_RFC2268
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 = {
GCRY_MAC_CMAC_SEED, {0, 0}, "CMAC_SEED",
&cmac_ops
};
#endif
#if USE_CAMELLIA
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 = {
GCRY_MAC_CMAC_IDEA, {0, 0}, "CMAC_IDEA",
&cmac_ops
};
#endif
#if USE_GOST28147
gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = {
GCRY_MAC_CMAC_GOST28147, {0, 0}, "CMAC_GOST28147",
&cmac_ops
};
#endif
diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c
index 9bc86d97..7a476f7c 100644
--- a/cipher/mac-gmac.c
+++ b/cipher/mac-gmac.c
@@ -1,185 +1,185 @@
/* mac-gmac.c - GMAC glue for MAC API
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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 "./mac-internal.h"
static int
map_mac_algo_to_cipher (int mac_algo)
{
switch (mac_algo)
{
default:
return GCRY_CIPHER_NONE;
case GCRY_MAC_GMAC_AES:
return GCRY_CIPHER_AES;
case GCRY_MAC_GMAC_CAMELLIA:
return GCRY_CIPHER_CAMELLIA128;
case GCRY_MAC_GMAC_TWOFISH:
return GCRY_CIPHER_TWOFISH;
case GCRY_MAC_GMAC_SERPENT:
return GCRY_CIPHER_SERPENT128;
case GCRY_MAC_GMAC_SEED:
return GCRY_CIPHER_SEED;
}
}
static gcry_err_code_t
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 cipher_algo;
unsigned int flags;
cipher_algo = map_mac_algo_to_cipher (h->spec->algo);
flags = (secure ? GCRY_CIPHER_SECURE : 0);
err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM,
flags);
if (err)
return err;
h->u.gmac.cipher_algo = cipher_algo;
h->u.gmac.ctx = hd;
return 0;
}
static void
gmac_close (gcry_mac_hd_t h)
{
_gcry_cipher_close (h->u.gmac.ctx);
h->u.gmac.ctx = NULL;
}
static gcry_err_code_t
gmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
{
return _gcry_cipher_setkey (h->u.gmac.ctx, key, keylen);
}
static gcry_err_code_t
gmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen)
{
return _gcry_cipher_setiv (h->u.gmac.ctx, iv, ivlen);
}
static gcry_err_code_t
gmac_reset (gcry_mac_hd_t h)
{
return _gcry_cipher_reset (h->u.gmac.ctx);
}
static gcry_err_code_t
gmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
return _gcry_cipher_authenticate (h->u.gmac.ctx, buf, buflen);
}
static gcry_err_code_t
gmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen)
{
if (*outlen > GCRY_GCM_BLOCK_LEN)
*outlen = GCRY_GCM_BLOCK_LEN;
return _gcry_cipher_gettag (h->u.gmac.ctx, outbuf, *outlen);
}
static gcry_err_code_t
gmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
return _gcry_cipher_checktag (h->u.gmac.ctx, buf, buflen);
}
static unsigned int
gmac_get_maclen (int algo)
{
(void)algo;
return GCRY_GCM_BLOCK_LEN;
}
static unsigned int
gmac_get_keylen (int algo)
{
return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo));
}
static gcry_mac_spec_ops_t gmac_ops = {
gmac_open,
gmac_close,
gmac_setkey,
gmac_setiv,
gmac_reset,
gmac_write,
gmac_read,
gmac_verify,
gmac_get_maclen,
gmac_get_keylen
};
#if USE_AES
gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = {
GCRY_MAC_GMAC_AES, {0, 1}, "GMAC_AES",
&gmac_ops
};
#endif
#if USE_TWOFISH
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 = {
GCRY_MAC_GMAC_SERPENT, {0, 0}, "GMAC_SERPENT",
&gmac_ops
};
#endif
#if USE_SEED
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 = {
GCRY_MAC_GMAC_CAMELLIA, {0, 0}, "GMAC_CAMELLIA",
&gmac_ops
};
#endif
diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c
index e488d03a..870c8478 100644
--- a/cipher/mac-hmac.c
+++ b/cipher/mac-hmac.c
@@ -1,396 +1,396 @@
/* mac-hmac.c - HMAC glue for MAC API
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "g10lib.h"
#include "./mac-internal.h"
#include "bufhelp.h"
static int
map_mac_algo_to_md (int mac_algo)
{
switch (mac_algo)
{
default:
return GCRY_MD_NONE;
case GCRY_MAC_HMAC_MD2:
return GCRY_MD_MD2;
case GCRY_MAC_HMAC_MD4:
return GCRY_MD_MD4;
case GCRY_MAC_HMAC_MD5:
return GCRY_MD_MD5;
case GCRY_MAC_HMAC_SHA1:
return GCRY_MD_SHA1;
case GCRY_MAC_HMAC_SHA224:
return GCRY_MD_SHA224;
case GCRY_MAC_HMAC_SHA256:
return GCRY_MD_SHA256;
case GCRY_MAC_HMAC_SHA384:
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:
return GCRY_MD_SHA3_256;
case GCRY_MAC_HMAC_SHA3_384:
return GCRY_MD_SHA3_384;
case GCRY_MAC_HMAC_SHA3_512:
return GCRY_MD_SHA3_512;
case GCRY_MAC_HMAC_RMD160:
return GCRY_MD_RMD160;
case GCRY_MAC_HMAC_TIGER1:
return GCRY_MD_TIGER1;
case GCRY_MAC_HMAC_WHIRLPOOL:
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;
}
}
static gcry_err_code_t
hmac_open (gcry_mac_hd_t h)
{
gcry_err_code_t err;
gcry_md_hd_t hd;
int secure = (h->magic == CTX_MAGIC_SECURE);
unsigned int flags;
int md_algo;
md_algo = map_mac_algo_to_md (h->spec->algo);
flags = GCRY_MD_FLAG_HMAC;
flags |= (secure ? GCRY_MD_FLAG_SECURE : 0);
err = _gcry_md_open (&hd, md_algo, flags);
if (err)
return err;
h->u.hmac.md_algo = md_algo;
h->u.hmac.md_ctx = hd;
return 0;
}
static void
hmac_close (gcry_mac_hd_t h)
{
_gcry_md_close (h->u.hmac.md_ctx);
h->u.hmac.md_ctx = NULL;
}
static gcry_err_code_t
hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
{
return _gcry_md_setkey (h->u.hmac.md_ctx, key, keylen);
}
static gcry_err_code_t
hmac_reset (gcry_mac_hd_t h)
{
_gcry_md_reset (h->u.hmac.md_ctx);
return 0;
}
static gcry_err_code_t
hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
_gcry_md_write (h->u.hmac.md_ctx, buf, buflen);
return 0;
}
static gcry_err_code_t
hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen)
{
unsigned int dlen;
const unsigned char *digest;
dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo);
digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo);
if (*outlen <= dlen)
buf_cpy (outbuf, digest, *outlen);
else
{
buf_cpy (outbuf, digest, dlen);
*outlen = dlen;
}
return 0;
}
static gcry_err_code_t
hmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
unsigned int dlen;
const unsigned char *digest;
dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo);
digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo);
if (buflen > dlen)
return GPG_ERR_INV_LENGTH;
return buf_eq_const (buf, digest, buflen) ? 0 : GPG_ERR_CHECKSUM;
}
static unsigned int
hmac_get_maclen (int algo)
{
return _gcry_md_get_algo_dlen (map_mac_algo_to_md (algo));
}
static unsigned int
hmac_get_keylen (int algo)
{
/* Return blocksize for default key length. */
switch (algo)
{
case GCRY_MD_SHA3_224:
return 1152 / 8;
case GCRY_MD_SHA3_256:
return 1088 / 8;
case GCRY_MD_SHA3_384:
return 832 / 8;
case GCRY_MD_SHA3_512:
return 576 / 8;
case GCRY_MAC_HMAC_SHA384:
case GCRY_MAC_HMAC_SHA512:
return 128;
case GCRY_MAC_HMAC_GOSTR3411_94:
return 32;
default:
return 64;
}
}
static const gcry_mac_spec_ops_t hmac_ops = {
hmac_open,
hmac_close,
hmac_setkey,
NULL,
hmac_reset,
hmac_write,
hmac_read,
hmac_verify,
hmac_get_maclen,
hmac_get_keylen
};
#if USE_SHA1
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 = {
GCRY_MAC_HMAC_SHA256, {0, 1}, "HMAC_SHA256",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_SHA512, {0, 1}, "HMAC_SHA512",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = {
GCRY_MAC_HMAC_SHA384, {0, 1}, "HMAC_SHA384",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = {
GCRY_MAC_HMAC_SHA512_256, {0, 1}, "HMAC_SHA512_256",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_SHA3_224, {0, 1}, "HMAC_SHA3_224",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_SHA3_384, {0, 1}, "HMAC_SHA3_384",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_GOSTR3411_94, {0, 0}, "HMAC_GOSTR3411_94",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_STRIBOG256, {0, 0}, "HMAC_STRIBOG256",
&hmac_ops
};
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 = {
GCRY_MAC_HMAC_WHIRLPOOL, {0, 0}, "HMAC_WHIRLPOOL",
&hmac_ops
};
#endif
#if USE_RMD160
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 = {
GCRY_MAC_HMAC_TIGER1, {0, 0}, "HMAC_TIGER",
&hmac_ops
};
#endif
#if USE_MD5
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 = {
GCRY_MAC_HMAC_MD4, {0, 0}, "HMAC_MD4",
&hmac_ops
};
#endif
#if USE_MD2
gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = {
GCRY_MAC_HMAC_MD2, {0, 0}, "HMAC_MD2",
&hmac_ops
};
#endif
#if USE_BLAKE2
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = {
GCRY_MAC_HMAC_BLAKE2B_512, {0, 0}, "HMAC_BLAKE2B_512",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = {
GCRY_MAC_HMAC_BLAKE2B_384, {0, 0}, "HMAC_BLAKE2B_384",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = {
GCRY_MAC_HMAC_BLAKE2B_256, {0, 0}, "HMAC_BLAKE2B_256",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = {
GCRY_MAC_HMAC_BLAKE2B_160, {0, 0}, "HMAC_BLAKE2B_160",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = {
GCRY_MAC_HMAC_BLAKE2S_256, {0, 0}, "HMAC_BLAKE2S_256",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = {
GCRY_MAC_HMAC_BLAKE2S_224, {0, 0}, "HMAC_BLAKE2S_224",
&hmac_ops
};
gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = {
GCRY_MAC_HMAC_BLAKE2S_160, {0, 0}, "HMAC_BLAKE2S_160",
&hmac_ops
};
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
gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = {
GCRY_MAC_HMAC_SM3, {0, 0}, "HMAC_SM3",
&hmac_ops
};
#endif
diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h
index 03f5b8da..de1dc201 100644
--- a/cipher/mac-internal.h
+++ b/cipher/mac-internal.h
@@ -1,256 +1,256 @@
/* mac-internal.h - Internal defs for mac.c
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "g10lib.h"
/* The data object used to hold a handle to an encryption object. */
struct gcry_mac_handle;
/* The data object used to hold poly1305-mac context. */
struct poly1305mac_context_s;
/*
*
* Message authentication code related definitions.
*
*/
/* Magic values for the context structure. */
#define CTX_MAGIC_NORMAL 0x59d9b8af
#define CTX_MAGIC_SECURE 0x12c27cd0
/* MAC module functions. */
typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h);
typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h);
typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h,
const unsigned char *key,
size_t keylen);
typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h,
const unsigned char *iv,
size_t ivlen);
typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h);
typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h,
const unsigned char *inbuf,
size_t inlen);
typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h,
unsigned char *outbuf,
size_t *outlen);
typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h,
const unsigned char *inbuf,
size_t inlen);
typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo);
typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo);
typedef struct gcry_mac_spec_ops
{
gcry_mac_open_func_t open;
gcry_mac_close_func_t close;
gcry_mac_setkey_func_t setkey;
gcry_mac_setiv_func_t setiv;
gcry_mac_reset_func_t reset;
gcry_mac_write_func_t write;
gcry_mac_read_func_t read;
gcry_mac_verify_func_t verify;
gcry_mac_get_maclen_func_t get_maclen;
gcry_mac_get_keylen_func_t get_keylen;
} gcry_mac_spec_ops_t;
/* Module specification structure for message authentication codes. */
typedef struct gcry_mac_spec
{
int algo;
struct {
unsigned int disabled:1;
unsigned int fips:1;
} flags;
const char *name;
const gcry_mac_spec_ops_t *ops;
} gcry_mac_spec_t;
/* The handle structure. */
struct gcry_mac_handle
{
int magic;
int algo;
const gcry_mac_spec_t *spec;
gcry_ctx_t gcry_ctx;
union {
struct {
gcry_md_hd_t md_ctx;
int md_algo;
} hmac;
struct {
gcry_cipher_hd_t ctx;
int cipher_algo;
unsigned int blklen;
} cmac;
struct {
gcry_cipher_hd_t ctx;
int cipher_algo;
} gmac;
struct {
struct poly1305mac_context_s *ctx;
} poly1305mac;
} u;
};
/*
* The HMAC algorithm specifications (mac-hmac.c).
*/
#if USE_SHA1
extern 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;
#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 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224;
extern 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;
#endif
#ifdef USE_GOST_R_3411_94
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94;
extern 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;
#endif
#if USE_WHIRLPOOL
extern 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;
#endif
#if USE_TIGER
extern 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;
#endif
#if USE_MD4
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4;
#endif
#if USE_BLAKE2
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160;
extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128;
#endif
#if USE_SM3
extern 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;
#endif
#if USE_DES
extern 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;
#endif
#if USE_AES
extern 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;
#endif
#if USE_SERPENT
extern 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;
#endif
#if USE_SEED
extern 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;
#endif
#ifdef USE_IDEA
extern 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;
#endif
/*
* The GMAC algorithm specifications (mac-gmac.c).
*/
#if USE_AES
extern 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;
#endif
#if USE_SERPENT
extern 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;
#endif
#if USE_CAMELLIA
extern 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;
#if USE_AES
extern 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;
#endif
#if USE_TWOFISH
extern 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;
#endif
#if USE_SEED
extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed;
#endif
diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c
index b80f87db..6841986f 100644
--- a/cipher/mac-poly1305.c
+++ b/cipher/mac-poly1305.c
@@ -1,362 +1,362 @@
/* mac-poly1305.c - Poly1305 based MACs
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "g10lib.h"
#include "mac-internal.h"
#include "poly1305-internal.h"
struct poly1305mac_context_s {
poly1305_context_t ctx;
gcry_cipher_hd_t hd;
struct {
unsigned int key_set:1;
unsigned int nonce_set:1;
unsigned int tag:1;
} marks;
byte tag[POLY1305_TAGLEN];
byte key[POLY1305_KEYLEN];
};
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);
unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0);
gcry_err_code_t err;
int cipher_algo;
if (secure)
mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx));
else
mac_ctx = xtrycalloc (1, sizeof(*mac_ctx));
if (!mac_ctx)
return gpg_err_code_from_syserror ();
h->u.poly1305mac.ctx = mac_ctx;
switch (h->spec->algo)
{
default:
/* already checked. */
case GCRY_MAC_POLY1305:
/* plain Poly1305. */
cipher_algo = -1;
return 0;
case GCRY_MAC_POLY1305_AES:
cipher_algo = GCRY_CIPHER_AES;
break;
case GCRY_MAC_POLY1305_CAMELLIA:
cipher_algo = GCRY_CIPHER_CAMELLIA128;
break;
case GCRY_MAC_POLY1305_TWOFISH:
cipher_algo = GCRY_CIPHER_TWOFISH;
break;
case GCRY_MAC_POLY1305_SERPENT:
cipher_algo = GCRY_CIPHER_SERPENT128;
break;
case GCRY_MAC_POLY1305_SEED:
cipher_algo = GCRY_CIPHER_SEED;
break;
}
err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo,
GCRY_CIPHER_MODE_ECB, flags);
if (err)
goto err_free;
return 0;
err_free:
xfree(h->u.poly1305mac.ctx);
return err;
}
static void
poly1305mac_close (gcry_mac_hd_t h)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
if (h->spec->algo != GCRY_MAC_POLY1305)
_gcry_cipher_close (mac_ctx->hd);
xfree(mac_ctx);
}
static gcry_err_code_t
poly1305mac_prepare_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
size_t block_keylen = keylen - 16;
/* Need at least 16 + 1 byte key. */
if (keylen <= 16)
return GPG_ERR_INV_KEYLEN;
/* For Poly1305-AES, first part of key is passed to Poly1305 as is. */
memcpy (mac_ctx->key, key + block_keylen, 16);
/* Remaining part is used as key for the block cipher. */
return _gcry_cipher_setkey (mac_ctx->hd, key, block_keylen);
}
static gcry_err_code_t
poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
gcry_err_code_t err;
memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx));
memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag));
memset(&mac_ctx->key, 0, sizeof(mac_ctx->key));
mac_ctx->marks.key_set = 0;
mac_ctx->marks.nonce_set = 0;
mac_ctx->marks.tag = 0;
if (h->spec->algo != GCRY_MAC_POLY1305)
{
err = poly1305mac_prepare_key (h, key, keylen);
if (err)
return err;
/* Poly1305-AES/etc also need nonce. */
mac_ctx->marks.key_set = 1;
mac_ctx->marks.nonce_set = 0;
}
else
{
/* For plain Poly1305, key is the nonce and setup is complete now. */
if (keylen != POLY1305_KEYLEN)
return GPG_ERR_INV_KEYLEN;
memcpy (mac_ctx->key, key, keylen);
err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN);
if (err)
{
memset(&mac_ctx->key, 0, sizeof(mac_ctx->key));
return err;
}
mac_ctx->marks.key_set = 1;
mac_ctx->marks.nonce_set = 1;
}
return 0;
}
static gcry_err_code_t
poly1305mac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
gcry_err_code_t err;
if (h->spec->algo == GCRY_MAC_POLY1305)
return GPG_ERR_INV_ARG;
if (ivlen != 16)
return GPG_ERR_INV_ARG;
if (!mac_ctx->marks.key_set)
return 0;
memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx));
memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag));
mac_ctx->marks.nonce_set = 0;
mac_ctx->marks.tag = 0;
/* Prepare second part of the poly1305 key. */
err = _gcry_cipher_encrypt (mac_ctx->hd, mac_ctx->key + 16, 16, iv, 16);
if (err)
return err;
err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN);
if (err)
return err;
mac_ctx->marks.nonce_set = 1;
return 0;
}
static gcry_err_code_t
poly1305mac_reset (gcry_mac_hd_t h)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set)
return GPG_ERR_INV_STATE;
memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx));
memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag));
mac_ctx->marks.key_set = 1;
mac_ctx->marks.nonce_set = 1;
mac_ctx->marks.tag = 0;
return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN);
}
static gcry_err_code_t
poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set ||
mac_ctx->marks.tag)
return GPG_ERR_INV_STATE;
_gcry_poly1305_update (&mac_ctx->ctx, buf, buflen);
return 0;
}
static gcry_err_code_t
poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set)
return GPG_ERR_INV_STATE;
if (!mac_ctx->marks.tag)
{
_gcry_poly1305_finish(&mac_ctx->ctx, mac_ctx->tag);
memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx));
mac_ctx->marks.tag = 1;
}
if (*outlen == 0)
return 0;
if (*outlen <= POLY1305_TAGLEN)
buf_cpy (outbuf, mac_ctx->tag, *outlen);
else
{
buf_cpy (outbuf, mac_ctx->tag, POLY1305_TAGLEN);
*outlen = POLY1305_TAGLEN;
}
return 0;
}
static gcry_err_code_t
poly1305mac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
{
struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx;
gcry_err_code_t err;
size_t outlen = 0;
/* Check and finalize tag. */
err = poly1305mac_read(h, NULL, &outlen);
if (err)
return err;
if (buflen > POLY1305_TAGLEN)
return GPG_ERR_INV_LENGTH;
return buf_eq_const (buf, mac_ctx->tag, buflen) ? 0 : GPG_ERR_CHECKSUM;
}
static unsigned int
poly1305mac_get_maclen (int algo)
{
(void)algo;
return POLY1305_TAGLEN;
}
static unsigned int
poly1305mac_get_keylen (int algo)
{
(void)algo;
return POLY1305_KEYLEN;
}
static gcry_mac_spec_ops_t poly1305mac_ops = {
poly1305mac_open,
poly1305mac_close,
poly1305mac_setkey,
poly1305mac_setiv,
poly1305mac_reset,
poly1305mac_write,
poly1305mac_read,
poly1305mac_verify,
poly1305mac_get_maclen,
poly1305mac_get_keylen
};
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 = {
GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES",
&poly1305mac_ops
};
#endif
#if USE_CAMELLIA
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 = {
GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH",
&poly1305mac_ops
};
#endif
#if USE_SERPENT
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 = {
GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED",
&poly1305mac_ops
};
#endif
diff --git a/cipher/mac.c b/cipher/mac.c
index 0bbac3e4..9e96d4a6 100644
--- a/cipher/mac.c
+++ b/cipher/mac.c
@@ -1,763 +1,763 @@
/* mac.c - message authentication code dispatcher
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "g10lib.h"
#include "mac-internal.h"
/* This is the list of the digest implementations included in
libgcrypt. */
static gcry_mac_spec_t * const mac_list[] = {
#if USE_SHA1
&_gcry_mac_type_spec_hmac_sha1,
#endif
#if USE_SHA256
&_gcry_mac_type_spec_hmac_sha256,
&_gcry_mac_type_spec_hmac_sha224,
#endif
#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,
&_gcry_mac_type_spec_hmac_sha3_256,
&_gcry_mac_type_spec_hmac_sha3_384,
&_gcry_mac_type_spec_hmac_sha3_512,
#endif
#ifdef 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
&_gcry_mac_type_spec_hmac_stribog256,
&_gcry_mac_type_spec_hmac_stribog512,
#endif
#if USE_WHIRLPOOL
&_gcry_mac_type_spec_hmac_whirlpool,
#endif
#if USE_RMD160
&_gcry_mac_type_spec_hmac_rmd160,
#endif
#if USE_TIGER
&_gcry_mac_type_spec_hmac_tiger1,
#endif
#if USE_MD5
&_gcry_mac_type_spec_hmac_md5,
#endif
#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
#if USE_DES
&_gcry_mac_type_spec_cmac_tripledes,
#endif
#if USE_CAST5
&_gcry_mac_type_spec_cmac_cast5,
#endif
#if USE_AES
&_gcry_mac_type_spec_cmac_aes,
&_gcry_mac_type_spec_gmac_aes,
&_gcry_mac_type_spec_poly1305mac_aes,
#endif
#if USE_TWOFISH
&_gcry_mac_type_spec_cmac_twofish,
&_gcry_mac_type_spec_gmac_twofish,
&_gcry_mac_type_spec_poly1305mac_twofish,
#endif
#if USE_SERPENT
&_gcry_mac_type_spec_cmac_serpent,
&_gcry_mac_type_spec_gmac_serpent,
&_gcry_mac_type_spec_poly1305mac_serpent,
#endif
#if USE_RFC2268
&_gcry_mac_type_spec_cmac_rfc2268,
#endif
#if USE_SEED
&_gcry_mac_type_spec_cmac_seed,
&_gcry_mac_type_spec_gmac_seed,
&_gcry_mac_type_spec_poly1305mac_seed,
#endif
#if USE_CAMELLIA
&_gcry_mac_type_spec_cmac_camellia,
&_gcry_mac_type_spec_gmac_camellia,
&_gcry_mac_type_spec_poly1305mac_camellia,
#endif
#ifdef USE_IDEA
&_gcry_mac_type_spec_cmac_idea,
#endif
#if USE_GOST28147
&_gcry_mac_type_spec_cmac_gost28147,
#endif
&_gcry_mac_type_spec_poly1305mac,
NULL,
};
/* HMAC implementations start with index 101 (enum gcry_mac_algos) */
static 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
#ifdef USE_GOST_R_3411_94
&_gcry_mac_type_spec_hmac_gost3411_94,
#else
NULL,
#endif
#ifdef 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
#ifdef 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 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
#ifdef USE_IDEA
&_gcry_mac_type_spec_cmac_idea,
#else
NULL,
#endif
#if USE_GOST28147
&_gcry_mac_type_spec_cmac_gost28147
#else
NULL
#endif
};
/* GMAC implementations start with index 401 (enum gcry_mac_algos) */
static 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 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;
}
/* Return the spec structure for the MAC algorithm ALGO. For an
unknown algorithm NULL is returned. */
static gcry_mac_spec_t *
spec_from_algo (int algo)
{
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 (spec)
gcry_assert (spec->algo == algo);
return spec;
}
/* Lookup a mac's spec by its name. */
static gcry_mac_spec_t *
spec_from_name (const char *name)
{
gcry_mac_spec_t *spec;
int idx;
for (idx = 0; (spec = mac_list[idx]); idx++)
if (!stricmp (name, spec->name))
return spec;
return NULL;
}
/****************
* Map a string to the mac algo
*/
int
_gcry_mac_map_name (const char *string)
{
gcry_mac_spec_t *spec;
if (!string)
return 0;
/* Not found, search a matching mac name. */
spec = spec_from_name (string);
if (spec)
return spec->algo;
return 0;
}
/****************
* This function simply returns the name of the algorithm or some constant
* string when there is no algo. It will never return NULL.
* Use the macro gcry_mac_test_algo() to check whether the algorithm
* is valid.
*/
const char *
_gcry_mac_algo_name (int algorithm)
{
gcry_mac_spec_t *spec;
spec = spec_from_algo (algorithm);
return spec ? spec->name : "?";
}
static gcry_err_code_t
check_mac_algo (int algorithm)
{
gcry_mac_spec_t *spec;
spec = spec_from_algo (algorithm);
if (spec && !spec->flags.disabled)
return 0;
return GPG_ERR_MAC_ALGO;
}
/****************
* Open a message digest handle for use with algorithm ALGO.
*/
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;
gcry_err_code_t err;
gcry_mac_hd_t h;
spec = spec_from_algo (algo);
if (!spec)
return GPG_ERR_MAC_ALGO;
else if (spec->flags.disabled)
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 ||
!spec->ops->read || !spec->ops->verify || !spec->ops->reset)
return GPG_ERR_MAC_ALGO;
if (secure)
h = xtrycalloc_secure (1, sizeof (*h));
else
h = xtrycalloc (1, sizeof (*h));
if (!h)
return gpg_err_code_from_syserror ();
h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
h->spec = spec;
h->algo = algo;
h->gcry_ctx = ctx;
err = h->spec->ops->open (h);
if (err)
xfree (h);
else
*hd = h;
return err;
}
static gcry_err_code_t
mac_reset (gcry_mac_hd_t hd)
{
if (hd->spec->ops->reset)
return hd->spec->ops->reset (hd);
return 0;
}
static void
mac_close (gcry_mac_hd_t hd)
{
if (hd->spec->ops->close)
hd->spec->ops->close (hd);
wipememory (hd, sizeof (*hd));
xfree (hd);
}
static gcry_err_code_t
mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
{
if (!hd->spec->ops->setkey)
return GPG_ERR_INV_ARG;
if (keylen > 0 && !key)
return GPG_ERR_INV_ARG;
return hd->spec->ops->setkey (hd, key, keylen);
}
static gcry_err_code_t
mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
{
if (!hd->spec->ops->setiv)
return GPG_ERR_INV_ARG;
if (ivlen > 0 && !iv)
return GPG_ERR_INV_ARG;
return hd->spec->ops->setiv (hd, iv, ivlen);
}
static gcry_err_code_t
mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
{
if (!hd->spec->ops->write)
return GPG_ERR_INV_ARG;
if (inlen > 0 && !inbuf)
return GPG_ERR_INV_ARG;
return hd->spec->ops->write (hd, inbuf, inlen);
}
static gcry_err_code_t
mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
{
if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read)
return GPG_ERR_INV_ARG;
return hd->spec->ops->read (hd, outbuf, outlen);
}
static gcry_err_code_t
mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
{
if (!buf || buflen == 0 || !hd->spec->ops->verify)
return GPG_ERR_INV_ARG;
return hd->spec->ops->verify (hd, buf, buflen);
}
/* Create a MAC object for algorithm ALGO. FLAGS may be
given as an bitwise OR of the gcry_mac_flags values.
H is guaranteed to be a valid handle or NULL on error. */
gpg_err_code_t
_gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags,
gcry_ctx_t ctx)
{
gcry_err_code_t rc;
gcry_mac_hd_t hd = NULL;
if ((flags & ~GCRY_MAC_FLAG_SECURE))
rc = GPG_ERR_INV_ARG;
else
rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx);
*h = rc ? NULL : hd;
return rc;
}
void
_gcry_mac_close (gcry_mac_hd_t hd)
{
if (hd)
mac_close (hd);
}
gcry_err_code_t
_gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
{
return mac_setkey (hd, key, keylen);
}
gcry_err_code_t
_gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
{
return mac_setiv (hd, iv, ivlen);
}
gcry_err_code_t
_gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen)
{
return mac_write (hd, inbuf, inlen);
}
gcry_err_code_t
_gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen)
{
return mac_read (hd, outbuf, outlen);
}
gcry_err_code_t
_gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
{
return mac_verify (hd, buf, buflen);
}
int
_gcry_mac_get_algo (gcry_mac_hd_t hd)
{
return hd->algo;
}
unsigned int
_gcry_mac_get_algo_maclen (int algo)
{
gcry_mac_spec_t *spec;
spec = spec_from_algo (algo);
if (!spec || !spec->ops || !spec->ops->get_maclen)
return 0;
return spec->ops->get_maclen (algo);
}
unsigned int
_gcry_mac_get_algo_keylen (int algo)
{
gcry_mac_spec_t *spec;
spec = spec_from_algo (algo);
if (!spec || !spec->ops || !spec->ops->get_keylen)
return 0;
return spec->ops->get_keylen (algo);
}
gcry_err_code_t
_gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
{
gcry_err_code_t rc;
/* Currently not used. */
(void) hd;
(void) buffer;
(void) buflen;
switch (cmd)
{
case GCRYCTL_RESET:
rc = mac_reset (hd);
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Return information about the given MAC algorithm ALGO.
GCRYCTL_TEST_ALGO:
Returns 0 if the specified algorithm ALGO is available for use.
BUFFER and NBYTES must be zero.
Note: Because this function is in most cases used to return an
integer value, we can make it easier for the caller to just look at
the return value. The caller will in all cases consult the value
and thereby detecting whether a error occurred or not (i.e. while
checking the block size)
*/
gcry_err_code_t
_gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
{
gcry_err_code_t rc = 0;
unsigned int ui;
switch (what)
{
case GCRYCTL_GET_KEYLEN:
if (buffer || (!nbytes))
rc = GPG_ERR_INV_ARG;
else
{
ui = _gcry_mac_get_algo_keylen (algo);
if (ui > 0)
*nbytes = (size_t) ui;
else
/* The only reason for an error is an invalid algo. */
rc = GPG_ERR_MAC_ALGO;
}
break;
case GCRYCTL_TEST_ALGO:
if (buffer || nbytes)
rc = GPG_ERR_INV_ARG;
else
rc = check_mac_algo (algo);
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
diff --git a/cipher/md.c b/cipher/md.c
index 6ca390ff..446879b1 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -1,1639 +1,1639 @@
/* md.c - message digest dispatcher
* Copyright (C) 1998, 1999, 2002, 2003, 2006,
* 2008 Free Software Foundation, Inc.
* Copyright (C) 2013, 2014 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/>.
+ * License along with this program; if not, see <https://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"
/* This is the list of the digest implementations included in
libgcrypt. */
static gcry_md_spec_t * const digest_list[] =
{
#if USE_CRC
&_gcry_digest_spec_crc32,
&_gcry_digest_spec_crc32_rfc1510,
&_gcry_digest_spec_crc24_rfc2440,
#endif
#if USE_SHA1
&_gcry_digest_spec_sha1,
#endif
#if USE_SHA256
&_gcry_digest_spec_sha256,
&_gcry_digest_spec_sha224,
#endif
#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,
&_gcry_digest_spec_sha3_256,
&_gcry_digest_spec_sha3_384,
&_gcry_digest_spec_sha3_512,
&_gcry_digest_spec_shake128,
&_gcry_digest_spec_shake256,
#endif
#if USE_GOST_R_3411_94
&_gcry_digest_spec_gost3411_94,
&_gcry_digest_spec_gost3411_cp,
#endif
#if USE_GOST_R_3411_12
&_gcry_digest_spec_stribog_256,
&_gcry_digest_spec_stribog_512,
#endif
#if USE_WHIRLPOOL
&_gcry_digest_spec_whirlpool,
#endif
#if USE_RMD160
&_gcry_digest_spec_rmd160,
#endif
#if USE_TIGER
&_gcry_digest_spec_tiger,
&_gcry_digest_spec_tiger1,
&_gcry_digest_spec_tiger2,
#endif
#if USE_MD5
&_gcry_digest_spec_md5,
#endif
#if USE_MD4
&_gcry_digest_spec_md4,
#endif
#if USE_MD2
&_gcry_digest_spec_md2,
#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,
#endif
#if USE_SM3
&_gcry_digest_spec_sm3,
#endif
NULL
};
/* Digest implementations starting with index 0 (enum gcry_md_algos) */
static 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 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;
struct gcry_md_list *next;
size_t actual_struct_size; /* Allocated size of this structure. */
PROPERLY_ALIGNED_TYPE context;
} GcryDigestEntry;
/* This structure is put right after the gcry_md_hd_t buffer, so that
* only one memory block is needed. */
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 finalized:1;
unsigned int bugemu1:1;
unsigned int hmac:1;
} flags;
GcryDigestEntry *list;
};
#define CTX_MAGIC_NORMAL 0x11071961
#define CTX_MAGIC_SECURE 0x16917011
static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
static void md_close (gcry_md_hd_t a);
static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
static byte *md_read( gcry_md_hd_t a, int algo );
static int md_get_algo( gcry_md_hd_t a );
static int md_digest_length( int algo );
static void md_start_debug ( gcry_md_hd_t a, const char *suffix );
static void md_stop_debug ( gcry_md_hd_t a );
static int
map_algo (int algo)
{
return algo;
}
/* Return the spec structure for the hash algorithm ALGO. For an
unknown algorithm NULL is returned. */
static gcry_md_spec_t *
spec_from_algo (int algo)
{
gcry_md_spec_t *spec = NULL;
algo = map_algo (algo);
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 *
spec_from_name (const char *name)
{
gcry_md_spec_t *spec;
int idx;
for (idx=0; (spec = digest_list[idx]); idx++)
{
if (!stricmp (name, spec->name))
return spec;
}
return NULL;
}
/* Lookup a hash's spec by its OID. */
static gcry_md_spec_t *
spec_from_oid (const char *oid)
{
gcry_md_spec_t *spec;
gcry_md_oid_spec_t *oid_specs;
int idx, j;
for (idx=0; (spec = digest_list[idx]); idx++)
{
oid_specs = spec->oids;
if (oid_specs)
{
for (j = 0; oid_specs[j].oidstring; j++)
if (!stricmp (oid, oid_specs[j].oidstring))
return spec;
}
}
return NULL;
}
static gcry_md_spec_t *
search_oid (const char *oid, gcry_md_oid_spec_t *oid_spec)
{
gcry_md_spec_t *spec;
int i;
if (!oid)
return NULL;
if (!strncmp (oid, "oid.", 4) || !strncmp (oid, "OID.", 4))
oid += 4;
spec = spec_from_oid (oid);
if (spec && spec->oids)
{
for (i = 0; spec->oids[i].oidstring; i++)
if (!stricmp (oid, spec->oids[i].oidstring))
{
if (oid_spec)
*oid_spec = spec->oids[i];
return spec;
}
}
return NULL;
}
/****************
* Map a string to the digest algo
*/
int
_gcry_md_map_name (const char *string)
{
gcry_md_spec_t *spec;
if (!string)
return 0;
/* If the string starts with a digit (optionally prefixed with
either "OID." or "oid."), we first look into our table of ASN.1
object identifiers to figure out the algorithm */
spec = search_oid (string, NULL);
if (spec)
return spec->algo;
/* Not found, search a matching digest name. */
spec = spec_from_name (string);
if (spec)
return spec->algo;
return 0;
}
/****************
* This function simply returns the name of the algorithm or some constant
* string when there is no algo. It will never return NULL.
* Use the macro gcry_md_test_algo() to check whether the algorithm
* is valid.
*/
const char *
_gcry_md_algo_name (int algorithm)
{
gcry_md_spec_t *spec;
spec = spec_from_algo (algorithm);
return spec ? spec->name : "?";
}
static gcry_err_code_t
check_digest_algo (int algorithm)
{
gcry_md_spec_t *spec;
spec = spec_from_algo (algorithm);
if (spec && !spec->flags.disabled)
return 0;
return GPG_ERR_DIGEST_ALGO;
}
/****************
* Open a message digest handle for use with algorithm ALGO.
* More algorithms may be added by md_enable(). The initial algorithm
* may be 0.
*/
static gcry_err_code_t
md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
{
gcry_err_code_t err = 0;
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;
/* Allocate a memory area to hold the caller visible buffer with it's
* control information and the data required by this module. Set the
* context pointer at the beginning to this area.
* We have to use this strange scheme because we want to hide the
* internal data but have a variable sized buffer.
*
* +---+------+---........------+-------------+
* !ctx! bctl ! buffer ! private !
* +---+------+---........------+-------------+
* ! ^
* !---------------------------!
*
* We have to make sure that private is well aligned.
*/
n = sizeof (struct gcry_md_handle) + bufsize;
n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
/ sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
/* Allocate and set the Context pointer to the private data */
if (secure)
hd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
else
hd = xtrymalloc (n + sizeof (struct gcry_md_context));
if (! hd)
err = gpg_err_code_from_errno (errno);
if (! err)
{
hd->ctx = ctx = (void *) ((char *) hd + n);
/* Setup the globally visible data (bctl in the diagram).*/
hd->bufsize = n - sizeof (struct gcry_md_handle) + 1;
hd->bufpos = 0;
/* Initialize the private data. */
memset (hd->ctx, 0, sizeof *hd->ctx);
ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
ctx->flags.secure = secure;
ctx->flags.hmac = hmac;
ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
}
if (! err)
{
/* Hmmm, should we really do that? - yes [-wk] */
_gcry_fast_random_poll ();
if (algo)
{
err = md_enable (hd, algo);
if (err)
md_close (hd);
}
}
if (! err)
*h = hd;
return err;
}
/* Create a message digest object for algorithm ALGO. FLAGS may be
given as an bitwise OR of the gcry_md_flags values. ALGO may be
given as 0 if the algorithms to be used are later set using
gcry_md_enable. H is guaranteed to be a valid handle or NULL on
error. */
gcry_err_code_t
_gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
{
gcry_err_code_t rc;
gcry_md_hd_t hd;
if ((flags & ~(GCRY_MD_FLAG_SECURE
| GCRY_MD_FLAG_HMAC
| GCRY_MD_FLAG_BUGEMU1)))
rc = GPG_ERR_INV_ARG;
else
rc = md_open (&hd, algo, flags);
*h = rc? NULL : hd;
return rc;
}
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;
GcryDigestEntry *entry;
gcry_err_code_t err = 0;
for (entry = h->list; entry; entry = entry->next)
if (entry->spec->algo == algorithm)
return 0; /* Already enabled */
spec = spec_from_algo (algorithm);
if (!spec)
{
log_debug ("md_enable: algorithm %d not available\n", algorithm);
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;
}
}
if (!err && h->flags.hmac && spec->read == NULL)
{
/* Expandable output function cannot act as part of HMAC. */
err = GPG_ERR_DIGEST_ALGO;
}
if (!err)
{
size_t size = (sizeof (*entry)
+ spec->contextsize * (h->flags.hmac? 3 : 1)
- sizeof (entry->context));
/* And allocate a new list entry. */
if (h->flags.secure)
entry = xtrymalloc_secure (size);
else
entry = xtrymalloc (size);
if (! entry)
err = gpg_err_code_from_errno (errno);
else
{
entry->spec = spec;
entry->next = h->list;
entry->actual_struct_size = size;
h->list = entry;
/* And init this instance. */
entry->spec->init (&entry->context.c,
h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
}
}
return err;
}
gcry_err_code_t
_gcry_md_enable (gcry_md_hd_t hd, int algorithm)
{
return md_enable (hd, algorithm);
}
static gcry_err_code_t
md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
{
gcry_err_code_t err = 0;
struct gcry_md_context *a = ahd->ctx;
struct gcry_md_context *b;
GcryDigestEntry *ar, *br;
gcry_md_hd_t bhd;
size_t n;
if (ahd->bufpos)
md_write (ahd, NULL, 0);
n = (char *) ahd->ctx - (char *) ahd;
if (a->flags.secure)
bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
else
bhd = xtrymalloc (n + sizeof (struct gcry_md_context));
if (!bhd)
{
err = gpg_err_code_from_syserror ();
goto leave;
}
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));
bhd->bufsize = ahd->bufsize;
bhd->bufpos = 0;
gcry_assert (! ahd->bufpos);
memcpy (b, a, sizeof *a);
b->list = NULL;
b->debug = NULL;
/* Copy the complete list of algorithms. The copied list is
reversed, but that doesn't matter. */
for (ar = a->list; ar; ar = ar->next)
{
if (a->flags.secure)
br = xtrymalloc_secure (ar->actual_struct_size);
else
br = xtrymalloc (ar->actual_struct_size);
if (!br)
{
err = gpg_err_code_from_syserror ();
md_close (bhd);
goto leave;
}
memcpy (br, ar, ar->actual_struct_size);
br->next = b->list;
b->list = br;
}
if (a->debug)
md_start_debug (bhd, "unknown");
*b_hd = bhd;
leave:
return err;
}
gcry_err_code_t
_gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
{
gcry_err_code_t rc;
rc = md_copy (hd, handle);
if (rc)
*handle = NULL;
return rc;
}
/*
* Reset all contexts and discard any buffered stuff. This may be used
* instead of a md_close(); md_open().
*/
void
_gcry_md_reset (gcry_md_hd_t a)
{
GcryDigestEntry *r;
/* Note: We allow this even in fips non operational mode. */
a->bufpos = a->ctx->flags.finalized = 0;
if (a->ctx->flags.hmac)
for (r = a->ctx->list; r; r = r->next)
{
memcpy (r->context.c, r->context.c + 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,
a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
}
}
static void
md_close (gcry_md_hd_t a)
{
GcryDigestEntry *r, *r2;
if (! a)
return;
if (a->ctx->debug)
md_stop_debug (a);
for (r = a->ctx->list; r; r = r2)
{
r2 = r->next;
wipememory (r, r->actual_struct_size);
xfree (r);
}
wipememory (a, a->ctx->actual_handle_size);
xfree(a);
}
void
_gcry_md_close (gcry_md_hd_t hd)
{
/* Note: We allow this even in fips non operational mode. */
md_close (hd);
}
static void
md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
{
GcryDigestEntry *r;
if (a->ctx->debug)
{
if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1)
BUG();
if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1)
BUG();
}
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);
}
a->bufpos = 0;
}
/* Note that this function may be used after finalize and read to keep
on writing to the transform function so to mitigate timing
attacks. */
void
_gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen)
{
md_write (hd, inbuf, inlen);
}
static void
md_final (gcry_md_hd_t a)
{
GcryDigestEntry *r;
if (a->ctx->flags.finalized)
return;
if (a->bufpos)
md_write (a, NULL, 0);
for (r = a->ctx->list; r; r = r->next)
(*r->spec->final) (&r->context.c);
a->ctx->flags.finalized = 1;
if (!a->ctx->flags.hmac)
return;
for (r = a->ctx->list; r; r = r->next)
{
byte *p;
size_t dlen = r->spec->mdlen;
byte *hash;
gcry_err_code_t err;
if (r->spec->read == NULL)
continue;
p = r->spec->read (&r->context.c);
if (a->ctx->flags.secure)
hash = xtrymalloc_secure (dlen);
else
hash = xtrymalloc (dlen);
if (!hash)
{
err = gpg_err_code_from_errno (errno);
_gcry_fatal_error (err, NULL);
}
memcpy (hash, p, dlen);
memcpy (r->context.c, r->context.c + r->spec->contextsize * 2,
r->spec->contextsize);
(*r->spec->write) (&r->context.c, hash, dlen);
(*r->spec->final) (&r->context.c);
xfree (hash);
}
}
static gcry_err_code_t
md_setkey (gcry_md_hd_t h, const unsigned char *key, size_t keylen)
{
gcry_err_code_t rc = 0;
GcryDigestEntry *r;
int algo_had_setkey = 0;
if (!h->ctx->list)
return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
if (h->ctx->flags.hmac)
return GPG_ERR_DIGEST_ALGO; /* Tried md_setkey for HMAC md. */
for (r = h->ctx->list; r; r = r->next)
{
switch (r->spec->algo)
{
#if USE_BLAKE2
/* TODO? add spec->init_with_key? */
case GCRY_MD_BLAKE2B_512:
case GCRY_MD_BLAKE2B_384:
case GCRY_MD_BLAKE2B_256:
case GCRY_MD_BLAKE2B_160:
case GCRY_MD_BLAKE2S_256:
case GCRY_MD_BLAKE2S_224:
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,
h->ctx->flags.bugemu1
? GCRY_MD_FLAG_BUGEMU1:0,
key, keylen, r->spec->algo);
break;
#endif
default:
rc = GPG_ERR_DIGEST_ALGO;
break;
}
if (rc)
break;
}
if (rc && !algo_had_setkey)
{
/* None of algorithms had setkey implementation, so contexts were not
* modified. Just return error. */
return rc;
}
else if (rc && algo_had_setkey)
{
/* Some of the contexts have been modified, but got error. Reset
* all contexts. */
_gcry_md_reset (h);
return rc;
}
/* Successful md_setkey implies reset. */
h->bufpos = h->ctx->flags.finalized = 0;
return 0;
}
static gcry_err_code_t
prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
{
GcryDigestEntry *r;
if (!a->ctx->list)
return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
if (!a->ctx->flags.hmac)
return GPG_ERR_DIGEST_ALGO; /* Tried prepare_macpads for non-HMAC md. */
for (r = a->ctx->list; r; r = r->next)
{
const unsigned char *k;
size_t k_len;
unsigned char *key_allocated = NULL;
int macpad_Bsize;
int i;
switch (r->spec->algo)
{
/* TODO: add spec->blocksize */
case GCRY_MD_SHA3_224:
macpad_Bsize = 1152 / 8;
break;
case GCRY_MD_SHA3_256:
macpad_Bsize = 1088 / 8;
break;
case GCRY_MD_SHA3_384:
macpad_Bsize = 832 / 8;
break;
case GCRY_MD_SHA3_512:
macpad_Bsize = 576 / 8;
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:
case GCRY_MD_BLAKE2B_160:
macpad_Bsize = 128;
break;
case GCRY_MD_GOSTR3411_94:
case GCRY_MD_GOSTR3411_CP:
macpad_Bsize = 32;
break;
default:
macpad_Bsize = 64;
break;
}
if ( keylen > macpad_Bsize )
{
k = key_allocated = xtrymalloc_secure (r->spec->mdlen);
if (!k)
return gpg_err_code_from_errno (errno);
_gcry_md_hash_buffer (r->spec->algo, key_allocated, key, keylen);
k_len = r->spec->mdlen;
gcry_assert ( k_len <= macpad_Bsize );
}
else
{
k = key;
k_len = keylen;
}
(*r->spec->init) (&r->context.c,
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->contextsize);
(*r->spec->init) (&r->context.c,
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->contextsize);
xfree (key_allocated);
}
a->bufpos = 0;
return 0;
}
gcry_err_code_t
_gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
{
gcry_err_code_t rc = 0;
(void)buflen; /* Currently not used. */
switch (cmd)
{
case GCRYCTL_FINALIZE:
md_final (hd);
break;
case GCRYCTL_START_DUMP:
md_start_debug (hd, buffer);
break;
case GCRYCTL_STOP_DUMP:
md_stop_debug ( hd );
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
gcry_err_code_t
_gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
{
gcry_err_code_t rc;
if (hd->ctx->flags.hmac)
{
rc = prepare_macpads (hd, key, keylen);
if (!rc)
_gcry_md_reset (hd);
}
else
{
rc = md_setkey (hd, key, keylen);
}
return rc;
}
/* The new debug interface. If SUFFIX is a string it creates an debug
file for the context HD. IF suffix is NULL, the file is closed and
debugging is stopped. */
void
_gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
{
if (suffix)
md_start_debug (hd, suffix);
else
md_stop_debug (hd);
}
/****************
* If ALGO is null get the digest for the used algo (which should be
* only one)
*/
static byte *
md_read( gcry_md_hd_t a, int algo )
{
GcryDigestEntry *r = a->ctx->list;
if (! algo)
{
/* Return the first algorithm */
if (r)
{
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);
}
}
else
{
for (r = a->ctx->list; r; r = r->next)
if (r->spec->algo == algo)
{
if (r->spec->read)
return r->spec->read (&r->context.c);
break;
}
}
if (r && !r->spec->read)
_gcry_fatal_error (GPG_ERR_DIGEST_ALGO,
"requested algo has no fixed digest length");
else
_gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo not in md context");
return NULL;
}
/*
* Read out the complete digest, this function implictly finalizes
* the hash.
*/
byte *
_gcry_md_read (gcry_md_hd_t hd, int algo)
{
/* This function is expected to always return a digest, thus we
can't return an error which we actually should do in
non-operational state. */
_gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
return md_read (hd, algo);
}
/****************
* If ALGO is null get the digest for the used algo (which should be
* only one)
*/
static gcry_err_code_t
md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen)
{
GcryDigestEntry *r = a->ctx->list;
if (!algo)
{
/* Return the first algorithm */
if (r && r->spec->extract)
{
if (r->next)
log_debug ("more than one algorithm in md_extract(0)\n");
r->spec->extract (&r->context.c, out, outlen);
return 0;
}
}
else
{
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);
return 0;
}
}
return GPG_ERR_DIGEST_ALGO;
}
/*
* Expand the output from XOF class digest, this function implictly finalizes
* the hash.
*/
gcry_err_code_t
_gcry_md_extract (gcry_md_hd_t hd, int algo, void *out, size_t outlen)
{
_gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
return md_extract (hd, algo, out, outlen);
}
/*
* Read out an intermediate digest. Not yet functional.
*/
gcry_err_code_t
_gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
{
(void)hd;
(void)algo;
(void)buffer;
(void)buflen;
/*md_digest ... */
fips_signal_error ("unimplemented function called");
return GPG_ERR_INTERNAL;
}
/*
* Shortcut function to hash a buffer with a given algo. The only
* guaranteed supported algorithms are RIPE-MD160 and SHA-1. The
* supplied digest buffer must be large enough to store the resulting
* hash. No error is returned, the function will abort on an invalid
* algo. DISABLED_ALGOS are ignored here. */
void
_gcry_md_hash_buffer (int algo, void *digest,
const void *buffer, size_t length)
{
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 (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 ();
}
}
if (spec->hash_buffer != NULL)
{
spec->hash_buffer (digest, buffer, length);
}
else if (spec->hash_buffers != NULL)
{
gcry_buffer_t iov;
iov.size = 0;
iov.data = (void *)buffer;
iov.off = 0;
iov.len = length;
spec->hash_buffers (digest, &iov, 1);
}
else
{
/* For the others we do not have a fast function, so we use the
normal functions. */
gcry_md_hd_t h;
gpg_err_code_t err;
err = md_open (&h, algo, 0);
if (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));
md_close (h);
}
}
/* 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)
{
gcry_md_spec_t *spec;
int hmac;
if (!iov || iovcnt < 0)
return GPG_ERR_INV_ARG;
if (flags & ~(GCRY_MD_FLAG_HMAC))
return GPG_ERR_INV_ARG;
hmac = !!(flags & GCRY_MD_FLAG_HMAC);
if (hmac && iovcnt < 1)
return GPG_ERR_INV_ARG;
spec = spec_from_algo (algo);
if (!spec)
{
log_debug ("md_hash_buffers: algorithm %d not available\n", algo);
return GPG_ERR_DIGEST_ALGO;
}
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 ();
}
}
if (!hmac && spec->hash_buffers)
{
spec->hash_buffers (digest, iov, iovcnt);
}
else
{
/* For the others we do not have a fast function, so we use the
normal functions. */
gcry_md_hd_t h;
gpg_err_code_t rc;
int dlen;
/* 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)
return rc;
if (hmac)
{
rc = _gcry_md_setkey (h,
(const char*)iov[0].data + iov[0].off,
iov[0].len);
if (rc)
{
md_close (h);
return rc;
}
iov++; iovcnt--;
}
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);
md_close (h);
}
return 0;
}
static int
md_get_algo (gcry_md_hd_t a)
{
GcryDigestEntry *r = a->ctx->list;
if (r && r->next)
{
fips_signal_error ("possible usage error");
log_error ("WARNING: more than one algorithm in md_get_algo()\n");
}
return r ? r->spec->algo : 0;
}
int
_gcry_md_get_algo (gcry_md_hd_t hd)
{
return md_get_algo (hd);
}
/****************
* Return the length of the digest
*/
static int
md_digest_length (int algorithm)
{
gcry_md_spec_t *spec;
spec = spec_from_algo (algorithm);
return spec? spec->mdlen : 0;
}
/****************
* Return the length of the digest in bytes.
* This function will return 0 in case of errors.
*/
unsigned int
_gcry_md_get_algo_dlen (int algorithm)
{
return md_digest_length (algorithm);
}
/* Hmmm: add a mode to enumerate the OIDs
* to make g10/sig-check.c more portable */
static const byte *
md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
{
gcry_md_spec_t *spec;
const byte *asnoid = NULL;
spec = spec_from_algo (algorithm);
if (spec)
{
if (asnlen)
*asnlen = spec->asnlen;
if (mdlen)
*mdlen = spec->mdlen;
asnoid = spec->asnoid;
}
else
log_bug ("no ASN.1 OID for md algo %d\n", algorithm);
return asnoid;
}
/****************
* Return information about the given cipher algorithm
* WHAT select the kind of information returned:
* GCRYCTL_TEST_ALGO:
* Returns 0 when the specified algorithm is available for use.
* buffer and nbytes must be zero.
* GCRYCTL_GET_ASNOID:
* Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
* the required length is returned.
* GCRYCTL_SELFTEST
* Helper for the regression tests - shall not be used by applications.
*
* Note: Because this function is in most cases used to return an
* integer value, we can make it easier for the caller to just look at
* the return value. The caller will in all cases consult the value
* and thereby detecting whether a error occurred or not (i.e. while checking
* the block size)
*/
gcry_err_code_t
_gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
gcry_err_code_t rc;
switch (what)
{
case GCRYCTL_TEST_ALGO:
if (buffer || nbytes)
rc = GPG_ERR_INV_ARG;
else
rc = check_digest_algo (algo);
break;
case GCRYCTL_GET_ASNOID:
/* We need to check that the algo is available because
md_asn_oid would otherwise raise an assertion. */
rc = check_digest_algo (algo);
if (!rc)
{
const char unsigned *asn;
size_t asnlen;
asn = md_asn_oid (algo, &asnlen, NULL);
if (buffer && (*nbytes >= asnlen))
{
memcpy (buffer, asn, asnlen);
*nbytes = asnlen;
}
else if (!buffer && nbytes)
*nbytes = asnlen;
else
{
if (buffer)
rc = GPG_ERR_TOO_SHORT;
else
rc = GPG_ERR_INV_ARG;
}
}
break;
case GCRYCTL_SELFTEST:
/* Helper function for the regression tests. */
rc = gpg_err_code (_gcry_md_selftest (algo, nbytes? (int)*nbytes : 0,
NULL));
break;
default:
rc = GPG_ERR_INV_OP;
break;
}
return rc;
}
static void
md_start_debug ( gcry_md_hd_t md, const char *suffix )
{
static int idx=0;
char buf[50];
if (fips_mode ())
return;
if ( md->ctx->debug )
{
log_debug("Oops: md debug already started\n");
return;
}
idx++;
snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix );
md->ctx->debug = fopen(buf, "w");
if ( !md->ctx->debug )
log_debug("md debug: can't open %s\n", buf );
}
static void
md_stop_debug( gcry_md_hd_t md )
{
if ( md->ctx->debug )
{
if ( md->bufpos )
md_write ( md, NULL, 0 );
fclose (md->ctx->debug);
md->ctx->debug = NULL;
}
{ /* a kludge to pull in the __muldi3 for Solaris */
volatile u32 a = (u32)(uintptr_t)md;
volatile u64 b = 42;
volatile u64 c;
c = a * b;
(void)c;
}
}
/*
* Return information about the digest handle.
* GCRYCTL_IS_SECURE:
* Returns 1 when the handle works on secured memory
* otherwise 0 is returned. There is no error return.
* GCRYCTL_IS_ALGO_ENABLED:
* Returns 1 if the algo is enabled for that handle.
* The algo must be passed as the address of an int.
*/
gcry_err_code_t
_gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
{
gcry_err_code_t rc = 0;
switch (cmd)
{
case GCRYCTL_IS_SECURE:
*nbytes = h->ctx->flags.secure;
break;
case GCRYCTL_IS_ALGO_ENABLED:
{
GcryDigestEntry *r;
int algo;
if ( !buffer || !nbytes || *nbytes != sizeof (int))
rc = GPG_ERR_INV_ARG;
else
{
algo = *(int*)buffer;
*nbytes = 0;
for(r=h->ctx->list; r; r = r->next ) {
if (r->spec->algo == algo)
{
*nbytes = 1;
break;
}
}
}
break;
}
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Explicitly initialize this module. */
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;
}
int
_gcry_md_is_secure (gcry_md_hd_t a)
{
size_t value;
if (_gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value))
value = 1; /* It seems to be better to assume secure memory on
error. */
return value;
}
int
_gcry_md_is_enabled (gcry_md_hd_t a, int algo)
{
size_t value;
value = sizeof algo;
if (_gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value))
value = 0;
return value;
}
/* Run the selftests for digest algorithm ALGO with optional reporting
function REPORT. */
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;
spec = spec_from_algo (algo);
if (spec && !spec->flags.disabled && spec->selftest)
ec = spec->selftest (algo, extended, report);
else
{
ec = (spec && spec->selftest) ? GPG_ERR_DIGEST_ALGO
/* */ : GPG_ERR_NOT_IMPLEMENTED;
if (report)
report ("digest", algo, "module",
(spec && !spec->flags.disabled)?
"no selftest available" :
spec? "algorithm disabled" : "algorithm not found");
}
return gpg_error (ec);
}
diff --git a/cipher/poly1305-internal.h b/cipher/poly1305-internal.h
index 19cee5f6..a648f0e5 100644
--- a/cipher/poly1305-internal.h
+++ b/cipher/poly1305-internal.h
@@ -1,64 +1,64 @@
/* poly1305-internal.h - Poly1305 internals
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef G10_POLY1305_INTERNAL_H
#define G10_POLY1305_INTERNAL_H
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#define POLY1305_TAGLEN 16
#define POLY1305_KEYLEN 32
#define POLY1305_BLOCKSIZE 16
typedef struct
{
u32 k[4];
u32 r[4];
u32 h[5];
} POLY1305_STATE;
typedef struct poly1305_context_s
{
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,
size_t keylen);
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);
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.c b/cipher/poly1305.c
index cded7cb2..35922ee3 100644
--- a/cipher/poly1305.c
+++ b/cipher/poly1305.c
@@ -1,687 +1,687 @@
/* poly1305.c - Poly1305 internals and generic implementation
* Copyright (C) 2014,2017,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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#include "poly1305-internal.h"
#include "mpi-internal.h"
#include "longlong.h"
static const char *selftest (void);
#undef USE_MPI_64BIT
#undef USE_MPI_32BIT
#if BYTES_PER_MPI_LIMB == 8 && defined(HAVE_U64_TYPEDEF)
# 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 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;
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->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);
}
#ifdef USE_MPI_64BIT
#if defined (__aarch64__) && __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__) && __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__ */
#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)
static unsigned int
poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
byte high_pad)
{
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);
}
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 */
/* minus 2^130-5 ... (+5) */
u = (-u) & 5;
add_ssaaaa(h1, h0, h1, h0, 0, u);
/* 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) */
#define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
__asm__ ("adds %0, %0, %5\n" \
"adcs %1, %1, %6\n" \
"adcs %2, %2, %7\n" \
"adcs %3, %3, %8\n" \
"adc %4, %4, %9\n" \
: "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
: "r" (B0), "r" (B1), "r" (B2), "r" (B3), "r" (B4) \
: "cc" )
#endif /* HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS */
#if defined (__i386__) && __GNUC__ >= 4
/* 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)
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];
h2 = st->h[2];
h3 = st->h[3];
h4 = st->h[4];
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)
{
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;
st->h[1] = h1;
st->h[2] = h2;
st->h[3] = h3;
st->h[4] = h4;
return 6 * sizeof (void *) + 28 * sizeof (u32);
}
static unsigned int poly1305_final (poly1305_context_t *ctx,
byte mac[POLY1305_TAGLEN])
{
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 (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];
h1 = st->h[1];
h2 = st->h[2];
h3 = st->h[3];
h4 = st->h[4];
/* 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 4 * sizeof (void *) + 10 * sizeof (u32) + burn;
}
#endif /* USE_MPI_32BIT */
unsigned int
_gcry_poly1305_update_burn (poly1305_context_t *ctx, const byte *m,
size_t bytes)
{
unsigned int burn = 0;
/* handle leftover */
if (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 < POLY1305_BLOCKSIZE)
return 0;
burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 1);
ctx->leftover = 0;
}
/* process full blocks */
if (bytes >= POLY1305_BLOCKSIZE)
{
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 */
if (bytes)
{
buf_cpy (ctx->buffer + ctx->leftover, m, 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])
{
unsigned int burn;
burn = poly1305_final (ctx, mac);
_gcry_burn_stack (burn);
}
gcry_err_code_t
_gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
size_t keylen)
{
static int initialized;
static const char *selftest_failed;
if (!initialized)
{
initialized = 1;
selftest_failed = selftest ();
if (selftest_failed)
log_error ("Poly1305 selftest failed (%s)\n", selftest_failed);
}
if (keylen != POLY1305_KEYLEN)
return GPG_ERR_INV_KEYLEN;
if (selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
poly1305_init (ctx, key);
return 0;
}
static void
poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes,
const byte * key)
{
poly1305_context_t ctx;
memset (&ctx, 0, sizeof (ctx));
_gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN);
_gcry_poly1305_update (&ctx, m, bytes);
_gcry_poly1305_finish (&ctx, mac);
wipememory (&ctx, sizeof (ctx));
}
static const char *
selftest (void)
{
/* example from nacl */
static const byte nacl_key[POLY1305_KEYLEN] = {
0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91,
0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25,
0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65,
0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
};
static const byte nacl_msg[131] = {
0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
0xe3, 0x55, 0xa5
};
static const byte nacl_mac[16] = {
0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
};
/* generates a final value of (2^130 - 2) == 3 */
static const byte wrap_key[POLY1305_KEYLEN] = {
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const byte wrap_msg[16] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const byte wrap_mac[16] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* mac of the macs of messages of length 0 to 256, where the key and messages
* have all their values set to the length
*/
static const byte total_key[POLY1305_KEYLEN] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const byte total_mac[16] = {
0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39
};
poly1305_context_t ctx;
poly1305_context_t total_ctx;
byte all_key[POLY1305_KEYLEN];
byte all_msg[256];
byte mac[16];
size_t i, j;
memset (&ctx, 0, sizeof (ctx));
memset (&total_ctx, 0, sizeof (total_ctx));
memset (mac, 0, sizeof (mac));
poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key);
if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
return "Poly1305 test 1 failed.";
/* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so
* make sure everything still works varying between them */
memset (mac, 0, sizeof (mac));
_gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN);
_gcry_poly1305_update (&ctx, nacl_msg + 0, 32);
_gcry_poly1305_update (&ctx, nacl_msg + 32, 64);
_gcry_poly1305_update (&ctx, nacl_msg + 96, 16);
_gcry_poly1305_update (&ctx, nacl_msg + 112, 8);
_gcry_poly1305_update (&ctx, nacl_msg + 120, 4);
_gcry_poly1305_update (&ctx, nacl_msg + 124, 2);
_gcry_poly1305_update (&ctx, nacl_msg + 126, 1);
_gcry_poly1305_update (&ctx, nacl_msg + 127, 1);
_gcry_poly1305_update (&ctx, nacl_msg + 128, 1);
_gcry_poly1305_update (&ctx, nacl_msg + 129, 1);
_gcry_poly1305_update (&ctx, nacl_msg + 130, 1);
_gcry_poly1305_finish (&ctx, mac);
if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0)
return "Poly1305 test 2 failed.";
memset (mac, 0, sizeof (mac));
poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key);
if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0)
return "Poly1305 test 3 failed.";
_gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN);
for (i = 0; i < 256; i++)
{
/* set key and message to 'i,i,i..' */
for (j = 0; j < sizeof (all_key); j++)
all_key[j] = i;
for (j = 0; j < i; j++)
all_msg[j] = i;
poly1305_auth (mac, all_msg, i, all_key);
_gcry_poly1305_update (&total_ctx, mac, 16);
}
_gcry_poly1305_finish (&total_ctx, mac);
if (memcmp (total_mac, mac, sizeof (total_mac)) != 0)
return "Poly1305 test 4 failed.";
return NULL;
}
diff --git a/cipher/pubkey-internal.h b/cipher/pubkey-internal.h
index b8167c77..49edb17d 100644
--- a/cipher/pubkey-internal.h
+++ b/cipher/pubkey-internal.h
@@ -1,104 +1,104 @@
/* pubkey-internal.h - Internal defs for pubkey.c
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_PUBKEY_INTERNAL_H
#define GCRY_PUBKEY_INTERNAL_H
/*-- pubkey-util.c --*/
gpg_err_code_t _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
int *r_flags,
enum pk_encoding *r_encoding);
gpg_err_code_t _gcry_pk_util_get_nbits (gcry_sexp_t list,
unsigned int *r_nbits);
gpg_err_code_t _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list,
unsigned long *r_e);
gpg_err_code_t _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig,
const char **algo_names,
gcry_sexp_t *r_parms,
int *r_eccflags);
gpg_err_code_t _gcry_pk_util_preparse_encval (gcry_sexp_t sexp,
const char **algo_names,
gcry_sexp_t *r_parms,
struct pk_encoding_ctx *ctx);
void _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
enum pk_operation op,
unsigned int nbits);
void _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx);
gcry_err_code_t _gcry_pk_util_data_to_mpi (gcry_sexp_t input,
gcry_mpi_t *ret_mpi,
struct pk_encoding_ctx *ctx);
/*-- rsa-common.c --*/
gpg_err_code_t
_gcry_rsa_pkcs1_encode_for_enc (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen,
const unsigned char *random_override,
size_t random_override_len);
gpg_err_code_t
_gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen,
unsigned int nbits, gcry_mpi_t value);
gpg_err_code_t
_gcry_rsa_pkcs1_encode_raw_for_sig (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen);
gpg_err_code_t
_gcry_rsa_pkcs1_encode_for_sig (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen,
int algo);
gpg_err_code_t
_gcry_rsa_oaep_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
const unsigned char *value, size_t valuelen,
const unsigned char *label, size_t labellen,
const void *random_override, size_t random_override_len);
gpg_err_code_t
_gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen,
unsigned int nbits, int algo,
gcry_mpi_t value,
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);
gpg_err_code_t
_gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
unsigned int nbits, int algo, size_t saltlen);
/*-- dsa-common.c --*/
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,
const unsigned char *h1,
unsigned int h1len,
int halgo,
unsigned int extraloops);
gpg_err_code_t _gcry_dsa_normalize_hash (gcry_mpi_t input,
gcry_mpi_t *out,
unsigned int qbits);
/*-- ecc.c --*/
gpg_err_code_t _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode,
mpi_ec_t ec);
#endif /*GCRY_PUBKEY_INTERNAL_H*/
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index ae0e1c46..70a0ad1c 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -1,1122 +1,1122 @@
/* pubkey-util.c - Supporting functions for all pubkey modules.
* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
* 2007, 2008, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013, 2015 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "pubkey-internal.h"
/* Callback for the pubkey algorithm code to verify PSS signatures.
OPAQUE is the data provided by the actual caller. The meaning of
TMP depends on the actual algorithm (but there is only RSA); now
for RSA it is the output of running the public key function on the
input. */
static int
pss_verify_cmp (void *opaque, gcry_mpi_t tmp)
{
struct pk_encoding_ctx *ctx = opaque;
gcry_mpi_t hash = ctx->verify_arg;
return _gcry_rsa_pss_verify (hash, tmp, ctx->nbits - 1,
ctx->hash_algo, ctx->saltlen);
}
/* Parser for a flag list. On return the encoding is stored at
R_ENCODING and the flags are stored at R_FLAGS. If any of them is
not needed, NULL may be passed. The function returns 0 on success
or an error code. */
gpg_err_code_t
_gcry_pk_util_parse_flaglist (gcry_sexp_t list,
int *r_flags, enum pk_encoding *r_encoding)
{
gpg_err_code_t rc = 0;
const char *s;
size_t n;
int i;
int encoding = PUBKEY_ENC_UNKNOWN;
int flags = 0;
int igninvflag = 0;
for (i = list ? sexp_length (list)-1 : 0; i > 0; i--)
{
s = sexp_nth_data (list, i, &n);
if (!s)
continue; /* Not a data element. */
switch (n)
{
case 3:
if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN)
{
encoding = PUBKEY_ENC_PSS;
flags |= PUBKEY_FLAG_FIXEDLEN;
}
else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
{
encoding = PUBKEY_ENC_RAW;
flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */
}
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 4:
if (!memcmp (s, "comp", 4))
flags |= PUBKEY_FLAG_COMP;
else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN)
{
encoding = PUBKEY_ENC_OAEP;
flags |= PUBKEY_FLAG_FIXEDLEN;
}
else if (!memcmp (s, "gost", 4))
{
encoding = PUBKEY_ENC_RAW;
flags |= PUBKEY_FLAG_GOST;
}
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 5:
if (!memcmp (s, "eddsa", 5))
{
encoding = PUBKEY_ENC_RAW;
flags |= PUBKEY_FLAG_EDDSA;
flags |= PUBKEY_FLAG_DJB_TWEAK;
}
else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
{
encoding = PUBKEY_ENC_PKCS1;
flags |= PUBKEY_FLAG_FIXEDLEN;
}
else if (!memcmp (s, "param", 5))
flags |= PUBKEY_FLAG_PARAM;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 6:
if (!memcmp (s, "nocomp", 6))
flags |= PUBKEY_FLAG_NOCOMP;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 7:
if (!memcmp (s, "rfc6979", 7))
flags |= PUBKEY_FLAG_RFC6979;
else if (!memcmp (s, "noparam", 7))
; /* Ignore - it is the default. */
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 8:
if (!memcmp (s, "use-x931", 8))
flags |= PUBKEY_FLAG_USE_X931;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 9:
if (!memcmp (s, "pkcs1-raw", 9) && encoding == PUBKEY_ENC_UNKNOWN)
{
encoding = PUBKEY_ENC_PKCS1_RAW;
flags |= PUBKEY_FLAG_FIXEDLEN;
}
else if (!memcmp (s, "djb-tweak", 9))
{
encoding = PUBKEY_ENC_RAW;
flags |= PUBKEY_FLAG_DJB_TWEAK;
}
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 10:
if (!memcmp (s, "igninvflag", 10))
igninvflag = 1;
else if (!memcmp (s, "no-keytest", 10))
flags |= PUBKEY_FLAG_NO_KEYTEST;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 11:
if (!memcmp (s, "no-blinding", 11))
flags |= PUBKEY_FLAG_NO_BLINDING;
else if (!memcmp (s, "use-fips186", 11))
flags |= PUBKEY_FLAG_USE_FIPS186;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
case 13:
if (!memcmp (s, "use-fips186-2", 13))
flags |= PUBKEY_FLAG_USE_FIPS186_2;
else if (!memcmp (s, "transient-key", 13))
flags |= PUBKEY_FLAG_TRANSIENT_KEY;
else if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
default:
if (!igninvflag)
rc = GPG_ERR_INV_FLAG;
break;
}
}
if (r_flags)
*r_flags = flags;
if (r_encoding)
*r_encoding = encoding;
return rc;
}
static int
get_hash_algo (const char *s, size_t n)
{
static const struct { const char *name; int algo; } hashnames[] = {
{ "sha1", GCRY_MD_SHA1 },
{ "md5", GCRY_MD_MD5 },
{ "sha256", GCRY_MD_SHA256 },
{ "ripemd160", GCRY_MD_RMD160 },
{ "rmd160", GCRY_MD_RMD160 },
{ "sha384", GCRY_MD_SHA384 },
{ "sha512", GCRY_MD_SHA512 },
{ "sha224", GCRY_MD_SHA224 },
{ "md2", GCRY_MD_MD2 },
{ "md4", GCRY_MD_MD4 },
{ "tiger", GCRY_MD_TIGER },
{ "haval", GCRY_MD_HAVAL },
{ "sha3-224", GCRY_MD_SHA3_224 },
{ "sha3-256", GCRY_MD_SHA3_256 },
{ "sha3-384", GCRY_MD_SHA3_384 },
{ "sha3-512", GCRY_MD_SHA3_512 },
{ "sm3", GCRY_MD_SM3 },
{ NULL, 0 }
};
int algo;
int i;
for (i=0; hashnames[i].name; i++)
{
if ( strlen (hashnames[i].name) == n
&& !memcmp (hashnames[i].name, s, n))
break;
}
if (hashnames[i].name)
algo = hashnames[i].algo;
else
{
/* In case of not listed or dynamically allocated hash
algorithm we fall back to this somewhat slower
method. Further, it also allows to use OIDs as
algorithm names. */
char *tmpname;
tmpname = xtrymalloc (n+1);
if (!tmpname)
algo = 0; /* Out of core - silently give up. */
else
{
memcpy (tmpname, s, n);
tmpname[n] = 0;
algo = _gcry_md_map_name (tmpname);
xfree (tmpname);
}
}
return algo;
}
/* Get the "nbits" parameter from an s-expression of the format:
*
* (algo
* (parameter_name_1 ....)
* ....
* (parameter_name_n ....))
*
* Example:
*
* (rsa
* (nbits 4:2048))
*
* On success the value for nbits is stored at R_NBITS. If no nbits
* parameter is found, the function returns success and stores 0 at
* R_NBITS. For parsing errors the function returns an error code and
* stores 0 at R_NBITS.
*/
gpg_err_code_t
_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
{
char buf[50];
const char *s;
size_t n;
*r_nbits = 0;
list = sexp_find_token (list, "nbits", 0);
if (!list)
return 0; /* No NBITS found. */
s = sexp_nth_data (list, 1, &n);
if (!s || n >= DIM (buf) - 1 )
{
/* NBITS given without a cdr. */
sexp_release (list);
return GPG_ERR_INV_OBJ;
}
memcpy (buf, s, n);
buf[n] = 0;
*r_nbits = (unsigned int)strtoul (buf, NULL, 0);
sexp_release (list);
return 0;
}
/* Get the optional "rsa-use-e" parameter from an s-expression of the
* format:
*
* (algo
* (parameter_name_1 ....)
* ....
* (parameter_name_n ....))
*
* Example:
*
* (rsa
* (nbits 4:2048)
* (rsa-use-e 2:41))
*
* On success the value for nbits is stored at R_E. If no rsa-use-e
* parameter is found, the function returns success and stores 65537 at
* R_E. For parsing errors the function returns an error code and
* stores 0 at R_E.
*/
gpg_err_code_t
_gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
{
char buf[50];
const char *s;
size_t n;
*r_e = 0;
list = sexp_find_token (list, "rsa-use-e", 0);
if (!list)
{
*r_e = 65537; /* Not given, use the value generated by old versions. */
return 0;
}
s = sexp_nth_data (list, 1, &n);
if (!s || n >= DIM (buf) - 1 )
{
/* No value or value too large. */
sexp_release (list);
return GPG_ERR_INV_OBJ;
}
memcpy (buf, s, n);
buf[n] = 0;
*r_e = strtoul (buf, NULL, 0);
sexp_release (list);
return 0;
}
/* Parse a "sig-val" s-expression and store the inner parameter list at
R_PARMS. ALGO_NAMES is used to verify that the algorithm in
"sig-val" is valid. Returns 0 on success and stores a new list at
R_PARMS which must be freed by the caller. On error R_PARMS is set
to NULL and an error code returned. If R_ECCFLAGS is not NULL flag
values are set into it; as of now they are only used with ecc
algorithms. */
gpg_err_code_t
_gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
gcry_sexp_t *r_parms, int *r_eccflags)
{
gpg_err_code_t rc;
gcry_sexp_t l1 = NULL;
gcry_sexp_t l2 = NULL;
char *name = NULL;
int i;
*r_parms = NULL;
if (r_eccflags)
*r_eccflags = 0;
/* Extract the signature value. */
l1 = sexp_find_token (s_sig, "sig-val", 0);
if (!l1)
{
rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */
goto leave;
}
l2 = sexp_nth (l1, 1);
if (!l2)
{
rc = GPG_ERR_NO_OBJ; /* No cadr for the sig object. */
goto leave;
}
name = sexp_nth_string (l2, 0);
if (!name)
{
rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
else if (!strcmp (name, "flags"))
{
/* Skip a "flags" parameter and look again for the algorithm
name. This is not used but here just for the sake of
consistent S-expressions we need to handle it. */
sexp_release (l2);
l2 = sexp_nth (l1, 2);
if (!l2)
{
rc = GPG_ERR_INV_OBJ;
goto leave;
}
xfree (name);
name = sexp_nth_string (l2, 0);
if (!name)
{
rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
}
for (i=0; algo_names[i]; i++)
if (!stricmp (name, algo_names[i]))
break;
if (!algo_names[i])
{
rc = GPG_ERR_CONFLICT; /* "sig-val" uses an unexpected algo. */
goto leave;
}
if (r_eccflags)
{
if (!strcmp (name, "eddsa"))
*r_eccflags = PUBKEY_FLAG_EDDSA;
if (!strcmp (name, "gost"))
*r_eccflags = PUBKEY_FLAG_GOST;
}
*r_parms = l2;
l2 = NULL;
rc = 0;
leave:
xfree (name);
sexp_release (l2);
sexp_release (l1);
return rc;
}
/* Parse a "enc-val" s-expression and store the inner parameter list
at R_PARMS. ALGO_NAMES is used to verify that the algorithm in
"enc-val" is valid. Returns 0 on success and stores a new list at
R_PARMS which must be freed by the caller. On error R_PARMS is set
to NULL and an error code returned. If R_ECCFLAGS is not NULL flag
values are set into it; as of now they are only used with ecc
algorithms.
(enc-val
[(flags [raw, pkcs1, oaep, no-blinding])]
[(hash-algo <algo>)]
[(label <label>)]
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>)))
HASH-ALGO and LABEL are specific to OAEP. CTX will be updated with
encoding information. */
gpg_err_code_t
_gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
gcry_sexp_t *r_parms,
struct pk_encoding_ctx *ctx)
{
gcry_err_code_t rc = 0;
gcry_sexp_t l1 = NULL;
gcry_sexp_t l2 = NULL;
char *name = NULL;
size_t n;
int parsed_flags = 0;
int i;
*r_parms = NULL;
/* Check that the first element is valid. */
l1 = sexp_find_token (sexp, "enc-val" , 0);
if (!l1)
{
rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object. */
goto leave;
}
l2 = sexp_nth (l1, 1);
if (!l2)
{
rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
goto leave;
}
/* Extract identifier of sublist. */
name = sexp_nth_string (l2, 0);
if (!name)
{
rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
if (!strcmp (name, "flags"))
{
const char *s;
/* There is a flags element - process it. */
rc = _gcry_pk_util_parse_flaglist (l2, &parsed_flags, &ctx->encoding);
if (rc)
goto leave;
if (ctx->encoding == PUBKEY_ENC_PSS)
{
rc = GPG_ERR_CONFLICT;
goto leave;
}
/* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
if (ctx->encoding == PUBKEY_ENC_OAEP)
{
/* Get HASH-ALGO. */
sexp_release (l2);
l2 = sexp_find_token (l1, "hash-algo", 0);
if (l2)
{
s = sexp_nth_data (l2, 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;
}
if (rc)
goto leave;
}
/* Get LABEL. */
sexp_release (l2);
l2 = sexp_find_token (l1, "label", 0);
if (l2)
{
s = sexp_nth_data (l2, 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;
}
}
if (rc)
goto leave;
}
}
/* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
for (i = 2; (sexp_release (l2), l2 = sexp_nth (l1, i)); i++)
{
s = sexp_nth_data (l2, 0, &n);
if (!(n == 9 && !memcmp (s, "hash-algo", 9))
&& !(n == 5 && !memcmp (s, "label", 5))
&& !(n == 15 && !memcmp (s, "random-override", 15)))
break;
}
if (!l2)
{
rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
goto leave;
}
/* Extract sublist identifier. */
xfree (name);
name = sexp_nth_string (l2, 0);
if (!name)
{
rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
}
else /* No flags - flag as legacy structure. */
parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;
for (i=0; algo_names[i]; i++)
if (!stricmp (name, algo_names[i]))
break;
if (!algo_names[i])
{
rc = GPG_ERR_CONFLICT; /* "enc-val" uses an unexpected algo. */
goto leave;
}
*r_parms = l2;
l2 = NULL;
ctx->flags |= parsed_flags;
rc = 0;
leave:
xfree (name);
sexp_release (l2);
sexp_release (l1);
return rc;
}
/* Initialize an encoding context. */
void
_gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
enum pk_operation op,
unsigned int nbits)
{
ctx->op = op;
ctx->nbits = nbits;
ctx->encoding = PUBKEY_ENC_UNKNOWN;
ctx->flags = 0;
if (fips_mode ())
{
ctx->hash_algo = GCRY_MD_SHA256;
}
else
{
ctx->hash_algo = GCRY_MD_SHA1;
}
ctx->label = NULL;
ctx->labellen = 0;
ctx->saltlen = 20;
ctx->verify_cmp = NULL;
ctx->verify_arg = NULL;
}
/* Free a context initialzied by _gcry_pk_util_init_encoding_ctx. */
void
_gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
{
xfree (ctx->label);
}
/* Take the hash value and convert into an MPI, suitable for
passing to the low level functions. We currently support the
old style way of passing just a MPI and the modern interface which
allows to pass flags so that we can choose between raw and pkcs1
padding - may be more padding options later.
(<mpi>)
or
(data
[(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
[(hash <algo> <value>)]
[(value <text>)]
[(hash-algo <algo>)]
[(label <label>)]
[(salt-length <length>)]
[(random-override <data>)]
)
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.
LABEL is specific to OAEP.
SALT-LENGTH is for PSS it is limited to 16384 bytes.
RANDOM-OVERRIDE is used to replace random nonces for regression
testing. */
gcry_err_code_t
_gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
struct pk_encoding_ctx *ctx)
{
gcry_err_code_t rc = 0;
gcry_sexp_t ldata, lhash, lvalue;
size_t n;
const char *s;
int unknown_flag = 0;
int parsed_flags = 0;
*ret_mpi = NULL;
ldata = sexp_find_token (input, "data", 0);
if (!ldata)
{ /* assume old style */
*ret_mpi = sexp_nth_mpi (input, 0, 0);
return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
}
/* See whether there is a flags list. */
{
gcry_sexp_t lflags = sexp_find_token (ldata, "flags", 0);
if (lflags)
{
if (_gcry_pk_util_parse_flaglist (lflags,
&parsed_flags, &ctx->encoding))
unknown_flag = 1;
sexp_release (lflags);
}
}
if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
/* Get HASH or MPI */
lhash = sexp_find_token (ldata, "hash", 0);
lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);
if (!(!lhash ^ !lvalue))
rc = GPG_ERR_INV_OBJ; /* none or both given */
else if (unknown_flag)
rc = GPG_ERR_INV_FLAG;
else if (ctx->encoding == PUBKEY_ENC_RAW
&& (parsed_flags & PUBKEY_FLAG_EDDSA))
{
/* Prepare for EdDSA. */
gcry_sexp_t list;
void *value;
size_t valuelen;
if (!lvalue)
{
rc = GPG_ERR_INV_OBJ;
goto leave;
}
/* 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);
}
else
rc = GPG_ERR_INV_OBJ;
if (rc)
goto leave;
/* Get VALUE. */
value = sexp_nth_buffer (lvalue, 1, &valuelen);
if (!value)
{
/* We assume that a zero length message is meant by
"(value)". This is commonly used by test vectors. Note
that S-expression do not allow zero length items. */
valuelen = 0;
value = xtrymalloc (1);
if (!value)
rc = gpg_err_code_from_syserror ();
}
else if ((valuelen * 8) < valuelen)
{
xfree (value);
rc = GPG_ERR_TOO_LARGE;
}
if (rc)
goto leave;
/* 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
&& ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
|| (parsed_flags & PUBKEY_FLAG_RFC6979)))
{
/* 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
{
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_buffer (lhash, 2, &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 if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
{
/* RFC6969 may only be used with the a hash value and not the
MPI based value. */
if (parsed_flags & PUBKEY_FLAG_RFC6979)
{
rc = GPG_ERR_CONFLICT;
goto leave;
}
/* Get the value */
*ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
if (!*ret_mpi)
rc = GPG_ERR_INV_OBJ;
}
else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
&& ctx->op == PUBKEY_OP_ENCRYPT)
{
const void * value;
size_t valuelen;
gcry_sexp_t list;
void *random_override = NULL;
size_t random_override_len = 0;
if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
rc = GPG_ERR_INV_OBJ;
else
{
/* 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;
}
rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
value, valuelen,
random_override,
random_override_len);
xfree (random_override);
}
}
else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
&& (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
{
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
&& (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
{
const void * value;
size_t valuelen;
if (sexp_length (lvalue) != 2)
rc = GPG_ERR_INV_OBJ;
else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen))
|| !valuelen )
rc = GPG_ERR_INV_OBJ;
else
rc = _gcry_rsa_pkcs1_encode_raw_for_sig (ret_mpi, ctx->nbits,
value, valuelen);
}
else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
&& ctx->op == PUBKEY_OP_ENCRYPT)
{
const void * value;
size_t valuelen;
if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
rc = GPG_ERR_INV_OBJ;
else
{
gcry_sexp_t list;
void *random_override = NULL;
size_t random_override_len = 0;
/* 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 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 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;
}
rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
value, valuelen,
ctx->label, ctx->labellen,
random_override, random_override_len);
xfree (random_override);
}
}
else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
&& 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;
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
{
gcry_sexp_t list;
/* 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);
}
/* 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;
}
/* 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);
xfree (random_override);
}
}
}
else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
&& 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
{
ctx->hash_algo = get_hash_algo (s, n);
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;
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);
}
*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;
}
}
}
else
rc = GPG_ERR_CONFLICT;
leave:
sexp_release (ldata);
sexp_release (lhash);
sexp_release (lvalue);
if (!rc)
ctx->flags = parsed_flags;
else
{
xfree (ctx->label);
ctx->label = NULL;
}
return rc;
}
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 4c07e33b..7cec133e 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1,970 +1,970 @@
/* pubkey.c - pubkey dispatcher
* Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
* 2007, 2008, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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 "pubkey-internal.h"
/* This is the list of the public-key algorithms included in
Libgcrypt. */
static gcry_pk_spec_t * const pubkey_list[] =
{
#if USE_ECC
&_gcry_pubkey_spec_ecc,
#endif
#if USE_RSA
&_gcry_pubkey_spec_rsa,
#endif
#if USE_DSA
&_gcry_pubkey_spec_dsa,
#endif
#if USE_ELGAMAL
&_gcry_pubkey_spec_elg,
#endif
NULL
};
static int
map_algo (int algo)
{
switch (algo)
{
case GCRY_PK_RSA_E: return GCRY_PK_RSA;
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_ECDH: return GCRY_PK_ECC;
default: return algo;
}
}
/* Return the spec structure for the public key algorithm ALGO. For
an unknown algorithm NULL is returned. */
static gcry_pk_spec_t *
spec_from_algo (int algo)
{
int idx;
gcry_pk_spec_t *spec;
algo = map_algo (algo);
for (idx = 0; (spec = pubkey_list[idx]); idx++)
if (algo == spec->algo)
return spec;
return NULL;
}
/* Return the spec structure for the public key algorithm with NAME.
For an unknown name NULL is returned. */
static gcry_pk_spec_t *
spec_from_name (const char *name)
{
gcry_pk_spec_t *spec;
int idx;
const char **aliases;
for (idx=0; (spec = pubkey_list[idx]); idx++)
{
if (!stricmp (name, spec->name))
return spec;
for (aliases = spec->aliases; *aliases; aliases++)
if (!stricmp (name, *aliases))
return spec;
}
return NULL;
}
/* Given the s-expression SEXP with the first element be either
* "private-key" or "public-key" return the spec structure for it. We
* look through the list to find a list beginning with "private-key"
* or "public-key" - the first one found is used. If WANT_PRIVATE is
* set the function will only succeed if a private key has been given.
* On success the spec is stored at R_SPEC. On error NULL is stored
* at R_SPEC and an error code returned. If R_PARMS is not NULL and
* the function returns success, the parameter list below
* "private-key" or "public-key" is stored there and the caller must
* call gcry_sexp_release on it.
*/
static gcry_err_code_t
spec_from_sexp (gcry_sexp_t sexp, int want_private,
gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms)
{
gcry_sexp_t list, l2;
char *name;
gcry_pk_spec_t *spec;
*r_spec = NULL;
if (r_parms)
*r_parms = NULL;
/* Check that the first element is valid. If we are looking for a
public key but a private key was supplied, we allow the use of
the private key anyway. The rationale for this is that the
private key is a superset of the public key. */
list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0);
if (!list && !want_private)
list = sexp_find_token (sexp, "private-key", 0);
if (!list)
return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
l2 = sexp_cadr (list);
sexp_release (list);
list = l2;
name = sexp_nth_string (list, 0);
if (!name)
{
sexp_release ( list );
return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
}
spec = spec_from_name (name);
xfree (name);
if (!spec)
{
sexp_release (list);
return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
}
*r_spec = spec;
if (r_parms)
*r_parms = list;
else
sexp_release (list);
return 0;
}
/* Disable the use of the algorithm ALGO. This is not thread safe and
should thus be called early. */
static void
disable_pubkey_algo (int algo)
{
gcry_pk_spec_t *spec = spec_from_algo (algo);
if (spec)
spec->flags.disabled = 1;
}
/*
* Map a string to the pubkey algo
*/
int
_gcry_pk_map_name (const char *string)
{
gcry_pk_spec_t *spec;
if (!string)
return 0;
spec = spec_from_name (string);
if (!spec)
return 0;
if (spec->flags.disabled)
return 0;
return spec->algo;
}
/* Map the public key algorithm whose ID is contained in ALGORITHM to
a string representation of the algorithm name. For unknown
algorithm IDs this functions returns "?". */
const char *
_gcry_pk_algo_name (int algo)
{
gcry_pk_spec_t *spec;
spec = spec_from_algo (algo);
if (spec)
return spec->name;
return "?";
}
/****************
* A USE of 0 means: don't care.
*/
static gcry_err_code_t
check_pubkey_algo (int algo, unsigned use)
{
gcry_err_code_t err = 0;
gcry_pk_spec_t *spec;
spec = spec_from_algo (algo);
if (spec)
{
if (((use & GCRY_PK_USAGE_SIGN)
&& (! (spec->use & GCRY_PK_USAGE_SIGN)))
|| ((use & GCRY_PK_USAGE_ENCR)
&& (! (spec->use & GCRY_PK_USAGE_ENCR))))
err = GPG_ERR_WRONG_PUBKEY_ALGO;
}
else
err = GPG_ERR_PUBKEY_ALGO;
return err;
}
/****************
* Return the number of public key material numbers
*/
static int
pubkey_get_npkey (int algo)
{
gcry_pk_spec_t *spec = spec_from_algo (algo);
return spec? strlen (spec->elements_pkey) : 0;
}
/****************
* Return the number of secret key material numbers
*/
static int
pubkey_get_nskey (int algo)
{
gcry_pk_spec_t *spec = spec_from_algo (algo);
return spec? strlen (spec->elements_skey) : 0;
}
/****************
* Return the number of signature material numbers
*/
static int
pubkey_get_nsig (int algo)
{
gcry_pk_spec_t *spec = spec_from_algo (algo);
return spec? strlen (spec->elements_sig) : 0;
}
/****************
* Return the number of encryption material numbers
*/
static int
pubkey_get_nenc (int algo)
{
gcry_pk_spec_t *spec = spec_from_algo (algo);
return spec? strlen (spec->elements_enc) : 0;
}
/*
Do a PK encrypt operation
Caller has to provide a public key as the SEXP pkey and data as a
SEXP with just one MPI in it. Alternatively S_DATA might be a
complex S-Expression, similar to the one used for signature
verification. This provides a flag which allows to handle PKCS#1
block type 2 padding. The function returns a sexp which may be
passed to to pk_decrypt.
Returns: 0 or an errorcode.
s_data = See comment for _gcry_pk_util_data_to_mpi
s_pkey = <key-as-defined-in-sexp_to_key>
r_ciph = (enc-val
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>)
))
*/
gcry_err_code_t
_gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
{
gcry_err_code_t rc;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms;
*r_ciph = NULL;
rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
if (rc)
goto leave;
if (spec->encrypt)
rc = spec->encrypt (r_ciph, s_data, keyparms);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (keyparms);
return rc;
}
/*
Do a PK decrypt operation
Caller has to provide a secret key as the SEXP skey and data in a
format as created by gcry_pk_encrypt. For historic reasons the
function returns simply an MPI as an S-expression part; this is
deprecated and the new method should be used which returns a real
S-expressionl this is selected by adding at least an empty flags
list to S_DATA.
Returns: 0 or an errorcode.
s_data = (enc-val
[(flags [raw, pkcs1, oaep])]
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>)
))
s_skey = <key-as-defined-in-sexp_to_key>
r_plain= Either an incomplete S-expression without the parentheses
or if the flags list is used (even if empty) a real S-expression:
(value PLAIN). In raw mode (or no flags given) the returned value
is to be interpreted as a signed MPI, thus it may have an extra
leading zero octet even if not included in the original data.
With pkcs1 or oaep decoding enabled the returned value is a
verbatim octet string.
*/
gcry_err_code_t
_gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
{
gcry_err_code_t rc;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms;
*r_plain = NULL;
rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
if (rc)
goto leave;
if (spec->decrypt)
rc = spec->decrypt (r_plain, s_data, keyparms);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (keyparms);
return rc;
}
/*
Create a signature.
Caller has to provide a secret key as the SEXP skey and data
expressed as a SEXP list hash with only one element which should
instantly be available as a MPI. Alternatively the structure given
below may be used for S_HASH, it provides the abiliy to pass flags
to the operation; the flags defined by now are "pkcs1" which does
PKCS#1 block type 1 style padding and "pss" for PSS encoding.
Returns: 0 or an errorcode.
In case of 0 the function returns a new SEXP with the
signature value; the structure of this signature depends on the
other arguments but is always suitable to be passed to
gcry_pk_verify
s_hash = See comment for _gcry-pk_util_data_to_mpi
s_skey = <key-as-defined-in-sexp_to_key>
r_sig = (sig-val
(<algo>
(<param_name1> <mpi>)
...
(<param_namen> <mpi>))
[(hash algo)])
Note that (hash algo) in R_SIG is not used.
*/
gcry_err_code_t
_gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
{
gcry_err_code_t rc;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms;
*r_sig = NULL;
rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
if (rc)
goto leave;
if (spec->sign)
rc = spec->sign (r_sig, s_hash, keyparms);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (keyparms);
return rc;
}
/*
Verify a signature.
Caller has to supply the public key pkey, the signature sig and his
hashvalue data. Public key has to be a standard public key given
as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
must be an S-Exp like the one in sign too. */
gcry_err_code_t
_gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
{
gcry_err_code_t rc;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms;
rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
if (rc)
goto leave;
if (spec->verify)
rc = spec->verify (s_sig, s_hash, keyparms);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (keyparms);
return rc;
}
/*
Test a key.
This may be used either for a public or a secret key to see whether
the internal structure is okay.
Returns: 0 or an errorcode.
NOTE: We currently support only secret key checking. */
gcry_err_code_t
_gcry_pk_testkey (gcry_sexp_t s_key)
{
gcry_err_code_t rc;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms;
rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
if (rc)
goto leave;
if (spec->check_secret_key)
rc = spec->check_secret_key (keyparms);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (keyparms);
return rc;
}
/*
Create a public key pair and return it in r_key.
How the key is created depends on s_parms:
(genkey
(algo
(parameter_name_1 ....)
....
(parameter_name_n ....)
))
The key is returned in a format depending on the
algorithm. Both, private and secret keys are returned
and optionally some additional informatin.
For elgamal we return this structure:
(key-data
(public-key
(elg
(p <mpi>)
(g <mpi>)
(y <mpi>)
)
)
(private-key
(elg
(p <mpi>)
(g <mpi>)
(y <mpi>)
(x <mpi>)
)
)
(misc-key-info
(pm1-factors n1 n2 ... nn)
))
*/
gcry_err_code_t
_gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
{
gcry_pk_spec_t *spec = NULL;
gcry_sexp_t list = NULL;
gcry_sexp_t l2 = NULL;
char *name = NULL;
gcry_err_code_t rc;
*r_key = NULL;
list = sexp_find_token (s_parms, "genkey", 0);
if (!list)
{
rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
goto leave;
}
l2 = sexp_cadr (list);
sexp_release (list);
list = l2;
l2 = NULL;
if (! list)
{
rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
goto leave;
}
name = _gcry_sexp_nth_string (list, 0);
if (!name)
{
rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
goto leave;
}
spec = spec_from_name (name);
xfree (name);
name = NULL;
if (!spec)
{
rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
goto leave;
}
if (spec->generate)
rc = spec->generate (list, r_key);
else
rc = GPG_ERR_NOT_IMPLEMENTED;
leave:
sexp_release (list);
xfree (name);
sexp_release (l2);
return rc;
}
/*
Get the number of nbits from the public key.
Hmmm: Should we have really this function or is it better to have a
more general function to retrieve different properties of the key? */
unsigned int
_gcry_pk_get_nbits (gcry_sexp_t key)
{
gcry_pk_spec_t *spec;
gcry_sexp_t parms;
unsigned int nbits;
/* Parsing KEY might be considered too much overhead. For example
for RSA we would only need to look at P and stop parsing right
away. However, with ECC things are more complicate in that only
a curve name might be specified. Thus we need to tear the sexp
apart. */
if (spec_from_sexp (key, 0, &spec, &parms))
return 0; /* Error - 0 is a suitable indication for that. */
nbits = spec->get_nbits (parms);
sexp_release (parms);
return nbits;
}
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
key parameters expressed in a way depending on the algorithm.
ARRAY must either be 20 bytes long or NULL; in the latter case a
newly allocated array of that size is returned, otherwise ARRAY or
NULL is returned to indicate an error which is most likely an
unknown algorithm. The function accepts public or secret keys. */
unsigned char *
_gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
{
gcry_sexp_t list = NULL;
gcry_sexp_t l2 = NULL;
gcry_pk_spec_t *spec = NULL;
const char *s;
char *name = NULL;
int idx;
const char *elems;
gcry_md_hd_t md = NULL;
int okay = 0;
/* Check that the first element is valid. */
list = sexp_find_token (key, "public-key", 0);
if (! list)
list = sexp_find_token (key, "private-key", 0);
if (! list)
list = sexp_find_token (key, "protected-private-key", 0);
if (! list)
list = sexp_find_token (key, "shadowed-private-key", 0);
if (! list)
return NULL; /* No public- or private-key object. */
l2 = sexp_cadr (list);
sexp_release (list);
list = l2;
l2 = NULL;
name = _gcry_sexp_nth_string (list, 0);
if (!name)
goto fail; /* Invalid structure of object. */
spec = spec_from_name (name);
if (!spec)
goto fail; /* Unknown algorithm. */
elems = spec->elements_grip;
if (!elems)
goto fail; /* No grip parameter. */
if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
goto fail;
if (spec->comp_keygrip)
{
/* Module specific method to compute a keygrip. */
if (spec->comp_keygrip (md, list))
goto fail;
}
else
{
/* Generic method to compute a keygrip. */
for (idx = 0, s = elems; *s; s++, idx++)
{
const char *data;
size_t datalen;
char buf[30];
l2 = sexp_find_token (list, s, 1);
if (! l2)
goto fail;
data = sexp_nth_data (l2, 1, &datalen);
if (! data)
goto fail;
snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
_gcry_md_write (md, buf, strlen (buf));
_gcry_md_write (md, data, datalen);
sexp_release (l2);
l2 = NULL;
_gcry_md_write (md, ")", 1);
}
}
if (!array)
{
array = xtrymalloc (20);
if (! array)
goto fail;
}
memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20);
okay = 1;
fail:
xfree (name);
sexp_release (l2);
_gcry_md_close (md);
sexp_release (list);
return okay? array : NULL;
}
const char *
_gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
{
const char *result = NULL;
gcry_pk_spec_t *spec;
gcry_sexp_t keyparms = NULL;
if (r_nbits)
*r_nbits = 0;
if (key)
{
iterator = 0;
if (spec_from_sexp (key, 0, &spec, &keyparms))
return NULL;
}
else
{
spec = spec_from_name ("ecc");
if (!spec)
return NULL;
}
if (spec->get_curve)
result = spec->get_curve (keyparms, iterator, r_nbits);
sexp_release (keyparms);
return result;
}
gcry_sexp_t
_gcry_pk_get_param (int algo, const char *name)
{
gcry_sexp_t result = NULL;
gcry_pk_spec_t *spec = NULL;
algo = map_algo (algo);
if (algo != GCRY_PK_ECC)
return NULL;
spec = spec_from_name ("ecc");
if (spec)
{
if (spec && spec->get_curve_param)
result = spec->get_curve_param (name);
}
return result;
}
gcry_err_code_t
_gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
{
gcry_err_code_t rc = 0;
switch (cmd)
{
case GCRYCTL_DISABLE_ALGO:
/* This one expects a buffer pointing to an integer with the
algo number. */
if ((! buffer) || (buflen != sizeof (int)))
rc = GPG_ERR_INV_ARG;
else
disable_pubkey_algo (*((int *) buffer));
break;
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Return information about the given algorithm
WHAT selects the kind of information returned:
GCRYCTL_TEST_ALGO:
Returns 0 when the specified algorithm is available for use.
Buffer must be NULL, nbytes may have the address of a variable
with the required usage of the algorithm. It may be 0 for don't
care or a combination of the GCRY_PK_USAGE_xxx flags;
GCRYCTL_GET_ALGO_USAGE:
Return the usage flags for the given algo. An invalid algo
returns 0. Disabled algos are ignored here because we
only want to know whether the algo is at all capable of
the usage.
Note: Because this function is in most cases used to return an
integer value, we can make it easier for the caller to just look at
the return value. The caller will in all cases consult the value
and thereby detecting whether a error occurred or not (i.e. while
checking the block size) */
gcry_err_code_t
_gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
{
gcry_err_code_t rc = 0;
switch (what)
{
case GCRYCTL_TEST_ALGO:
{
int use = nbytes ? *nbytes : 0;
if (buffer)
rc = GPG_ERR_INV_ARG;
else if (check_pubkey_algo (algorithm, use))
rc = GPG_ERR_PUBKEY_ALGO;
break;
}
case GCRYCTL_GET_ALGO_USAGE:
{
gcry_pk_spec_t *spec;
spec = spec_from_algo (algorithm);
*nbytes = spec? spec->use : 0;
break;
}
case GCRYCTL_GET_ALGO_NPKEY:
{
/* FIXME? */
int npkey = pubkey_get_npkey (algorithm);
*nbytes = npkey;
break;
}
case GCRYCTL_GET_ALGO_NSKEY:
{
/* FIXME? */
int nskey = pubkey_get_nskey (algorithm);
*nbytes = nskey;
break;
}
case GCRYCTL_GET_ALGO_NSIGN:
{
/* FIXME? */
int nsign = pubkey_get_nsig (algorithm);
*nbytes = nsign;
break;
}
case GCRYCTL_GET_ALGO_NENCR:
{
/* FIXME? */
int nencr = pubkey_get_nenc (algorithm);
*nbytes = nencr;
break;
}
default:
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* 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 a new S-expression is stored at R_SEXP and
0 is returned, on error NULL is store there and an error code is
returned. MODE is either 0 or one of the GCRY_PK_GET_xxx values.
As of now it only support 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. Note also that the name
of the function is gcry_pubkey_xxx and not gcry_pk_xxx. The idea
is that we will eventually provide variants of the existing
gcry_pk_xxx functions which will take a context parameter. */
gcry_err_code_t
_gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
{
mpi_ec_t ec;
if (!r_sexp)
return GPG_ERR_INV_VALUE;
*r_sexp = NULL;
switch (mode)
{
case 0:
case GCRY_PK_GET_PUBKEY:
case GCRY_PK_GET_SECKEY:
break;
default:
return GPG_ERR_INV_VALUE;
}
if (!ctx)
return GPG_ERR_NO_CRYPT_CTX;
ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC);
if (ec)
return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec);
return GPG_ERR_WRONG_CRYPT_CTX;
}
/* Explicitly initialize this module. */
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;
}
/* Run the selftests for pubkey algorithm ALGO with optional reporting
function REPORT. */
gpg_error_t
_gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
{
gcry_err_code_t ec;
gcry_pk_spec_t *spec;
algo = map_algo (algo);
spec = spec_from_algo (algo);
if (spec && !spec->flags.disabled && spec->selftest)
ec = spec->selftest (algo, extended, report);
else
{
ec = GPG_ERR_PUBKEY_ALGO;
/* Fixme: We need to change the report function to allow passing
of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */
if (report)
report ("pubkey", algo, "module",
spec && !spec->flags.disabled?
"no selftest available" :
spec? "algorithm disabled" :
"algorithm not found");
}
return gpg_error (ec);
}
diff --git a/cipher/rijndael-aarch64.S b/cipher/rijndael-aarch64.S
index e77dd4e0..1c0ed11d 100644
--- a/cipher/rijndael-aarch64.S
+++ b/cipher/rijndael-aarch64.S
@@ -1,514 +1,514 @@
/* rijndael-aarch64.S - ARMv8/AArch64 assembly implementation of AES cipher
*
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include "asm-common-aarch64.h"
#if defined(__AARCH64EL__)
#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
.text
/* register macros */
#define CTX x0
#define RDST x1
#define RSRC x2
#define NROUNDS w3
#define RTAB x4
#define RMASK w5
#define RA w8
#define RB w9
#define RC w10
#define RD w11
#define RNA w12
#define RNB w13
#define RNC w14
#define RND w15
#define RT0 w6
#define RT1 w7
#define RT2 w16
#define xRT0 x6
#define xRT1 x7
#define xRT2 x16
#define xw8 x8
#define xw9 x9
#define xw10 x10
#define xw11 x11
#define xw12 x12
#define xw13 x13
#define xw14 x14
#define xw15 x15
/***********************************************************************
* ARMv8/AArch64 assembly implementation of the AES cipher
***********************************************************************/
#define preload_first_key(round, ra) \
ldr ra, [CTX, #(((round) * 16) + 0 * 4)];
#define dummy(round, ra) /* nothing */
#define addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldp rna, rnb, [CTX]; \
ldp rnc, rnd, [CTX, #8]; \
eor ra, ra, rna; \
eor rb, rb, rnb; \
eor rc, rc, rnc; \
preload_key(1, rna); \
eor rd, rd, rnd;
#define do_encround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
\
and RT0, RMASK, ra, lsl#2; \
ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
and RT1, RMASK, ra, lsr#(8 - 2); \
ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldr RT0, [RTAB, xRT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rna, rna, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rd, lsl#2; \
ldr ra, [RTAB, x##ra]; \
\
eor rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#(8 - 2); \
eor rnc, rnc, RT2, ror #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
eor rnb, rnb, ra, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnd, rnd, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rc, lsl#2; \
ldr rd, [RTAB, x##rd]; \
\
eor rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
eor rnb, rnb, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
eor rna, rna, rd, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnc, rnc, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rb, lsl#2; \
ldr rc, [RTAB, x##rc]; \
\
eor rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
eor rna, rna, RT2, ror #16; \
and RT2, RMASK, rb, lsr#(16 - 2); \
eor rnd, rnd, rc, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rb, RMASK, rb, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnb, rnb, RT0; \
ldr RT2, [RTAB, xRT2]; \
eor rna, rna, RT1, ror #24; \
ldr rb, [RTAB, x##rb]; \
\
eor rnd, rnd, RT2, ror #16; \
preload_key((next_r) + 1, ra); \
eor rnc, rnc, rb, ror #8;
#define do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
and RT0, RMASK, ra, lsl#2; \
and RT1, RMASK, ra, lsr#(8 - 2); \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldrb rna, [RTAB, xRT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
ldrb rnd, [RTAB, xRT1]; \
and RT0, RMASK, rd, lsl#2; \
ldrb rnc, [RTAB, xRT2]; \
ror rnd, rnd, #24; \
ldrb rnb, [RTAB, x##ra]; \
and RT1, RMASK, rd, lsr#(8 - 2); \
ror rnc, rnc, #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
ror rnb, rnb, #8; \
ldrb RT0, [RTAB, xRT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
ldrb RT1, [RTAB, xRT1]; \
\
orr rnd, rnd, RT0; \
ldrb RT2, [RTAB, xRT2]; \
and RT0, RMASK, rc, lsl#2; \
ldrb rd, [RTAB, x##rd]; \
orr rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
orr rnb, rnb, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
orr rna, rna, rd, ror #8; \
ldrb RT0, [RTAB, xRT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
ldrb RT1, [RTAB, xRT1]; \
\
orr rnc, rnc, RT0; \
ldrb RT2, [RTAB, xRT2]; \
and RT0, RMASK, rb, lsl#2; \
ldrb rc, [RTAB, x##rc]; \
orr rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
orr rna, rna, RT2, ror #16; \
ldrb RT0, [RTAB, xRT0]; \
and RT2, RMASK, rb, lsr#(16 - 2); \
ldrb RT1, [RTAB, xRT1]; \
orr rnd, rnd, rc, ror #8; \
ldrb RT2, [RTAB, xRT2]; \
and rb, RMASK, rb, lsr#(24 - 2); \
ldrb rb, [RTAB, x##rb]; \
\
orr rnb, rnb, RT0; \
orr rna, rna, RT1, ror #24; \
orr rnd, rnd, RT2, ror #16; \
orr rnc, rnc, rb, ror #8;
#define firstencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); \
do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
#define encround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
#define lastencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
add CTX, CTX, #(((round) + 1) * 16); \
add RTAB, RTAB, #1; \
do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
.globl _gcry_aes_arm_encrypt_block
ELF(.type _gcry_aes_arm_encrypt_block,%function;)
_gcry_aes_arm_encrypt_block:
/* input:
* %x0: keysched, CTX
* %x1: dst
* %x2: src
* %w3: number of rounds.. 10, 12 or 14
* %x4: encryption table
*/
CFI_STARTPROC();
/* read input block */
/* aligned load */
ldp RA, RB, [RSRC];
ldp RC, RD, [RSRC, #8];
#ifndef __AARCH64EL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
mov RMASK, #(0xff<<2);
firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
cmp NROUNDS, #12;
bge .Lenc_not_128;
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
.Lenc_done:
/* store output block */
/* aligned store */
#ifndef __AARCH64EL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
/* write output block */
stp RA, RB, [RDST];
stp RC, RD, [RDST, #8];
mov x0, #(0);
ret;
.ltorg
.Lenc_not_128:
beq .Lenc_192
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
b .Lenc_done;
.ltorg
.Lenc_192:
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
b .Lenc_done;
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)]; \
ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
eor ra, ra, rna; \
ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
eor rb, rb, rnb; \
ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
eor rc, rc, rnc; \
preload_first_key((round) - 1, rna); \
eor rd, rd, rnd;
#define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
\
and RT0, RMASK, ra, lsl#2; \
ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
and RT1, RMASK, ra, lsr#(8 - 2); \
ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldr RT0, [RTAB, xRT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rna, rna, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rb, lsl#2; \
ldr ra, [RTAB, x##ra]; \
\
eor rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
eor rnc, rnc, RT2, ror #16; \
and RT2, RMASK, rb, lsr#(16 - 2); \
eor rnd, rnd, ra, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rb, RMASK, rb, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnb, rnb, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rc, lsl#2; \
ldr rb, [RTAB, x##rb]; \
\
eor rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
eor rnd, rnd, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
eor rna, rna, rb, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnc, rnc, RT0; \
ldr RT2, [RTAB, xRT2]; \
and RT0, RMASK, rd, lsl#2; \
ldr rc, [RTAB, x##rc]; \
\
eor rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#(8 - 2); \
eor rna, rna, RT2, ror #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
eor rnb, rnb, rc, ror #8; \
ldr RT0, [RTAB, xRT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
\
ldr RT1, [RTAB, xRT1]; \
eor rnd, rnd, RT0; \
ldr RT2, [RTAB, xRT2]; \
eor rna, rna, RT1, ror #24; \
ldr rd, [RTAB, x##rd]; \
\
eor rnb, rnb, RT2, ror #16; \
preload_key((next_r) - 1, ra); \
eor rnc, rnc, rd, ror #8;
#define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
and RT0, RMASK, ra; \
and RT1, RMASK, ra, lsr#8; \
and RT2, RMASK, ra, lsr#16; \
ldrb rna, [RTAB, xRT0]; \
lsr ra, ra, #24; \
ldrb rnb, [RTAB, xRT1]; \
and RT0, RMASK, rb; \
ldrb rnc, [RTAB, xRT2]; \
ror rnb, rnb, #24; \
ldrb rnd, [RTAB, x##ra]; \
and RT1, RMASK, rb, lsr#8; \
ror rnc, rnc, #16; \
and RT2, RMASK, rb, lsr#16; \
ror rnd, rnd, #8; \
ldrb RT0, [RTAB, xRT0]; \
lsr rb, rb, #24; \
ldrb RT1, [RTAB, xRT1]; \
\
orr rnb, rnb, RT0; \
ldrb RT2, [RTAB, xRT2]; \
and RT0, RMASK, rc; \
ldrb rb, [RTAB, x##rb]; \
orr rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#8; \
orr rnd, rnd, RT2, ror #16; \
and RT2, RMASK, rc, lsr#16; \
orr rna, rna, rb, ror #8; \
ldrb RT0, [RTAB, xRT0]; \
lsr rc, rc, #24; \
ldrb RT1, [RTAB, xRT1]; \
\
orr rnc, rnc, RT0; \
ldrb RT2, [RTAB, xRT2]; \
and RT0, RMASK, rd; \
ldrb rc, [RTAB, x##rc]; \
orr rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#8; \
orr rna, rna, RT2, ror #16; \
ldrb RT0, [RTAB, xRT0]; \
and RT2, RMASK, rd, lsr#16; \
ldrb RT1, [RTAB, xRT1]; \
orr rnb, rnb, rc, ror #8; \
ldrb RT2, [RTAB, xRT2]; \
lsr rd, rd, #24; \
ldrb rd, [RTAB, x##rd]; \
\
orr rnd, rnd, RT0; \
orr rna, rna, RT1, ror #24; \
orr rnb, rnb, RT2, ror #16; \
orr rnc, rnc, rd, ror #8;
#define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
#define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
#define set_last_round_rmask(_, __) \
mov RMASK, #0xff;
#define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
add RTAB, RTAB, #(4 * 256); \
do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
.globl _gcry_aes_arm_decrypt_block
ELF(.type _gcry_aes_arm_decrypt_block,%function;)
_gcry_aes_arm_decrypt_block:
/* input:
* %x0: keysched, CTX
* %x1: dst
* %x2: src
* %w3: number of rounds.. 10, 12 or 14
* %x4: decryption table
*/
CFI_STARTPROC();
/* read input block */
/* aligned load */
ldp RA, RB, [RSRC];
ldp RC, RD, [RSRC, #8];
#ifndef __AARCH64EL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
mov RMASK, #(0xff << 2);
cmp NROUNDS, #12;
bge .Ldec_256;
firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
.Ldec_tail:
decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
/* store output block */
/* aligned store */
#ifndef __AARCH64EL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
/* write output block */
stp RA, RB, [RDST];
stp RC, RD, [RDST, #8];
mov x0, #(0);
ret;
.ltorg
.Ldec_256:
beq .Ldec_192;
firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
b .Ldec_tail;
.ltorg
.Ldec_192:
firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
b .Ldec_tail;
CFI_ENDPROC();
ELF(.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block;)
#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
#endif /*__AARCH64EL__ */
diff --git a/cipher/rijndael-aesni.c b/cipher/rijndael-aesni.c
index a2a62abd..ec3b0909 100644
--- a/cipher/rijndael-aesni.c
+++ b/cipher/rijndael-aesni.c
@@ -1,3886 +1,3886 @@
/* AES-NI accelerated AES for Libgcrypt
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 2008, 2011, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcmp() */
#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_AESNI
#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 ALWAYS_INLINE inline __attribute__((always_inline))
#define NO_INLINE __attribute__((noinline))
typedef struct u128_s
{
u32 a, b, c, d;
} __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 ALWAYS_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
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 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_7() \
do { asm volatile ("movdqu %%xmm6, %0\n\t" \
"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_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+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_7_variable
# define aesni_prepare() 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_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
_gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
{
aesni_prepare_2_7_variable;
aesni_prepare();
aesni_prepare_2_7();
if (ctx->rounds < 12)
{
/* 128-bit key */
#define AESKEYGENASSIST_xmm1_xmm2(imm8) \
".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
#define AESKEY_EXPAND128 \
"pshufd $0xff, %%xmm2, %%xmm2\n\t" \
"movdqa %%xmm1, %%xmm3\n\t" \
"pslldq $4, %%xmm3\n\t" \
"pxor %%xmm3, %%xmm1\n\t" \
"pslldq $4, %%xmm3\n\t" \
"pxor %%xmm3, %%xmm1\n\t" \
"pslldq $4, %%xmm3\n\t" \
"pxor %%xmm3, %%xmm2\n\t" \
"pxor %%xmm2, %%xmm1\n\t"
asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key */
"movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x01)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x02)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x04)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x08)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x10)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x20)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x40)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x80)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x1b)
AESKEY_EXPAND128
"movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x36)
AESKEY_EXPAND128
"movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */
:
: [key] "r" (key), [ksch] "r" (ctx->keyschenc)
: "cc", "memory" );
#undef AESKEYGENASSIST_xmm1_xmm2
#undef AESKEY_EXPAND128
}
else if (ctx->rounds == 12)
{
/* 192-bit key */
#define AESKEYGENASSIST_xmm3_xmm2(imm8) \
".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
#define AESKEY_EXPAND192 \
"pshufd $0x55, %%xmm2, %%xmm2\n\t" \
"movdqu %%xmm1, %%xmm4\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pxor %%xmm2, %%xmm1\n\t" \
"pshufd $0xff, %%xmm1, %%xmm2\n\t" \
"movdqu %%xmm3, %%xmm4\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm3\n\t" \
"pxor %%xmm2, %%xmm3\n\t"
asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */
"movq 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..23] */
"movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
"movdqa %%xmm3, %%xmm5\n\t"
AESKEYGENASSIST_xmm3_xmm2(0x01)
AESKEY_EXPAND192
"shufpd $0, %%xmm1, %%xmm5\n\t"
"movdqa %%xmm5, 0x10(%[ksch])\n\t" /* ksch[1] := xmm5 */
"movdqa %%xmm1, %%xmm6\n\t"
"shufpd $1, %%xmm3, %%xmm6\n\t"
"movdqa %%xmm6, 0x20(%[ksch])\n\t" /* ksch[2] := xmm6 */
AESKEYGENASSIST_xmm3_xmm2(0x02)
AESKEY_EXPAND192
"movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */
"movdqa %%xmm3, %%xmm5\n\t"
AESKEYGENASSIST_xmm3_xmm2(0x04)
AESKEY_EXPAND192
"shufpd $0, %%xmm1, %%xmm5\n\t"
"movdqa %%xmm5, 0x40(%[ksch])\n\t" /* ksch[4] := xmm5 */
"movdqa %%xmm1, %%xmm6\n\t"
"shufpd $1, %%xmm3, %%xmm6\n\t"
"movdqa %%xmm6, 0x50(%[ksch])\n\t" /* ksch[5] := xmm6 */
AESKEYGENASSIST_xmm3_xmm2(0x08)
AESKEY_EXPAND192
"movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
"movdqa %%xmm3, %%xmm5\n\t"
AESKEYGENASSIST_xmm3_xmm2(0x10)
AESKEY_EXPAND192
"shufpd $0, %%xmm1, %%xmm5\n\t"
"movdqa %%xmm5, 0x70(%[ksch])\n\t" /* ksch[7] := xmm5 */
"movdqa %%xmm1, %%xmm6\n\t"
"shufpd $1, %%xmm3, %%xmm6\n\t"
"movdqa %%xmm6, 0x80(%[ksch])\n\t" /* ksch[8] := xmm6 */
AESKEYGENASSIST_xmm3_xmm2(0x20)
AESKEY_EXPAND192
"movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */
"movdqa %%xmm3, %%xmm5\n\t"
AESKEYGENASSIST_xmm3_xmm2(0x40)
AESKEY_EXPAND192
"shufpd $0, %%xmm1, %%xmm5\n\t"
"movdqa %%xmm5, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm5 */
"movdqa %%xmm1, %%xmm6\n\t"
"shufpd $1, %%xmm3, %%xmm6\n\t"
"movdqa %%xmm6, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm6 */
AESKEYGENASSIST_xmm3_xmm2(0x80)
AESKEY_EXPAND192
"movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */
:
: [key] "r" (key), [ksch] "r" (ctx->keyschenc)
: "cc", "memory" );
#undef AESKEYGENASSIST_xmm3_xmm2
#undef AESKEY_EXPAND192
}
else if (ctx->rounds > 12)
{
/* 256-bit key */
#define AESKEYGENASSIST_xmm1_xmm2(imm8) \
".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
#define AESKEYGENASSIST_xmm3_xmm2(imm8) \
".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
#define AESKEY_EXPAND256_A \
"pshufd $0xff, %%xmm2, %%xmm2\n\t" \
"movdqa %%xmm1, %%xmm4\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm1\n\t" \
"pxor %%xmm2, %%xmm1\n\t"
#define AESKEY_EXPAND256_B \
"pshufd $0xaa, %%xmm2, %%xmm2\n\t" \
"movdqa %%xmm3, %%xmm4\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm3\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm3\n\t" \
"pslldq $4, %%xmm4\n\t" \
"pxor %%xmm4, %%xmm3\n\t" \
"pxor %%xmm2, %%xmm3\n\t"
asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */
"movdqu 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..31] */
"movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
"movdqa %%xmm3, 0x10(%[ksch])\n\t" /* ksch[1] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x01)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0x30(%[ksch])\n\t" /* ksch[3] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x02)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0x50(%[ksch])\n\t" /* ksch[5] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x04)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0x70(%[ksch])\n\t" /* ksch[7] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x08)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0x90(%[ksch])\n\t" /* ksch[9] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x10)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x20)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */
AESKEYGENASSIST_xmm1_xmm2(0x00)
AESKEY_EXPAND256_B
"movdqa %%xmm3, 0xd0(%[ksch])\n\t" /* ksch[13] := xmm3 */
AESKEYGENASSIST_xmm3_xmm2(0x40)
AESKEY_EXPAND256_A
"movdqa %%xmm1, 0xe0(%[ksch])\n\t" /* ksch[14] := xmm1 */
:
: [key] "r" (key), [ksch] "r" (ctx->keyschenc)
: "cc", "memory" );
#undef AESKEYGENASSIST_xmm1_xmm2
#undef AESKEYGENASSIST_xmm3_xmm2
#undef AESKEY_EXPAND256_A
#undef AESKEY_EXPAND256_B
}
aesni_cleanup();
aesni_cleanup_2_7();
}
/* Make a decryption key from an encryption key. */
static ALWAYS_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
preparation. */
u128_t *ekey = (u128_t *)ctx->keyschenc;
u128_t *dkey = (u128_t *)ctx->keyschdec;
int rr;
int r;
#define DO_AESNI_AESIMC() \
asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
/*"aesimc %%xmm1, %%xmm1\n\t"*/ \
".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \
"movdqa %%xmm1, %[dkey]" \
: [dkey] "=m" (dkey[r]) \
: [ekey] "m" (ekey[rr]) \
: "memory")
dkey[0] = ekey[ctx->rounds];
r=1;
rr=ctx->rounds-1;
DO_AESNI_AESIMC(); r++; rr--; /* round 1 */
DO_AESNI_AESIMC(); r++; rr--; /* round 2 */
DO_AESNI_AESIMC(); r++; rr--; /* round 3 */
DO_AESNI_AESIMC(); r++; rr--; /* round 4 */
DO_AESNI_AESIMC(); r++; rr--; /* round 5 */
DO_AESNI_AESIMC(); r++; rr--; /* round 6 */
DO_AESNI_AESIMC(); r++; rr--; /* round 7 */
DO_AESNI_AESIMC(); r++; rr--; /* round 8 */
DO_AESNI_AESIMC(); r++; rr--; /* round 9 */
if (ctx->rounds > 10)
{
DO_AESNI_AESIMC(); r++; rr--; /* round 10 */
DO_AESNI_AESIMC(); r++; rr--; /* round 11 */
if (ctx->rounds > 12)
{
DO_AESNI_AESIMC(); r++; rr--; /* round 12 */
DO_AESNI_AESIMC(); r++; rr--; /* round 13 */
}
}
dkey[r] = ekey[0];
#undef DO_AESNI_AESIMC
}
void
_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 ALWAYS_INLINE void
do_aesni_enc (const RIJNDAEL_context *ctx)
{
#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
asm volatile ("movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
"pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */
"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
"movdqa 0xa0(%[key]), %%xmm1\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
"movdqa 0xb0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
"movdqa 0xc0(%[key]), %%xmm1\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
"movdqa 0xd0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
"movdqa 0xe0(%[key]), %%xmm1\n"
".Lenclast%=:\n\t"
aesenclast_xmm1_xmm0
"\n"
:
: [key] "r" (ctx->keyschenc),
[rounds] "r" (ctx->rounds)
: "cc", "memory");
#undef aesenc_xmm1_xmm0
#undef aesenclast_xmm1_xmm0
}
/* Decrypt one block using the Intel AES-NI instructions. Block is input
* and output through SSE register xmm0. */
static ALWAYS_INLINE void
do_aesni_dec (const RIJNDAEL_context *ctx)
{
#define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
#define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t"
asm volatile ("movdqa (%[key]), %%xmm1\n\t"
"pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */
"movdqa 0x10(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x20(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x30(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x40(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x50(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x60(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x70(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x80(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0x90(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0xa0(%[key]), %%xmm1\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesdec_xmm1_xmm0
"movdqa 0xb0(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0xc0(%[key]), %%xmm1\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesdec_xmm1_xmm0
"movdqa 0xd0(%[key]), %%xmm1\n\t"
aesdec_xmm1_xmm0
"movdqa 0xe0(%[key]), %%xmm1\n"
".Ldeclast%=:\n\t"
aesdeclast_xmm1_xmm0
"\n"
:
: [key] "r" (ctx->keyschdec),
[rounds] "r" (ctx->rounds)
: "cc", "memory");
#undef aesdec_xmm1_xmm0
#undef aesdeclast_xmm1_xmm0
}
/* Encrypt four blocks using the Intel AES-NI instructions. Blocks are input
* and output through SSE registers xmm1 to xmm4. */
static ALWAYS_INLINE void
do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
{
#define aesenc_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
#define aesenc_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd0\n\t"
#define aesenc_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd8\n\t"
#define aesenc_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe0\n\t"
#define aesenclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc8\n\t"
#define aesenclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd0\n\t"
#define aesenclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd8\n\t"
#define aesenclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe0\n\t"
asm volatile ("movdqa (%[key]), %%xmm0\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] */
"movdqa 0x10(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x20(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x30(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x40(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x50(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x60(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x70(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x80(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0x90(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0xa0(%[key]), %%xmm0\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0xb0(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0xc0(%[key]), %%xmm0\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0xd0(%[key]), %%xmm0\n\t"
aesenc_xmm0_xmm1
aesenc_xmm0_xmm2
aesenc_xmm0_xmm3
aesenc_xmm0_xmm4
"movdqa 0xe0(%[key]), %%xmm0\n"
".Ldeclast%=:\n\t"
aesenclast_xmm0_xmm1
aesenclast_xmm0_xmm2
aesenclast_xmm0_xmm3
aesenclast_xmm0_xmm4
: /* no output */
: [key] "r" (ctx->keyschenc),
[rounds] "r" (ctx->rounds)
: "cc", "memory");
#undef aesenc_xmm0_xmm1
#undef aesenc_xmm0_xmm2
#undef aesenc_xmm0_xmm3
#undef aesenc_xmm0_xmm4
#undef aesenclast_xmm0_xmm1
#undef aesenclast_xmm0_xmm2
#undef aesenclast_xmm0_xmm3
#undef aesenclast_xmm0_xmm4
}
/* Decrypt four blocks using the Intel AES-NI instructions. Blocks are input
* and output through SSE registers xmm1 to xmm4. */
static ALWAYS_INLINE void
do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
{
#define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
#define aesdec_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd0\n\t"
#define aesdec_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd8\n\t"
#define aesdec_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xde, 0xe0\n\t"
#define aesdeclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc8\n\t"
#define aesdeclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd0\n\t"
#define aesdeclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd8\n\t"
#define aesdeclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xe0\n\t"
asm volatile ("movdqa (%[key]), %%xmm0\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] */
"movdqa 0x10(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x20(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x30(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x40(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x50(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x60(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x70(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x80(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0x90(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0xa0(%[key]), %%xmm0\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0xb0(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0xc0(%[key]), %%xmm0\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Ldeclast%=\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0xd0(%[key]), %%xmm0\n\t"
aesdec_xmm0_xmm1
aesdec_xmm0_xmm2
aesdec_xmm0_xmm3
aesdec_xmm0_xmm4
"movdqa 0xe0(%[key]), %%xmm0\n"
".Ldeclast%=:\n\t"
aesdeclast_xmm0_xmm1
aesdeclast_xmm0_xmm2
aesdeclast_xmm0_xmm3
aesdeclast_xmm0_xmm4
: /* no output */
: [key] "r" (ctx->keyschdec),
[rounds] "r" (ctx->rounds)
: "cc", "memory");
#undef aesdec_xmm0_xmm1
#undef aesdec_xmm0_xmm2
#undef aesdec_xmm0_xmm3
#undef aesdec_xmm0_xmm4
#undef aesdeclast_xmm0_xmm1
#undef aesdeclast_xmm0_xmm2
#undef aesdeclast_xmm0_xmm3
#undef aesdeclast_xmm0_xmm4
}
#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 ALWAYS_INLINE void
do_aesni_enc_vec8 (const RIJNDAEL_context *ctx)
{
asm volatile ("movdqa (%[key]), %%xmm0\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] */
"movdqa 0x10(%[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 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 .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"
"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"
: /* 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 ALWAYS_INLINE void
do_aesni_dec_vec8 (const RIJNDAEL_context *ctx)
{
asm volatile ("movdqa (%[key]), %%xmm0\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] */
"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"
"aesdeclast %%xmm0, %%xmm1\n\t"
"aesdeclast %%xmm0, %%xmm2\n\t"
"aesdeclast %%xmm0, %%xmm3\n\t"
"aesdeclast %%xmm0, %%xmm4\n\t"
"aesdeclast %%xmm0, %%xmm8\n\t"
"aesdeclast %%xmm0, %%xmm9\n\t"
"aesdeclast %%xmm0, %%xmm10\n\t"
"aesdeclast %%xmm0, %%xmm11\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
do_aesni_ctr (const RIJNDAEL_context *ctx,
unsigned char *ctr, unsigned char *b, const unsigned char *a)
{
#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */
"pcmpeqd %%xmm1, %%xmm1\n\t"
"psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */
"pshufb %%xmm6, %%xmm5\n\t"
"psubq %%xmm1, %%xmm5\n\t" /* xmm5++ (big endian) */
/* detect if 64-bit carry handling is needed */
"cmpl $0xffffffff, 8(%[ctr])\n\t"
"jne .Lno_carry%=\n\t"
"cmpl $0xffffffff, 12(%[ctr])\n\t"
"jne .Lno_carry%=\n\t"
"pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */
"psubq %%xmm1, %%xmm5\n\t" /* add carry to upper 64bits */
".Lno_carry%=:\n\t"
"pshufb %%xmm6, %%xmm5\n\t"
"movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */
"pxor (%[key]), %%xmm0\n\t" /* xmm1 ^= key[0] */
"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
"movdqa 0xa0(%[key]), %%xmm1\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
"movdqa 0xb0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
"movdqa 0xc0(%[key]), %%xmm1\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
"movdqa 0xd0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
"movdqa 0xe0(%[key]), %%xmm1\n"
".Lenclast%=:\n\t"
aesenclast_xmm1_xmm0
"movdqu %[src], %%xmm1\n\t" /* xmm1 := input */
"pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */
"movdqu %%xmm0, %[dst]" /* Store EncCTR. */
: [dst] "=m" (*b)
: [src] "m" (*a),
[ctr] "r" (ctr),
[key] "r" (ctx->keyschenc),
[rounds] "g" (ctx->rounds)
: "cc", "memory");
#undef aesenc_xmm1_xmm0
#undef aesenclast_xmm1_xmm0
}
/* Four blocks at a time variant of do_aesni_ctr. */
static void
do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
unsigned char *ctr, unsigned char *b, const unsigned char *a)
{
static const byte bige_addb_const[4][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 }
};
const void *bige_addb = bige_addb_const;
#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
#define aesenc_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
#define aesenc_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
#define aesenc_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
#define aesenclast_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
#define aesenclast_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
#define aesenclast_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
/* 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
*/
asm volatile (/* detect if 8-bit carry handling is needed */
"cmpb $0xfb, 15(%[ctr])\n\t"
"ja .Ladd32bit%=\n\t"
"movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */
"movdqa 0*16(%[addb]), %%xmm2\n\t" /* xmm2 := be(1) */
"movdqa 1*16(%[addb]), %%xmm3\n\t" /* xmm3 := be(2) */
"movdqa 2*16(%[addb]), %%xmm4\n\t" /* xmm4 := be(3) */
"movdqa 3*16(%[addb]), %%xmm5\n\t" /* xmm5 := be(4) */
"paddb %%xmm0, %%xmm2\n\t" /* xmm2 := be(1) + CTR (xmm0) */
"paddb %%xmm0, %%xmm3\n\t" /* xmm3 := be(2) + CTR (xmm0) */
"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"
".Ladd32bit%=:\n\t"
"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, %%xmm5\n\t" /* xmm5 := xmm4 */
"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 $0xfffffffc, %%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 == 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_xmm5%=:\n\t"
"psubq %%xmm1, %%xmm5\n\t"
".Lno_carry%=:\n\t"
"movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
"pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := be(xmm2) */
"pshufb %%xmm6, %%xmm3\n\t" /* xmm3 := be(xmm3) */
"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). */
:
: [ctr] "r" (ctr),
[key] "r" (ctx->keyschenc),
[addb] "r" (bige_addb)
: "%esi", "cc", "memory");
asm volatile ("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] */
"movdqa 0x10(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x20(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x30(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x40(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x50(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x60(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x70(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x80(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0x90(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0xa0(%[key]), %%xmm1\n\t"
"cmpl $10, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0xb0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0xc0(%[key]), %%xmm1\n\t"
"cmpl $12, %[rounds]\n\t"
"jz .Lenclast%=\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0xd0(%[key]), %%xmm1\n\t"
aesenc_xmm1_xmm0
aesenc_xmm1_xmm2
aesenc_xmm1_xmm3
aesenc_xmm1_xmm4
"movdqa 0xe0(%[key]), %%xmm1\n"
".Lenclast%=:\n\t"
aesenclast_xmm1_xmm0
aesenclast_xmm1_xmm2
aesenclast_xmm1_xmm3
aesenclast_xmm1_xmm4
:
: [key] "r" (ctx->keyschenc),
[rounds] "r" (ctx->rounds)
: "cc", "memory");
asm volatile ("movdqu (%[src]), %%xmm1\n\t" /* Get block 1. */
"pxor %%xmm1, %%xmm0\n\t" /* EncCTR-1 ^= input */
"movdqu %%xmm0, (%[dst])\n\t" /* Store block 1 */
"movdqu 16(%[src]), %%xmm1\n\t" /* Get block 2. */
"pxor %%xmm1, %%xmm2\n\t" /* EncCTR-2 ^= input */
"movdqu %%xmm2, 16(%[dst])\n\t" /* Store block 2. */
"movdqu 32(%[src]), %%xmm1\n\t" /* Get block 3. */
"pxor %%xmm1, %%xmm3\n\t" /* EncCTR-3 ^= input */
"movdqu %%xmm3, 32(%[dst])\n\t" /* Store block 3. */
"movdqu 48(%[src]), %%xmm1\n\t" /* Get block 4. */
"pxor %%xmm1, %%xmm4\n\t" /* EncCTR-4 ^= input */
"movdqu %%xmm4, 48(%[dst])" /* Store block 4. */
:
: [src] "r" (a),
[dst] "r" (b)
: "memory");
#undef aesenc_xmm1_xmm0
#undef aesenc_xmm1_xmm2
#undef aesenc_xmm1_xmm3
#undef aesenc_xmm1_xmm4
#undef aesenclast_xmm1_xmm0
#undef aesenclast_xmm1_xmm2
#undef aesenclast_xmm1_xmm3
#undef aesenclast_xmm1_xmm4
}
#ifdef __x86_64__
/* Eight blocks at a time variant of do_aesni_ctr. */
static 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 */
"cmpb $0xf7, 15(%[ctr])\n\t"
"ja .Ladd32bit%=\n\t"
"movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */
"movdqa 0*16(%[addb]), %%xmm2\n\t" /* xmm2 := be(1) */
"movdqa 1*16(%[addb]), %%xmm3\n\t" /* xmm3 := be(2) */
"movdqa 2*16(%[addb]), %%xmm4\n\t" /* xmm4 := be(3) */
"movdqa 3*16(%[addb]), %%xmm8\n\t" /* xmm8 := be(4) */
"movdqa 4*16(%[addb]), %%xmm9\n\t" /* xmm9 := be(5) */
"movdqa 5*16(%[addb]), %%xmm10\n\t" /* xmm10 := be(6) */
"movdqa 6*16(%[addb]), %%xmm11\n\t" /* xmm11 := be(7) */
"movdqa 7*16(%[addb]), %%xmm5\n\t" /* xmm5 := be(8) */
"movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
"paddb %%xmm0, %%xmm2\n\t" /* xmm2 := be(1) + CTR (xmm0) */
"paddb %%xmm0, %%xmm3\n\t" /* xmm3 := be(2) + CTR (xmm0) */
"paddb %%xmm0, %%xmm4\n\t" /* xmm4 := be(3) + CTR (xmm0) */
"paddb %%xmm0, %%xmm8\n\t" /* xmm8 := be(4) + CTR (xmm0) */
"paddb %%xmm0, %%xmm9\n\t" /* xmm9 := be(5) + CTR (xmm0) */
"paddb %%xmm0, %%xmm10\n\t" /* xmm10 := be(6) + CTR (xmm0) */
"paddb %%xmm0, %%xmm11\n\t" /* xmm11 := be(7) + CTR (xmm0) */
"paddb %%xmm0, %%xmm5\n\t" /* xmm5 := be(8) + CTR (xmm0) */
"jmp .Lstore_ctr%=\n\t"
".Ladd32bit%=:\n\t"
"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] */
"pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := be(xmm2) */
"pshufb %%xmm6, %%xmm3\n\t" /* xmm3 := be(xmm3) */
"pshufb %%xmm6, %%xmm4\n\t" /* xmm4 := be(xmm4) */
"pshufb %%xmm6, %%xmm5\n\t" /* xmm5 := be(xmm5) */
"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) */
".Lstore_ctr%=:\n\t"
"movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */
:
: [ctr] "r" (ctr),
[key] "r" (ctx->keyschenc),
[addb] "r" (bige_addb)
: "%esi", "cc", "memory");
asm volatile ("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] */
"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] */
"movdqa 0x10(%[key]), %%xmm1\n\t"
"cmpl $12, %[rounds]\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 0x20(%[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 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)
: "cc", "memory");
asm volatile ("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. */
"pxor %%xmm1, %%xmm12\n\t" /* block1 ^= lastkey */
"aesenclast %%xmm12, %%xmm0\n\t"
"movdqu 5*16(%[src]), %%xmm12\n\t" /* Get block 6. */
"pxor %%xmm1, %%xmm13\n\t" /* block2 ^= lastkey */
"aesenclast %%xmm13, %%xmm2\n\t"
"movdqu 6*16(%[src]), %%xmm13\n\t" /* Get block 7. */
"pxor %%xmm1, %%xmm14\n\t" /* block3 ^= lastkey */
"aesenclast %%xmm14, %%xmm3\n\t"
"movdqu 7*16(%[src]), %%xmm14\n\t" /* Get block 8. */
"pxor %%xmm1, %%xmm15\n\t" /* block4 ^= lastkey */
"aesenclast %%xmm15, %%xmm4\n\t"
"movdqu %%xmm0, 0*16(%[dst])\n\t" /* Store block 1 */
"pxor %%xmm1, %%xmm7\n\t" /* block5 ^= lastkey */
"aesenclast %%xmm7, %%xmm8\n\t"
"movdqu %%xmm0, 0*16(%[dst])\n\t" /* Store block 1 */
"pxor %%xmm1, %%xmm12\n\t" /* block6 ^= lastkey */
"aesenclast %%xmm12, %%xmm9\n\t"
"movdqu %%xmm2, 1*16(%[dst])\n\t" /* Store block 2. */
"pxor %%xmm1, %%xmm13\n\t" /* block7 ^= lastkey */
"aesenclast %%xmm13, %%xmm10\n\t"
"movdqu %%xmm3, 2*16(%[dst])\n\t" /* Store block 3. */
"pxor %%xmm1, %%xmm14\n\t" /* block8 ^= lastkey */
"aesenclast %%xmm14, %%xmm11\n\t"
"movdqu %%xmm4, 3*16(%[dst])\n\t" /* Store block 4. */
"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
_gcry_aes_aesni_encrypt (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_enc (ctx);
asm volatile ("movdqu %%xmm0, %[dst]\n\t"
: [dst] "=m" (*dst)
:
: "memory" );
aesni_cleanup ();
return 0;
}
void
_gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *iv,
unsigned char *outbuf, const unsigned char *inbuf,
size_t nblocks)
{
aesni_prepare ();
asm volatile ("movdqu %[iv], %%xmm0\n\t"
: /* No output */
: [iv] "m" (*iv)
: "memory" );
for ( ;nblocks; nblocks-- )
{
do_aesni_enc (ctx);
asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"movdqu %%xmm0, %[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" );
aesni_cleanup ();
}
void
_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_7_variable;
aesni_prepare ();
aesni_prepare_2_7();
asm volatile ("movdqu %[iv], %%xmm5\n\t"
: /* No output */
: [iv] "m" (*iv)
: "memory" );
for ( ;nblocks; nblocks-- )
{
asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm5, %%xmm0\n\t"
: /* No output */
: [inbuf] "m" (*inbuf)
: "memory" );
do_aesni_enc (ctx);
asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
if (!cbc_mac)
outbuf += BLOCKSIZE;
}
asm volatile ("movdqu %%xmm5, %[iv]\n\t"
: [iv] "=m" (*iv)
:
: "memory" );
aesni_cleanup ();
aesni_cleanup_2_7 ();
}
void
_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_7_variable;
aesni_prepare ();
aesni_prepare_2_7();
asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
"movdqa %[ctr], %%xmm5\n\t" /* Preload CTR */
: /* No output */
: [mask] "m" (*be_mask),
[ctr] "m" (*ctr)
: "memory");
#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;
inbuf += 4*BLOCKSIZE;
}
for ( ;nblocks; nblocks-- )
{
do_aesni_ctr (ctx, ctr, outbuf, inbuf);
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
aesni_cleanup ();
aesni_cleanup_2_7 ();
}
unsigned int
_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
_gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *iv,
unsigned char *outbuf, const unsigned char *inbuf,
size_t nblocks)
{
aesni_prepare_2_7_variable;
aesni_prepare ();
aesni_prepare_2_7();
asm volatile ("movdqu %[iv], %%xmm6\n\t"
: /* No output */
: [iv] "m" (*iv)
: "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
("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"
: /* No output */
: [inbuf] "r" (inbuf)
: "memory");
do_aesni_enc_vec8 (ctx);
asm volatile
(
"pxor %%xmm12, %%xmm1\n\t"
"movdqu 4*16(%[inbuf]), %%xmm12\n\t"
"pxor %%xmm13, %%xmm2\n\t"
"movdqu 5*16(%[inbuf]), %%xmm13\n\t"
"pxor %%xmm14, %%xmm3\n\t"
"movdqu 6*16(%[inbuf]), %%xmm14\n\t"
"pxor %%xmm15, %%xmm4\n\t"
"movdqu 7*16(%[inbuf]), %%xmm15\n\t"
"pxor %%xmm12, %%xmm8\n\t"
"movdqu %%xmm1, 0*16(%[outbuf])\n\t"
"pxor %%xmm13, %%xmm9\n\t"
"movdqu %%xmm2, 1*16(%[outbuf])\n\t"
"pxor %%xmm14, %%xmm10\n\t"
"movdqu %%xmm3, 2*16(%[outbuf])\n\t"
"pxor %%xmm15, %%xmm11\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 %%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]), %%xmm6\n\t" /* update IV */
: /* No output */
: [inbuf] "r" (inbuf)
: "memory");
do_aesni_enc_vec4 (ctx);
asm volatile
("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
"pxor %%xmm5, %%xmm1\n\t"
"movdqu %%xmm1, 0*16(%[outbuf])\n\t"
"movdqu 1*16(%[inbuf]), %%xmm5\n\t"
"pxor %%xmm5, %%xmm2\n\t"
"movdqu %%xmm2, 1*16(%[outbuf])\n\t"
"movdqu 2*16(%[inbuf]), %%xmm5\n\t"
"pxor %%xmm5, %%xmm3\n\t"
"movdqu %%xmm3, 2*16(%[outbuf])\n\t"
"movdqu 3*16(%[inbuf]), %%xmm5\n\t"
"pxor %%xmm5, %%xmm4\n\t"
"movdqu %%xmm4, 3*16(%[outbuf])\n\t"
: /* No output */
: [inbuf] "r" (inbuf),
[outbuf] "r" (outbuf)
: "memory");
outbuf += 4*BLOCKSIZE;
inbuf += 4*BLOCKSIZE;
}
asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
for ( ;nblocks; nblocks-- )
{
do_aesni_enc (ctx);
asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
"movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm0, %%xmm6\n\t"
"movdqu %%xmm6, %[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" );
aesni_cleanup ();
aesni_cleanup_2_7 ();
}
void
_gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *iv,
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;
}
asm volatile
("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
: /* No output */
: [iv] "m" (*iv)
: "memory");
#ifdef __x86_64__
if (nblocks >= 8)
{
aesni_prepare_8_15_variable;
aesni_prepare_8_15();
for ( ;nblocks >= 8 ; nblocks -= 8 )
{
asm volatile
("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"
: /* No output */
: [inbuf] "r" (inbuf)
: "memory");
do_aesni_dec_vec8 (ctx);
asm volatile
("pxor %%xmm5, %%xmm1\n\t" /* xor IV with output */
"pxor %%xmm12, %%xmm2\n\t" /* xor IV with output */
"movdqu 4*16(%[inbuf]), %%xmm12\n\t"
"pxor %%xmm13, %%xmm3\n\t" /* xor IV with output */
"movdqu 5*16(%[inbuf]), %%xmm13\n\t"
"pxor %%xmm14, %%xmm4\n\t" /* xor IV with output */
"movdqu 6*16(%[inbuf]), %%xmm14\n\t"
"pxor %%xmm15, %%xmm8\n\t" /* xor IV with output */
"movdqu 7*16(%[inbuf]), %%xmm5\n\t"
"pxor %%xmm12, %%xmm9\n\t" /* xor IV with output */
"movdqu %%xmm1, 0*16(%[outbuf])\n\t"
"pxor %%xmm13, %%xmm10\n\t" /* xor IV with output */
"movdqu %%xmm2, 1*16(%[outbuf])\n\t"
"pxor %%xmm14, %%xmm11\n\t" /* xor IV with output */
"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 */
"movdqu 1*16(%[inbuf]), %%xmm2\n\t"
"movdqu 2*16(%[inbuf]), %%xmm3\n\t"
"movdqu 3*16(%[inbuf]), %%xmm4\n\t"
: /* No output */
: [inbuf] "r" (inbuf)
: "memory");
do_aesni_dec_vec4 (ctx);
asm volatile
("pxor %%xmm5, %%xmm1\n\t" /* xor IV with output */
"movdqu 0*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
"movdqu %%xmm1, 0*16(%[outbuf])\n\t"
"pxor %%xmm5, %%xmm2\n\t" /* xor IV with output */
"movdqu 1*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
"movdqu %%xmm2, 1*16(%[outbuf])\n\t"
"pxor %%xmm5, %%xmm3\n\t" /* xor IV with output */
"movdqu 2*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
"movdqu %%xmm3, 2*16(%[outbuf])\n\t"
"pxor %%xmm5, %%xmm4\n\t" /* xor IV with output */
"movdqu 3*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
"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
("movdqu %[inbuf], %%xmm0\n\t"
"movdqa %%xmm0, %%xmm2\n\t" /* use xmm2 as savebuf */
: /* No output */
: [inbuf] "m" (*inbuf)
: "memory");
/* uses only xmm0 and xmm1 */
do_aesni_dec (ctx);
asm volatile
("pxor %%xmm5, %%xmm0\n\t" /* xor IV with output */
"movdqu %%xmm0, %[outbuf]\n\t"
"movdqu %%xmm2, %%xmm5\n\t" /* store savebuf as new IV */
: [outbuf] "=m" (*outbuf)
:
: "memory");
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
asm volatile
("movdqu %%xmm5, %[iv]\n\t" /* store IV */
: /* No output */
: [iv] "m" (*iv)
: "memory");
aesni_cleanup ();
aesni_cleanup_2_7 ();
}
static ALWAYS_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"
"vpxor %[ptr4], %%ymm0, %%ymm0\n\t"
"vpxor %[ptr5], %%ymm4, %%ymm4\n\t"
"vpxor %[ptr6], %%ymm5, %%ymm5\n\t"
"vpxor %[ptr7], %%ymm7, %%ymm7\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)),
[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"
"vxorpd %[ptr4], %%ymm0, %%ymm0\n\t"
"vxorpd %[ptr5], %%ymm4, %%ymm4\n\t"
"vxorpd %[ptr6], %%ymm5, %%ymm5\n\t"
"vxorpd %[ptr7], %%ymm7, %%ymm7\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)),
[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 unsigned int NO_INLINE
aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks)
{
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;
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_7 ();
/* Preload Offset */
asm volatile ("movdqu %[iv], %%xmm5\n\t"
"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 = aes_ocb_get_l(c, ++n);
/* 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, %%xmm7\n\t"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_aesni_enc (ctx);
asm volatile ("pxor %%xmm5, %%xmm0\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
#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"
"aesenclast %%xmm5, %%xmm11\n\t"
"pxor %[lxfkey], %%xmm11\n\t"
"movdqu %%xmm1, %[outbuf0]\n\t"
"movdqu %%xmm2, %[outbuf1]\n\t"
"movdqu %%xmm3, %[outbuf2]\n\t"
"movdqu %%xmm4, %[outbuf3]\n\t"
"movdqu %%xmm8, %[outbuf4]\n\t"
"movdqu %%xmm9, %[outbuf5]\n\t"
"movdqu %%xmm10, %[outbuf6]\n\t"
"movdqu %%xmm11, %[outbuf7]\n\t"
: [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
[outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
[outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
[outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
[outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE)),
[outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE)),
[outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE)),
[outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
: [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
[tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
[tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE)),
[lxfkey] "m" (*lxf_key)
: "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 = aes_ocb_get_l(c, n);
/* 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"
"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], %%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]),
[l3] "m" (*l)
: "memory" );
asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
"pxor %%xmm5, %%xmm3\n\t"
"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 ("pxor %%xmm6, %%xmm5\n\t"
"pxor %%xmm4, %%xmm5\n\t"
"movdqu %[inbuf3], %%xmm4\n\t"
"pxor %%xmm4, %%xmm7\n\t"
"pxor %%xmm5, %%xmm4\n\t"
:
: [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
: "memory" );
do_aesni_enc_vec4 (ctx);
asm volatile ("pxor %[tmpbuf0],%%xmm1\n\t"
"movdqu %%xmm1, %[outbuf0]\n\t"
"pxor %[tmpbuf1],%%xmm2\n\t"
"movdqu %%xmm2, %[outbuf1]\n\t"
"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)),
[outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
: [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
[tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
[tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE))
: "memory" );
outbuf += 4*BLOCKSIZE;
inbuf += 4*BLOCKSIZE;
}
for ( ;nblocks; nblocks-- )
{
l = aes_ocb_get_l(c, ++n);
/* 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, %%xmm7\n\t"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_aesni_enc (ctx);
asm volatile ("pxor %%xmm5, %%xmm0\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
c->u_mode.ocb.data_nblocks = n;
asm volatile ("movdqu %%xmm5, %[iv]\n\t"
"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_7 ();
return 0;
}
static unsigned int NO_INLINE
aesni_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;
u64 n = c->u_mode.ocb.data_nblocks;
const unsigned char *l;
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_7 ();
if ( !ctx->decryption_prepared )
{
do_aesni_prepare_decryption ( ctx );
ctx->decryption_prepared = 1;
}
/* Preload Offset */
asm volatile ("movdqu %[iv], %%xmm5\n\t"
: /* No output */
: [iv] "m" (*c->u_iv.iv)
: "memory" );
for ( ;nblocks && n % 4; nblocks-- )
{
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) */
asm volatile ("movdqu %[l], %%xmm1\n\t"
"movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm1, %%xmm5\n\t"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_aesni_dec (ctx);
asm volatile ("pxor %%xmm5, %%xmm0\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
#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"
"aesdeclast %%xmm5, %%xmm11\n\t"
"pxor %[lxfkey], %%xmm11\n\t"
"movdqu %%xmm1, %[outbuf0]\n\t"
"movdqu %%xmm2, %[outbuf1]\n\t"
"movdqu %%xmm3, %[outbuf2]\n\t"
"movdqu %%xmm4, %[outbuf3]\n\t"
"movdqu %%xmm8, %[outbuf4]\n\t"
"movdqu %%xmm9, %[outbuf5]\n\t"
"movdqu %%xmm10, %[outbuf6]\n\t"
"movdqu %%xmm11, %[outbuf7]\n\t"
: [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
[outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
[outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
[outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
[outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE)),
[outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE)),
[outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE)),
[outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
: [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
[tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
[tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE)),
[lxfkey] "m" (*lxf_key)
: "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 = aes_ocb_get_l(c, n);
/* Offset_i = Offset_{i-1} xor L_{ntz(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"
"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], %%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]),
[l3] "m" (*l)
: "memory" );
asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
"pxor %%xmm5, %%xmm3\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 %%xmm0, %%xmm3\n\t"
"movdqa %%xmm0, %[tmpbuf2]\n\t"
: [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
:
[inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
: "memory" );
asm volatile ("pxor %%xmm6, %%xmm5\n\t"
"pxor %%xmm4, %%xmm5\n\t"
"movdqu %[inbuf3], %%xmm4\n\t"
"pxor %%xmm5, %%xmm4\n\t"
:
: [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
: "memory" );
do_aesni_dec_vec4 (ctx);
asm volatile ("pxor %[tmpbuf0],%%xmm1\n\t"
"movdqu %%xmm1, %[outbuf0]\n\t"
"pxor %[tmpbuf1],%%xmm2\n\t"
"movdqu %%xmm2, %[outbuf1]\n\t"
"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)),
[outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
: [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
[tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
[tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE))
: "memory" );
outbuf += 4*BLOCKSIZE;
inbuf += 4*BLOCKSIZE;
}
for ( ;nblocks; nblocks-- )
{
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"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_aesni_dec (ctx);
asm volatile ("pxor %%xmm5, %%xmm0\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
c->u_mode.ocb.data_nblocks = n;
asm volatile ("movdqu %%xmm5, %[iv]\n\t"
: [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_7 ();
return 0;
}
size_t
_gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks, int encrypt)
{
if (encrypt)
return aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
else
return aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
}
size_t
_gcry_aes_aesni_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;
u64 n = c->u_mode.ocb.aad_nblocks;
const unsigned char *l;
aesni_prepare_2_7_variable;
aesni_prepare ();
aesni_prepare_2_7 ();
/* Preload Offset and Sum */
asm volatile ("movdqu %[iv], %%xmm5\n\t"
"movdqu %[ctr], %%xmm6\n\t"
: /* No output */
: [iv] "m" (*c->u_mode.ocb.aad_offset),
[ctr] "m" (*c->u_mode.ocb.aad_sum)
: "memory" );
for ( ;nblocks && n % 4; nblocks-- )
{
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 %[l], %%xmm1\n\t"
"movdqu %[abuf], %%xmm0\n\t"
"pxor %%xmm1, %%xmm5\n\t"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[abuf] "m" (*abuf)
: "memory" );
do_aesni_enc (ctx);
asm volatile ("pxor %%xmm0, %%xmm6\n\t"
:
:
: "memory" );
abuf += BLOCKSIZE;
}
#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"
"movdqu %[abuf4], %%xmm8\n\t"
"movdqu %[abuf5], %%xmm9\n\t"
"movdqu %[abuf6], %%xmm10\n\t"
"movdqu %[abuf7], %%xmm11\n\t"
:
: [abuf0] "m" (*(abuf + 0 * BLOCKSIZE)),
[abuf1] "m" (*(abuf + 1 * BLOCKSIZE)),
[abuf2] "m" (*(abuf + 2 * BLOCKSIZE)),
[abuf3] "m" (*(abuf + 3 * BLOCKSIZE)),
[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"
"pxor %%xmm5, %%xmm4\n\t"
"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"
:
:
: "memory" );
do_aesni_enc_vec8 (ctx);
asm volatile ("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 = 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"
"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], %%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]),
[l3] "m" (*l)
: "memory" );
asm volatile ("movdqu %[abuf1], %%xmm2\n\t"
"pxor %%xmm5, %%xmm3\n\t"
"pxor %%xmm3, %%xmm2\n\t"
:
: [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
: "memory" );
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 %%xmm5, %%xmm4\n\t"
:
: [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
: "memory" );
do_aesni_enc_vec4 (ctx);
asm volatile ("pxor %%xmm1, %%xmm6\n\t"
"pxor %%xmm2, %%xmm6\n\t"
"pxor %%xmm3, %%xmm6\n\t"
"pxor %%xmm4, %%xmm6\n\t"
:
:
: "memory" );
abuf += 4*BLOCKSIZE;
}
for ( ;nblocks; nblocks-- )
{
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 %[l], %%xmm1\n\t"
"movdqu %[abuf], %%xmm0\n\t"
"pxor %%xmm1, %%xmm5\n\t"
"pxor %%xmm5, %%xmm0\n\t"
:
: [l] "m" (*l),
[abuf] "m" (*abuf)
: "memory" );
do_aesni_enc (ctx);
asm volatile ("pxor %%xmm0, %%xmm6\n\t"
:
:
: "memory" );
abuf += BLOCKSIZE;
}
c->u_mode.ocb.aad_nblocks = n;
asm volatile ("movdqu %%xmm5, %[iv]\n\t"
"movdqu %%xmm6, %[ctr]\n\t"
: [iv] "=m" (*c->u_mode.ocb.aad_offset),
[ctr] "=m" (*c->u_mode.ocb.aad_sum)
:
: "memory" );
aesni_cleanup ();
aesni_cleanup_2_7 ();
return 0;
}
static const u64 xts_gfmul_const[16] __attribute__ ((aligned (16))) =
{ 0x87, 0x01 };
static void
_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" );
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
_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" );
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
_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 */
diff --git a/cipher/rijndael-amd64.S b/cipher/rijndael-amd64.S
index 3dcaa856..a341f1fe 100644
--- a/cipher/rijndael-amd64.S
+++ b/cipher/rijndael-amd64.S
@@ -1,477 +1,477 @@
/* rinjdael-amd64.S - AMD64 assembly implementation of AES cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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(USE_AES)
#include "asm-common-amd64.h"
.text
/* table macros */
#define E0 (0)
#define Es0 (1)
#define Esize 4
#define Essize 4
#define D0 (0)
#define Ds0 (4 * 256)
#define Dsize 4
#define Dssize 1
/* register macros */
#define CTX %rdi
#define RTAB %r12
#define RA %rax
#define RB %rbx
#define RC %rcx
#define RD %rdx
#define RAd %eax
#define RBd %ebx
#define RCd %ecx
#define RDd %edx
#define RAbl %al
#define RBbl %bl
#define RCbl %cl
#define RDbl %dl
#define RAbh %ah
#define RBbh %bh
#define RCbh %ch
#define RDbh %dh
#define RNA %r8
#define RNB %r9
#define RNC %r10
#define RND %r11
#define RNAd %r8d
#define RNBd %r9d
#define RNCd %r10d
#define RNDd %r11d
#define RT0 %rbp
#define RT1 %rsi
#define RT0d %ebp
#define RT1d %esi
/* helper macros */
#define do16bit(op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
movzbl source ## bl, t0 ## d; \
movzbl source ## bh, t1 ## d; \
op ## l table1(RTAB,t0,tablemul), dest1 ## d; \
op ## l table2(RTAB,t1,tablemul), dest2 ## d;
#define do16bit_shr(shf, op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
movzbl source ## bl, t0 ## d; \
movzbl source ## bh, t1 ## d; \
shrl $(shf), source ## d; \
op ## l table1(RTAB,t0,tablemul), dest1 ## d; \
op ## l table2(RTAB,t1,tablemul), dest2 ## d;
#define last_do16bit(op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
movzbl source ## bl, t0 ## d; \
movzbl source ## bh, t1 ## d; \
movzbl table1(RTAB,t0,tablemul), t0 ## d; \
movzbl table2(RTAB,t1,tablemul), t1 ## d; \
op ## l t0 ## d, dest1 ## d; \
op ## l t1 ## d, dest2 ## d;
#define last_do16bit_shr(shf, op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \
movzbl source ## bl, t0 ## d; \
movzbl source ## bh, t1 ## d; \
shrl $(shf), source ## d; \
movzbl table1(RTAB,t0,tablemul), t0 ## d; \
movzbl table2(RTAB,t1,tablemul), t1 ## d; \
op ## l t0 ## d, dest1 ## d; \
op ## l t1 ## d, dest2 ## d;
/***********************************************************************
* AMD64 assembly implementation of the AES cipher
***********************************************************************/
#define addroundkey(round, ra, rb, rc, rd) \
xorl (((round) * 16) + 0 * 4)(CTX), ra ## d; \
xorl (((round) * 16) + 1 * 4)(CTX), rb ## d; \
xorl (((round) * 16) + 2 * 4)(CTX), rc ## d; \
xorl (((round) * 16) + 3 * 4)(CTX), rd ## d;
#define do_encround(next_r) \
do16bit_shr(16, mov, RA, Esize, E0, RNA, E0, RND, RT0, RT1); \
do16bit( mov, RA, Esize, E0, RNC, E0, RNB, RT0, RT1); \
movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
roll $8, RNDd; \
xorl RNAd, RAd; \
roll $8, RNCd; \
roll $8, RNBd; \
roll $8, RAd; \
\
do16bit_shr(16, xor, RD, Esize, E0, RND, E0, RNC, RT0, RT1); \
do16bit( xor, RD, Esize, E0, RNB, E0, RA, RT0, RT1); \
movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
roll $8, RNCd; \
xorl RNDd, RDd; \
roll $8, RNBd; \
roll $8, RAd; \
roll $8, RDd; \
\
do16bit_shr(16, xor, RC, Esize, E0, RNC, E0, RNB, RT0, RT1); \
do16bit( xor, RC, Esize, E0, RA, E0, RD, RT0, RT1); \
movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
roll $8, RNBd; \
xorl RNCd, RCd; \
roll $8, RAd; \
roll $8, RDd; \
roll $8, RCd; \
\
do16bit_shr(16, xor, RB, Esize, E0, RNB, E0, RA, RT0, RT1); \
do16bit( xor, RB, Esize, E0, RD, E0, RC, RT0, RT1); \
movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
roll $8, RAd; \
xorl RNBd, RBd; \
roll $16, RDd; \
roll $24, RCd;
#define do_lastencround(next_r) \
do16bit_shr(16, movzb, RA, Essize, Es0, RNA, Es0, RND, RT0, RT1); \
do16bit( movzb, RA, Essize, Es0, RNC, Es0, RNB, RT0, RT1); \
movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
roll $8, RNDd; \
xorl RNAd, RAd; \
roll $8, RNCd; \
roll $8, RNBd; \
roll $8, RAd; \
\
last_do16bit_shr(16, xor, RD, Essize, Es0, RND, Es0, RNC, RT0, RT1); \
last_do16bit( xor, RD, Essize, Es0, RNB, Es0, RA, RT0, RT1); \
movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
roll $8, RNCd; \
xorl RNDd, RDd; \
roll $8, RNBd; \
roll $8, RAd; \
roll $8, RDd; \
\
last_do16bit_shr(16, xor, RC, Essize, Es0, RNC, Es0, RNB, RT0, RT1); \
last_do16bit( xor, RC, Essize, Es0, RA, Es0, RD, RT0, RT1); \
movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
roll $8, RNBd; \
xorl RNCd, RCd; \
roll $8, RAd; \
roll $8, RDd; \
roll $8, RCd; \
\
last_do16bit_shr(16, xor, RB, Essize, Es0, RNB, Es0, RA, RT0, RT1); \
last_do16bit( xor, RB, Essize, Es0, RD, Es0, RC, RT0, RT1); \
movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
roll $8, RAd; \
xorl RNBd, RBd; \
roll $16, RDd; \
roll $24, RCd;
#define firstencround(round) \
addroundkey(round, RA, RB, RC, RD); \
do_encround((round) + 1);
#define encround(round) \
do_encround((round) + 1);
#define lastencround(round) \
do_lastencround((round) + 1);
.align 8
.globl _gcry_aes_amd64_encrypt_block
ELF(.type _gcry_aes_amd64_encrypt_block,@function;)
_gcry_aes_amd64_encrypt_block:
/* input:
* %rdi: keysched, CTX
* %rsi: dst
* %rdx: src
* %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;
/* read input block */
movl 0 * 4(%rdx), RAd;
movl 1 * 4(%rdx), RBd;
movl 2 * 4(%rdx), RCd;
movl 3 * 4(%rdx), RDd;
firstencround(0);
encround(1);
encround(2);
encround(3);
encround(4);
encround(5);
encround(6);
encround(7);
encround(8);
cmpl $12, (1 * 8)(%rsp);
jnb .Lenc_not_128;
lastencround(9);
.align 4
.Lenc_done:
/* write output block */
movq (0 * 8)(%rsp), %rsi;
movl RAd, 0 * 4(%rsi);
movl RBd, 1 * 4(%rsi);
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;
EXIT_SYSV_FUNC
ret;
CFI_RESTORE_STATE();
.align 4
.Lenc_not_128:
je .Lenc_192
encround(9);
encround(10);
encround(11);
encround(12);
lastencround(13);
jmp .Lenc_done;
.align 4
.Lenc_192:
encround(9);
encround(10);
lastencround(11);
jmp .Lenc_done;
CFI_ENDPROC();
ELF(.size _gcry_aes_amd64_encrypt_block,.-_gcry_aes_amd64_encrypt_block;)
#define do_decround(next_r) \
do16bit_shr(16, mov, RA, Dsize, D0, RNA, D0, RNB, RT0, RT1); \
do16bit( mov, RA, Dsize, D0, RNC, D0, RND, RT0, RT1); \
movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
roll $8, RNBd; \
xorl RNAd, RAd; \
roll $8, RNCd; \
roll $8, RNDd; \
roll $8, RAd; \
\
do16bit_shr(16, xor, RB, Dsize, D0, RNB, D0, RNC, RT0, RT1); \
do16bit( xor, RB, Dsize, D0, RND, D0, RA, RT0, RT1); \
movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
roll $8, RNCd; \
xorl RNBd, RBd; \
roll $8, RNDd; \
roll $8, RAd; \
roll $8, RBd; \
\
do16bit_shr(16, xor, RC, Dsize, D0, RNC, D0, RND, RT0, RT1); \
do16bit( xor, RC, Dsize, D0, RA, D0, RB, RT0, RT1); \
movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
roll $8, RNDd; \
xorl RNCd, RCd; \
roll $8, RAd; \
roll $8, RBd; \
roll $8, RCd; \
\
do16bit_shr(16, xor, RD, Dsize, D0, RND, D0, RA, RT0, RT1); \
do16bit( xor, RD, Dsize, D0, RB, D0, RC, RT0, RT1); \
movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
roll $8, RAd; \
xorl RNDd, RDd; \
roll $16, RBd; \
roll $24, RCd;
#define do_lastdecround(next_r) \
do16bit_shr(16, movzb, RA, Dssize, Ds0, RNA, Ds0, RNB, RT0, RT1); \
do16bit( movzb, RA, Dssize, Ds0, RNC, Ds0, RND, RT0, RT1); \
movl (((next_r) * 16) + 0 * 4)(CTX), RAd; \
roll $8, RNBd; \
xorl RNAd, RAd; \
roll $8, RNCd; \
roll $8, RNDd; \
roll $8, RAd; \
\
last_do16bit_shr(16, xor, RB, Dssize, Ds0, RNB, Ds0, RNC, RT0, RT1); \
last_do16bit( xor, RB, Dssize, Ds0, RND, Ds0, RA, RT0, RT1); \
movl (((next_r) * 16) + 1 * 4)(CTX), RBd; \
roll $8, RNCd; \
xorl RNBd, RBd; \
roll $8, RNDd; \
roll $8, RAd; \
roll $8, RBd; \
\
last_do16bit_shr(16, xor, RC, Dssize, Ds0, RNC, Ds0, RND, RT0, RT1); \
last_do16bit( xor, RC, Dssize, Ds0, RA, Ds0, RB, RT0, RT1); \
movl (((next_r) * 16) + 2 * 4)(CTX), RCd; \
roll $8, RNDd; \
xorl RNCd, RCd; \
roll $8, RAd; \
roll $8, RBd; \
roll $8, RCd; \
\
last_do16bit_shr(16, xor, RD, Dssize, Ds0, RND, Ds0, RA, RT0, RT1); \
last_do16bit( xor, RD, Dssize, Ds0, RB, Ds0, RC, RT0, RT1); \
movl (((next_r) * 16) + 3 * 4)(CTX), RDd; \
roll $8, RAd; \
xorl RNDd, RDd; \
roll $16, RBd; \
roll $24, RCd;
#define firstdecround(round) \
addroundkey((round + 1), RA, RB, RC, RD); \
do_decround(round);
#define decround(round) \
do_decround(round);
#define lastdecround(round) \
do_lastdecround(round);
.align 8
.globl _gcry_aes_amd64_decrypt_block
ELF(.type _gcry_aes_amd64_decrypt_block,@function;)
_gcry_aes_amd64_decrypt_block:
/* input:
* %rdi: keysched, CTX
* %rsi: dst
* %rdx: src
* %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;
/* read input block */
movl 0 * 4(%rdx), RAd;
movl 1 * 4(%rdx), RBd;
movl 2 * 4(%rdx), RCd;
movl 3 * 4(%rdx), RDd;
cmpl $12, (1 * 8)(%rsp);
jnb .Ldec_256;
firstdecround(9);
.align 4
.Ldec_tail:
decround(8);
decround(7);
decround(6);
decround(5);
decround(4);
decround(3);
decround(2);
decround(1);
lastdecround(0);
/* write output block */
movq (0 * 8)(%rsp), %rsi;
movl RAd, 0 * 4(%rsi);
movl RBd, 1 * 4(%rsi);
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;
EXIT_SYSV_FUNC
ret;
CFI_RESTORE_STATE();
.align 4
.Ldec_256:
je .Ldec_192;
firstdecround(13);
decround(12);
decround(11);
decround(10);
decround(9);
jmp .Ldec_tail;
.align 4
.Ldec_192:
firstdecround(11);
decround(10);
decround(9);
jmp .Ldec_tail;
CFI_ENDPROC();
ELF(.size _gcry_aes_amd64_decrypt_block,.-_gcry_aes_amd64_decrypt_block;)
#endif /*USE_AES*/
#endif /*__x86_64*/
diff --git a/cipher/rijndael-arm.S b/cipher/rijndael-arm.S
index e680c817..90f4554c 100644
--- a/cipher/rijndael-arm.S
+++ b/cipher/rijndael-arm.S
@@ -1,581 +1,581 @@
/* rijndael-arm.S - ARM assembly implementation of AES cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.arm
/* register macros */
#define CTX %r0
#define RTAB %lr
#define RMASK %ip
#define RA %r4
#define RB %r5
#define RC %r6
#define RD %r7
#define RNA %r8
#define RNB %r9
#define RNC %r10
#define RND %r11
#define RT0 %r1
#define RT1 %r2
#define RT2 %r3
/* helper macros */
#define ldr_unaligned_le(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 0)]; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 3)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_le(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 0)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 1)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 2)]; \
strb rtmp0, [rdst, #((offs) + 3)];
/***********************************************************************
* ARM assembly implementation of the AES cipher
***********************************************************************/
#define preload_first_key(round, ra) \
ldr ra, [CTX, #(((round) * 16) + 0 * 4)];
#define dummy(round, ra) /* nothing */
#define addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldm CTX, {rna, rnb, rnc, rnd}; \
eor ra, rna; \
eor rb, rnb; \
eor rc, rnc; \
preload_key(1, rna); \
eor rd, rnd;
#define do_encround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
\
and RT0, RMASK, ra, lsl#2; \
ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
and RT1, RMASK, ra, lsr#(8 - 2); \
ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldr RT0, [RTAB, RT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rna, rna, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rd, lsl#2; \
ldr ra, [RTAB, ra]; \
\
eor rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#(8 - 2); \
eor rnc, rnc, RT2, ror #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
eor rnb, rnb, ra, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnd, rnd, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rc, lsl#2; \
ldr rd, [RTAB, rd]; \
\
eor rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
eor rnb, rnb, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
eor rna, rna, rd, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnc, rnc, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rb, lsl#2; \
ldr rc, [RTAB, rc]; \
\
eor rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
eor rna, rna, RT2, ror #16; \
and RT2, RMASK, rb, lsr#(16 - 2); \
eor rnd, rnd, rc, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rb, RMASK, rb, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnb, rnb, RT0; \
ldr RT2, [RTAB, RT2]; \
eor rna, rna, RT1, ror #24; \
ldr rb, [RTAB, rb]; \
\
eor rnd, rnd, RT2, ror #16; \
preload_key((next_r) + 1, ra); \
eor rnc, rnc, rb, ror #8;
#define do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
and RT0, RMASK, ra, lsl#2; \
and RT1, RMASK, ra, lsr#(8 - 2); \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldrb rna, [RTAB, RT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
ldrb rnd, [RTAB, RT1]; \
and RT0, RMASK, rd, lsl#2; \
ldrb rnc, [RTAB, RT2]; \
mov rnd, rnd, ror #24; \
ldrb rnb, [RTAB, ra]; \
and RT1, RMASK, rd, lsr#(8 - 2); \
mov rnc, rnc, ror #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
mov rnb, rnb, ror #8; \
ldrb RT0, [RTAB, RT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
ldrb RT1, [RTAB, RT1]; \
\
orr rnd, rnd, RT0; \
ldrb RT2, [RTAB, RT2]; \
and RT0, RMASK, rc, lsl#2; \
ldrb rd, [RTAB, rd]; \
orr rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
orr rnb, rnb, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
orr rna, rna, rd, ror #8; \
ldrb RT0, [RTAB, RT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
ldrb RT1, [RTAB, RT1]; \
\
orr rnc, rnc, RT0; \
ldrb RT2, [RTAB, RT2]; \
and RT0, RMASK, rb, lsl#2; \
ldrb rc, [RTAB, rc]; \
orr rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
orr rna, rna, RT2, ror #16; \
ldrb RT0, [RTAB, RT0]; \
and RT2, RMASK, rb, lsr#(16 - 2); \
ldrb RT1, [RTAB, RT1]; \
orr rnd, rnd, rc, ror #8; \
ldrb RT2, [RTAB, RT2]; \
and rb, RMASK, rb, lsr#(24 - 2); \
ldrb rb, [RTAB, rb]; \
\
orr rnb, rnb, RT0; \
orr rna, rna, RT1, ror #24; \
orr rnd, rnd, RT2, ror #16; \
orr rnc, rnc, rb, ror #8;
#define firstencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); \
do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
#define encround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
#define lastencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
add CTX, #(((round) + 1) * 16); \
add RTAB, #1; \
do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
.align 3
.globl _gcry_aes_arm_encrypt_block
.type _gcry_aes_arm_encrypt_block,%function;
_gcry_aes_arm_encrypt_block:
/* input:
* %r0: keysched, CTX
* %r1: dst
* %r2: src
* %r3: number of rounds.. 10, 12 or 14
* %st+0: encryption table
*/
push {%r4-%r11, %ip, %lr};
/* read input block */
/* test if src is unaligned */
tst %r2, #3;
beq 1f;
/* unaligned load */
ldr_unaligned_le(RA, %r2, 0, RNA);
ldr_unaligned_le(RB, %r2, 4, RNB);
ldr_unaligned_le(RC, %r2, 8, RNA);
ldr_unaligned_le(RD, %r2, 12, RNB);
b 2f;
.ltorg
1:
/* aligned load */
ldm %r2, {RA, RB, RC, RD};
#ifndef __ARMEL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
2:
ldr RTAB, [%sp, #40];
sub %sp, #16;
str %r1, [%sp, #4]; /* dst */
mov RMASK, #0xff;
str %r3, [%sp, #8]; /* nrounds */
mov RMASK, RMASK, lsl#2; /* byte mask */
firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
ldr RT0, [%sp, #8]; /* nrounds */
cmp RT0, #12;
bge .Lenc_not_128;
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
.Lenc_done:
ldr RT0, [%sp, #4]; /* dst */
add %sp, #16;
/* store output block */
/* test if dst is unaligned */
tst RT0, #3;
beq 1f;
/* unaligned store */
str_unaligned_le(RA, RT0, 0, RNA, RNB);
str_unaligned_le(RB, RT0, 4, RNA, RNB);
str_unaligned_le(RC, RT0, 8, RNA, RNB);
str_unaligned_le(RD, RT0, 12, RNA, RNB);
b 2f;
.ltorg
1:
/* aligned store */
#ifndef __ARMEL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
/* write output block */
stm RT0, {RA, RB, RC, RD};
2:
mov r0, #(10 * 4);
pop {%r4-%r11, %ip, %pc};
.ltorg
.Lenc_not_128:
beq .Lenc_192
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
b .Lenc_done;
.ltorg
.Lenc_192:
encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
b .Lenc_done;
.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)]; \
ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
eor ra, rna; \
ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
eor rb, rnb; \
ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
eor rc, rnc; \
preload_first_key((round) - 1, rna); \
eor rd, rnd;
#define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
\
and RT0, RMASK, ra, lsl#2; \
ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
and RT1, RMASK, ra, lsr#(8 - 2); \
ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
and RT2, RMASK, ra, lsr#(16 - 2); \
ldr RT0, [RTAB, RT0]; \
and ra, RMASK, ra, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rna, rna, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rb, lsl#2; \
ldr ra, [RTAB, ra]; \
\
eor rnb, rnb, RT1, ror #24; \
and RT1, RMASK, rb, lsr#(8 - 2); \
eor rnc, rnc, RT2, ror #16; \
and RT2, RMASK, rb, lsr#(16 - 2); \
eor rnd, rnd, ra, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rb, RMASK, rb, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnb, rnb, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rc, lsl#2; \
ldr rb, [RTAB, rb]; \
\
eor rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#(8 - 2); \
eor rnd, rnd, RT2, ror #16; \
and RT2, RMASK, rc, lsr#(16 - 2); \
eor rna, rna, rb, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rc, RMASK, rc, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnc, rnc, RT0; \
ldr RT2, [RTAB, RT2]; \
and RT0, RMASK, rd, lsl#2; \
ldr rc, [RTAB, rc]; \
\
eor rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#(8 - 2); \
eor rna, rna, RT2, ror #16; \
and RT2, RMASK, rd, lsr#(16 - 2); \
eor rnb, rnb, rc, ror #8; \
ldr RT0, [RTAB, RT0]; \
and rd, RMASK, rd, lsr#(24 - 2); \
\
ldr RT1, [RTAB, RT1]; \
eor rnd, rnd, RT0; \
ldr RT2, [RTAB, RT2]; \
eor rna, rna, RT1, ror #24; \
ldr rd, [RTAB, rd]; \
\
eor rnb, rnb, RT2, ror #16; \
preload_key((next_r) - 1, ra); \
eor rnc, rnc, rd, ror #8;
#define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
and RT0, RMASK, ra; \
and RT1, RMASK, ra, lsr#8; \
and RT2, RMASK, ra, lsr#16; \
ldrb rna, [RTAB, RT0]; \
mov ra, ra, lsr#24; \
ldrb rnb, [RTAB, RT1]; \
and RT0, RMASK, rb; \
ldrb rnc, [RTAB, RT2]; \
mov rnb, rnb, ror #24; \
ldrb rnd, [RTAB, ra]; \
and RT1, RMASK, rb, lsr#8; \
mov rnc, rnc, ror #16; \
and RT2, RMASK, rb, lsr#16; \
mov rnd, rnd, ror #8; \
ldrb RT0, [RTAB, RT0]; \
mov rb, rb, lsr#24; \
ldrb RT1, [RTAB, RT1]; \
\
orr rnb, rnb, RT0; \
ldrb RT2, [RTAB, RT2]; \
and RT0, RMASK, rc; \
ldrb rb, [RTAB, rb]; \
orr rnc, rnc, RT1, ror #24; \
and RT1, RMASK, rc, lsr#8; \
orr rnd, rnd, RT2, ror #16; \
and RT2, RMASK, rc, lsr#16; \
orr rna, rna, rb, ror #8; \
ldrb RT0, [RTAB, RT0]; \
mov rc, rc, lsr#24; \
ldrb RT1, [RTAB, RT1]; \
\
orr rnc, rnc, RT0; \
ldrb RT2, [RTAB, RT2]; \
and RT0, RMASK, rd; \
ldrb rc, [RTAB, rc]; \
orr rnd, rnd, RT1, ror #24; \
and RT1, RMASK, rd, lsr#8; \
orr rna, rna, RT2, ror #16; \
ldrb RT0, [RTAB, RT0]; \
and RT2, RMASK, rd, lsr#16; \
ldrb RT1, [RTAB, RT1]; \
orr rnb, rnb, rc, ror #8; \
ldrb RT2, [RTAB, RT2]; \
mov rd, rd, lsr#24; \
ldrb rd, [RTAB, rd]; \
\
orr rnd, rnd, RT0; \
orr rna, rna, RT1, ror #24; \
orr rnb, rnb, RT2, ror #16; \
orr rnc, rnc, rd, ror #8;
#define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
#define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
#define set_last_round_rmask(_, __) \
mov RMASK, #0xff;
#define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
add RTAB, #(4 * 256); \
do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
.align 3
.globl _gcry_aes_arm_decrypt_block
.type _gcry_aes_arm_decrypt_block,%function;
_gcry_aes_arm_decrypt_block:
/* input:
* %r0: keysched, CTX
* %r1: dst
* %r2: src
* %r3: number of rounds.. 10, 12 or 14
* %st+0: decryption table
*/
push {%r4-%r11, %ip, %lr};
/* read input block */
/* test if src is unaligned */
tst %r2, #3;
beq 1f;
/* unaligned load */
ldr_unaligned_le(RA, %r2, 0, RNA);
ldr_unaligned_le(RB, %r2, 4, RNB);
ldr_unaligned_le(RC, %r2, 8, RNA);
ldr_unaligned_le(RD, %r2, 12, RNB);
b 2f;
.ltorg
1:
/* aligned load */
ldm %r2, {RA, RB, RC, RD};
#ifndef __ARMEL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
2:
ldr RTAB, [%sp, #40];
sub %sp, #16;
mov RMASK, #0xff;
str %r1, [%sp, #4]; /* dst */
mov RMASK, RMASK, lsl#2; /* byte mask */
cmp %r3, #12;
bge .Ldec_256;
firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
.Ldec_tail:
decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
ldr RT0, [%sp, #4]; /* dst */
add %sp, #16;
/* store output block */
/* test if dst is unaligned */
tst RT0, #3;
beq 1f;
/* unaligned store */
str_unaligned_le(RA, RT0, 0, RNA, RNB);
str_unaligned_le(RB, RT0, 4, RNA, RNB);
str_unaligned_le(RC, RT0, 8, RNA, RNB);
str_unaligned_le(RD, RT0, 12, RNA, RNB);
b 2f;
.ltorg
1:
/* aligned store */
#ifndef __ARMEL__
rev RA, RA;
rev RB, RB;
rev RC, RC;
rev RD, RD;
#endif
/* write output block */
stm RT0, {RA, RB, RC, RD};
2:
mov r0, #(10 * 4);
pop {%r4-%r11, %ip, %pc};
.ltorg
.Ldec_256:
beq .Ldec_192;
firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
b .Ldec_tail;
.ltorg
.Ldec_192:
firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
b .Ldec_tail;
.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
#endif /*HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS*/
#endif /*__ARMEL__ */
diff --git a/cipher/rijndael-armv8-aarch32-ce.S b/cipher/rijndael-armv8-aarch32-ce.S
index 66440bd4..7e54a1ea 100644
--- a/cipher/rijndael-armv8-aarch32-ce.S
+++ b/cipher/rijndael-armv8-aarch32-ce.S
@@ -1,1867 +1,1867 @@
/* rijndael-armv8-aarch32-ce.S - ARMv8/CE accelerated AES
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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_AARCH32_CRYPTO)
.syntax unified
.arch armv8-a
.fpu crypto-neon-fp-armv8
.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
/* AES macros */
#define aes_preload_keys(keysched, rekeysched) \
vldmia keysched!, {q5-q7}; \
mov rekeysched, keysched; \
vldmialo keysched!, {q8-q15}; /* 128-bit */ \
addeq keysched, #(2*16); \
vldmiaeq keysched!, {q10-q15}; /* 192-bit */ \
addhi keysched, #(4*16); \
vldmiahi keysched!, {q12-q15}; /* 256-bit */ \
#define do_aes_one128(ed, mcimc, qo, qb) \
aes##ed.8 qb, q5; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q6; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q7; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q8; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q9; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q10; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q11; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q12; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q13; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q14; \
veor qo, qb, q15;
#define do_aes_one128re(ed, mcimc, qo, qb, keysched, rekeysched) \
vldm rekeysched, {q8-q9}; \
do_aes_one128(ed, mcimc, qo, qb);
#define do_aes_one192(ed, mcimc, qo, qb, keysched, rekeysched) \
vldm rekeysched!, {q8}; \
aes##ed.8 qb, q5; \
aes##mcimc.8 qb, qb; \
vldm rekeysched, {q9}; \
aes##ed.8 qb, q6; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q7; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q8; \
aes##mcimc.8 qb, qb; \
vldmia keysched!, {q8}; \
aes##ed.8 qb, q9; \
aes##mcimc.8 qb, qb; \
sub rekeysched, #(1*16); \
aes##ed.8 qb, q10; \
aes##mcimc.8 qb, qb; \
vldm keysched, {q9}; \
aes##ed.8 qb, q11; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q12; \
aes##mcimc.8 qb, qb; \
sub keysched, #16; \
aes##ed.8 qb, q13; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q14; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q15; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q8; \
veor qo, qb, q9; \
#define do_aes_one256(ed, mcimc, qo, qb, keysched, rekeysched) \
vldmia rekeysched!, {q8}; \
aes##ed.8 qb, q5; \
aes##mcimc.8 qb, qb; \
vldmia rekeysched!, {q9}; \
aes##ed.8 qb, q6; \
aes##mcimc.8 qb, qb; \
vldmia rekeysched!, {q10}; \
aes##ed.8 qb, q7; \
aes##mcimc.8 qb, qb; \
vldm rekeysched, {q11}; \
aes##ed.8 qb, q8; \
aes##mcimc.8 qb, qb; \
vldmia keysched!, {q8}; \
aes##ed.8 qb, q9; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q10; \
aes##mcimc.8 qb, qb; \
vldmia keysched!, {q9}; \
aes##ed.8 qb, q11; \
aes##mcimc.8 qb, qb; \
sub rekeysched, #(3*16); \
aes##ed.8 qb, q12; \
aes##mcimc.8 qb, qb; \
vldmia keysched!, {q10}; \
aes##ed.8 qb, q13; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q14; \
aes##mcimc.8 qb, qb; \
vldm keysched, {q11}; \
aes##ed.8 qb, q15; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q8; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q9; \
aes##mcimc.8 qb, qb; \
aes##ed.8 qb, q10; \
veor qo, qb, q11; \
sub keysched, #(3*16); \
#define aes_round_4(ed, mcimc, b0, b1, b2, b3, key) \
aes##ed.8 b0, key; \
aes##mcimc.8 b0, b0; \
aes##ed.8 b1, key; \
aes##mcimc.8 b1, b1; \
aes##ed.8 b2, key; \
aes##mcimc.8 b2, b2; \
aes##ed.8 b3, key; \
aes##mcimc.8 b3, b3;
#define do_aes_4_128(ed, mcimc, b0, b1, b2, b3) \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q5); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q6); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q7); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q8); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q9); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q10); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q11); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q12); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q13); \
aes##ed.8 b0, q14; \
veor b0, b0, q15; \
aes##ed.8 b1, q14; \
veor b1, b1, q15; \
aes##ed.8 b2, q14; \
veor b2, b2, q15; \
aes##ed.8 b3, q14; \
veor b3, b3, q15;
#define do_aes_4_128re(ed, mcimc, b0, b1, b2, b3, keysched, rekeysched) \
vldm rekeysched, {q8-q9}; \
do_aes_4_128(ed, mcimc, b0, b1, b2, b3);
#define do_aes_4_192(ed, mcimc, b0, b1, b2, b3, keysched, rekeysched) \
vldm rekeysched!, {q8}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q5); \
vldm rekeysched, {q9}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q6); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q7); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q8); \
vldmia keysched!, {q8}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q9); \
sub rekeysched, #(1*16); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q10); \
vldm keysched, {q9}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q11); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q12); \
sub keysched, #16; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q13); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q14); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q15); \
aes##ed.8 b0, q8; \
veor b0, b0, q9; \
aes##ed.8 b1, q8; \
veor b1, b1, q9; \
aes##ed.8 b2, q8; \
veor b2, b2, q9; \
aes##ed.8 b3, q8; \
veor b3, b3, q9;
#define do_aes_4_256(ed, mcimc, b0, b1, b2, b3, keysched, rekeysched) \
vldmia rekeysched!, {q8}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q5); \
vldmia rekeysched!, {q9}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q6); \
vldmia rekeysched!, {q10}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q7); \
vldm rekeysched, {q11}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q8); \
vldmia keysched!, {q8}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q9); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q10); \
vldmia keysched!, {q9}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q11); \
sub rekeysched, #(3*16); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q12); \
vldmia keysched!, {q10}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q13); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q14); \
vldm keysched, {q11}; \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q15); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q8); \
aes_round_4(ed, mcimc, b0, b1, b2, b3, q9); \
sub keysched, #(3*16); \
aes##ed.8 b0, q10; \
veor b0, b0, q11; \
aes##ed.8 b1, q10; \
veor b1, b1, q11; \
aes##ed.8 b2, q10; \
veor b2, b2, q11; \
aes##ed.8 b3, q10; \
veor b3, b3, q11;
/* Other functional macros */
#define CLEAR_REG(reg) veor reg, reg;
/*
* unsigned int _gcry_aes_enc_armv8_ce(void *keysched, byte *dst,
* const byte *src,
* unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_enc_armv8_ce
.type _gcry_aes_enc_armv8_ce,%function;
_gcry_aes_enc_armv8_ce:
/* input:
* r0: keysched
* r1: dst
* r2: src
* r3: nrounds
*/
vldmia r0!, {q1-q3} /* load 3 round keys */
cmp r3, #12
vld1.8 {q0}, [r2]
bhi .Lenc1_256
beq .Lenc1_192
.Lenc1_128:
.Lenc1_tail:
vldmia r0, {q8-q15} /* load 8 round keys */
aese.8 q0, q1
aesmc.8 q0, q0
CLEAR_REG(q1)
aese.8 q0, q2
aesmc.8 q0, q0
CLEAR_REG(q2)
aese.8 q0, q3
aesmc.8 q0, q0
CLEAR_REG(q3)
aese.8 q0, q8
aesmc.8 q0, q0
CLEAR_REG(q8)
aese.8 q0, q9
aesmc.8 q0, q0
CLEAR_REG(q9)
aese.8 q0, q10
aesmc.8 q0, q0
CLEAR_REG(q10)
aese.8 q0, q11
aesmc.8 q0, q0
CLEAR_REG(q11)
aese.8 q0, q12
aesmc.8 q0, q0
CLEAR_REG(q12)
aese.8 q0, q13
aesmc.8 q0, q0
CLEAR_REG(q13)
aese.8 q0, q14
veor q0, q15
CLEAR_REG(q14)
CLEAR_REG(q15)
vst1.8 {q0}, [r1]
CLEAR_REG(q0)
mov r0, #0
bx lr
.Lenc1_192:
aese.8 q0, q1
aesmc.8 q0, q0
vmov q1, q3
aese.8 q0, q2
aesmc.8 q0, q0
vldm r0!, {q2-q3} /* load 3 round keys */
b .Lenc1_tail
.Lenc1_256:
vldm r0!, {q15} /* load 1 round key */
aese.8 q0, q1
aesmc.8 q0, q0
aese.8 q0, q2
aesmc.8 q0, q0
aese.8 q0, q3
aesmc.8 q0, q0
vldm r0!, {q1-q3} /* load 3 round keys */
aese.8 q0, q15
aesmc.8 q0, q0
b .Lenc1_tail
.size _gcry_aes_enc_armv8_ce,.-_gcry_aes_enc_armv8_ce;
/*
* unsigned int _gcry_aes_dec_armv8_ce(void *keysched, byte *dst,
* const byte *src,
* unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_dec_armv8_ce
.type _gcry_aes_dec_armv8_ce,%function;
_gcry_aes_dec_armv8_ce:
/* input:
* r0: keysched
* r1: dst
* r2: src
* r3: nrounds
*/
vldmia r0!, {q1-q3} /* load 3 round keys */
cmp r3, #12
vld1.8 {q0}, [r2]
bhi .Ldec1_256
beq .Ldec1_192
.Ldec1_128:
.Ldec1_tail:
vldmia r0, {q8-q15} /* load 8 round keys */
aesd.8 q0, q1
aesimc.8 q0, q0
CLEAR_REG(q1)
aesd.8 q0, q2
aesimc.8 q0, q0
CLEAR_REG(q2)
aesd.8 q0, q3
aesimc.8 q0, q0
CLEAR_REG(q3)
aesd.8 q0, q8
aesimc.8 q0, q0
CLEAR_REG(q8)
aesd.8 q0, q9
aesimc.8 q0, q0
CLEAR_REG(q9)
aesd.8 q0, q10
aesimc.8 q0, q0
CLEAR_REG(q10)
aesd.8 q0, q11
aesimc.8 q0, q0
CLEAR_REG(q11)
aesd.8 q0, q12
aesimc.8 q0, q0
CLEAR_REG(q12)
aesd.8 q0, q13
aesimc.8 q0, q0
CLEAR_REG(q13)
aesd.8 q0, q14
veor q0, q15
CLEAR_REG(q14)
CLEAR_REG(q15)
vst1.8 {q0}, [r1]
CLEAR_REG(q0)
mov r0, #0
bx lr
.Ldec1_192:
aesd.8 q0, q1
aesimc.8 q0, q0
vmov q1, q3
aesd.8 q0, q2
aesimc.8 q0, q0
vldm r0!, {q2-q3} /* load 3 round keys */
b .Ldec1_tail
.Ldec1_256:
vldm r0!, {q15} /* load 1 round key */
aesd.8 q0, q1
aesimc.8 q0, q0
aesd.8 q0, q2
aesimc.8 q0, q0
aesd.8 q0, q3
aesimc.8 q0, q0
vldm r0!, {q1-q3} /* load 3 round keys */
aesd.8 q0, q15
aesimc.8 q0, q0
b .Ldec1_tail
.size _gcry_aes_dec_armv8_ce,.-_gcry_aes_dec_armv8_ce;
/*
* void _gcry_aes_cbc_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, size_t nblocks,
* int cbc_mac, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cbc_enc_armv8_ce
.type _gcry_aes_cbc_enc_armv8_ce,%function;
_gcry_aes_cbc_enc_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* %st+0: nblocks => r4
* %st+4: cbc_mac => r5
* %st+8: nrounds => r6
*/
push {r4-r6,lr} /* 4*4 = 16b */
ldr r4, [sp, #(16+0)]
ldr r5, [sp, #(16+4)]
cmp r4, #0
ldr r6, [sp, #(16+8)]
beq .Lcbc_enc_skip
cmp r5, #0
vpush {q4-q7}
moveq r5, #16
movne r5, #0
cmp r6, #12
vld1.8 {q1}, [r3] /* load IV */
aes_preload_keys(r0, lr);
beq .Lcbc_enc_loop192
bhi .Lcbc_enc_loop256
#define CBC_ENC(bits, ...) \
.Lcbc_enc_loop##bits: \
vld1.8 {q0}, [r2]!; /* load plaintext */ \
veor q1, q0, q1; \
subs r4, r4, #1; \
\
do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__); \
\
vst1.8 {q1}, [r1], r5; /* store ciphertext */ \
\
bne .Lcbc_enc_loop##bits; \
b .Lcbc_enc_done;
CBC_ENC(128)
CBC_ENC(192, r0, lr)
CBC_ENC(256, r0, lr)
#undef CBC_ENC
.Lcbc_enc_done:
vst1.8 {q1}, [r3] /* store IV */
CLEAR_REG(q0)
CLEAR_REG(q1)
CLEAR_REG(q2)
CLEAR_REG(q3)
CLEAR_REG(q8)
CLEAR_REG(q9)
vpop {q4-q7}
CLEAR_REG(q10)
CLEAR_REG(q11)
CLEAR_REG(q12)
CLEAR_REG(q13)
CLEAR_REG(q14)
.Lcbc_enc_skip:
pop {r4-r6,pc}
.size _gcry_aes_cbc_enc_armv8_ce,.-_gcry_aes_cbc_enc_armv8_ce;
/*
* void _gcry_aes_cbc_dec_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cbc_dec_armv8_ce
.type _gcry_aes_cbc_dec_armv8_ce,%function;
_gcry_aes_cbc_dec_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* %st+0: nblocks => r4
* %st+4: nrounds => r5
*/
push {r4-r6,lr} /* 4*4 = 16b */
ldr r4, [sp, #(16+0)]
ldr r5, [sp, #(16+4)]
cmp r4, #0
beq .Lcbc_dec_skip
vpush {q4-q7}
cmp r5, #12
vld1.8 {q0}, [r3] /* load IV */
aes_preload_keys(r0, r6);
beq .Lcbc_dec_entry_192
bhi .Lcbc_dec_entry_256
#define CBC_DEC(bits, ...) \
.Lcbc_dec_entry_##bits: \
cmp r4, #4; \
blo .Lcbc_dec_loop_##bits; \
\
.Lcbc_dec_loop4_##bits: \
\
vld1.8 {q1-q2}, [r2]!; /* load ciphertext */ \
sub r4, r4, #4; \
vld1.8 {q3-q4}, [r2]; /* load ciphertext */ \
cmp r4, #4; \
sub r2, #32; \
\
do_aes_4_##bits(d, imc, q1, q2, q3, q4, ##__VA_ARGS__); \
\
veor q1, q1, q0; \
vld1.8 {q0}, [r2]!; /* load next IV */ \
veor q2, q2, q0; \
vld1.8 {q0}, [r2]!; /* load next IV */ \
vst1.8 {q1-q2}, [r1]!; /* store plaintext */ \
veor q3, q3, q0; \
vld1.8 {q0}, [r2]!; /* load next IV */ \
veor q4, q4, q0; \
vld1.8 {q0}, [r2]!; /* load next IV */ \
vst1.8 {q3-q4}, [r1]!; /* store plaintext */ \
\
bhs .Lcbc_dec_loop4_##bits; \
cmp r4, #0; \
beq .Lcbc_dec_done; \
\
.Lcbc_dec_loop_##bits: \
vld1.8 {q1}, [r2]!; /* load ciphertext */ \
subs r4, r4, #1; \
vmov q2, q1; \
\
do_aes_one##bits(d, imc, q1, q1, ##__VA_ARGS__); \
\
veor q1, q1, q0; \
vmov q0, q2; \
vst1.8 {q1}, [r1]!; /* store plaintext */ \
\
bne .Lcbc_dec_loop_##bits; \
b .Lcbc_dec_done;
CBC_DEC(128)
CBC_DEC(192, r0, r6)
CBC_DEC(256, r0, r6)
#undef CBC_DEC
.Lcbc_dec_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)
vpop {q4-q7}
CLEAR_REG(q10)
CLEAR_REG(q11)
CLEAR_REG(q12)
CLEAR_REG(q13)
CLEAR_REG(q14)
.Lcbc_dec_skip:
pop {r4-r6,pc}
.size _gcry_aes_cbc_dec_armv8_ce,.-_gcry_aes_cbc_dec_armv8_ce;
/*
* void _gcry_aes_cfb_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cfb_enc_armv8_ce
.type _gcry_aes_cfb_enc_armv8_ce,%function;
_gcry_aes_cfb_enc_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* %st+0: nblocks => r4
* %st+4: nrounds => r5
*/
push {r4-r6,lr} /* 4*4 = 16b */
ldr r4, [sp, #(16+0)]
ldr r5, [sp, #(16+4)]
cmp r4, #0
beq .Lcfb_enc_skip
vpush {q4-q7}
cmp r5, #12
vld1.8 {q0}, [r3] /* load IV */
aes_preload_keys(r0, r6);
beq .Lcfb_enc_entry_192
bhi .Lcfb_enc_entry_256
#define CFB_ENC(bits, ...) \
.Lcfb_enc_entry_##bits: \
.Lcfb_enc_loop_##bits: \
vld1.8 {q1}, [r2]!; /* load plaintext */ \
subs r4, r4, #1; \
\
do_aes_one##bits(e, mc, q0, q0, ##__VA_ARGS__); \
\
veor q0, q1, q0; \
vst1.8 {q0}, [r1]!; /* store ciphertext */ \
\
bne .Lcfb_enc_loop_##bits; \
b .Lcfb_enc_done;
CFB_ENC(128)
CFB_ENC(192, r0, r6)
CFB_ENC(256, r0, r6)
#undef CFB_ENC
.Lcfb_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)
vpop {q4-q7}
CLEAR_REG(q10)
CLEAR_REG(q11)
CLEAR_REG(q12)
CLEAR_REG(q13)
CLEAR_REG(q14)
.Lcfb_enc_skip:
pop {r4-r6,pc}
.size _gcry_aes_cfb_enc_armv8_ce,.-_gcry_aes_cfb_enc_armv8_ce;
/*
* void _gcry_aes_cfb_dec_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cfb_dec_armv8_ce
.type _gcry_aes_cfb_dec_armv8_ce,%function;
_gcry_aes_cfb_dec_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* %st+0: nblocks => r4
* %st+4: nrounds => r5
*/
push {r4-r6,lr} /* 4*4 = 16b */
ldr r4, [sp, #(16+0)]
ldr r5, [sp, #(16+4)]
cmp r4, #0
beq .Lcfb_dec_skip
vpush {q4-q7}
cmp r5, #12
vld1.8 {q0}, [r3] /* load IV */
aes_preload_keys(r0, r6);
beq .Lcfb_dec_entry_192
bhi .Lcfb_dec_entry_256
#define CFB_DEC(bits, ...) \
.Lcfb_dec_entry_##bits: \
cmp r4, #4; \
blo .Lcfb_dec_loop_##bits; \
\
.Lcfb_dec_loop4_##bits: \
\
vld1.8 {q2-q3}, [r2]!; /* load ciphertext */ \
vmov q1, q0; \
sub r4, r4, #4; \
vld1.8 {q4}, [r2]; /* load ciphertext */ \
sub r2, #32; \
cmp r4, #4; \
\
do_aes_4_##bits(e, mc, q1, q2, q3, q4, ##__VA_ARGS__); \
\
vld1.8 {q0}, [r2]!; /* load ciphertext */ \
veor q1, q1, q0; \
vld1.8 {q0}, [r2]!; /* load ciphertext */ \
veor q2, q2, q0; \
vst1.8 {q1-q2}, [r1]!; /* store plaintext */ \
vld1.8 {q0}, [r2]!; \
veor q3, q3, q0; \
vld1.8 {q0}, [r2]!; /* load next IV / ciphertext */ \
veor q4, q4, q0; \
vst1.8 {q3-q4}, [r1]!; /* store plaintext */ \
\
bhs .Lcfb_dec_loop4_##bits; \
cmp r4, #0; \
beq .Lcfb_dec_done; \
\
.Lcfb_dec_loop_##bits: \
\
vld1.8 {q1}, [r2]!; /* load ciphertext */ \
\
subs r4, r4, #1; \
\
do_aes_one##bits(e, mc, q0, q0, ##__VA_ARGS__); \
\
veor q2, q1, q0; \
vmov q0, q1; \
vst1.8 {q2}, [r1]!; /* store plaintext */ \
\
bne .Lcfb_dec_loop_##bits; \
b .Lcfb_dec_done;
CFB_DEC(128)
CFB_DEC(192, r0, r6)
CFB_DEC(256, r0, r6)
#undef CFB_DEC
.Lcfb_dec_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)
vpop {q4-q7}
CLEAR_REG(q10)
CLEAR_REG(q11)
CLEAR_REG(q12)
CLEAR_REG(q13)
CLEAR_REG(q14)
.Lcfb_dec_skip:
pop {r4-r6,pc}
.size _gcry_aes_cfb_dec_armv8_ce,.-_gcry_aes_cfb_dec_armv8_ce;
/*
* void _gcry_aes_ctr_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_ctr_enc_armv8_ce
.type _gcry_aes_ctr_enc_armv8_ce,%function;
_gcry_aes_ctr_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 .Lctr_enc_skip
cmp r5, #12
ldm r3, {r7-r10}
vld1.8 {q0}, [r3] /* load IV */
rev r7, r7
rev r8, r8
rev r9, r9
rev r10, r10
aes_preload_keys(r0, r6);
beq .Lctr_enc_entry_192
bhi .Lctr_enc_entry_256
#define CTR_ENC(bits, ...) \
.Lctr_enc_entry_##bits: \
cmp r4, #4; \
blo .Lctr_enc_loop_##bits; \
\
.Lctr_enc_loop4_##bits: \
cmp r10, #0xfffffffc; \
sub r4, r4, #4; \
blo .Lctr_enc_loop4_##bits##_nocarry; \
cmp r9, #0xffffffff; \
bne .Lctr_enc_loop4_##bits##_nocarry; \
\
adds r10, #1; \
vmov q1, q0; \
blcs .Lctr_overflow_one; \
rev r11, r10; \
vmov.32 d1[1], r11; \
\
adds r10, #1; \
vmov q2, q0; \
blcs .Lctr_overflow_one; \
rev r11, r10; \
vmov.32 d1[1], r11; \
\
adds r10, #1; \
vmov q3, q0; \
blcs .Lctr_overflow_one; \
rev r11, r10; \
vmov.32 d1[1], r11; \
\
adds r10, #1; \
vmov q4, q0; \
blcs .Lctr_overflow_one; \
rev r11, r10; \
vmov.32 d1[1], r11; \
\
b .Lctr_enc_loop4_##bits##_store_ctr; \
\
.Lctr_enc_loop4_##bits##_nocarry: \
\
veor q2, q2; \
vrev64.8 q1, q0; \
vceq.u32 d5, d5; \
vadd.u64 q3, q2, q2; \
vadd.u64 q4, q3, q2; \
vadd.u64 q0, q3, q3; \
vsub.u64 q2, q1, q2; \
vsub.u64 q3, q1, q3; \
vsub.u64 q4, q1, q4; \
vsub.u64 q0, q1, q0; \
vrev64.8 q1, q1; \
vrev64.8 q2, q2; \
vrev64.8 q3, q3; \
vrev64.8 q0, q0; \
vrev64.8 q4, q4; \
add r10, #4; \
\
.Lctr_enc_loop4_##bits##_store_ctr: \
\
vst1.8 {q0}, [r3]; \
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 .Lctr_enc_loop4_##bits; \
cmp r4, #0; \
beq .Lctr_enc_done; \
\
.Lctr_enc_loop_##bits: \
\
adds r10, #1; \
vmov q1, q0; \
blcs .Lctr_overflow_one; \
rev r11, r10; \
subs r4, r4, #1; \
vld1.8 {q2}, [r2]!; /* load ciphertext */ \
vmov.32 d1[1], r11; \
\
do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__); \
\
veor q1, q2, q1; \
vst1.8 {q1}, [r1]!; /* store plaintext */ \
\
bne .Lctr_enc_loop_##bits; \
b .Lctr_enc_done;
CTR_ENC(128)
CTR_ENC(192, r0, r6)
CTR_ENC(256, r0, r6)
#undef CTR_ENC
.Lctr_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)
.Lctr_enc_skip:
pop {r4-r12,lr}
vpop {q4-q7}
bx lr
.Lctr_overflow_one:
adcs r9, #0
adcs r8, #0
adc r7, #0
rev r11, r9
rev r12, r8
vmov.32 d1[0], r11
rev r11, r7
vmov.32 d0[1], r12
vmov.32 d0[0], r11
bx lr
.size _gcry_aes_ctr_enc_armv8_ce,.-_gcry_aes_ctr_enc_armv8_ce;
/*
* void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_enc_armv8_ce
.type _gcry_aes_ocb_enc_armv8_ce,%function;
_gcry_aes_ocb_enc_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: offset
* %st+0: checksum => r4
* %st+4: Ls => r5
* %st+8: nblocks => r6 (0 < nblocks <= 32)
* %st+12: nrounds => r7
* %st+16: blkn => lr
*/
vpush {q4-q7}
push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
ldr r7, [sp, #(104+12)]
ldr r4, [sp, #(104+0)]
ldr r5, [sp, #(104+4)]
ldr r6, [sp, #(104+8)]
ldr lr, [sp, #(104+16)]
cmp r7, #12
vld1.8 {q0}, [r3] /* load offset */
aes_preload_keys(r0, r12);
beq .Locb_enc_entry_192
bhi .Locb_enc_entry_256
#define OCB_ENC(bits, ...) \
.Locb_enc_entry_##bits: \
cmp r6, #4; \
add lr, #1; \
blo .Locb_enc_loop_##bits; \
\
.Locb_enc_loop4_##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 r9, lr, #1; \
add r10, lr, #2; \
add r11, lr, #3; \
rbit r8, lr; \
add lr, lr, #4; \
rbit r9, r9; \
rbit r10, r10; \
rbit r11, r11; \
clz r8, r8; /* ntz(i+0) */ \
clz r9, r9; /* ntz(i+1) */ \
clz r10, r10; /* ntz(i+2) */ \
clz r11, r11; /* ntz(i+3) */ \
add r8, r5, r8, lsl #4; \
add r9, r5, r9, lsl #4; \
add r10, r5, r10, lsl #4; \
add r11, r5, r11, lsl #4; \
\
sub r6, #4; \
\
vld1.8 {q9}, [r8]; /* load L_{ntz(i+0)} */ \
vld1.8 {q1-q2}, [r2]!; /* load P_i+<0-1> */ \
vld1.8 {q8}, [r4]; /* load Checksum_{i-1} */ \
veor q0, q0, q9; /* Offset_i+0 */ \
vld1.8 {q9}, [r9]; /* load L_{ntz(i+1)} */ \
veor q8, q8, q1; /* Checksum_i+0 */ \
veor q1, q1, q0; /* P_i+0 xor Offset_i+0 */\
vld1.8 {q3-q4}, [r2]!; /* load P_i+<2-3> */ \
vst1.8 {q0}, [r1]!; /* store Offset_i+0 */\
veor q0, q0, q9; /* Offset_i+1 */ \
vld1.8 {q9}, [r10]; /* load L_{ntz(i+2)} */ \
veor q8, q8, q2; /* Checksum_i+1 */ \
veor q2, q2, q0; /* P_i+1 xor Offset_i+1 */\
vst1.8 {q0}, [r1]!; /* store Offset_i+1 */\
veor q0, q0, q9; /* Offset_i+2 */ \
vld1.8 {q9}, [r11]; /* load L_{ntz(i+3)} */ \
veor q8, q8, q3; /* Checksum_i+2 */ \
veor q3, q3, q0; /* P_i+2 xor Offset_i+2 */\
vst1.8 {q0}, [r1]!; /* store Offset_i+2 */\
veor q0, q0, q9; /* Offset_i+3 */ \
veor q8, q8, q4; /* Checksum_i+3 */ \
veor q4, q4, q0; /* P_i+3 xor Offset_i+3 */\
vst1.8 {q0}, [r1]; /* store Offset_i+3 */\
sub r1, #(3*16); \
vst1.8 {q8}, [r4]; /* store Checksum_i+3 */\
\
cmp r6, #4; \
\
do_aes_4_##bits(e, mc, q1, q2, q3, q4, ##__VA_ARGS__); \
\
mov r8, r1; \
vld1.8 {q8-q9}, [r1]!; \
veor q1, q1, q8; \
veor q2, q2, q9; \
vld1.8 {q8-q9}, [r1]!; \
vst1.8 {q1-q2}, [r8]!; \
veor q3, q3, q8; \
veor q4, q4, q9; \
vst1.8 {q3-q4}, [r8]; \
\
bhs .Locb_enc_loop4_##bits; \
cmp r6, #0; \
beq .Locb_enc_done; \
\
.Locb_enc_loop_##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) */ \
\
rbit r8, lr; \
add lr, #1; \
clz r8, r8; /* ntz(i) */ \
add r8, r5, r8, lsl #4; \
\
vld1.8 {q1}, [r2]!; /* load plaintext */ \
vld1.8 {q2}, [r8]; /* load L_{ntz(i)} */ \
vld1.8 {q3}, [r4]; /* load checksum */ \
subs r6, #1; \
veor q0, q0, q2; \
veor q3, q3, q1; \
veor q1, q1, q0; \
vst1.8 {q3}, [r4]; /* store checksum */ \
\
do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__); \
\
veor q1, q1, q0; \
vst1.8 {q1}, [r1]!; /* store ciphertext */ \
\
bne .Locb_enc_loop_##bits; \
b .Locb_enc_done;
OCB_ENC(128re, r0, r12)
OCB_ENC(192, r0, r12)
OCB_ENC(256, r0, r12)
#undef OCB_ENC
.Locb_enc_done:
vst1.8 {q0}, [r3] /* store offset */
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)
pop {r4-r12,lr}
vpop {q4-q7}
bx lr
.size _gcry_aes_ocb_enc_armv8_ce,.-_gcry_aes_ocb_enc_armv8_ce;
/*
* void _gcry_aes_ocb_dec_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_dec_armv8_ce
.type _gcry_aes_ocb_dec_armv8_ce,%function;
_gcry_aes_ocb_dec_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: offset
* %st+0: checksum => r4
* %st+4: Ls => r5
* %st+8: nblocks => r6 (0 < nblocks <= 32)
* %st+12: nrounds => r7
* %st+16: blkn => lr
*/
vpush {q4-q7}
push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
ldr r7, [sp, #(104+12)]
ldr r4, [sp, #(104+0)]
ldr r5, [sp, #(104+4)]
ldr r6, [sp, #(104+8)]
ldr lr, [sp, #(104+16)]
cmp r7, #12
vld1.8 {q0}, [r3] /* load offset */
aes_preload_keys(r0, r12);
beq .Locb_dec_entry_192
bhi .Locb_dec_entry_256
#define OCB_DEC(bits, ...) \
.Locb_dec_entry_##bits: \
cmp r6, #4; \
add lr, #1; \
blo .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 r9, lr, #1; \
add r10, lr, #2; \
add r11, lr, #3; \
rbit r8, lr; \
add lr, lr, #4; \
rbit r9, r9; \
rbit r10, r10; \
rbit r11, r11; \
clz r8, r8; /* ntz(i+0) */ \
clz r9, r9; /* ntz(i+1) */ \
clz r10, r10; /* ntz(i+2) */ \
clz r11, r11; /* ntz(i+3) */ \
add r8, r5, r8, lsl #4; \
add r9, r5, r9, lsl #4; \
add r10, r5, r10, lsl #4; \
add r11, r5, r11, lsl #4; \
\
sub r6, #4; \
\
vld1.8 {q9}, [r8]; /* load L_{ntz(i+0)} */ \
vld1.8 {q1-q2}, [r2]!; /* load P_i+<0-1> */ \
veor q0, q0, q9; /* Offset_i+0 */ \
vld1.8 {q9}, [r9]; /* load L_{ntz(i+1)} */ \
veor q1, q1, q0; /* P_i+0 xor Offset_i+0 */\
vld1.8 {q3-q4}, [r2]!; /* load P_i+<2-3> */ \
vst1.8 {q0}, [r1]!; /* store Offset_i+0 */\
veor q0, q0, q9; /* Offset_i+1 */ \
vld1.8 {q9}, [r10]; /* load L_{ntz(i+2)} */ \
veor q2, q2, q0; /* P_i+1 xor Offset_i+1 */\
vst1.8 {q0}, [r1]!; /* store Offset_i+1 */\
veor q0, q0, q9; /* Offset_i+2 */ \
vld1.8 {q9}, [r11]; /* load L_{ntz(i+3)} */ \
veor q3, q3, q0; /* P_i+2 xor Offset_i+2 */\
vst1.8 {q0}, [r1]!; /* store Offset_i+2 */\
veor q0, q0, q9; /* Offset_i+3 */ \
veor q4, q4, q0; /* P_i+3 xor Offset_i+3 */\
vst1.8 {q0}, [r1]; /* store Offset_i+3 */\
sub r1, #(3*16); \
\
cmp r6, #4; \
\
do_aes_4_##bits(d, imc, q1, q2, q3, q4, ##__VA_ARGS__); \
\
mov r8, r1; \
vld1.8 {q8-q9}, [r1]!; \
veor q1, q1, q8; \
veor q2, q2, q9; \
vld1.8 {q8-q9}, [r1]!; \
vst1.8 {q1-q2}, [r8]!; \
veor q1, q1, q2; \
vld1.8 {q2}, [r4]; /* load Checksum_{i-1} */ \
veor q3, q3, q8; \
veor q1, q1, q3; \
veor q4, q4, q9; \
veor q1, q1, q4; \
vst1.8 {q3-q4}, [r8]; \
veor q2, q2, q1; \
vst1.8 {q2}, [r4]; /* store Checksum_i+3 */ \
\
bhs .Locb_dec_loop4_##bits; \
cmp r6, #0; \
beq .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 r8, lr; \
add lr, #1; \
clz r8, r8; /* ntz(i) */ \
add r8, r5, r8, lsl #4; \
\
vld1.8 {q2}, [r8]; /* load L_{ntz(i)} */ \
vld1.8 {q1}, [r2]!; /* load ciphertext */ \
subs r6, #1; \
veor q0, q0, q2; \
veor q1, q1, q0; \
\
do_aes_one##bits(d, imc, q1, q1, ##__VA_ARGS__) \
\
vld1.8 {q2}, [r4]; /* load checksum */ \
veor q1, q1, q0; \
vst1.8 {q1}, [r1]!; /* store plaintext */ \
veor q2, q2, q1; \
vst1.8 {q2}, [r4]; /* store checksum */ \
\
bne .Locb_dec_loop_##bits; \
b .Locb_dec_done;
OCB_DEC(128re, r0, r12)
OCB_DEC(192, r0, r12)
OCB_DEC(256, r0, r12)
#undef OCB_DEC
.Locb_dec_done:
vst1.8 {q0}, [r3] /* store offset */
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)
pop {r4-r12,lr}
vpop {q4-q7}
bx lr
.size _gcry_aes_ocb_dec_armv8_ce,.-_gcry_aes_ocb_dec_armv8_ce;
/*
* void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
* const unsigned char *abuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_auth_armv8_ce
.type _gcry_aes_ocb_auth_armv8_ce,%function;
_gcry_aes_ocb_auth_armv8_ce:
/* input:
* r0: keysched
* r1: abuf
* r2: offset
* r3: checksum
* %st+0: Ls => r5
* %st+4: nblocks => r6 (0 < nblocks <= 32)
* %st+8: nrounds => r7
* %st+12: blkn => lr
*/
vpush {q4-q7}
push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
ldr r7, [sp, #(104+8)]
ldr r5, [sp, #(104+0)]
ldr r6, [sp, #(104+4)]
ldr lr, [sp, #(104+12)]
cmp r7, #12
vld1.8 {q0}, [r2] /* load offset */
aes_preload_keys(r0, r12);
beq .Locb_auth_entry_192
bhi .Locb_auth_entry_256
#define OCB_AUTH(bits, ...) \
.Locb_auth_entry_##bits: \
cmp r6, #4; \
add lr, #1; \
blo .Locb_auth_loop_##bits; \
\
.Locb_auth_loop4_##bits: \
\
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ \
\
add r9, lr, #1; \
add r10, lr, #2; \
add r11, lr, #3; \
rbit r8, lr; \
add lr, lr, #4; \
rbit r9, r9; \
rbit r10, r10; \
rbit r11, r11; \
clz r8, r8; /* ntz(i+0) */ \
clz r9, r9; /* ntz(i+1) */ \
clz r10, r10; /* ntz(i+2) */ \
clz r11, r11; /* ntz(i+3) */ \
add r8, r5, r8, lsl #4; \
add r9, r5, r9, lsl #4; \
add r10, r5, r10, lsl #4; \
add r11, r5, r11, lsl #4; \
\
sub r6, #4; \
\
vld1.8 {q9}, [r8]; /* load L_{ntz(i+0)} */ \
vld1.8 {q1-q2}, [r1]!; /* load A_i+<0-1> */ \
veor q0, q0, q9; /* Offset_i+0 */ \
vld1.8 {q9}, [r9]; /* load L_{ntz(i+1)} */ \
veor q1, q1, q0; /* A_i+0 xor Offset_i+0 */\
vld1.8 {q3-q4}, [r1]!; /* load A_i+<2-3> */ \
veor q0, q0, q9; /* Offset_i+1 */ \
vld1.8 {q9}, [r10]; /* load L_{ntz(i+2)} */ \
veor q2, q2, q0; /* A_i+1 xor Offset_i+1 */\
veor q0, q0, q9; /* Offset_i+2 */ \
vld1.8 {q9}, [r11]; /* load L_{ntz(i+3)} */ \
veor q3, q3, q0; /* A_i+2 xor Offset_i+2 */\
veor q0, q0, q9; /* Offset_i+3 */ \
veor q4, q4, q0; /* A_i+3 xor Offset_i+3 */\
\
cmp r6, #4; \
\
do_aes_4_##bits(e, mc, q1, q2, q3, q4, ##__VA_ARGS__); \
\
veor q1, q1, q2; \
veor q3, q3, q4; \
vld1.8 {q2}, [r3]; \
veor q1, q1, q3; \
veor q2, q2, q1; \
vst1.8 {q2}, [r3]; \
\
bhs .Locb_auth_loop4_##bits; \
cmp r6, #0; \
beq .Locb_auth_done; \
\
.Locb_auth_loop_##bits: \
\
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ \
\
rbit r8, lr; \
add lr, #1; \
clz r8, r8; /* ntz(i) */ \
add r8, r5, r8, lsl #4; \
\
vld1.8 {q2}, [r8]; /* load L_{ntz(i)} */ \
vld1.8 {q1}, [r1]!; /* load aadtext */ \
subs r6, #1; \
veor q0, q0, q2; \
vld1.8 {q2}, [r3]; /* load checksum */ \
veor q1, q1, q0; \
\
do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__) \
\
veor q2, q2, q1; \
vst1.8 {q2}, [r3]; /* store checksum */ \
\
bne .Locb_auth_loop_##bits; \
b .Locb_auth_done;
OCB_AUTH(128re, r0, r12)
OCB_AUTH(192, r0, r12)
OCB_AUTH(256, r0, r12)
#undef OCB_AUTH
.Locb_auth_done:
vst1.8 {q0}, [r2] /* store offset */
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)
pop {r4-r12,lr}
vpop {q4-q7}
bx lr
.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);
*/
.align 3
.globl _gcry_aes_sbox4_armv8_ce
.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.
*/
vmov.i8 q0, #0x52
vmov.i8 q1, #0
vmov s0, r0
aese.8 q0, q1
veor d0, d1
vpadd.i32 d0, d0, d1
vmov r0, s0
CLEAR_REG(q0)
bx lr
.size _gcry_aes_sbox4_armv8_ce,.-_gcry_aes_sbox4_armv8_ce;
/*
* void _gcry_aes_invmixcol_armv8_ce(void *dst, const void *src);
*/
.align 3
.globl _gcry_aes_invmixcol_armv8_ce
.type _gcry_aes_invmixcol_armv8_ce,%function;
_gcry_aes_invmixcol_armv8_ce:
vld1.8 {q0}, [r1]
aesimc.8 q0, q0
vst1.8 {q0}, [r0]
CLEAR_REG(q0)
bx lr
.size _gcry_aes_invmixcol_armv8_ce,.-_gcry_aes_invmixcol_armv8_ce;
#endif
diff --git a/cipher/rijndael-armv8-aarch64-ce.S b/cipher/rijndael-armv8-aarch64-ce.S
index 3af29e0d..2f51ff17 100644
--- a/cipher/rijndael-armv8-aarch64-ce.S
+++ b/cipher/rijndael-armv8-aarch64-ce.S
@@ -1,1613 +1,1613 @@
/* rijndael-armv8-aarch64-ce.S - ARMv8/CE accelerated AES
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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
/* Register macros */
#define vk0 v17
#define vk1 v18
#define vk2 v19
#define vk3 v20
#define vk4 v21
#define vk5 v22
#define vk6 v23
#define vk7 v24
#define vk8 v25
#define vk9 v26
#define vk10 v27
#define vk11 v28
#define vk12 v29
#define vk13 v30
#define vk14 v31
/* AES macros */
#define aes_preload_keys(keysched, nrounds) \
cmp nrounds, #12; \
ld1 {vk0.16b-vk3.16b}, [keysched], #64; \
ld1 {vk4.16b-vk7.16b}, [keysched], #64; \
ld1 {vk8.16b-vk10.16b}, [keysched], #48; \
b.lo 1f; \
ld1 {vk11.16b-vk12.16b}, [keysched], #32; \
b.eq 1f; \
ld1 {vk13.16b-vk14.16b}, [keysched]; \
1: ;
#define do_aes_one128(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; \
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, 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; \
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;
#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; \
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, 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; \
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; \
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;
#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; \
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, 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; \
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; \
aes##mcimc vb.16b, vb.16b; \
aes##ed vb.16b, vk10.16b; \
aes##mcimc vb.16b, vb.16b; \
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;
#define aes_round_4(ed, mcimc, b0, b1, b2, b3, key) \
aes##ed b0.16b, key.16b; \
aes##mcimc b0.16b, b0.16b; \
aes##ed b1.16b, key.16b; \
aes##mcimc b1.16b, b1.16b; \
aes##ed b2.16b, key.16b; \
aes##mcimc b2.16b, b2.16b; \
aes##ed b3.16b, key.16b; \
aes##mcimc b3.16b, b3.16b;
#define aes_lastround_4(ed, b0, b1, b2, b3, key1, 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;
#define do_aes_4_128(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); \
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);
#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); \
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_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);
#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); \
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_round_4(ed, mcimc, b0, b1, b2, b3, vk9); \
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);
/* Other functional macros */
#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
#define aes_clear_keys(nrounds) \
cmp nrounds, #12; \
CLEAR_REG(vk0); \
CLEAR_REG(vk1); \
CLEAR_REG(vk2); \
CLEAR_REG(vk3); \
CLEAR_REG(vk4); \
CLEAR_REG(vk5); \
CLEAR_REG(vk6); \
CLEAR_REG(vk7); \
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: ;
/*
* unsigned int _gcry_aes_enc_armv8_ce(void *keysched, byte *dst,
* const byte *src,
* unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_enc_armv8_ce
ELF(.type _gcry_aes_enc_armv8_ce,%function;)
_gcry_aes_enc_armv8_ce:
/* input:
* x0: keysched
* x1: dst
* x2: src
* w3: nrounds
*/
CFI_STARTPROC();
aes_preload_keys(x0, w3);
ld1 {v0.16b}, [x2]
b.hi .Lenc1_256
b.eq .Lenc1_192
.Lenc1_128:
do_aes_one128(e, mc, v0, v0);
.Lenc1_tail:
CLEAR_REG(vk0)
CLEAR_REG(vk1)
CLEAR_REG(vk2)
CLEAR_REG(vk3)
CLEAR_REG(vk4)
CLEAR_REG(vk5)
CLEAR_REG(vk6)
CLEAR_REG(vk7)
CLEAR_REG(vk8)
CLEAR_REG(vk9)
CLEAR_REG(vk10)
st1 {v0.16b}, [x1]
CLEAR_REG(v0)
mov x0, #0
ret
.Lenc1_192:
do_aes_one192(e, mc, v0, v0);
CLEAR_REG(vk11)
CLEAR_REG(vk12)
b .Lenc1_tail
.Lenc1_256:
do_aes_one256(e, mc, v0, v0);
CLEAR_REG(vk11)
CLEAR_REG(vk12)
CLEAR_REG(vk13)
CLEAR_REG(vk14)
b .Lenc1_tail
CFI_ENDPROC();
ELF(.size _gcry_aes_enc_armv8_ce,.-_gcry_aes_enc_armv8_ce;)
/*
* unsigned int _gcry_aes_dec_armv8_ce(void *keysched, byte *dst,
* const byte *src,
* unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_dec_armv8_ce
ELF(.type _gcry_aes_dec_armv8_ce,%function;)
_gcry_aes_dec_armv8_ce:
/* input:
* x0: keysched
* x1: dst
* x2: src
* w3: nrounds
*/
CFI_STARTPROC();
aes_preload_keys(x0, w3);
ld1 {v0.16b}, [x2]
b.hi .Ldec1_256
b.eq .Ldec1_192
.Ldec1_128:
do_aes_one128(d, imc, v0, v0);
.Ldec1_tail:
CLEAR_REG(vk0)
CLEAR_REG(vk1)
CLEAR_REG(vk2)
CLEAR_REG(vk3)
CLEAR_REG(vk4)
CLEAR_REG(vk5)
CLEAR_REG(vk6)
CLEAR_REG(vk7)
CLEAR_REG(vk8)
CLEAR_REG(vk9)
CLEAR_REG(vk10)
st1 {v0.16b}, [x1]
CLEAR_REG(v0)
mov x0, #0
ret
.Ldec1_192:
do_aes_one192(d, imc, v0, v0);
CLEAR_REG(vk11)
CLEAR_REG(vk12)
b .Ldec1_tail
.Ldec1_256:
do_aes_one256(d, imc, v0, v0);
CLEAR_REG(vk11)
CLEAR_REG(vk12)
CLEAR_REG(vk13)
CLEAR_REG(vk14)
b .Ldec1_tail
CFI_ENDPROC();
ELF(.size _gcry_aes_dec_armv8_ce,.-_gcry_aes_dec_armv8_ce;)
/*
* void _gcry_aes_cbc_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, size_t nblocks,
* int cbc_mac, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cbc_enc_armv8_ce
ELF(.type _gcry_aes_cbc_enc_armv8_ce,%function;)
_gcry_aes_cbc_enc_armv8_ce:
/* input:
* x0: keysched
* x1: outbuf
* x2: inbuf
* x3: iv
* x4: nblocks
* w5: cbc_mac
* w6: nrounds
*/
CFI_STARTPROC();
cbz x4, .Lcbc_enc_skip
cmp w5, #0
ld1 {v1.16b}, [x3] /* load IV */
cset x5, eq
aes_preload_keys(x0, w6);
lsl x5, x5, #4
b.eq .Lcbc_enc_loop192
b.hi .Lcbc_enc_loop256
#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; \
\
do_aes_one##bits(e, mc, v1, v1); \
\
st1 {v1.16b}, [x1], x5; /* store ciphertext */ \
\
cbnz x4, .Lcbc_enc_loop##bits; \
b .Lcbc_enc_done;
CBC_ENC(128)
CBC_ENC(192)
CBC_ENC(256)
#undef CBC_ENC
.Lcbc_enc_done:
aes_clear_keys(w6)
st1 {v1.16b}, [x3] /* store IV */
CLEAR_REG(v1)
CLEAR_REG(v0)
.Lcbc_enc_skip:
ret
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,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cbc_dec_armv8_ce
ELF(.type _gcry_aes_cbc_dec_armv8_ce,%function;)
_gcry_aes_cbc_dec_armv8_ce:
/* input:
* x0: keysched
* x1: outbuf
* x2: inbuf
* x3: iv
* x4: nblocks
* w5: nrounds
*/
CFI_STARTPROC();
cbz x4, .Lcbc_dec_skip
ld1 {v0.16b}, [x3] /* load IV */
aes_preload_keys(x0, w5);
b.eq .Lcbc_dec_entry_192
b.hi .Lcbc_dec_entry_256
#define CBC_DEC(bits) \
.Lcbc_dec_entry_##bits: \
cmp x4, #4; \
b.lo .Lcbc_dec_loop_##bits; \
\
.Lcbc_dec_loop4_##bits: \
\
ld1 {v1.16b-v4.16b}, [x2], #64; /* load ciphertext */ \
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; \
\
do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
\
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 */ \
\
b.hs .Lcbc_dec_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
CLEAR_REG(v16); \
cbz x4, .Lcbc_dec_done; \
\
.Lcbc_dec_loop_##bits: \
ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
sub x4, x4, #1; \
mov v2.16b, v1.16b; \
\
do_aes_one##bits(d, imc, v1, v1); \
\
eor v1.16b, v1.16b, v0.16b; \
mov v0.16b, v2.16b; \
st1 {v1.16b}, [x1], #16; /* store plaintext */ \
\
cbnz x4, .Lcbc_dec_loop_##bits; \
b .Lcbc_dec_done;
CBC_DEC(128)
CBC_DEC(192)
CBC_DEC(256)
#undef CBC_DEC
.Lcbc_dec_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store IV */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
.Lcbc_dec_skip:
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_cbc_dec_armv8_ce,.-_gcry_aes_cbc_dec_armv8_ce;)
/*
* void _gcry_aes_ctr_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_ctr_enc_armv8_ce
ELF(.type _gcry_aes_ctr_enc_armv8_ce,%function;)
_gcry_aes_ctr_enc_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* x4: nblocks
* w5: nrounds
*/
CFI_STARTPROC();
cbz x4, .Lctr_enc_skip
mov x6, #1
movi v16.16b, #0
mov v16.D[1], x6
/* load IV */
ldp x9, x10, [x3]
ld1 {v0.16b}, [x3]
rev x9, x9
rev x10, x10
aes_preload_keys(x0, w5);
b.eq .Lctr_enc_entry_192
b.hi .Lctr_enc_entry_256
#define CTR_ENC(bits) \
.Lctr_enc_entry_##bits: \
cmp x4, #4; \
b.lo .Lctr_enc_loop_##bits; \
\
.Lctr_enc_loop4_##bits: \
cmp x10, #0xfffffffffffffffc; \
sub x4, x4, #4; \
b.lo .Lctr_enc_loop4_##bits##_nocarry; \
\
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; \
\
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; \
\
b .Lctr_enc_loop4_##bits##_store_ctr; \
\
.Lctr_enc_loop4_##bits##_nocarry: \
\
add v3.2d, v16.2d, v16.2d; /* 2 */ \
rev64 v6.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: \
\
st1 {v0.16b}, [x3]; \
cmp x4, #4; \
ld1 {v5.16b-v7.16b}, [x2], #48; /* preload ciphertext */ \
\
do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
\
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 */ \
\
b.hs .Lctr_enc_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
cbz x4, .Lctr_enc_done; \
\
.Lctr_enc_loop_##bits: \
\
adds x10, x10, #1; \
mov v1.16b, v0.16b; \
adc x9, x9, xzr; \
mov v0.D[1], x10; \
mov v0.D[0], x9; \
sub x4, x4, #1; \
ld1 {v2.16b}, [x2], #16; /* load ciphertext */ \
rev64 v0.16b, v0.16b; \
\
do_aes_one##bits(e, mc, v1, v1); \
\
eor v1.16b, v2.16b, v1.16b; \
st1 {v1.16b}, [x1], #16; /* store plaintext */ \
\
cbnz x4, .Lctr_enc_loop_##bits; \
b .Lctr_enc_done;
CTR_ENC(128)
CTR_ENC(192)
CTR_ENC(256)
#undef CTR_ENC
.Lctr_enc_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store IV */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
.Lctr_enc_skip:
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ctr_enc_armv8_ce,.-_gcry_aes_ctr_enc_armv8_ce;)
/*
* void _gcry_aes_cfb_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cfb_enc_armv8_ce
ELF(.type _gcry_aes_cfb_enc_armv8_ce,%function;)
_gcry_aes_cfb_enc_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* x4: nblocks
* w5: nrounds
*/
CFI_STARTPROC();
cbz x4, .Lcfb_enc_skip
/* load IV */
ld1 {v0.16b}, [x3]
aes_preload_keys(x0, w5);
b.eq .Lcfb_enc_entry_192
b.hi .Lcfb_enc_entry_256
#define CFB_ENC(bits) \
.Lcfb_enc_entry_##bits: \
.Lcfb_enc_loop_##bits: \
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 */ \
\
cbnz x4, .Lcfb_enc_loop_##bits; \
b .Lcfb_enc_done;
CFB_ENC(128)
CFB_ENC(192)
CFB_ENC(256)
#undef CFB_ENC
.Lcfb_enc_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store IV */
CLEAR_REG(v0)
CLEAR_REG(v1)
.Lcfb_enc_skip:
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_cfb_enc_armv8_ce,.-_gcry_aes_cfb_enc_armv8_ce;)
/*
* void _gcry_aes_cfb_dec_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *iv, unsigned int nrounds);
*/
.align 3
.globl _gcry_aes_cfb_dec_armv8_ce
ELF(.type _gcry_aes_cfb_dec_armv8_ce,%function;)
_gcry_aes_cfb_dec_armv8_ce:
/* input:
* r0: keysched
* r1: outbuf
* r2: inbuf
* r3: iv
* x4: nblocks
* w5: nrounds
*/
CFI_STARTPROC();
cbz x4, .Lcfb_dec_skip
/* load IV */
ld1 {v0.16b}, [x3]
aes_preload_keys(x0, w5);
b.eq .Lcfb_dec_entry_192
b.hi .Lcfb_dec_entry_256
#define CFB_DEC(bits) \
.Lcfb_dec_entry_##bits: \
cmp x4, #4; \
b.lo .Lcfb_dec_loop_##bits; \
\
.Lcfb_dec_loop4_##bits: \
\
ld1 {v2.16b-v4.16b}, [x2], #48; /* load ciphertext */ \
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 */ \
\
do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
\
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 */ \
\
b.hs .Lcfb_dec_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
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); \
\
eor v2.16b, v1.16b, v0.16b; \
mov v0.16b, v1.16b; \
st1 {v2.16b}, [x1], #16; /* store plaintext */ \
\
cbnz x4, .Lcfb_dec_loop_##bits; \
b .Lcfb_dec_done;
CFB_DEC(128)
CFB_DEC(192)
CFB_DEC(256)
#undef CFB_DEC
.Lcfb_dec_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store IV */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
.Lcfb_dec_skip:
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_cfb_dec_armv8_ce,.-_gcry_aes_cfb_dec_armv8_ce;)
/*
* void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_enc_armv8_ce
ELF(.type _gcry_aes_ocb_enc_armv8_ce,%function;)
_gcry_aes_ocb_enc_armv8_ce:
/* input:
* x0: keysched
* x1: outbuf
* x2: inbuf
* x3: offset
* x4: checksum
* x5: Ltable
* x6: nblocks (0 < nblocks <= 32)
* w7: nrounds
* %st+0: blkn => w12
*/
CFI_STARTPROC();
ldr w12, [sp]
ld1 {v0.16b}, [x3] /* load offset */
ld1 {v16.16b}, [x4] /* load checksum */
aes_preload_keys(x0, w7);
b.eq .Locb_enc_entry_192
b.hi .Locb_enc_entry_256
#define OCB_ENC(bits, ...) \
.Locb_enc_entry_##bits: \
cmp x6, #4; \
add x12, x12, #1; \
b.lo .Locb_enc_loop_##bits; \
\
.Locb_enc_loop4_##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) */ \
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 {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_4_##bits(e, mc, 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 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; \
\
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; \
\
.Locb_enc_loop_##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) */ \
\
rbit x8, x12; \
add x12, x12, #1; \
clz x8, x8; /* ntz(i) */ \
add x8, x5, x8, 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; \
\
do_aes_one##bits(e, mc, v1, v1); \
\
eor v1.16b, v1.16b, v0.16b; \
st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
\
cbnz x6, .Locb_enc_loop_##bits; \
b .Locb_enc_done;
OCB_ENC(128)
OCB_ENC(192)
OCB_ENC(256)
#undef OCB_ENC
.Locb_enc_done:
aes_clear_keys(w7)
st1 {v16.16b}, [x4] /* store checksum */
st1 {v0.16b}, [x3] /* store offset */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
CLEAR_REG(v16)
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ocb_enc_armv8_ce,.-_gcry_aes_ocb_enc_armv8_ce;)
/*
* void _gcry_aes_ocb_dec_armv8_ce (const void *keysched,
* unsigned char *outbuf,
* const unsigned char *inbuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_dec_armv8_ce
ELF(.type _gcry_aes_ocb_dec_armv8_ce,%function;)
_gcry_aes_ocb_dec_armv8_ce:
/* input:
* x0: keysched
* x1: outbuf
* x2: inbuf
* x3: offset
* x4: checksum
* x5: Ltable
* x6: nblocks (0 < nblocks <= 32)
* w7: nrounds
* %st+0: blkn => w12
*/
CFI_STARTPROC();
ldr w12, [sp]
ld1 {v0.16b}, [x3] /* load offset */
ld1 {v16.16b}, [x4] /* load checksum */
aes_preload_keys(x0, w7);
b.eq .Locb_dec_entry_192
b.hi .Locb_dec_entry_256
#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;
OCB_DEC(128)
OCB_DEC(192)
OCB_DEC(256)
#undef OCB_DEC
.Locb_dec_done:
aes_clear_keys(w7)
st1 {v16.16b}, [x4] /* store checksum */
st1 {v0.16b}, [x3] /* store offset */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
CLEAR_REG(v16)
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ocb_dec_armv8_ce,.-_gcry_aes_ocb_dec_armv8_ce;)
/*
* void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
* const unsigned char *abuf,
* unsigned char *offset,
* unsigned char *checksum,
* unsigned char *L_table,
* size_t nblocks,
* unsigned int nrounds,
* unsigned int blkn);
*/
.align 3
.globl _gcry_aes_ocb_auth_armv8_ce
ELF(.type _gcry_aes_ocb_auth_armv8_ce,%function;)
_gcry_aes_ocb_auth_armv8_ce:
/* input:
* x0: keysched
* x1: abuf
* x2: offset => x3
* x3: checksum => x4
* x4: Ltable => x5
* x5: nblocks => x6 (0 < nblocks <= 32)
* w6: nrounds => w7
* w7: blkn => w12
*/
CFI_STARTPROC();
mov w12, w7
mov w7, w6
mov x6, x5
mov x5, x4
mov x4, x3
mov x3, x2
aes_preload_keys(x0, w7);
ld1 {v0.16b}, [x3] /* load offset */
ld1 {v16.16b}, [x4] /* load checksum */
beq .Locb_auth_entry_192
bhi .Locb_auth_entry_256
#define OCB_AUTH(bits) \
.Locb_auth_entry_##bits: \
cmp x6, #4; \
add w12, w12, #1; \
b.lo .Locb_auth_loop_##bits; \
\
.Locb_auth_loop4_##bits: \
\
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_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) */ \
add x8, x5, x8, lsl #4; \
ld1 {v1.16b-v4.16b}, [x1], #64; /* load A_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; /* A_i+0 xor Offset_i+0 */ \
eor v7.16b, v7.16b, v6.16b; /* Offset_i+2 */ \
eor v2.16b, v2.16b, v6.16b; /* A_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; /* A_i+2 xor Offset_i+2 */ \
eor v4.16b, v4.16b, v0.16b; /* A_i+3 xor Offset_i+3 */ \
\
do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
\
eor v1.16b, v1.16b, v2.16b; \
eor v16.16b, v16.16b, v3.16b; \
eor v1.16b, v1.16b, v4.16b; \
eor v16.16b, v16.16b, v1.16b; \
\
b.hs .Locb_auth_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
cbz x6, .Locb_auth_done; \
\
.Locb_auth_loop_##bits: \
\
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ \
\
rbit w8, w12; \
add w12, w12, #1; \
clz w8, w8; /* ntz(i) */ \
add x8, x5, x8, lsl #4; \
\
ld1 {v1.16b}, [x1], #16; /* load aadtext */ \
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(e, mc, v1, v1) \
\
eor v16.16b, v16.16b, v1.16b; \
\
cbnz x6, .Locb_auth_loop_##bits; \
b .Locb_auth_done;
OCB_AUTH(128)
OCB_AUTH(192)
OCB_AUTH(256)
#undef OCB_AUTH
.Locb_auth_done:
aes_clear_keys(w7)
st1 {v16.16b}, [x4] /* store checksum */
st1 {v0.16b}, [x3] /* store offset */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
CLEAR_REG(v16)
ret
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
/* 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);
b.eq .Lxts_enc_entry_192
b.hi .Lxts_enc_entry_256
#define XTS_ENC(bits) \
.Lxts_enc_entry_##bits: \
cmp x4, #4; \
b.lo .Lxts_enc_loop_##bits; \
\
.Lxts_enc_loop4_##bits: \
\
ext v4.16b, v0.16b, v0.16b, #8; \
\
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 v3.16b, v3.16b, v2.16b; \
ld1 {v1.16b-v2.16b}, [x2], #32; /* load plaintext */ \
st1 {v3.16b}, [x3]; \
sub x4, x4, #4; \
eor v1.16b, v1.16b, v0.16b; \
\
ld1 {v3.16b-v4.16b}, [x2], #32; /* load plaintext */ \
cmp x4, #4; \
eor v2.16b, v2.16b, v5.16b; \
eor v3.16b, v3.16b, v6.16b; \
eor v4.16b, v4.16b, v7.16b; \
\
do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
\
eor v1.16b, v1.16b, v0.16b; \
ld1 {v0.16b}, [x3]; \
eor v2.16b, v2.16b, v5.16b; \
eor v3.16b, v3.16b, v6.16b; \
eor v4.16b, v4.16b, v7.16b; \
st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
\
b.hs .Lxts_enc_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
cbz x4, .Lxts_enc_done; \
\
.Lxts_enc_loop_##bits: \
\
ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
ext v3.16b, v0.16b, v0.16b, #8; \
mov v2.16b, v0.16b; \
sshr v3.2d, v3.2d, #63; \
add v0.2d, v0.2d, v0.2d; \
and v3.16b, v3.16b, v16.16b; \
eor v1.16b, v1.16b, v2.16b; \
eor v0.16b, v0.16b, v3.16b; \
sub x4, x4, #1; \
\
do_aes_one##bits(e, mc, v1, v1); \
\
eor v1.16b, v1.16b, v2.16b; \
st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
\
cbnz x4, .Lxts_enc_loop_##bits; \
b .Lxts_enc_done;
XTS_ENC(128)
XTS_ENC(192)
XTS_ENC(256)
#undef XTS_ENC
.Lxts_enc_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store tweak */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
.Lxts_enc_skip:
ret
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
/* 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);
b.eq .Lxts_dec_entry_192
b.hi .Lxts_dec_entry_256
#define XTS_DEC(bits) \
.Lxts_dec_entry_##bits: \
cmp x4, #4; \
b.lo .Lxts_dec_loop_##bits; \
\
.Lxts_dec_loop4_##bits: \
\
ext v4.16b, v0.16b, v0.16b, #8; \
\
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 v3.16b, v3.16b, v2.16b; \
ld1 {v1.16b-v2.16b}, [x2], #32; /* load plaintext */ \
st1 {v3.16b}, [x3]; \
sub x4, x4, #4; \
eor v1.16b, v1.16b, v0.16b; \
\
ld1 {v3.16b-v4.16b}, [x2], #32; /* load plaintext */ \
cmp x4, #4; \
eor v2.16b, v2.16b, v5.16b; \
eor v3.16b, v3.16b, v6.16b; \
eor v4.16b, v4.16b, v7.16b; \
\
do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
\
eor v1.16b, v1.16b, v0.16b; \
ld1 {v0.16b}, [x3]; \
eor v2.16b, v2.16b, v5.16b; \
eor v3.16b, v3.16b, v6.16b; \
eor v4.16b, v4.16b, v7.16b; \
st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
\
b.hs .Lxts_dec_loop4_##bits; \
CLEAR_REG(v3); \
CLEAR_REG(v4); \
CLEAR_REG(v5); \
CLEAR_REG(v6); \
CLEAR_REG(v7); \
cbz x4, .Lxts_dec_done; \
\
.Lxts_dec_loop_##bits: \
\
ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
ext v3.16b, v0.16b, v0.16b, #8; \
mov v2.16b, v0.16b; \
sshr v3.2d, v3.2d, #63; \
add v0.2d, v0.2d, v0.2d; \
and v3.16b, v3.16b, v16.16b; \
eor v1.16b, v1.16b, v2.16b; \
eor v0.16b, v0.16b, v3.16b; \
sub x4, x4, #1; \
\
do_aes_one##bits(d, imc, v1, v1); \
\
eor v1.16b, v1.16b, v2.16b; \
st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
\
cbnz x4, .Lxts_dec_loop_##bits; \
b .Lxts_dec_done;
XTS_DEC(128)
XTS_DEC(192)
XTS_DEC(256)
#undef XTS_DEC
.Lxts_dec_done:
aes_clear_keys(w5)
st1 {v0.16b}, [x3] /* store tweak */
CLEAR_REG(v0)
CLEAR_REG(v1)
CLEAR_REG(v2)
.Lxts_dec_skip:
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_xts_dec_armv8_ce,.-_gcry_aes_xts_dec_armv8_ce;)
/*
* u32 _gcry_aes_sbox4_armv8_ce(u32 in4b);
*/
.align 3
.globl _gcry_aes_sbox4_armv8_ce
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
aese v0.16b, v1.16b
addv s0, v0.4s
mov w0, v0.S[0]
CLEAR_REG(v0)
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_sbox4_armv8_ce,.-_gcry_aes_sbox4_armv8_ce;)
/*
* void _gcry_aes_invmixcol_armv8_ce(void *dst, const void *src);
*/
.align 3
.globl _gcry_aes_invmixcol_armv8_ce
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
CFI_ENDPROC();
ELF(.size _gcry_aes_invmixcol_armv8_ce,.-_gcry_aes_invmixcol_armv8_ce;)
#endif
diff --git a/cipher/rijndael-armv8-ce.c b/cipher/rijndael-armv8-ce.c
index 6e46830e..2281f233 100644
--- a/cipher/rijndael-armv8-ce.c
+++ b/cipher/rijndael-armv8-ce.c
@@ -1,414 +1,414 @@
/* ARMv8 Crypto Extension AES for Libgcrypt
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcmp() */
#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_ARM_CE
typedef struct u128_s { u32 a, b, c, d; } u128_t;
extern u32 _gcry_aes_sbox4_armv8_ce(u32 in4b);
extern void _gcry_aes_invmixcol_armv8_ce(u128_t *dst, const u128_t *src);
extern unsigned int _gcry_aes_enc_armv8_ce(const void *keysched, byte *dst,
const byte *src,
unsigned int nrounds);
extern unsigned int _gcry_aes_dec_armv8_ce(const void *keysched, byte *dst,
const byte *src,
unsigned int nrounds);
extern void _gcry_aes_cbc_enc_armv8_ce (const void *keysched,
unsigned char *outbuf,
const unsigned char *inbuf,
unsigned char *iv, size_t nblocks,
int cbc_mac, unsigned int nrounds);
extern void _gcry_aes_cbc_dec_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_cfb_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_cfb_dec_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_ctr_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,
unsigned char *offset,
unsigned char *checksum,
unsigned char *L_table,
size_t nblocks,
unsigned int nrounds,
unsigned int blkn);
extern void _gcry_aes_ocb_dec_armv8_ce (const void *keysched,
unsigned char *outbuf,
const unsigned char *inbuf,
unsigned char *offset,
unsigned char *checksum,
unsigned char *L_table,
size_t nblocks,
unsigned int nrounds,
unsigned int blkn);
extern void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
const unsigned char *abuf,
unsigned char *offset,
unsigned char *checksum,
unsigned char *L_table,
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,
unsigned char *offset, unsigned char *checksum,
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)
{
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;
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] ^= _gcry_aes_sbox4_armv8_ce(rol(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] ^= _gcry_aes_sbox4_armv8_ce(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);
}
#undef W
#undef tk
#undef k
#undef W_u32
#undef tk_u32
#undef k_u32
wipememory(&tkk, sizeof(tkk));
}
/* Make a decryption key from an encryption key. */
void
_gcry_aes_armv8_ce_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;
#define DO_AESIMC() _gcry_aes_invmixcol_armv8_ce(&dkey[r], &ekey[rr])
dkey[0] = ekey[rounds];
r = 1;
rr = rounds-1;
DO_AESIMC(); r++; rr--; /* round 1 */
DO_AESIMC(); r++; rr--; /* round 2 */
DO_AESIMC(); r++; rr--; /* round 3 */
DO_AESIMC(); r++; rr--; /* round 4 */
DO_AESIMC(); r++; rr--; /* round 5 */
DO_AESIMC(); r++; rr--; /* round 6 */
DO_AESIMC(); r++; rr--; /* round 7 */
DO_AESIMC(); r++; rr--; /* round 8 */
DO_AESIMC(); r++; rr--; /* round 9 */
if (rounds >= 12)
{
if (rounds > 12)
{
DO_AESIMC(); r++; rr--; /* round 10 */
DO_AESIMC(); r++; rr--; /* round 11 */
}
DO_AESIMC(); r++; rr--; /* round 12 / 10 */
DO_AESIMC(); r++; rr--; /* round 13 / 11 */
}
dkey[r] = ekey[0];
#undef DO_AESIMC
}
unsigned int
_gcry_aes_armv8_ce_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
const unsigned char *src)
{
const void *keysched = ctx->keyschenc32;
unsigned int nrounds = ctx->rounds;
return _gcry_aes_enc_armv8_ce(keysched, dst, src, nrounds);
}
unsigned int
_gcry_aes_armv8_ce_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
const unsigned char *src)
{
const void *keysched = ctx->keyschdec32;
unsigned int nrounds = ctx->rounds;
return _gcry_aes_dec_armv8_ce(keysched, dst, src, nrounds);
}
void
_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;
unsigned int nrounds = ctx->rounds;
_gcry_aes_cbc_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, cbc_mac,
nrounds);
}
void
_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 *iv,
unsigned char *outbuf, const unsigned char *inbuf,
size_t nblocks)
{
const void *keysched = ctx->keyschenc32;
unsigned int nrounds = ctx->rounds;
_gcry_aes_cfb_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
}
void
_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;
unsigned int nrounds = ctx->rounds;
_gcry_aes_cfb_dec_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
}
void
_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;
unsigned int nrounds = ctx->rounds;
_gcry_aes_ctr_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)
{
RIJNDAEL_context *ctx = (void *)&c->context.c;
const void *keysched = encrypt ? ctx->keyschenc32 : ctx->keyschdec32;
ocb_crypt_fn_t crypt_fn = encrypt ? _gcry_aes_ocb_enc_armv8_ce
: _gcry_aes_ocb_dec_armv8_ce;
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_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;
}
size_t
_gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c, void *abuf_arg,
size_t nblocks)
{
RIJNDAEL_context *ctx = (void *)&c->context.c;
const void *keysched = ctx->keyschenc32;
const unsigned char *abuf = abuf_arg;
unsigned int nrounds = ctx->rounds;
u64 blkn = c->u_mode.ocb.aad_nblocks;
c->u_mode.ocb.aad_nblocks = blkn + nblocks;
_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-internal.h b/cipher/rijndael-internal.h
index 876d55fe..99c839cb 100644
--- a/cipher/rijndael-internal.h
+++ b/cipher/rijndael-internal.h
@@ -1,168 +1,168 @@
/* Rijndael (AES) for GnuPG
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 2008, 2011, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef G10_RIJNDAEL_INTERNAL_H
#define G10_RIJNDAEL_INTERNAL_H
#include "types.h" /* for byte and u32 typedefs */
#define MAXKC (256/32)
#define MAXROUNDS 14
#define BLOCKSIZE (128/8)
/* Helper macro to force alignment to 16 bytes. */
#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# define ATTR_ALIGNED_16 __attribute__ ((aligned (16)))
#else
# define ATTR_ALIGNED_16
#endif
/* 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))
# define USE_AMD64_ASM 1
#endif
/* USE_SSSE3 indicates whether to use SSSE3 code. */
#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_ARM_ASM indicates whether to use ARM assembly code. */
#undef USE_ARM_ASM
#if defined(__ARMEL__)
# ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
# define USE_ARM_ASM 1
# endif
#endif
#if defined(__AARCH64EL__)
# ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
# define USE_ARM_ASM 1
# endif
#endif
/* USE_PADLOCK indicates whether to compile the padlock specific
code. */
#undef USE_PADLOCK
#ifdef ENABLE_PADLOCK_SUPPORT
# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)
# define USE_PADLOCK 1
# endif
# endif
#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
gcc 3. However, to be on the safe side we require at least gcc 4. */
#undef USE_AESNI
#ifdef ENABLE_AESNI_SUPPORT
# if ((defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__))
# if __GNUC__ >= 4
# define USE_AESNI 1
# endif
# endif
#endif /* ENABLE_AESNI_SUPPORT */
/* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly
* code. */
#undef USE_ARM_CE
#ifdef ENABLE_ARM_CRYPTO_SUPPORT
# if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
&& defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO)
# define USE_ARM_CE 1
# elif defined(__AARCH64EL__) \
&& defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
# define USE_ARM_CE 1
# endif
#endif /* ENABLE_ARM_CRYPTO_SUPPORT */
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);
/* Our context object. */
typedef struct RIJNDAEL_context_s
{
/* The first fields are the keyschedule arrays. This is so that
they are aligned on a 16 byte boundary if using gcc. This
alignment is required for the AES-NI code and a good idea in any
case. The alignment is guaranteed due to the way cipher.c
allocates the space for the context. The PROPERLY_ALIGNED_TYPE
hack is used to force a minimal alignment if not using gcc of if
the alignment requirement is higher that 16 bytes. */
union
{
PROPERLY_ALIGNED_TYPE dummy;
byte keyschedule[MAXROUNDS+1][4][4];
u32 keyschedule32[MAXROUNDS+1][4];
#ifdef USE_PADLOCK
/* The key as passed to the padlock engine. It is only used if
the padlock engine is used (USE_PADLOCK, below). */
unsigned char padlock_key[16] __attribute__ ((aligned (16)));
#endif /*USE_PADLOCK*/
} u1;
union
{
PROPERLY_ALIGNED_TYPE dummy;
byte keyschedule[MAXROUNDS+1][4][4];
u32 keyschedule32[MAXROUNDS+1][4];
} 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. */
unsigned int use_avx2:1; /* AVX2 shall be used. */
#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*/
rijndael_cryptfn_t encrypt_fn;
rijndael_cryptfn_t decrypt_fn;
rijndael_prefetchfn_t prefetch_enc_fn;
rijndael_prefetchfn_t prefetch_dec_fn;
} RIJNDAEL_context ATTR_ALIGNED_16;
/* Macros defining alias for the keyschedules. */
#define keyschenc u1.keyschedule
#define keyschenc32 u1.keyschedule32
#define keyschdec u2.keyschedule
#define keyschdec32 u2.keyschedule32
#define padlockkey u1.padlock_key
#endif /* G10_RIJNDAEL_INTERNAL_H */
diff --git a/cipher/rijndael-padlock.c b/cipher/rijndael-padlock.c
index 234751b9..8d808d96 100644
--- a/cipher/rijndael-padlock.c
+++ b/cipher/rijndael-padlock.c
@@ -1,104 +1,104 @@
/* Padlock accelerated AES for Libgcrypt
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 2008, 2011, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcmp() */
#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"
#ifdef USE_PADLOCK
/* Encrypt or decrypt one block using the padlock engine. A and B may
be the same. */
static unsigned int
do_padlock (const RIJNDAEL_context *ctx, unsigned char *bx,
const unsigned char *ax, int decrypt_flag)
{
/* BX and AX are not necessary correctly aligned. Thus we need to
copy them here. */
unsigned char a[16] __attribute__ ((aligned (16)));
unsigned char b[16] __attribute__ ((aligned (16)));
unsigned int cword[4] __attribute__ ((aligned (16)));
unsigned char *pa = a;
unsigned char *pb = b;
int blocks;
/* The control word fields are:
127:12 11:10 9 8 7 6 5 4 3:0
RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */
cword[0] = (ctx->rounds & 15); /* (The mask is just a safeguard.) */
cword[1] = 0;
cword[2] = 0;
cword[3] = 0;
if (decrypt_flag)
cword[0] |= 0x00000200;
memcpy (a, ax, 16);
blocks = 1; /* Init counter for just one block. */
#ifdef __x86_64__
asm volatile
("pushfq\n\t" /* Force key reload. */
"popfq\n\t"
".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */
: "+S" (pa), "+D" (pb), "+c" (blocks)
: "d" (cword), "b" (ctx->padlockkey)
: "cc", "memory"
);
#else
asm volatile
("pushfl\n\t" /* Force key reload. */
"popfl\n\t"
"xchg %4, %%ebx\n\t" /* Load key. */
".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XCRYPT ECB. */
"xchg %4, %%ebx\n" /* Restore GOT register. */
: "+S" (pa), "+D" (pb), "+c" (blocks)
: "d" (cword), "r" (ctx->padlockkey)
: "cc", "memory"
);
#endif
memcpy (bx, b, 16);
return (48 + 15 /* possible padding for alignment */);
}
unsigned int
_gcry_aes_padlock_encrypt (const RIJNDAEL_context *ctx,
unsigned char *bx, const unsigned char *ax)
{
return do_padlock(ctx, bx, ax, 0);
}
unsigned int
_gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx,
unsigned char *bx, const unsigned char *ax)
{
return do_padlock(ctx, bx, ax, 1);
}
#endif /* USE_PADLOCK */
diff --git a/cipher/rijndael-ssse3-amd64-asm.S b/cipher/rijndael-ssse3-amd64-asm.S
index 8124eb21..10e9f9a4 100644
--- a/cipher/rijndael-ssse3-amd64-asm.S
+++ b/cipher/rijndael-ssse3-amd64-asm.S
@@ -1,874 +1,874 @@
/* SSSE3 vector permutation AES for Libgcrypt
* Copyright (C) 2014-2017 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*
* The code is based on the public domain library libvpaes version 0.5
- * available at http://crypto.stanford.edu/vpaes/ and which carries
+ * available at https://crypto.stanford.edu/vpaes/ and which carries
* this notice:
*
* libvpaes: constant-time SSSE3 AES encryption and decryption.
* version 0.5
*
* By Mike Hamburg, Stanford University, 2009. Public domain.
* I wrote essentially all of this code. I did not write the test
* vectors; they are the NIST known answer tests. I hereby release all
* the code and documentation here that I wrote into the public domain.
*
* This is an implementation of AES following my paper,
* "Accelerating AES with Vector Permute Instructions
- * CHES 2009; http://shiftleft.org/papers/vector_aes/
+ * CHES 2009; https://shiftleft.org/papers/vector_aes/
*/
#if defined(__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))
#include "asm-common-amd64.h"
.text
##
## _gcry_aes_ssse3_enc_preload
##
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
movdqa .Lk_inv+16(%rax), %xmm11 # inva
movdqa .Lk_sb1 (%rax), %xmm13 # sb1u
movdqa .Lk_sb1+16(%rax), %xmm12 # sb1t
movdqa .Lk_sb2 (%rax), %xmm15 # sb2u
movdqa .Lk_sb2+16(%rax), %xmm14 # sb2t
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ssse3_enc_preload,.-_gcry_aes_ssse3_enc_preload)
##
## _gcry_aes_ssse3_dec_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
movdqa .Lk_inv+16(%rax), %xmm11 # inva
movdqa .Lk_dsb9 (%rax), %xmm13 # sb9u
movdqa .Lk_dsb9+16(%rax), %xmm12 # sb9t
movdqa .Lk_dsbd (%rax), %xmm15 # sbdu
movdqa .Lk_dsbb (%rax), %xmm14 # sbbu
movdqa .Lk_dsbe (%rax), %xmm8 # sbeu
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ssse3_dec_preload,.-_gcry_aes_ssse3_dec_preload)
##
## Constant-time SSSE3 AES core implementation.
##
## By Mike Hamburg (Stanford University), 2009
## Public domain.
##
##
## _aes_encrypt_core
##
## AES-encrypt %xmm0.
##
## Inputs:
## %xmm0 = input
## %xmm9-%xmm15 as in .Laes_preheat
## (%rdi) = scheduled keys
## %rsi = nrounds
##
## Output in %xmm0
## Clobbers %xmm1-%xmm4, %r9, %r11, %rax, %rcx, %rdx
## Preserves %xmm6 - %xmm7 so you get some local vectors
##
##
.align 16
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
movdqa .Lk_ipt (%rcx), %xmm2 # iptlo
movdqa %xmm9, %xmm1
pandn %xmm0, %xmm1
psrld $4, %xmm1
pand %xmm9, %xmm0
pshufb %xmm0, %xmm2
movdqa .Lk_ipt+16(%rcx), %xmm0 # ipthi
pshufb %xmm1, %xmm0
pxor (%rdx),%xmm2
pxor %xmm2, %xmm0
add $16, %rdx
jmp .Laes_entry
.align 8
.Laes_loop:
# middle of middle round
movdqa %xmm13, %xmm4 # 4 : sb1u
pshufb %xmm2, %xmm4 # 4 = sb1u
pxor (%rdx), %xmm4 # 4 = sb1u + k
movdqa %xmm12, %xmm0 # 0 : sb1t
pshufb %xmm3, %xmm0 # 0 = sb1t
pxor %xmm4, %xmm0 # 0 = A
movdqa %xmm15, %xmm4 # 4 : sb2u
pshufb %xmm2, %xmm4 # 4 = sb2u
movdqa .Lk_mc_forward-.Lk_mc_backward(%rsi,%rdi), %xmm1
movdqa %xmm14, %xmm2 # 2 : sb2t
pshufb %xmm3, %xmm2 # 2 = sb2t
pxor %xmm4, %xmm2 # 2 = 2A
movdqa %xmm0, %xmm3 # 3 = A
pshufb %xmm1, %xmm0 # 0 = B
pxor %xmm2, %xmm0 # 0 = 2A+B
pshufb (%rsi,%rdi), %xmm3 # 3 = D
lea 16(%esi),%esi # next mc
pxor %xmm0, %xmm3 # 3 = 2A+B+D
lea 16(%rdx),%rdx # next key
pshufb %xmm1, %xmm0 # 0 = 2B+C
pxor %xmm3, %xmm0 # 0 = 2A+3B+C+D
and $48, %rsi # ... mod 4
dec %rax # nr--
.Laes_entry:
# top of round
movdqa %xmm9, %xmm1 # 1 : i
pandn %xmm0, %xmm1 # 1 = i<<4
psrld $4, %xmm1 # 1 = i
pand %xmm9, %xmm0 # 0 = k
movdqa %xmm11, %xmm2 # 2 : a/k
pshufb %xmm0, %xmm2 # 2 = a/k
pxor %xmm1, %xmm0 # 0 = j
movdqa %xmm10, %xmm3 # 3 : 1/i
pshufb %xmm1, %xmm3 # 3 = 1/i
pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k
movdqa %xmm10, %xmm4 # 4 : 1/j
pshufb %xmm0, %xmm4 # 4 = 1/j
pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k
movdqa %xmm10, %xmm2 # 2 : 1/iak
pshufb %xmm3, %xmm2 # 2 = 1/iak
pxor %xmm0, %xmm2 # 2 = io
movdqa %xmm10, %xmm3 # 3 : 1/jak
pshufb %xmm4, %xmm3 # 3 = 1/jak
pxor %xmm1, %xmm3 # 3 = jo
jnz .Laes_loop
# middle of last round
movdqa .Lk_sbo(%rcx), %xmm4 # 3 : sbou
pshufb %xmm2, %xmm4 # 4 = sbou
pxor (%rdx), %xmm4 # 4 = sb1u + k
movdqa .Lk_sbo+16(%rcx), %xmm0 # 0 : sbot
pshufb %xmm3, %xmm0 # 0 = sb1t
pxor %xmm4, %xmm0 # 0 = A
pshufb .Lk_sr(%rsi,%rcx), %xmm0
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _aes_encrypt_core,.-_aes_encrypt_core)
##
## Decryption core
##
## Same API as encryption core.
##
.align 16
.globl _gcry_aes_ssse3_decrypt_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
subl $1, %esi
movl %esi, %eax
shll $4, %esi
xorl $48, %esi
andl $48, %esi
movdqa .Lk_dipt (%rcx), %xmm2 # iptlo
movdqa %xmm9, %xmm1
pandn %xmm0, %xmm1
psrld $4, %xmm1
pand %xmm9, %xmm0
pshufb %xmm0, %xmm2
movdqa .Lk_dipt+16(%rcx), %xmm0 # ipthi
pshufb %xmm1, %xmm0
pxor (%rdx), %xmm2
pxor %xmm2, %xmm0
movdqa .Lk_mc_forward+48(%rcx), %xmm5
lea 16(%rdx), %rdx
neg %rax
jmp .Laes_dec_entry
.align 16
.Laes_dec_loop:
##
## Inverse mix columns
##
movdqa %xmm13, %xmm4 # 4 : sb9u
pshufb %xmm2, %xmm4 # 4 = sb9u
pxor (%rdx), %xmm4
movdqa %xmm12, %xmm0 # 0 : sb9t
pshufb %xmm3, %xmm0 # 0 = sb9t
movdqa .Lk_dsbd+16(%rcx),%xmm1 # 1 : sbdt
pxor %xmm4, %xmm0 # 0 = ch
lea 16(%rdx), %rdx # next round key
pshufb %xmm5, %xmm0 # MC ch
movdqa %xmm15, %xmm4 # 4 : sbdu
pshufb %xmm2, %xmm4 # 4 = sbdu
pxor %xmm0, %xmm4 # 4 = ch
pshufb %xmm3, %xmm1 # 1 = sbdt
pxor %xmm4, %xmm1 # 1 = ch
pshufb %xmm5, %xmm1 # MC ch
movdqa %xmm14, %xmm4 # 4 : sbbu
pshufb %xmm2, %xmm4 # 4 = sbbu
inc %rax # nr--
pxor %xmm1, %xmm4 # 4 = ch
movdqa .Lk_dsbb+16(%rcx),%xmm0 # 0 : sbbt
pshufb %xmm3, %xmm0 # 0 = sbbt
pxor %xmm4, %xmm0 # 0 = ch
pshufb %xmm5, %xmm0 # MC ch
movdqa %xmm8, %xmm4 # 4 : sbeu
pshufb %xmm2, %xmm4 # 4 = sbeu
pshufd $0x93, %xmm5, %xmm5
pxor %xmm0, %xmm4 # 4 = ch
movdqa .Lk_dsbe+16(%rcx),%xmm0 # 0 : sbet
pshufb %xmm3, %xmm0 # 0 = sbet
pxor %xmm4, %xmm0 # 0 = ch
.Laes_dec_entry:
# top of round
movdqa %xmm9, %xmm1 # 1 : i
pandn %xmm0, %xmm1 # 1 = i<<4
psrld $4, %xmm1 # 1 = i
pand %xmm9, %xmm0 # 0 = k
movdqa %xmm11, %xmm2 # 2 : a/k
pshufb %xmm0, %xmm2 # 2 = a/k
pxor %xmm1, %xmm0 # 0 = j
movdqa %xmm10, %xmm3 # 3 : 1/i
pshufb %xmm1, %xmm3 # 3 = 1/i
pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k
movdqa %xmm10, %xmm4 # 4 : 1/j
pshufb %xmm0, %xmm4 # 4 = 1/j
pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k
movdqa %xmm10, %xmm2 # 2 : 1/iak
pshufb %xmm3, %xmm2 # 2 = 1/iak
pxor %xmm0, %xmm2 # 2 = io
movdqa %xmm10, %xmm3 # 3 : 1/jak
pshufb %xmm4, %xmm3 # 3 = 1/jak
pxor %xmm1, %xmm3 # 3 = jo
jnz .Laes_dec_loop
# middle of last round
movdqa .Lk_dsbo(%rcx), %xmm4 # 3 : sbou
pshufb %xmm2, %xmm4 # 4 = sbou
pxor (%rdx), %xmm4 # 4 = sb1u + k
movdqa .Lk_dsbo+16(%rcx), %xmm0 # 0 : sbot
pshufb %xmm3, %xmm0 # 0 = sb1t
pxor %xmm4, %xmm0 # 0 = A
pshufb .Lk_sr(%rsi,%rcx), %xmm0
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _aes_decrypt_core,.-_aes_decrypt_core)
########################################################
## ##
## AES key schedule ##
## ##
########################################################
.align 16
.globl _gcry_aes_ssse3_schedule_core
ELF(.type _gcry_aes_ssse3_schedule_core,@function)
_gcry_aes_ssse3_schedule_core:
_aes_schedule_core:
# rdi = key
# 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
movdqa (%r10), %xmm9 # 0F
movdqa .Lk_inv (%r10), %xmm10 # inv
movdqa .Lk_inv+16(%r10), %xmm11 # inva
movdqa .Lk_sb1 (%r10), %xmm13 # sb1u
movdqa .Lk_sb1+16(%r10), %xmm12 # sb1t
movdqa .Lk_sb2 (%r10), %xmm15 # sb2u
movdqa .Lk_sb2+16(%r10), %xmm14 # sb2t
movdqa .Lk_rcon(%r10), %xmm8 # load rcon
movdqu (%rdi), %xmm0 # load key (unaligned)
# input transform
movdqu %xmm0, %xmm3
lea .Lk_ipt(%r10), %r11
call .Laes_schedule_transform
movdqu %xmm0, %xmm7
test %rcx, %rcx
jnz .Laes_schedule_am_decrypting
# encrypting, output zeroth round key after transform
movdqa %xmm0, (%rdx)
jmp .Laes_schedule_go
.Laes_schedule_am_decrypting:
# decrypting, output zeroth round key after shiftrows
pshufb .Lk_sr(%r8,%r10),%xmm3
movdqa %xmm3, (%rdx)
xor $48, %r8
.Laes_schedule_go:
cmp $192, %rsi
je .Laes_schedule_192
cmp $256, %rsi
je .Laes_schedule_256
# 128: fall though
##
## .Laes_schedule_128
##
## 128-bit specific part of key schedule.
##
## This schedule is really simple, because all its parts
## are accomplished by the subroutines.
##
.Laes_schedule_128:
mov $10, %rsi
.Laes_schedule_128_L:
call .Laes_schedule_round
dec %rsi
jz .Laes_schedule_mangle_last
call .Laes_schedule_mangle # write output
jmp .Laes_schedule_128_L
##
## .Laes_schedule_192
##
## 192-bit specific part of key schedule.
##
## The main body of this schedule is the same as the 128-bit
## schedule, but with more smearing. The long, high side is
## stored in %xmm7 as before, and the short, low side is in
## the high bits of %xmm6.
##
## This schedule is somewhat nastier, however, because each
## round produces 192 bits of key material, or 1.5 round keys.
## Therefore, on each cycle we do 2 rounds and produce 3 round
## keys.
##
.Laes_schedule_192:
movdqu 8(%rdi),%xmm0 # load key part 2 (very unaligned)
call .Laes_schedule_transform # input transform
pshufd $0x0E, %xmm0, %xmm6
pslldq $8, %xmm6 # clobber low side with zeros
mov $4, %rsi
.Laes_schedule_192_L:
call .Laes_schedule_round
palignr $8,%xmm6,%xmm0
call .Laes_schedule_mangle # save key n
call .Laes_schedule_192_smear
call .Laes_schedule_mangle # save key n+1
call .Laes_schedule_round
dec %rsi
jz .Laes_schedule_mangle_last
call .Laes_schedule_mangle # save key n+2
call .Laes_schedule_192_smear
jmp .Laes_schedule_192_L
##
## .Laes_schedule_192_smear
##
## Smear the short, low side in the 192-bit key schedule.
##
## Inputs:
## %xmm7: high side, b a x y
## %xmm6: low side, d c 0 0
## %xmm13: 0
##
## Outputs:
## %xmm6: b+c+d b+c 0 0
## %xmm0: b+c+d b+c b a
##
.Laes_schedule_192_smear:
pshufd $0x80, %xmm6, %xmm0 # d c 0 0 -> c 0 0 0
pxor %xmm0, %xmm6 # -> c+d c 0 0
pshufd $0xFE, %xmm7, %xmm0 # b a _ _ -> b b b a
pxor %xmm6, %xmm0 # -> b+c+d b+c b a
pshufd $0x0E, %xmm0, %xmm6
pslldq $8, %xmm6 # clobber low side with zeros
ret
##
## .Laes_schedule_256
##
## 256-bit specific part of key schedule.
##
## The structure here is very similar to the 128-bit
## schedule, but with an additional 'low side' in
## %xmm6. The low side's rounds are the same as the
## high side's, except no rcon and no rotation.
##
.Laes_schedule_256:
movdqu 16(%rdi),%xmm0 # load key part 2 (unaligned)
call .Laes_schedule_transform # input transform
mov $7, %rsi
.Laes_schedule_256_L:
call .Laes_schedule_mangle # output low result
movdqa %xmm0, %xmm6 # save cur_lo in xmm6
# high round
call .Laes_schedule_round
dec %rsi
jz .Laes_schedule_mangle_last
call .Laes_schedule_mangle
# low round. swap xmm7 and xmm6
pshufd $0xFF, %xmm0, %xmm0
movdqa %xmm7, %xmm5
movdqa %xmm6, %xmm7
call .Laes_schedule_low_round
movdqa %xmm5, %xmm7
jmp .Laes_schedule_256_L
##
## .Laes_schedule_round
##
## Runs one main round of the key schedule on %xmm0, %xmm7
##
## Specifically, runs subbytes on the high dword of %xmm0
## then rotates it by one byte and xors into the low dword of
## %xmm7.
##
## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
## next rcon.
##
## Smears the dwords of %xmm7 by xoring the low into the
## second low, result into third, result into highest.
##
## Returns results in %xmm7 = %xmm0.
## Clobbers %xmm1-%xmm4, %r11.
##
.Laes_schedule_round:
# extract rcon from xmm8
pxor %xmm1, %xmm1
palignr $15, %xmm8, %xmm1
palignr $15, %xmm8, %xmm8
pxor %xmm1, %xmm7
# rotate
pshufd $0xFF, %xmm0, %xmm0
palignr $1, %xmm0, %xmm0
# fall through...
# low round: same as high round, but no rotation and no rcon.
.Laes_schedule_low_round:
# smear xmm7
movdqa %xmm7, %xmm1
pslldq $4, %xmm7
pxor %xmm1, %xmm7
movdqa %xmm7, %xmm1
pslldq $8, %xmm7
pxor %xmm1, %xmm7
pxor .Lk_s63(%r10), %xmm7
# subbytes
movdqa %xmm9, %xmm1
pandn %xmm0, %xmm1
psrld $4, %xmm1 # 1 = i
pand %xmm9, %xmm0 # 0 = k
movdqa %xmm11, %xmm2 # 2 : a/k
pshufb %xmm0, %xmm2 # 2 = a/k
pxor %xmm1, %xmm0 # 0 = j
movdqa %xmm10, %xmm3 # 3 : 1/i
pshufb %xmm1, %xmm3 # 3 = 1/i
pxor %xmm2, %xmm3 # 3 = iak = 1/i + a/k
movdqa %xmm10, %xmm4 # 4 : 1/j
pshufb %xmm0, %xmm4 # 4 = 1/j
pxor %xmm2, %xmm4 # 4 = jak = 1/j + a/k
movdqa %xmm10, %xmm2 # 2 : 1/iak
pshufb %xmm3, %xmm2 # 2 = 1/iak
pxor %xmm0, %xmm2 # 2 = io
movdqa %xmm10, %xmm3 # 3 : 1/jak
pshufb %xmm4, %xmm3 # 3 = 1/jak
pxor %xmm1, %xmm3 # 3 = jo
movdqa .Lk_sb1(%r10), %xmm4 # 4 : sbou
pshufb %xmm2, %xmm4 # 4 = sbou
movdqa .Lk_sb1+16(%r10), %xmm0 # 0 : sbot
pshufb %xmm3, %xmm0 # 0 = sb1t
pxor %xmm4, %xmm0 # 0 = sbox output
# add in smeared stuff
pxor %xmm7, %xmm0
movdqa %xmm0, %xmm7
ret
##
## .Laes_schedule_transform
##
## Linear-transform %xmm0 according to tables at (%r11)
##
## Requires that %xmm9 = 0x0F0F... as in preheat
## Output in %xmm0
## Clobbers %xmm1, %xmm2
##
.Laes_schedule_transform:
movdqa %xmm9, %xmm1
pandn %xmm0, %xmm1
psrld $4, %xmm1
pand %xmm9, %xmm0
movdqa (%r11), %xmm2 # lo
pshufb %xmm0, %xmm2
movdqa 16(%r11), %xmm0 # hi
pshufb %xmm1, %xmm0
pxor %xmm2, %xmm0
ret
##
## .Laes_schedule_mangle
##
## Mangle xmm0 from (basis-transformed) standard version
## to our version.
##
## On encrypt,
## xor with 0x63
## multiply by circulant 0,1,1,1
## apply shiftrows transform
##
## On decrypt,
## xor with 0x63
## multiply by 'inverse mixcolumns' circulant E,B,D,9
## deskew
## apply shiftrows transform
##
##
## Writes out to (%rdx), and increments or decrements it
## Keeps track of round number mod 4 in %r8
## Preserves xmm0
## Clobbers xmm1-xmm5
##
.Laes_schedule_mangle:
movdqa %xmm0, %xmm4 # save xmm0 for later
movdqa .Lk_mc_forward(%r10),%xmm5
test %rcx, %rcx
jnz .Laes_schedule_mangle_dec
# encrypting
add $16, %rdx
pxor .Lk_s63(%r10),%xmm4
pshufb %xmm5, %xmm4
movdqa %xmm4, %xmm3
pshufb %xmm5, %xmm4
pxor %xmm4, %xmm3
pshufb %xmm5, %xmm4
pxor %xmm4, %xmm3
jmp .Laes_schedule_mangle_both
.Laes_schedule_mangle_dec:
lea .Lk_dks_1(%r10), %r11 # first table: *9
call .Laes_schedule_transform
movdqa %xmm0, %xmm3
pshufb %xmm5, %xmm3
add $32, %r11 # next table: *B
call .Laes_schedule_transform
pxor %xmm0, %xmm3
pshufb %xmm5, %xmm3
add $32, %r11 # next table: *D
call .Laes_schedule_transform
pxor %xmm0, %xmm3
pshufb %xmm5, %xmm3
add $32, %r11 # next table: *E
call .Laes_schedule_transform
pxor %xmm0, %xmm3
pshufb %xmm5, %xmm3
movdqa %xmm4, %xmm0 # restore %xmm0
add $-16, %rdx
.Laes_schedule_mangle_both:
pshufb .Lk_sr(%r8,%r10),%xmm3
add $-16, %r8
and $48, %r8
movdqa %xmm3, (%rdx)
ret
##
## .Laes_schedule_mangle_last
##
## Mangler for last round of key schedule
## Mangles %xmm0
## when encrypting, outputs out(%xmm0) ^ 63
## when decrypting, outputs unskew(%xmm0)
##
## Always called right before return... jumps to cleanup and exits
##
.Laes_schedule_mangle_last:
# schedule last round key from xmm0
lea .Lk_deskew(%r10),%r11 # prepare to deskew
test %rcx, %rcx
jnz .Laes_schedule_mangle_last_dec
# encrypting
pshufb .Lk_sr(%r8,%r10),%xmm0 # output permute
lea .Lk_opt(%r10), %r11 # prepare to output transform
add $32, %rdx
.Laes_schedule_mangle_last_dec:
add $-16, %rdx
pxor .Lk_s63(%r10), %xmm0
call .Laes_schedule_transform # output transform
movdqa %xmm0, (%rdx) # save last key
#_aes_cleanup
pxor %xmm0, %xmm0
pxor %xmm1, %xmm1
pxor %xmm2, %xmm2
pxor %xmm3, %xmm3
pxor %xmm4, %xmm4
pxor %xmm5, %xmm5
pxor %xmm6, %xmm6
pxor %xmm7, %xmm7
pxor %xmm8, %xmm8
EXIT_SYSV_FUNC
ret
CFI_ENDPROC();
ELF(.size _gcry_aes_ssse3_schedule_core,.-_gcry_aes_ssse3_schedule_core)
########################################################
## ##
## Constants ##
## ##
########################################################
.align 16
ELF(.type _aes_consts,@object)
.Laes_consts:
_aes_consts:
# s0F
.Lk_s0F = .-.Laes_consts
.quad 0x0F0F0F0F0F0F0F0F
.quad 0x0F0F0F0F0F0F0F0F
# input transform (lo, hi)
.Lk_ipt = .-.Laes_consts
.quad 0xC2B2E8985A2A7000
.quad 0xCABAE09052227808
.quad 0x4C01307D317C4D00
.quad 0xCD80B1FCB0FDCC81
# inv, inva
.Lk_inv = .-.Laes_consts
.quad 0x0E05060F0D080180
.quad 0x040703090A0B0C02
.quad 0x01040A060F0B0780
.quad 0x030D0E0C02050809
# sb1u, sb1t
.Lk_sb1 = .-.Laes_consts
.quad 0xB19BE18FCB503E00
.quad 0xA5DF7A6E142AF544
.quad 0x3618D415FAE22300
.quad 0x3BF7CCC10D2ED9EF
# sb2u, sb2t
.Lk_sb2 = .-.Laes_consts
.quad 0xE27A93C60B712400
.quad 0x5EB7E955BC982FCD
.quad 0x69EB88400AE12900
.quad 0xC2A163C8AB82234A
# sbou, sbot
.Lk_sbo = .-.Laes_consts
.quad 0xD0D26D176FBDC700
.quad 0x15AABF7AC502A878
.quad 0xCFE474A55FBB6A00
.quad 0x8E1E90D1412B35FA
# mc_forward
.Lk_mc_forward = .-.Laes_consts
.quad 0x0407060500030201
.quad 0x0C0F0E0D080B0A09
.quad 0x080B0A0904070605
.quad 0x000302010C0F0E0D
.quad 0x0C0F0E0D080B0A09
.quad 0x0407060500030201
.quad 0x000302010C0F0E0D
.quad 0x080B0A0904070605
# mc_backward
.Lk_mc_backward = .-.Laes_consts
.quad 0x0605040702010003
.quad 0x0E0D0C0F0A09080B
.quad 0x020100030E0D0C0F
.quad 0x0A09080B06050407
.quad 0x0E0D0C0F0A09080B
.quad 0x0605040702010003
.quad 0x0A09080B06050407
.quad 0x020100030E0D0C0F
# sr
.Lk_sr = .-.Laes_consts
.quad 0x0706050403020100
.quad 0x0F0E0D0C0B0A0908
.quad 0x030E09040F0A0500
.quad 0x0B06010C07020D08
.quad 0x0F060D040B020900
.quad 0x070E050C030A0108
.quad 0x0B0E0104070A0D00
.quad 0x0306090C0F020508
# rcon
.Lk_rcon = .-.Laes_consts
.quad 0x1F8391B9AF9DEEB6
.quad 0x702A98084D7C7D81
# s63: all equal to 0x63 transformed
.Lk_s63 = .-.Laes_consts
.quad 0x5B5B5B5B5B5B5B5B
.quad 0x5B5B5B5B5B5B5B5B
# output transform
.Lk_opt = .-.Laes_consts
.quad 0xFF9F4929D6B66000
.quad 0xF7974121DEBE6808
.quad 0x01EDBD5150BCEC00
.quad 0xE10D5DB1B05C0CE0
# deskew tables: inverts the sbox's 'skew'
.Lk_deskew = .-.Laes_consts
.quad 0x07E4A34047A4E300
.quad 0x1DFEB95A5DBEF91A
.quad 0x5F36B5DC83EA6900
.quad 0x2841C2ABF49D1E77
##
## Decryption stuff
## Key schedule constants
##
# decryption key schedule: x -> invskew x*9
.Lk_dks_1 = .-.Laes_consts
.quad 0xB6116FC87ED9A700
.quad 0x4AED933482255BFC
.quad 0x4576516227143300
.quad 0x8BB89FACE9DAFDCE
# decryption key schedule: invskew x*9 -> invskew x*D
.Lk_dks_2 = .-.Laes_consts
.quad 0x27438FEBCCA86400
.quad 0x4622EE8AADC90561
.quad 0x815C13CE4F92DD00
.quad 0x73AEE13CBD602FF2
# decryption key schedule: invskew x*D -> invskew x*B
.Lk_dks_3 = .-.Laes_consts
.quad 0x03C4C50201C6C700
.quad 0xF83F3EF9FA3D3CFB
.quad 0xEE1921D638CFF700
.quad 0xA5526A9D7384BC4B
# decryption key schedule: invskew x*B -> invskew x*E + 0x63
.Lk_dks_4 = .-.Laes_consts
.quad 0xE3C390B053732000
.quad 0xA080D3F310306343
.quad 0xA0CA214B036982E8
.quad 0x2F45AEC48CE60D67
##
## Decryption stuff
## Round function constants
##
# decryption input transform
.Lk_dipt = .-.Laes_consts
.quad 0x0F505B040B545F00
.quad 0x154A411E114E451A
.quad 0x86E383E660056500
.quad 0x12771772F491F194
# decryption sbox output *9*u, *9*t
.Lk_dsb9 = .-.Laes_consts
.quad 0x851C03539A86D600
.quad 0xCAD51F504F994CC9
.quad 0xC03B1789ECD74900
.quad 0x725E2C9EB2FBA565
# decryption sbox output *D*u, *D*t
.Lk_dsbd = .-.Laes_consts
.quad 0x7D57CCDFE6B1A200
.quad 0xF56E9B13882A4439
.quad 0x3CE2FAF724C6CB00
.quad 0x2931180D15DEEFD3
# decryption sbox output *B*u, *B*t
.Lk_dsbb = .-.Laes_consts
.quad 0xD022649296B44200
.quad 0x602646F6B0F2D404
.quad 0xC19498A6CD596700
.quad 0xF3FF0C3E3255AA6B
# decryption sbox output *E*u, *E*t
.Lk_dsbe = .-.Laes_consts
.quad 0x46F2929626D4D000
.quad 0x2242600464B4F6B0
.quad 0x0C55A6CDFFAAC100
.quad 0x9467F36B98593E32
# decryption sbox final output
.Lk_dsbo = .-.Laes_consts
.quad 0x1387EA537EF94000
.quad 0xC7AA6DB9D4943E2D
.quad 0x12D7560F93441D00
.quad 0xCA4B8159D8C58E9C
ELF(.size _aes_consts,.-_aes_consts)
#endif
#endif
diff --git a/cipher/rijndael-ssse3-amd64.c b/cipher/rijndael-ssse3-amd64.c
index 0c1ae6e6..7c6b417a 100644
--- a/cipher/rijndael-ssse3-amd64.c
+++ b/cipher/rijndael-ssse3-amd64.c
@@ -1,736 +1,736 @@
/* SSSE3 vector permutation AES for Libgcrypt
* Copyright (C) 2014-2017 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*
* The code is based on the public domain library libvpaes version 0.5
- * available at http://crypto.stanford.edu/vpaes/ and which carries
+ * available at https://crypto.stanford.edu/vpaes/ and which carries
* this notice:
*
* libvpaes: constant-time SSSE3 AES encryption and decryption.
* version 0.5
*
* By Mike Hamburg, Stanford University, 2009. Public domain.
* I wrote essentially all of this code. I did not write the test
* vectors; they are the NIST known answer tests. I hereby release all
* the code and documentation here that I wrote into the public domain.
*
* This is an implementation of AES following my paper,
* "Accelerating AES with Vector Permute Instructions"
- * CHES 2009; http://shiftleft.org/papers/vector_aes/
+ * CHES 2009; https://shiftleft.org/papers/vector_aes/
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcmp() */
#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_SSSE3
#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
/* Copy of ocb_get_l needed here as GCC is unable to inline ocb_get_l
because of 'pragma target'. */
static 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 (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(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);
/* Two macros to be called prior and after the use of SSSE3
instructions. There should be no external function calls between
the use of these macros. There purpose is to make sure that the
SSE registers are cleared and won't reveal any information about
the key or the data. */
#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
# define SSSE3_STATE_SIZE (16 * 10)
/* XMM6-XMM15 are callee-saved registers on WIN64. */
# define vpaes_ssse3_prepare() \
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" (ssse3_state) \
: "memory" )
# define vpaes_ssse3_cleanup() \
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" (ssse3_state) \
: "memory" )
#else
# define SSSE3_STATE_SIZE 1
# define vpaes_ssse3_prepare() (void)ssse3_state
# define vpaes_ssse3_cleanup() \
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" \
"pxor %%xmm8, %%xmm8 \n\t" \
::: "memory" )
#endif
#define vpaes_ssse3_prepare_enc() \
vpaes_ssse3_prepare(); \
_gcry_aes_ssse3_enc_preload();
#define vpaes_ssse3_prepare_dec() \
vpaes_ssse3_prepare(); \
_gcry_aes_ssse3_dec_preload();
void
_gcry_aes_ssse3_do_setkey (RIJNDAEL_context *ctx, const byte *key)
{
unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
byte ssse3_state[SSSE3_STATE_SIZE];
vpaes_ssse3_prepare();
_gcry_aes_ssse3_schedule_core(key, keybits, &ctx->keyschenc32[0][0], 0, 48);
/* Save key for setting up decryption. */
if (keybits > 192)
asm volatile ("movdqu (%[src]), %%xmm0\n\t"
"movdqu 16(%[src]), %%xmm1\n\t"
"movdqu %%xmm0, (%[dst])\n\t"
"movdqu %%xmm1, 16(%[dst])\n\t"
: /* No output */
: [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
: "memory" );
else if (keybits == 192)
asm volatile ("movdqu (%[src]), %%xmm0\n\t"
"movq 16(%[src]), %%xmm1\n\t"
"movdqu %%xmm0, (%[dst])\n\t"
"movq %%xmm1, 16(%[dst])\n\t"
: /* No output */
: [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
: "memory" );
else
asm volatile ("movdqu (%[src]), %%xmm0\n\t"
"movdqu %%xmm0, (%[dst])\n\t"
: /* No output */
: [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
: "memory" );
vpaes_ssse3_cleanup();
}
/* Make a decryption key from an encryption key. */
static inline void
do_ssse3_prepare_decryption (RIJNDAEL_context *ctx,
byte ssse3_state[SSSE3_STATE_SIZE])
{
unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
vpaes_ssse3_prepare();
_gcry_aes_ssse3_schedule_core(&ctx->keyschdec32[0][0], keybits,
&ctx->keyschdec32[ctx->rounds][0], 1,
(keybits == 192) ? 0 : 32);
vpaes_ssse3_cleanup();
}
void
_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
do_vpaes_ssse3_enc (const RIJNDAEL_context *ctx, unsigned int nrounds)
{
_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
do_vpaes_ssse3_dec (const RIJNDAEL_context *ctx, unsigned int nrounds)
{
_gcry_aes_ssse3_decrypt_core(ctx->keyschdec32, nrounds);
}
unsigned int
_gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
const unsigned char *src)
{
unsigned int nrounds = ctx->rounds;
byte ssse3_state[SSSE3_STATE_SIZE];
vpaes_ssse3_prepare_enc ();
asm volatile ("movdqu %[src], %%xmm0\n\t"
:
: [src] "m" (*src)
: "memory" );
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("movdqu %%xmm0, %[dst]\n\t"
: [dst] "=m" (*dst)
:
: "memory" );
vpaes_ssse3_cleanup ();
return 0;
}
void
_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];
vpaes_ssse3_prepare_enc ();
asm volatile ("movdqu %[iv], %%xmm0\n\t"
: /* No output */
: [iv] "m" (*iv)
: "memory" );
for ( ;nblocks; nblocks-- )
{
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"movdqu %%xmm0, %[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" );
vpaes_ssse3_cleanup ();
}
void
_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];
vpaes_ssse3_prepare_enc ();
asm volatile ("movdqu %[iv], %%xmm7\n\t"
: /* No output */
: [iv] "m" (*iv)
: "memory" );
for ( ;nblocks; nblocks-- )
{
asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm7, %%xmm0\n\t"
: /* No output */
: [inbuf] "m" (*inbuf)
: "memory" );
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("movdqa %%xmm0, %%xmm7\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
if (!cbc_mac)
outbuf += BLOCKSIZE;
}
asm volatile ("movdqu %%xmm7, %[iv]\n\t"
: [iv] "=m" (*iv)
:
: "memory" );
vpaes_ssse3_cleanup ();
}
void
_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 };
unsigned int nrounds = ctx->rounds;
byte ssse3_state[SSSE3_STATE_SIZE];
u64 ctrlow;
vpaes_ssse3_prepare_enc ();
asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
"movdqa (%[ctr]), %%xmm7\n\t" /* Preload CTR */
"movq 8(%[ctr]), %q[ctrlow]\n\t"
"bswapq %q[ctrlow]\n\t"
: [ctrlow] "=r" (ctrlow)
: [mask] "m" (*be_mask),
[ctr] "r" (ctr)
: "memory", "cc");
for ( ;nblocks; nblocks-- )
{
asm volatile ("movdqa %%xmm7, %%xmm0\n\t" /* xmm0 := CTR (xmm7) */
"pcmpeqd %%xmm1, %%xmm1\n\t"
"psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */
"pshufb %%xmm6, %%xmm7\n\t"
"psubq %%xmm1, %%xmm7\n\t" /* xmm7++ (big endian) */
/* detect if 64-bit carry handling is needed */
"incq %q[ctrlow]\n\t"
"jnz .Lno_carry%=\n\t"
"pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */
"psubq %%xmm1, %%xmm7\n\t" /* add carry to upper 64bits */
".Lno_carry%=:\n\t"
"pshufb %%xmm6, %%xmm7\n\t"
: [ctrlow] "+r" (ctrlow)
:
: "cc", "memory");
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("movdqu %[src], %%xmm1\n\t" /* xmm1 := input */
"pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */
"movdqu %%xmm0, %[dst]" /* Store EncCTR. */
: [dst] "=m" (*outbuf)
: [src] "m" (*inbuf)
: "memory");
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
asm volatile ("movdqu %%xmm7, %[ctr]\n\t" /* Update CTR (mem). */
: [ctr] "=m" (*ctr)
:
: "memory" );
vpaes_ssse3_cleanup ();
}
unsigned int
_gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
const unsigned char *src)
{
unsigned int nrounds = ctx->rounds;
byte ssse3_state[SSSE3_STATE_SIZE];
vpaes_ssse3_prepare_dec ();
asm volatile ("movdqu %[src], %%xmm0\n\t"
:
: [src] "m" (*src)
: "memory" );
do_vpaes_ssse3_dec (ctx, nrounds);
asm volatile ("movdqu %%xmm0, %[dst]\n\t"
: [dst] "=m" (*dst)
:
: "memory" );
vpaes_ssse3_cleanup ();
return 0;
}
void
_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];
vpaes_ssse3_prepare_enc ();
asm volatile ("movdqu %[iv], %%xmm0\n\t"
: /* No output */
: [iv] "m" (*iv)
: "memory" );
for ( ;nblocks; nblocks-- )
{
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
"movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm0, %%xmm6\n\t"
"movdqu %%xmm6, %[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" );
vpaes_ssse3_cleanup ();
}
void
_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 */
: /* No output */
: [iv] "m" (*iv)
: "memory");
for ( ;nblocks; nblocks-- )
{
asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
"movdqa %%xmm0, %%xmm6\n\t" /* use xmm6 as savebuf */
: /* No output */
: [inbuf] "m" (*inbuf)
: "memory");
do_vpaes_ssse3_dec (ctx, nrounds);
asm volatile ("pxor %%xmm7, %%xmm0\n\t" /* xor IV with output */
"movdqu %%xmm0, %[outbuf]\n\t"
"movdqu %%xmm6, %%xmm7\n\t" /* store savebuf as new IV */
: [outbuf] "=m" (*outbuf)
:
: "memory");
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
asm volatile ("movdqu %%xmm7, %[iv]\n\t" /* store IV */
: /* No output */
: [iv] "m" (*iv)
: "memory");
vpaes_ssse3_cleanup ();
}
static void
ssse3_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks)
{
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;
unsigned int nrounds = ctx->rounds;
byte ssse3_state[SSSE3_STATE_SIZE];
vpaes_ssse3_prepare_enc ();
/* Preload Offset and Checksum */
asm volatile ("movdqu %[iv], %%xmm7\n\t"
"movdqu %[ctr], %%xmm6\n\t"
: /* No output */
: [iv] "m" (*c->u_iv.iv),
[ctr] "m" (*c->u_ctr.ctr)
: "memory" );
for ( ;nblocks; nblocks-- )
{
const unsigned char *l;
l = aes_ocb_get_l(c, ++n);
/* 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) */
asm volatile ("movdqu %[l], %%xmm1\n\t"
"movdqu %[inbuf], %%xmm0\n\t"
"pxor %%xmm1, %%xmm7\n\t"
"pxor %%xmm0, %%xmm6\n\t"
"pxor %%xmm7, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("pxor %%xmm7, %%xmm0\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
c->u_mode.ocb.data_nblocks = n;
asm volatile ("movdqu %%xmm7, %[iv]\n\t"
"movdqu %%xmm6, %[ctr]\n\t"
: [iv] "=m" (*c->u_iv.iv),
[ctr] "=m" (*c->u_ctr.ctr)
:
: "memory" );
vpaes_ssse3_cleanup ();
}
static void
ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks)
{
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;
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 */
asm volatile ("movdqu %[iv], %%xmm7\n\t"
"movdqu %[ctr], %%xmm6\n\t"
: /* No output */
: [iv] "m" (*c->u_iv.iv),
[ctr] "m" (*c->u_ctr.ctr)
: "memory" );
for ( ;nblocks; nblocks-- )
{
const unsigned char *l;
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, %%xmm7\n\t"
"pxor %%xmm7, %%xmm0\n\t"
:
: [l] "m" (*l),
[inbuf] "m" (*inbuf)
: "memory" );
do_vpaes_ssse3_dec (ctx, nrounds);
asm volatile ("pxor %%xmm7, %%xmm0\n\t"
"pxor %%xmm0, %%xmm6\n\t"
"movdqu %%xmm0, %[outbuf]\n\t"
: [outbuf] "=m" (*outbuf)
:
: "memory" );
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
c->u_mode.ocb.data_nblocks = n;
asm volatile ("movdqu %%xmm7, %[iv]\n\t"
"movdqu %%xmm6, %[ctr]\n\t"
: [iv] "=m" (*c->u_iv.iv),
[ctr] "=m" (*c->u_ctr.ctr)
:
: "memory" );
vpaes_ssse3_cleanup ();
}
size_t
_gcry_aes_ssse3_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks, int encrypt)
{
if (encrypt)
ssse3_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
else
ssse3_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
return 0;
}
size_t
_gcry_aes_ssse3_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;
u64 n = c->u_mode.ocb.aad_nblocks;
unsigned int nrounds = ctx->rounds;
byte ssse3_state[SSSE3_STATE_SIZE];
vpaes_ssse3_prepare_enc ();
/* Preload Offset and Sum */
asm volatile ("movdqu %[iv], %%xmm7\n\t"
"movdqu %[ctr], %%xmm6\n\t"
: /* No output */
: [iv] "m" (*c->u_mode.ocb.aad_offset),
[ctr] "m" (*c->u_mode.ocb.aad_sum)
: "memory" );
for ( ;nblocks; nblocks-- )
{
const unsigned char *l;
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 %[l], %%xmm1\n\t"
"movdqu %[abuf], %%xmm0\n\t"
"pxor %%xmm1, %%xmm7\n\t"
"pxor %%xmm7, %%xmm0\n\t"
:
: [l] "m" (*l),
[abuf] "m" (*abuf)
: "memory" );
do_vpaes_ssse3_enc (ctx, nrounds);
asm volatile ("pxor %%xmm0, %%xmm6\n\t"
:
:
: "memory" );
abuf += BLOCKSIZE;
}
c->u_mode.ocb.aad_nblocks = n;
asm volatile ("movdqu %%xmm7, %[iv]\n\t"
"movdqu %%xmm6, %[ctr]\n\t"
: [iv] "=m" (*c->u_mode.ocb.aad_offset),
[ctr] "=m" (*c->u_mode.ocb.aad_sum)
:
: "memory" );
vpaes_ssse3_cleanup ();
return 0;
}
#if __clang__
# pragma clang attribute pop
#endif
#endif /* USE_SSSE3 */
diff --git a/cipher/rijndael-tables.h b/cipher/rijndael-tables.h
index 83594700..a2851aca 100644
--- a/cipher/rijndael-tables.h
+++ b/cipher/rijndael-tables.h
@@ -1,208 +1,208 @@
/* rijndael-tables.h - Rijndael (AES) for GnuPG,
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* To keep the actual implementation at a readable size we use this
include file to define the tables. */
static const u32 encT[256] =
{
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
};
static const struct
{
u32 T[256];
byte inv_sbox[256];
} dec_tables =
{
{
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5,
0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295,
0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e,
0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362,
0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52,
0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566,
0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed,
0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e,
0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4,
0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060,
0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967,
0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c,
0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624,
0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b,
0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12,
0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14,
0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b,
0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7,
0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177,
0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498,
0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54,
0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382,
0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb,
0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83,
0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef,
0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029,
0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117,
0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4,
0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d,
0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a,
0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773,
0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2,
0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff,
0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
},
{
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
}
};
#define decT dec_tables.T
#define inv_sbox dec_tables.inv_sbox
static const u32 rcon[30] =
{
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
};
diff --git a/cipher/rijndael.c b/cipher/rijndael.c
index 1001b1d5..50687132 100644
--- a/cipher/rijndael.c
+++ b/cipher/rijndael.c
@@ -1,2083 +1,2083 @@
/* Rijndael (AES) for GnuPG
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 2008, 2011, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*******************************************************************
* The code here is based on the optimized implementation taken from
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000,
* which carries this notice:
*------------------------------------------
* rijndael-alg-fst.c v2.3 April '2000
*
* Optimised ANSI C code
*
* authors: v1.0: Antoon Bosselaers
* v2.0: Vincent Rijmen
* v2.3: Paulo Barreto
*
* This code is placed in the public domain.
*------------------------------------------
*
* The SP800-38a document is available at:
- * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ * https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcmp() */
#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_AMD64_ASM
/* AMD64 assembly implementations of AES */
extern unsigned int _gcry_aes_amd64_encrypt_block(const void *keysched_enc,
unsigned char *out,
const unsigned char *in,
int rounds,
const void *encT);
extern unsigned int _gcry_aes_amd64_decrypt_block(const void *keysched_dec,
unsigned char *out,
const unsigned char *in,
int rounds,
const void *decT);
#endif /*USE_AMD64_ASM*/
#ifdef USE_AESNI
/* AES-NI (AMD64 & i386) accelerated implementations of AES */
extern void _gcry_aes_aesni_do_setkey(RIJNDAEL_context *ctx, const byte *key);
extern void _gcry_aes_aesni_prepare_decryption(RIJNDAEL_context *ctx);
extern unsigned int _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx,
unsigned char *dst,
const unsigned char *src);
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 (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_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_SSSE3
/* SSSE3 (AMD64) vector permutation implementation of AES */
extern void _gcry_aes_ssse3_do_setkey(RIJNDAEL_context *ctx, const byte *key);
extern void _gcry_aes_ssse3_prepare_decryption(RIJNDAEL_context *ctx);
extern unsigned int _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx,
unsigned char *dst,
const unsigned char *src);
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 (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 (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
extern unsigned int _gcry_aes_padlock_encrypt (const RIJNDAEL_context *ctx,
unsigned char *bx,
const unsigned char *ax);
extern unsigned int _gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx,
unsigned char *bx,
const unsigned char *ax);
#endif
#ifdef USE_ARM_ASM
/* ARM assembly implementations of AES */
extern unsigned int _gcry_aes_arm_encrypt_block(const void *keysched_enc,
unsigned char *out,
const unsigned char *in,
int rounds,
const void *encT);
extern unsigned int _gcry_aes_arm_decrypt_block(const void *keysched_dec,
unsigned char *out,
const unsigned char *in,
int rounds,
const void *decT);
#endif /*USE_ARM_ASM*/
#ifdef USE_ARM_CE
/* ARMv8 Crypto Extension implementations of AES */
extern void _gcry_aes_armv8_ce_setkey(RIJNDAEL_context *ctx, const byte *key);
extern void _gcry_aes_armv8_ce_prepare_decryption(RIJNDAEL_context *ctx);
extern unsigned int _gcry_aes_armv8_ce_encrypt(const RIJNDAEL_context *ctx,
unsigned char *dst,
const unsigned char *src);
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 (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 (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*/
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);
/* All the numbers. */
#include "rijndael-tables.h"
/* Function prototypes. */
static const char *selftest(void);
/* Prefetching for encryption/decryption tables. */
static void prefetch_table(const volatile byte *tab, size_t len)
{
size_t i;
for (i = 0; i < len; i += 8 * 32)
{
(void)tab[i + 0 * 32];
(void)tab[i + 1 * 32];
(void)tab[i + 2 * 32];
(void)tab[i + 3 * 32];
(void)tab[i + 4 * 32];
(void)tab[i + 5 * 32];
(void)tab[i + 6 * 32];
(void)tab[i + 7 * 32];
}
(void)tab[len - 1];
}
static void prefetch_enc(void)
{
prefetch_table((const void *)encT, sizeof(encT));
}
static void prefetch_dec(void)
{
prefetch_table((const void *)&dec_tables, sizeof(dec_tables));
}
/* Perform the key setup. */
static gcry_err_code_t
do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen,
gcry_cipher_hd_t hd)
{
static int initialized = 0;
static const char *selftest_failed = 0;
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
(void)hd;
/* 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
self-tests are not fully thread-safe and it might happen that a
failed self-test won't get noticed in another thread.
FIXME: We might want to have a central registry of succeeded
self-tests. */
if (!fips_mode () && !initialized)
{
initialized = 1;
selftest_failed = selftest ();
if (selftest_failed)
log_error ("%s\n", selftest_failed );
}
if (selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
if( keylen == 128/8 )
{
rounds = 10;
KC = 4;
}
else if ( keylen == 192/8 )
{
rounds = 12;
KC = 6;
}
else if ( keylen == 256/8 )
{
rounds = 14;
KC = 8;
}
else
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
if (0)
{
;
}
#ifdef USE_AESNI
else if (hwfeatures & HWF_INTEL_AESNI)
{
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->use_avx = !!(hwfeatures & HWF_INTEL_AVX);
ctx->use_avx2 = !!(hwfeatures & HWF_INTEL_AVX2);
if (hd)
{
hd->bulk.cfb_enc = _gcry_aes_aesni_cfb_enc;
hd->bulk.cfb_dec = _gcry_aes_aesni_cfb_dec;
hd->bulk.cbc_enc = _gcry_aes_aesni_cbc_enc;
hd->bulk.cbc_dec = _gcry_aes_aesni_cbc_dec;
hd->bulk.ctr_enc = _gcry_aes_aesni_ctr_enc;
hd->bulk.ocb_crypt = _gcry_aes_aesni_ocb_crypt;
hd->bulk.ocb_auth = _gcry_aes_aesni_ocb_auth;
hd->bulk.xts_crypt = _gcry_aes_aesni_xts_crypt;
}
}
#endif
#ifdef USE_PADLOCK
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;
memcpy (ctx->padlockkey, key, keylen);
}
#endif
#ifdef USE_SSSE3
else if (hwfeatures & HWF_INTEL_SSSE3)
{
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;
if (hd)
{
hd->bulk.cfb_enc = _gcry_aes_ssse3_cfb_enc;
hd->bulk.cfb_dec = _gcry_aes_ssse3_cfb_dec;
hd->bulk.cbc_enc = _gcry_aes_ssse3_cbc_enc;
hd->bulk.cbc_dec = _gcry_aes_ssse3_cbc_dec;
hd->bulk.ctr_enc = _gcry_aes_ssse3_ctr_enc;
hd->bulk.ocb_crypt = _gcry_aes_ssse3_ocb_crypt;
hd->bulk.ocb_auth = _gcry_aes_ssse3_ocb_auth;
}
}
#endif
#ifdef USE_ARM_CE
else if (hwfeatures & HWF_ARM_AES)
{
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;
if (hd)
{
hd->bulk.cfb_enc = _gcry_aes_armv8_ce_cfb_enc;
hd->bulk.cfb_dec = _gcry_aes_armv8_ce_cfb_dec;
hd->bulk.cbc_enc = _gcry_aes_armv8_ce_cbc_enc;
hd->bulk.cbc_dec = _gcry_aes_armv8_ce_cbc_dec;
hd->bulk.ctr_enc = _gcry_aes_armv8_ce_ctr_enc;
hd->bulk.ocb_crypt = _gcry_aes_armv8_ce_ocb_crypt;
hd->bulk.ocb_auth = _gcry_aes_armv8_ce_ocb_auth;
hd->bulk.xts_crypt = _gcry_aes_armv8_ce_xts_crypt;
}
}
#endif
else
{
ctx->encrypt_fn = do_encrypt;
ctx->decrypt_fn = do_decrypt;
ctx->prefetch_enc_fn = prefetch_enc;
ctx->prefetch_dec_fn = prefetch_dec;
}
/* NB: We don't yet support Padlock hardware key generation. */
if (0)
{
;
}
#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;
union
{
PROPERLY_ALIGNED_TYPE dummy;
byte data[MAXKC][4];
u32 data32[MAXKC];
} tkk[2];
#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)
prefetch_enc();
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)
{
/* While not enough round key material calculated calculate
new values. */
tk[0][0] ^= sbox[tk[KC-1][1] * 4];
tk[0][1] ^= sbox[tk[KC-1][2] * 4];
tk[0][2] ^= sbox[tk[KC-1][3] * 4];
tk[0][3] ^= sbox[tk[KC-1][0] * 4];
tk[0][0] ^= rcon[rconpointer++];
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[KC/2][0] ^= sbox[tk[KC/2 - 1][0] * 4];
tk[KC/2][1] ^= sbox[tk[KC/2 - 1][1] * 4];
tk[KC/2][2] ^= sbox[tk[KC/2 - 1][2] * 4];
tk[KC/2][3] ^= sbox[tk[KC/2 - 1][3] * 4];
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;
}
}
}
#undef W
#undef tk
#undef k
#undef W_u32
#undef tk_u32
#undef k_u32
wipememory(&tkk, sizeof(tkk));
}
return 0;
}
static gcry_err_code_t
rijndael_setkey (void *context, const byte *key, const unsigned keylen,
gcry_cipher_hd_t hd)
{
RIJNDAEL_context *ctx = context;
return do_setkey (ctx, key, keylen, hd);
}
/* Make a decryption key from an encryption key. */
static void
prepare_decryption( RIJNDAEL_context *ctx )
{
int r;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_prepare_decryption (ctx);
}
#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];
}
}
#if !defined(USE_ARM_ASM) && !defined(USE_AMD64_ASM)
/* Encrypt one block. A and B may be the same. */
static unsigned int
do_encrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
const unsigned char *a)
{
#define rk (ctx->keyschenc32)
const byte *sbox = ((const byte *)encT) + 1;
int rounds = ctx->rounds;
int r;
u32 sa[4];
u32 sb[4];
sb[0] = buf_get_le32(a + 0);
sb[1] = buf_get_le32(a + 4);
sb[2] = buf_get_le32(a + 8);
sb[3] = buf_get_le32(a + 12);
sa[0] = sb[0] ^ rk[0][0];
sa[1] = sb[1] ^ rk[0][1];
sa[2] = sb[2] ^ rk[0][2];
sa[3] = sb[3] ^ rk[0][3];
sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[1][0] ^ sb[0];
sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[1][1] ^ sb[1];
sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[1][2] ^ sb[2];
sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[1][3] ^ sb[3];
for (r = 2; r < rounds; r++)
{
sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[r][0] ^ sb[0];
sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[r][1] ^ sb[1];
sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[r][2] ^ sb[2];
sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[r][3] ^ sb[3];
r++;
sb[0] = rol(encT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[3] = rol(encT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(encT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[1] = rol(encT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[r][0] ^ sb[0];
sb[1] ^= rol(encT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(encT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(encT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sb[2] ^= rol(encT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[r][1] ^ sb[1];
sb[2] ^= rol(encT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sa[1] ^= rol(encT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(encT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sb[3] ^= rol(encT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[r][2] ^ sb[2];
sb[3] ^= rol(encT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[2] ^= rol(encT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(encT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(encT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[r][3] ^ sb[3];
}
/* 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);
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);
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);
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);
sa[3] = rk[r][3] ^ sb[3];
buf_put_le32(b + 0, sa[0]);
buf_put_le32(b + 4, sa[1]);
buf_put_le32(b + 8, sa[2]);
buf_put_le32(b + 12, sa[3]);
#undef rk
return (56 + 2*sizeof(int));
}
#endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/
static unsigned int
do_encrypt (const RIJNDAEL_context *ctx,
unsigned char *bx, const unsigned char *ax)
{
#ifdef USE_AMD64_ASM
return _gcry_aes_amd64_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds,
encT);
#elif defined(USE_ARM_ASM)
return _gcry_aes_arm_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds, encT);
#else
return do_encrypt_fn (ctx, bx, ax);
#endif /* !USE_ARM_ASM && !USE_AMD64_ASM*/
}
static unsigned int
rijndael_encrypt (void *context, byte *b, const byte *a)
{
RIJNDAEL_context *ctx = context;
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_fn();
return ctx->encrypt_fn (ctx, b, a);
}
/* Bulk encryption of complete blocks in CFB mode. Caller needs to
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
_gcry_aes_cfb_enc (void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_cfb_enc (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
_gcry_aes_ssse3_cfb_enc (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_cfb_enc (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_ARM_CE*/
else
{
rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_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. */
cipher_block_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE);
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
}
if (burn_depth)
_gcry_burn_stack (burn_depth + 4 * sizeof(void *));
}
/* Bulk encryption of complete blocks in CBC mode. Caller needs to
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
_gcry_aes_cbc_enc (void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks, int cbc_mac)
{
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned char *last_iv;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_cbc_enc (ctx, iv, outbuf, inbuf, nblocks, cbc_mac);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
_gcry_aes_ssse3_cbc_enc (ctx, iv, outbuf, inbuf, nblocks, cbc_mac);
return;
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_cbc_enc (ctx, iv, outbuf, inbuf, nblocks, cbc_mac);
return;
}
#endif /*USE_ARM_CE*/
else
{
rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_fn();
last_iv = iv;
for ( ;nblocks; nblocks-- )
{
cipher_block_xor(outbuf, inbuf, last_iv, BLOCKSIZE);
burn_depth = encrypt_fn (ctx, outbuf, outbuf);
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 *));
}
/* Bulk encryption of complete blocks in CTR mode. Caller needs to
make sure that CTR is aligned on a 16 byte boundary if AESNI; the
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
_gcry_aes_ctr_enc (void *context, unsigned char *ctr,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_ctr_enc (ctx, ctr, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
_gcry_aes_ssse3_ctr_enc (ctx, ctr, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_ctr_enc (ctx, ctr, outbuf, inbuf, nblocks);
return;
}
#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;
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_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. */
cipher_block_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE);
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
/* Increment the counter. */
cipher_block_add(ctr, 1, BLOCKSIZE);
}
wipememory(&tmp, sizeof(tmp));
}
if (burn_depth)
_gcry_burn_stack (burn_depth + 4 * sizeof(void *));
}
#if !defined(USE_ARM_ASM) && !defined(USE_AMD64_ASM)
/* Decrypt one block. A and B may be the same. */
static unsigned int
do_decrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
const unsigned char *a)
{
#define rk (ctx->keyschdec32)
int rounds = ctx->rounds;
int r;
u32 sa[4];
u32 sb[4];
sb[0] = buf_get_le32(a + 0);
sb[1] = buf_get_le32(a + 4);
sb[2] = buf_get_le32(a + 8);
sb[3] = buf_get_le32(a + 12);
sa[0] = sb[0] ^ rk[rounds][0];
sa[1] = sb[1] ^ rk[rounds][1];
sa[2] = sb[2] ^ rk[rounds][2];
sa[3] = sb[3] ^ rk[rounds][3];
for (r = rounds - 1; r > 1; r--)
{
sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[r][0] ^ sb[0];
sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[r][1] ^ sb[1];
sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[r][2] ^ sb[2];
sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[r][3] ^ sb[3];
r--;
sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[r][0] ^ sb[0];
sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[r][1] ^ sb[1];
sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[r][2] ^ sb[2];
sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[r][3] ^ sb[3];
}
sb[0] = rol(decT[(byte)(sa[0] >> (0 * 8))], (0 * 8));
sb[1] = rol(decT[(byte)(sa[0] >> (1 * 8))], (1 * 8));
sb[2] = rol(decT[(byte)(sa[0] >> (2 * 8))], (2 * 8));
sb[3] = rol(decT[(byte)(sa[0] >> (3 * 8))], (3 * 8));
sa[0] = rk[1][0] ^ sb[0];
sb[1] ^= rol(decT[(byte)(sa[1] >> (0 * 8))], (0 * 8));
sb[2] ^= rol(decT[(byte)(sa[1] >> (1 * 8))], (1 * 8));
sb[3] ^= rol(decT[(byte)(sa[1] >> (2 * 8))], (2 * 8));
sa[0] ^= rol(decT[(byte)(sa[1] >> (3 * 8))], (3 * 8));
sa[1] = rk[1][1] ^ sb[1];
sb[2] ^= rol(decT[(byte)(sa[2] >> (0 * 8))], (0 * 8));
sb[3] ^= rol(decT[(byte)(sa[2] >> (1 * 8))], (1 * 8));
sa[0] ^= rol(decT[(byte)(sa[2] >> (2 * 8))], (2 * 8));
sa[1] ^= rol(decT[(byte)(sa[2] >> (3 * 8))], (3 * 8));
sa[2] = rk[1][2] ^ sb[2];
sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
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);
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);
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);
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);
sa[3] = sb[3] ^ rk[0][3];
buf_put_le32(b + 0, sa[0]);
buf_put_le32(b + 4, sa[1]);
buf_put_le32(b + 8, sa[2]);
buf_put_le32(b + 12, sa[3]);
#undef rk
return (56+2*sizeof(int));
}
#endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/
/* Decrypt one block. AX and BX may be the same. */
static unsigned int
do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx,
const unsigned char *ax)
{
#ifdef USE_AMD64_ASM
return _gcry_aes_amd64_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds,
&dec_tables);
#elif defined(USE_ARM_ASM)
return _gcry_aes_arm_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds,
&dec_tables);
#else
return do_decrypt_fn (ctx, bx, ax);
#endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/
}
static inline void
check_decryption_preparation (RIJNDAEL_context *ctx)
{
if ( !ctx->decryption_prepared )
{
prepare_decryption ( ctx );
ctx->decryption_prepared = 1;
}
}
static unsigned int
rijndael_decrypt (void *context, byte *b, const byte *a)
{
RIJNDAEL_context *ctx = context;
check_decryption_preparation (ctx);
if (ctx->prefetch_dec_fn)
ctx->prefetch_dec_fn();
return ctx->decrypt_fn (ctx, b, a);
}
/* Bulk decryption of complete blocks in CFB mode. Caller needs to
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
_gcry_aes_cfb_dec (void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_cfb_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
_gcry_aes_ssse3_cfb_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_cfb_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_ARM_CE*/
else
{
rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_fn();
for ( ;nblocks; nblocks-- )
{
burn_depth = encrypt_fn (ctx, iv, iv);
cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE);
outbuf += BLOCKSIZE;
inbuf += BLOCKSIZE;
}
}
if (burn_depth)
_gcry_burn_stack (burn_depth + 4 * sizeof(void *));
}
/* Bulk decryption of complete blocks in CBC mode. Caller needs to
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
_gcry_aes_cbc_dec (void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
_gcry_aes_ssse3_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
return;
}
#endif /*USE_ARM_CE*/
else
{
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();
for ( ;nblocks; nblocks-- )
{
/* 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);
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 *));
}
/* Bulk encryption/decryption of complete blocks in OCB mode. */
size_t
_gcry_aes_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;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned int burn_depth = 0;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
return _gcry_aes_aesni_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
return _gcry_aes_ssse3_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
return _gcry_aes_armv8_ce_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
}
#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)} */
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 */
cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
/* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
}
else
{
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)} */
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) */
cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
burn_depth = decrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
/* Checksum_i = Checksum_{i-1} xor P_i */
cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
}
if (burn_depth)
_gcry_burn_stack (burn_depth + 4 * sizeof(void *));
return 0;
}
/* Bulk authentication of complete blocks in OCB mode. */
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;
if (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
return _gcry_aes_aesni_ocb_auth (c, abuf, nblocks);
}
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
else if (ctx->use_ssse3)
{
return _gcry_aes_ssse3_ocb_auth (c, abuf, nblocks);
}
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
return _gcry_aes_armv8_ce_ocb_auth (c, abuf, nblocks);
}
#endif /*USE_ARM_CE*/
else
{
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.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;
}
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. */
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 (0)
;
#ifdef USE_AESNI
else if (ctx->use_aesni)
{
_gcry_aes_aesni_xts_crypt (ctx, tweak, outbuf, inbuf, nblocks, encrypt);
return;
}
#endif /*USE_AESNI*/
#ifdef USE_ARM_CE
else if (ctx->use_arm_ce)
{
_gcry_aes_armv8_ce_xts_crypt (ctx, tweak, outbuf, inbuf, nblocks, encrypt);
return;
}
#endif /*USE_ARM_CE*/
else
{
if (encrypt)
{
if (ctx->prefetch_enc_fn)
ctx->prefetch_enc_fn();
crypt_fn = ctx->encrypt_fn;
}
else
{
check_decryption_preparation (ctx);
if (ctx->prefetch_dec_fn)
ctx->prefetch_dec_fn();
crypt_fn = ctx->decrypt_fn;
}
tweak_next_lo = buf_get_le64 (tweak + 0);
tweak_next_hi = buf_get_le64 (tweak + 8);
while (nblocks)
{
tweak_lo = tweak_next_lo;
tweak_hi = tweak_next_hi;
/* Xor-Encrypt/Decrypt-Xor block. */
tmp_lo = buf_get_le64 (inbuf + 0) ^ tweak_lo;
tmp_hi = buf_get_le64 (inbuf + 8) ^ tweak_hi;
buf_put_le64 (outbuf + 0, tmp_lo);
buf_put_le64 (outbuf + 8, tmp_hi);
/* 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);
outbuf += GCRY_XTS_BLOCK_LEN;
inbuf += GCRY_XTS_BLOCK_LEN;
nblocks--;
}
buf_put_le64 (tweak + 0, tweak_next_lo);
buf_put_le64 (tweak + 8, tweak_next_hi);
}
if (burn_depth)
_gcry_burn_stack (burn_depth + 5 * sizeof(void *));
}
/* Run the self-tests for AES 128. Returns NULL on success. */
static const char*
selftest_basic_128 (void)
{
RIJNDAEL_context *ctx;
unsigned char *ctxmem;
unsigned char scratch[16];
/* The test vectors are from the AES supplied ones; more or less
randomly taken from ecb_tbl.txt (I=42,81,14) */
#if 1
static const unsigned char plaintext_128[16] =
{
0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
};
static const unsigned char key_128[16] =
{
0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
};
static const unsigned char ciphertext_128[16] =
{
0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
};
#else
/* Test vectors from fips-197, appendix C. */
# warning debug test vectors in use
static const unsigned char plaintext_128[16] =
{
0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff
};
static const unsigned char key_128[16] =
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
/* 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, */
/* 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c */
};
static const unsigned char ciphertext_128[16] =
{
0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30,
0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a
};
#endif
/* Because gcc/ld can only align the CTX struct on 8 bytes on the
stack, we need to allocate that context on the heap. */
ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem);
if (!ctx)
return "failed to allocate memory";
rijndael_setkey (ctx, key_128, sizeof (key_128), NULL);
rijndael_encrypt (ctx, scratch, plaintext_128);
if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128)))
{
xfree (ctxmem);
return "AES-128 test encryption failed.";
}
rijndael_decrypt (ctx, scratch, scratch);
xfree (ctxmem);
if (memcmp (scratch, plaintext_128, sizeof (plaintext_128)))
return "AES-128 test decryption failed.";
return NULL;
}
/* Run the self-tests for AES 192. Returns NULL on success. */
static const char*
selftest_basic_192 (void)
{
RIJNDAEL_context *ctx;
unsigned char *ctxmem;
unsigned char scratch[16];
static unsigned char plaintext_192[16] =
{
0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
};
static unsigned char key_192[24] =
{
0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
};
static const unsigned char ciphertext_192[16] =
{
0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
};
ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem);
if (!ctx)
return "failed to allocate memory";
rijndael_setkey (ctx, key_192, sizeof(key_192), NULL);
rijndael_encrypt (ctx, scratch, plaintext_192);
if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
{
xfree (ctxmem);
return "AES-192 test encryption failed.";
}
rijndael_decrypt (ctx, scratch, scratch);
xfree (ctxmem);
if (memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
return "AES-192 test decryption failed.";
return NULL;
}
/* Run the self-tests for AES 256. Returns NULL on success. */
static const char*
selftest_basic_256 (void)
{
RIJNDAEL_context *ctx;
unsigned char *ctxmem;
unsigned char scratch[16];
static unsigned char plaintext_256[16] =
{
0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
};
static unsigned char key_256[32] =
{
0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
};
static const unsigned char ciphertext_256[16] =
{
0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
};
ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem);
if (!ctx)
return "failed to allocate memory";
rijndael_setkey (ctx, key_256, sizeof(key_256), NULL);
rijndael_encrypt (ctx, scratch, plaintext_256);
if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
{
xfree (ctxmem);
return "AES-256 test encryption failed.";
}
rijndael_decrypt (ctx, scratch, scratch);
xfree (ctxmem);
if (memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
return "AES-256 test decryption failed.";
return NULL;
}
/* Run the self-tests for AES-CTR-128, tests IV increment of bulk CTR
encryption. Returns NULL on success. */
static const char*
selftest_ctr_128 (void)
{
const int nblocks = 8+1;
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);
}
/* Run the self-tests for AES-CBC-128, tests bulk CBC decryption.
Returns NULL on success. */
static const char*
selftest_cbc_128 (void)
{
const int nblocks = 8+2;
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);
}
/* Run the self-tests for AES-CFB-128, tests bulk CFB decryption.
Returns NULL on success. */
static const char*
selftest_cfb_128 (void)
{
const int nblocks = 8+2;
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);
}
/* Run all the self-tests and return NULL on success. This function
is used for the on-the-fly self-tests. */
static const char *
selftest (void)
{
const char *r;
if ( (r = selftest_basic_128 ())
|| (r = selftest_basic_192 ())
|| (r = selftest_basic_256 ()) )
return r;
if ( (r = selftest_ctr_128 ()) )
return r;
if ( (r = selftest_cbc_128 ()) )
return r;
if ( (r = selftest_cfb_128 ()) )
return r;
return r;
}
/* SP800-38a.pdf for AES-128. */
static const char *
selftest_fips_128_38a (int requested_mode)
{
static const struct tv
{
int mode;
const unsigned char key[16];
const unsigned char iv[16];
struct
{
const unsigned char input[16];
const unsigned char output[16];
} data[4];
} tv[2] =
{
{
GCRY_CIPHER_MODE_CFB, /* F.3.13, CFB128-AES128 */
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{
{ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
{ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
{ { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
{ 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f,
0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } },
{ { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
{ 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40,
0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } },
{ { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
{ 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e,
0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } }
}
},
{
GCRY_CIPHER_MODE_OFB,
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{
{ { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
{ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
{ { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
{ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } },
{ { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
{ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } },
{ { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
{ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } },
}
}
};
unsigned char scratch[16];
gpg_error_t err;
int tvi, idx;
gcry_cipher_hd_t hdenc = NULL;
gcry_cipher_hd_t hddec = NULL;
#define Fail(a) do { \
_gcry_cipher_close (hdenc); \
_gcry_cipher_close (hddec); \
return a; \
} while (0)
gcry_assert (sizeof tv[0].data[0].input == sizeof scratch);
gcry_assert (sizeof tv[0].data[0].output == sizeof scratch);
for (tvi=0; tvi < DIM (tv); tvi++)
if (tv[tvi].mode == requested_mode)
break;
if (tvi == DIM (tv))
Fail ("no test data for this mode");
err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0);
if (err)
Fail ("open");
err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0);
if (err)
Fail ("open");
err = _gcry_cipher_setkey (hdenc, tv[tvi].key, sizeof tv[tvi].key);
if (!err)
err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key);
if (err)
Fail ("set key");
err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv);
if (!err)
err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv);
if (err)
Fail ("set IV");
for (idx=0; idx < DIM (tv[tvi].data); idx++)
{
err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch,
tv[tvi].data[idx].input,
sizeof tv[tvi].data[idx].input);
if (err)
Fail ("encrypt command");
if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch))
Fail ("encrypt mismatch");
err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch,
tv[tvi].data[idx].output,
sizeof tv[tvi].data[idx].output);
if (err)
Fail ("decrypt command");
if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch))
Fail ("decrypt mismatch");
}
#undef Fail
_gcry_cipher_close (hdenc);
_gcry_cipher_close (hddec);
return NULL;
}
/* Complete selftest for AES-128 with all modes and driver code. */
static gpg_err_code_t
selftest_fips_128 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
what = "low-level";
errtxt = selftest_basic_128 ();
if (errtxt)
goto failed;
if (extended)
{
what = "cfb";
errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB);
if (errtxt)
goto failed;
what = "ofb";
errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("cipher", GCRY_CIPHER_AES128, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
/* Complete selftest for AES-192. */
static gpg_err_code_t
selftest_fips_192 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
(void)extended; /* No extended tests available. */
what = "low-level";
errtxt = selftest_basic_192 ();
if (errtxt)
goto failed;
return 0; /* Succeeded. */
failed:
if (report)
report ("cipher", GCRY_CIPHER_AES192, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
/* Complete selftest for AES-256. */
static gpg_err_code_t
selftest_fips_256 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
(void)extended; /* No extended tests available. */
what = "low-level";
errtxt = selftest_basic_256 ();
if (errtxt)
goto failed;
return 0; /* Succeeded. */
failed:
if (report)
report ("cipher", GCRY_CIPHER_AES256, 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_CIPHER_AES128:
ec = selftest_fips_128 (extended, report);
break;
case GCRY_CIPHER_AES192:
ec = selftest_fips_192 (extended, report);
break;
case GCRY_CIPHER_AES256:
ec = selftest_fips_256 (extended, report);
break;
default:
ec = GPG_ERR_CIPHER_ALGO;
break;
}
return ec;
}
static const char *rijndael_names[] =
{
"RIJNDAEL",
"AES128",
"AES-128",
NULL
};
static 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 },
{ NULL }
};
gcry_cipher_spec_t _gcry_cipher_spec_aes =
{
GCRY_CIPHER_AES, {0, 1},
"AES", rijndael_names, rijndael_oids, 16, 128,
sizeof (RIJNDAEL_context),
rijndael_setkey, rijndael_encrypt, rijndael_decrypt,
NULL, NULL,
run_selftests
};
static const char *rijndael192_names[] =
{
"RIJNDAEL192",
"AES-192",
NULL
};
static 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 },
{ NULL }
};
gcry_cipher_spec_t _gcry_cipher_spec_aes192 =
{
GCRY_CIPHER_AES192, {0, 1},
"AES192", rijndael192_names, rijndael192_oids, 16, 192,
sizeof (RIJNDAEL_context),
rijndael_setkey, rijndael_encrypt, rijndael_decrypt,
NULL, NULL,
run_selftests
};
static const char *rijndael256_names[] =
{
"RIJNDAEL256",
"AES-256",
NULL
};
static 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 },
{ NULL }
};
gcry_cipher_spec_t _gcry_cipher_spec_aes256 =
{
GCRY_CIPHER_AES256, {0, 1},
"AES256", rijndael256_names, rijndael256_oids, 16, 256,
sizeof (RIJNDAEL_context),
rijndael_setkey, rijndael_encrypt, rijndael_decrypt,
NULL, NULL,
run_selftests
};
diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c
index 29b7bc81..4bd31f5b 100644
--- a/cipher/rsa-common.c
+++ b/cipher/rsa-common.c
@@ -1,1038 +1,1038 @@
/* rsa-common.c - Supporting functions for RSA
* Copyright (C) 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
#include "pubkey-internal.h"
/* Turn VALUE into an octet string and store it in an allocated buffer
at R_FRAME or - if R_RAME is NULL - copy it into the caller
provided buffer SPACE; either SPACE or R_FRAME may be used. If
SPACE if not NULL, the caller must provide a buffer of at least
NBYTES. If the resulting octet string is shorter than NBYTES pad
it to the left with zeroes. If VALUE does not fit into NBYTES
return an error code. */
static gpg_err_code_t
octet_string_from_mpi (unsigned char **r_frame, void *space,
gcry_mpi_t value, size_t nbytes)
{
return _gcry_mpi_to_octet_string (r_frame, space, value, nbytes);
}
/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block
type 2 padding. 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, RANDOM_OVERRIDE_LEN} is given it is used as
the seed instead of using a random string for it. This feature is
only useful for regression tests. Note that this value may not
contain zero bytes.
We encode the value in this way:
0 2 RND(n bytes) 0 VALUE
0 is a marker we unfortunately can't encode because we return an
MPI which strips all leading zeroes.
2 is the block type.
RND are non-zero random bytes.
(Note that OpenPGP includes the cipher algorithm and a checksum in
VALUE; the caller needs to prepare the value accordingly.)
*/
gpg_err_code_t
_gcry_rsa_pkcs1_encode_for_enc (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen,
const unsigned char *random_override,
size_t random_override_len)
{
gcry_err_code_t rc = 0;
unsigned char *frame = NULL;
size_t nframe = (nbits+7) / 8;
int i;
size_t n;
unsigned char *p;
if (valuelen + 7 > nframe || !nframe)
{
/* Can't encode a VALUELEN value in a NFRAME bytes frame. */
return GPG_ERR_TOO_SHORT; /* The key is too short. */
}
if ( !(frame = xtrymalloc_secure (nframe)))
return gpg_err_code_from_syserror ();
n = 0;
frame[n++] = 0;
frame[n++] = 2; /* block type */
i = nframe - 3 - valuelen;
gcry_assert (i > 0);
if (random_override)
{
int j;
if (random_override_len != i)
{
xfree (frame);
return GPG_ERR_INV_ARG;
}
/* Check that random does not include a zero byte. */
for (j=0; j < random_override_len; j++)
if (!random_override[j])
{
xfree (frame);
return GPG_ERR_INV_ARG;
}
memcpy (frame + n, random_override, random_override_len);
n += random_override_len;
}
else
{
p = _gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
/* Replace zero bytes by new values. */
for (;;)
{
int j, k;
unsigned char *pp;
/* Count the zero bytes. */
for (j=k=0; j < i; j++)
{
if (!p[j])
k++;
}
if (!k)
break; /* Okay: no (more) zero bytes. */
k += k/128 + 3; /* Better get some more. */
pp = _gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
for (j=0; j < i && k; )
{
if (!p[j])
p[j] = pp[--k];
if (p[j])
j++;
}
xfree (pp);
}
memcpy (frame+n, p, i);
n += i;
xfree (p);
}
frame[n++] = 0;
memcpy (frame+n, value, valuelen);
n += valuelen;
gcry_assert (n == nframe);
rc = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe);
if (!rc &&DBG_CIPHER)
log_mpidump ("PKCS#1 block type 2 encoded data", *r_result);
xfree (frame);
return rc;
}
/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding.
NBITS is the size of the secret key. On success the result is
stored as a newly allocated buffer at R_RESULT and its valid length at
R_RESULTLEN. On error NULL is stored at R_RESULT. */
gpg_err_code_t
_gcry_rsa_pkcs1_decode_for_enc (unsigned char **r_result, size_t *r_resultlen,
unsigned int nbits, gcry_mpi_t value)
{
gcry_error_t err;
unsigned char *frame = NULL;
size_t nframe = (nbits+7) / 8;
size_t n;
*r_result = NULL;
if ( !(frame = xtrymalloc_secure (nframe)))
return gpg_err_code_from_syserror ();
err = _gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &n, value);
if (err)
{
xfree (frame);
return gcry_err_code (err);
}
nframe = n; /* Set NFRAME to the actual length. */
/* FRAME = 0x00 || 0x02 || PS || 0x00 || M
pkcs#1 requires that the first byte is zero. Our MPIs usually
strip leading zero bytes; thus we are not able to detect them.
However due to the way gcry_mpi_print is implemented we may see
leading zero bytes nevertheless. We handle this by making the
first zero byte optional. */
if (nframe < 4)
{
xfree (frame);
return GPG_ERR_ENCODING_PROBLEM; /* Too short. */
}
n = 0;
if (!frame[0])
n++;
if (frame[n++] != 0x02)
{
xfree (frame);
return GPG_ERR_ENCODING_PROBLEM; /* Wrong block type. */
}
/* Skip the non-zero random bytes and the terminating zero byte. */
for (; n < nframe && frame[n] != 0x00; n++)
;
if (n+1 >= nframe)
{
xfree (frame);
return GPG_ERR_ENCODING_PROBLEM; /* No zero byte. */
}
n++; /* Skip the zero byte. */
/* To avoid an extra allocation we reuse the frame buffer. The only
caller of this function will anyway free the result soon. */
memmove (frame, frame + n, nframe - n);
*r_result = frame;
*r_resultlen = nframe - n;
if (DBG_CIPHER)
log_printhex ("value extracted from PKCS#1 block type 2 encoded data",
*r_result, *r_resultlen);
return 0;
}
/* Encode {VALUE,VALUELEN} for an NBITS keys and hash algorithm ALGO
using the pkcs#1 block type 1 padding. On success the result is
stored as a new MPI at R_RESULT. On error the value at R_RESULT is
undefined.
We encode the value in this way:
0 1 PAD(n bytes) 0 ASN(asnlen bytes) VALUE(valuelen bytes)
0 is a marker we unfortunately can't encode because we return an
MPI which strips all leading zeroes.
1 is the block type.
PAD consists of 0xff bytes.
0 marks the end of the padding.
ASN is the DER encoding of the hash algorithm; along with the VALUE
it yields a valid DER encoding.
(Note that PGP prior to version 2.3 encoded the message digest as:
0 1 MD(16 bytes) 0 PAD(n bytes) 1
The MD is always 16 bytes here because it's always MD5. GnuPG
does not not support pre-v2.3 signatures, but I'm including this
comment so the information is easily found if needed.)
*/
gpg_err_code_t
_gcry_rsa_pkcs1_encode_for_sig (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen,
int algo)
{
gcry_err_code_t rc = 0;
byte asn[100];
byte *frame = NULL;
size_t nframe = (nbits+7) / 8;
int i;
size_t n;
size_t asnlen, dlen;
asnlen = DIM(asn);
dlen = _gcry_md_get_algo_dlen (algo);
if (_gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
{
/* We don't have yet all of the above algorithms. */
return GPG_ERR_NOT_IMPLEMENTED;
}
if ( valuelen != dlen )
{
/* Hash value does not match the length of digest for
the given algorithm. */
return GPG_ERR_CONFLICT;
}
if ( !dlen || dlen + asnlen + 4 > nframe)
{
/* Can't encode an DLEN byte digest MD into an NFRAME byte
frame. */
return GPG_ERR_TOO_SHORT;
}
if ( !(frame = xtrymalloc (nframe)) )
return gpg_err_code_from_syserror ();
/* Assemble the pkcs#1 block type 1. */
n = 0;
frame[n++] = 0;
frame[n++] = 1; /* block type */
i = nframe - valuelen - asnlen - 3 ;
gcry_assert (i > 1);
memset (frame+n, 0xff, i );
n += i;
frame[n++] = 0;
memcpy (frame+n, asn, asnlen);
n += asnlen;
memcpy (frame+n, value, valuelen );
n += valuelen;
gcry_assert (n == nframe);
/* Convert it into an MPI. */
rc = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe);
if (!rc && DBG_CIPHER)
log_mpidump ("PKCS#1 block type 1 encoded data", *r_result);
xfree (frame);
return rc;
}
/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block
type 1 padding. On success the result is stored as a new MPI at
R_RESULT. On error the value at R_RESULT is undefined.
We encode the value in this way:
0 1 PAD(n bytes) 0 VALUE(valuelen bytes)
0 is a marker we unfortunately can't encode because we return an
MPI which strips all leading zeroes.
1 is the block type.
PAD consists of 0xff bytes.
0 marks the end of the padding.
(Note that PGP prior to version 2.3 encoded the message digest as:
0 1 MD(16 bytes) 0 PAD(n bytes) 1
The MD is always 16 bytes here because it's always MD5. GnuPG
does not not support pre-v2.3 signatures, but I'm including this
comment so the information is easily found if needed.)
*/
gpg_err_code_t
_gcry_rsa_pkcs1_encode_raw_for_sig (gcry_mpi_t *r_result, unsigned int nbits,
const unsigned char *value, size_t valuelen)
{
gcry_err_code_t rc = 0;
gcry_error_t err;
byte *frame = NULL;
size_t nframe = (nbits+7) / 8;
int i;
size_t n;
if ( !valuelen || valuelen + 4 > nframe)
{
/* Can't encode an DLEN byte digest MD into an NFRAME byte
frame. */
return GPG_ERR_TOO_SHORT;
}
if ( !(frame = xtrymalloc (nframe)) )
return gpg_err_code_from_syserror ();
/* Assemble the pkcs#1 block type 1. */
n = 0;
frame[n++] = 0;
frame[n++] = 1; /* block type */
i = nframe - valuelen - 3 ;
gcry_assert (i > 1);
memset (frame+n, 0xff, i );
n += i;
frame[n++] = 0;
memcpy (frame+n, value, valuelen );
n += valuelen;
gcry_assert (n == nframe);
/* Convert it into an MPI. */
err = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe);
if (err)
rc = gcry_err_code (err);
else if (DBG_CIPHER)
log_mpidump ("PKCS#1 block type 1 encoded data", *r_result);
xfree (frame);
return rc;
}
/* Mask generation function for OAEP. See RFC-3447 B.2.1. */
static gcry_err_code_t
mgf1 (unsigned char *output, size_t outlen, unsigned char *seed, size_t seedlen,
int algo)
{
size_t dlen, nbytes, n;
int idx;
gcry_md_hd_t hd;
gcry_err_code_t err;
err = _gcry_md_open (&hd, algo, 0);
if (err)
return err;
dlen = _gcry_md_get_algo_dlen (algo);
/* We skip step 1 which would be assert(OUTLEN <= 2^32). The loop
in step 3 is merged with step 4 by concatenating no more octets
than what would fit into OUTPUT. The ceiling for the counter IDX
is implemented indirectly. */
nbytes = 0; /* Step 2. */
idx = 0;
while ( nbytes < outlen )
{
unsigned char c[4], *digest;
if (idx)
_gcry_md_reset (hd);
c[0] = (idx >> 24) & 0xFF;
c[1] = (idx >> 16) & 0xFF;
c[2] = (idx >> 8) & 0xFF;
c[3] = idx & 0xFF;
idx++;
_gcry_md_write (hd, seed, seedlen);
_gcry_md_write (hd, c, 4);
digest = _gcry_md_read (hd, 0);
n = (outlen - nbytes < dlen)? (outlen - nbytes) : dlen;
memcpy (output+nbytes, digest, n);
nbytes += n;
}
_gcry_md_close (hd);
return GPG_ERR_NO_ERROR;
}
/* RFC-3447 (pkcs#1 v2.1) OAEP encoding. NBITS is the length of the
key measured in bits. ALGO is the hash function; it must be a
valid and usable algorithm. {VALUE,VALUELEN} is the message to
encrypt. {LABEL,LABELLEN} is the optional label to be associated
with the message, if LABEL is NULL the default is to use the empty
string as label. On success the encoded ciphertext is returned at
R_RESULT.
If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as
the seed instead of using a random string for it. This feature is
only useful for regression tests.
Here is figure 1 from the RFC depicting the process:
+----------+---------+-------+
DB = | lHash | PS | M |
+----------+---------+-------+
|
+----------+ V
| seed |--> MGF ---> xor
+----------+ |
| |
+--+ V |
|00| xor <----- MGF <-----|
+--+ | |
| | |
V V V
+--+----------+----------------------------+
EM = |00|maskedSeed| maskedDB |
+--+----------+----------------------------+
*/
gpg_err_code_t
_gcry_rsa_oaep_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
const unsigned char *value, size_t valuelen,
const unsigned char *label, size_t labellen,
const void *random_override, size_t random_override_len)
{
gcry_err_code_t rc = 0;
unsigned char *frame = NULL;
size_t nframe = (nbits+7) / 8;
unsigned char *p;
size_t hlen;
size_t n;
*r_result = NULL;
/* Set defaults for LABEL. */
if (!label || !labellen)
{
label = (const unsigned char*)"";
labellen = 0;
}
hlen = _gcry_md_get_algo_dlen (algo);
/* We skip step 1a which would be to check that LABELLEN is not
greater than 2^61-1. See rfc-3447 7.1.1. */
/* Step 1b. Note that the obsolete rfc-2437 uses the check:
valuelen > nframe - 2 * hlen - 1 . */
if (valuelen > nframe - 2 * hlen - 2 || !nframe)
{
/* Can't encode a VALUELEN value in a NFRAME bytes frame. */
return GPG_ERR_TOO_SHORT; /* The key is too short. */
}
/* Allocate the frame. */
frame = xtrycalloc_secure (1, nframe);
if (!frame)
return gpg_err_code_from_syserror ();
/* Step 2a: Compute the hash of the label. We store it in the frame
where later the maskedDB will commence. */
_gcry_md_hash_buffer (algo, frame + 1 + hlen, label, labellen);
/* Step 2b: Set octet string to zero. */
/* This has already been done while allocating FRAME. */
/* Step 2c: Create DB by concatenating lHash, PS, 0x01 and M. */
n = nframe - valuelen - 1;
frame[n] = 0x01;
memcpy (frame + n + 1, value, valuelen);
/* Step 3d: Generate seed. We store it where the maskedSeed will go
later. */
if (random_override)
{
if (random_override_len != hlen)
{
xfree (frame);
return GPG_ERR_INV_ARG;
}
memcpy (frame + 1, random_override, hlen);
}
else
_gcry_randomize (frame + 1, hlen, GCRY_STRONG_RANDOM);
/* Step 2e and 2f: Create maskedDB. */
{
unsigned char *dmask;
dmask = xtrymalloc_secure (nframe - hlen - 1);
if (!dmask)
{
rc = gpg_err_code_from_syserror ();
xfree (frame);
return rc;
}
rc = mgf1 (dmask, nframe - hlen - 1, frame+1, hlen, algo);
if (rc)
{
xfree (dmask);
xfree (frame);
return rc;
}
for (n = 1 + hlen, p = dmask; n < nframe; n++)
frame[n] ^= *p++;
xfree (dmask);
}
/* Step 2g and 2h: Create maskedSeed. */
{
unsigned char *smask;
smask = xtrymalloc_secure (hlen);
if (!smask)
{
rc = gpg_err_code_from_syserror ();
xfree (frame);
return rc;
}
rc = mgf1 (smask, hlen, frame + 1 + hlen, nframe - hlen - 1, algo);
if (rc)
{
xfree (smask);
xfree (frame);
return rc;
}
for (n = 1, p = smask; n < 1 + hlen; n++)
frame[n] ^= *p++;
xfree (smask);
}
/* Step 2i: Concatenate 0x00, maskedSeed and maskedDB. */
/* This has already been done by using in-place operations. */
/* Convert the stuff into an MPI as expected by the caller. */
rc = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, nframe, NULL);
if (!rc && DBG_CIPHER)
log_mpidump ("OAEP encoded data", *r_result);
xfree (frame);
return rc;
}
/* RFC-3447 (pkcs#1 v2.1) OAEP decoding. NBITS is the length of the
key measured in bits. ALGO is the hash function; it must be a
valid and usable algorithm. VALUE is the raw decrypted message
{LABEL,LABELLEN} is the optional label to be associated with the
message, if LABEL is NULL the default is to use the empty string as
label. On success the plaintext is returned as a newly allocated
buffer at R_RESULT; its valid length is stored at R_RESULTLEN. On
error NULL is stored at R_RESULT. */
gpg_err_code_t
_gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen,
unsigned int nbits, int algo,
gcry_mpi_t value,
const unsigned char *label, size_t labellen)
{
gcry_err_code_t rc;
unsigned char *frame = NULL; /* Encoded messages (EM). */
unsigned char *masked_seed; /* Points into FRAME. */
unsigned char *masked_db; /* Points into FRAME. */
unsigned char *seed = NULL; /* Allocated space for the seed and DB. */
unsigned char *db; /* Points into SEED. */
unsigned char *lhash = NULL; /* Hash of the label. */
size_t nframe; /* Length of the ciphertext (EM). */
size_t hlen; /* Length of the hash digest. */
size_t db_len; /* Length of DB and masked_db. */
size_t nkey = (nbits+7)/8; /* Length of the key in bytes. */
int failed = 0; /* Error indicator. */
size_t n;
*r_result = NULL;
/* This code is implemented as described by rfc-3447 7.1.2. */
/* Set defaults for LABEL. */
if (!label || !labellen)
{
label = (const unsigned char*)"";
labellen = 0;
}
/* Get the length of the digest. */
hlen = _gcry_md_get_algo_dlen (algo);
/* Hash the label right away. */
lhash = xtrymalloc (hlen);
if (!lhash)
return gpg_err_code_from_syserror ();
_gcry_md_hash_buffer (algo, lhash, label, labellen);
/* Turn the MPI into an octet string. If the octet string is
shorter than the key we pad it to the left with zeroes. This may
happen due to the leading zero in OAEP frames and due to the
following random octets (seed^mask) which may have leading zero
bytes. This all is needed to cope with our leading zeroes
suppressing MPI implementation. The code implictly implements
Step 1b (bail out if NFRAME != N). */
rc = octet_string_from_mpi (&frame, NULL, value, nkey);
if (rc)
{
xfree (lhash);
return GPG_ERR_ENCODING_PROBLEM;
}
nframe = nkey;
/* Step 1c: Check that the key is long enough. */
if ( nframe < 2 * hlen + 2 )
{
xfree (frame);
xfree (lhash);
return GPG_ERR_ENCODING_PROBLEM;
}
/* Step 2 has already been done by the caller and the
gcry_mpi_aprint above. */
/* Allocate space for SEED and DB. */
seed = xtrymalloc_secure (nframe - 1);
if (!seed)
{
rc = gpg_err_code_from_syserror ();
xfree (frame);
xfree (lhash);
return rc;
}
db = seed + hlen;
/* To avoid chosen ciphertext attacks from now on we make sure to
run all code even in the error case; this avoids possible timing
attacks as described by Manger. */
/* Step 3a: Hash the label. */
/* This has already been done. */
/* Step 3b: Separate the encoded message. */
masked_seed = frame + 1;
masked_db = frame + 1 + hlen;
db_len = nframe - 1 - hlen;
/* Step 3c and 3d: seed = maskedSeed ^ mgf(maskedDB, hlen). */
if (mgf1 (seed, hlen, masked_db, db_len, algo))
failed = 1;
for (n = 0; n < hlen; n++)
seed[n] ^= masked_seed[n];
/* Step 3e and 3f: db = maskedDB ^ mgf(seed, db_len). */
if (mgf1 (db, db_len, seed, hlen, algo))
failed = 1;
for (n = 0; n < db_len; n++)
db[n] ^= masked_db[n];
/* Step 3g: Check lhash, an possible empty padding string terminated
by 0x01 and the first byte of EM being 0. */
if (memcmp (lhash, db, hlen))
failed = 1;
for (n = hlen; n < db_len; n++)
if (db[n] == 0x01)
break;
if (n == db_len)
failed = 1;
if (frame[0])
failed = 1;
xfree (lhash);
xfree (frame);
if (failed)
{
xfree (seed);
return GPG_ERR_ENCODING_PROBLEM;
}
/* Step 4: Output M. */
/* To avoid an extra allocation we reuse the seed buffer. The only
caller of this function will anyway free the result soon. */
n++;
memmove (seed, db + n, db_len - n);
*r_result = seed;
*r_resultlen = db_len - n;
seed = NULL;
if (DBG_CIPHER)
log_printhex ("value extracted from OAEP encoded data",
*r_result, *r_resultlen);
return 0;
}
/* 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.
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.
Here is figure 2 from the RFC (errata 595 applied) depicting the
process:
+-----------+
| M |
+-----------+
|
V
Hash
|
V
+--------+----------+----------+
M' = |Padding1| mHash | salt |
+--------+----------+----------+
|
+--------+----------+ V
DB = |Padding2| salt | Hash
+--------+----------+ |
| |
V | +----+
xor <--- MGF <---| |0xbc|
| | +----+
| | |
V V V
+-------------------+----------+----+
EM = | maskedDB | H |0xbc|
+-------------------+----------+----+
*/
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)
{
gcry_err_code_t rc = 0;
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. */
unsigned char *h; /* Points into EM. */
unsigned char *buf = NULL; /* Help buffer. */
size_t buflen; /* Length of BUF. */
unsigned char *mhash; /* Points into BUF. */
unsigned char *salt; /* Points into BUF. */
unsigned char *dbmask; /* Points into BUF. */
unsigned char *p;
size_t n;
/* This code is implemented as described by rfc-3447 9.1.1. */
/* Get the length of the digest. */
hlen = _gcry_md_get_algo_dlen (algo);
gcry_assert (hlen); /* We expect a valid ALGO here. */
/* Allocate a help buffer and setup some pointers. */
buflen = 8 + hlen + saltlen + (emlen - hlen - 1);
buf = xtrymalloc (buflen);
if (!buf)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
mhash = buf + 8;
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)
{
rc = GPG_ERR_INV_LENGTH;
goto leave;
}
memcpy (mhash, value, hlen);
/* Step 3: Check length constraints. */
if (emlen < hlen + saltlen + 2)
{
rc = GPG_ERR_TOO_SHORT;
goto leave;
}
/* Allocate space for EM. */
em = xtrymalloc (emlen);
if (!em)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
h = em + emlen - 1 - hlen;
/* Step 4: Create a salt. */
if (saltlen)
{
if (random_override)
{
if (random_override_len != saltlen)
{
rc = GPG_ERR_INV_ARG;
goto leave;
}
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);
/* Step 7 and 8: DB = PS || 0x01 || salt. */
/* Note that we use EM to store DB and later Xor in-place. */
p = em + emlen - 1 - hlen - saltlen - 1;
memset (em, 0, p - em);
*p++ = 0x01;
memcpy (p, salt, saltlen);
/* Step 9: dbmask = MGF(H, emlen - hlen - 1). */
mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo);
/* Step 10: maskedDB = DB ^ dbMask */
for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++)
em[n] ^= *p;
/* Step 11: Set the leftmost bits to zero. */
em[0] &= 0xFF >> (8 * emlen - nbits);
/* Step 12: EM = maskedDB || H || 0xbc. */
em[emlen-1] = 0xbc;
/* Convert EM into an MPI. */
rc = _gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, em, emlen, NULL);
if (!rc && DBG_CIPHER)
log_mpidump ("PSS encoded data", *r_result);
leave:
if (em)
{
wipememory (em, emlen);
xfree (em);
}
if (buf)
{
wipememory (buf, buflen);
xfree (buf);
}
return rc;
}
/* 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
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,
unsigned int nbits, int algo, size_t saltlen)
{
gcry_err_code_t rc = 0;
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. */
unsigned char *salt; /* Points into EM. */
unsigned char *h; /* Points into EM. */
unsigned char *buf = NULL; /* Help buffer. */
size_t buflen; /* Length of BUF. */
unsigned char *dbmask; /* Points into BUF. */
unsigned char *mhash; /* Points into BUF. */
unsigned char *p;
size_t n;
/* This code is implemented as described by rfc-3447 9.1.2. */
/* Get the length of the digest. */
hlen = _gcry_md_get_algo_dlen (algo);
gcry_assert (hlen); /* We expect a valid ALGO here. */
/* Allocate a help buffer and setup some pointers.
This buffer is used for two purposes:
+------------------------------+-------+
1. | dbmask | mHash |
+------------------------------+-------+
emlen - hlen - 1 hlen
+----------+-------+---------+-+-------+
2. | padding1 | mHash | salt | | mHash |
+----------+-------+---------+-+-------+
8 hlen saltlen hlen
*/
buflen = 8 + hlen + saltlen;
if (buflen < emlen - hlen - 1)
buflen = emlen - hlen - 1;
buflen += hlen;
buf = xtrymalloc (buflen);
if (!buf)
{
rc = gpg_err_code_from_syserror ();
goto leave;
}
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;
/* Convert the signature into an octet string. */
rc = octet_string_from_mpi (&em, NULL, encoded, emlen);
if (rc)
goto leave;
/* Step 3: Check length of EM. Because we internally use MPI
functions we can't do this properly; EMLEN is always the length
of the key because octet_string_from_mpi needs to left pad the
result with zero to cope with the fact that our MPIs suppress all
leading zeroes. Thus what we test here are merely the digest and
salt lengths to the key. */
if (emlen < hlen + saltlen + 2)
{
rc = GPG_ERR_TOO_SHORT; /* For the hash and saltlen. */
goto leave;
}
/* Step 4: Check last octet. */
if (em[emlen - 1] != 0xbc)
{
rc = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
/* Step 5: Split EM. */
h = em + emlen - 1 - hlen;
/* Step 6: Check the leftmost bits. */
if ((em[0] & ~(0xFF >> (8 * emlen - nbits))))
{
rc = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
/* Step 7: dbmask = MGF(H, emlen - hlen - 1). */
mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo);
/* Step 8: maskedDB = DB ^ dbMask. */
for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++)
em[n] ^= *p;
/* Step 9: Set leftmost bits in DB to zero. */
em[0] &= 0xFF >> (8 * emlen - nbits);
/* Step 10: Check the padding of DB. */
for (n = 0; n < emlen - hlen - saltlen - 2 && !em[n]; n++)
;
if (n != emlen - hlen - saltlen - 2 || em[n++] != 1)
{
rc = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
/* Step 11: Extract salt from DB. */
salt = em + n;
/* Step 12: M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */
memset (buf, 0, 8);
memcpy (buf+8, mhash, hlen);
memcpy (buf+8+hlen, salt, saltlen);
/* Step 13: H' = Hash(M'). */
_gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen);
/* Step 14: Check H == H'. */
rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR;
leave:
if (em)
{
wipememory (em, emlen);
xfree (em);
}
if (buf)
{
wipememory (buf, buflen);
xfree (buf);
}
return rc;
}
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 575ea949..fefb35f7 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -1,2035 +1,2035 @@
/* rsa.c - RSA implementation
* Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
* Copyright (C) 2000, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* This code uses an algorithm protected by U.S. Patent #4,405,829
which expired on September 20, 2000. The patent holder placed that
patent into the public domain on Sep 6th, 2000.
*/
#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 "pubkey-internal.h"
typedef struct
{
gcry_mpi_t n; /* modulus */
gcry_mpi_t e; /* exponent */
} RSA_public_key;
typedef struct
{
gcry_mpi_t n; /* public modulus */
gcry_mpi_t e; /* public exponent */
gcry_mpi_t d; /* exponent */
gcry_mpi_t p; /* prime p. */
gcry_mpi_t q; /* prime q. */
gcry_mpi_t u; /* inverse of p mod q. */
} RSA_secret_key;
static const char *rsa_names[] =
{
"rsa",
"openpgp-rsa",
"oid.1.2.840.113549.1.1.1",
NULL,
};
/* A sample 2048 bit RSA key used for the selftests. */
static const char sample_secret_key[] =
" (private-key"
" (rsa"
" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)"
" (e #010001#)"
" (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
" 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
" 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
" 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
" 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
" EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
" 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
" 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401#)"
" (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
" 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
" 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
" 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F1783#)"
" (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46"
" 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
" 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
" 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B919#)"
" (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
" 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
" A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
" AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7#)))";
/* A sample 2048 bit RSA key used for the selftests (public only). */
static const char sample_public_key[] =
" (public-key"
" (rsa"
" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)"
" (e #010001#)))";
static int test_keys (RSA_secret_key *sk, unsigned nbits);
static int check_secret_key (RSA_secret_key *sk);
static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey);
static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey);
static unsigned int rsa_get_nbits (gcry_sexp_t parms);
/* Check that a freshly generated key actually works. Returns 0 on success. */
static int
test_keys (RSA_secret_key *sk, unsigned int nbits)
{
int result = -1; /* Default to failure. */
RSA_public_key pk;
gcry_mpi_t plaintext = mpi_new (nbits);
gcry_mpi_t ciphertext = mpi_new (nbits);
gcry_mpi_t decr_plaintext = mpi_new (nbits);
gcry_mpi_t signature = mpi_new (nbits);
/* Put the relevant parameters into a public key structure. */
pk.n = sk->n;
pk.e = sk->e;
/* Create a random plaintext. */
_gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
/* Encrypt using the public key. */
public (ciphertext, plaintext, &pk);
/* Check that the cipher text does not match the plaintext. */
if (!mpi_cmp (ciphertext, plaintext))
goto leave; /* Ciphertext is identical to the plaintext. */
/* Decrypt using the secret key. */
secret (decr_plaintext, ciphertext, sk);
/* Check that the decrypted plaintext matches the original plaintext. */
if (mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Plaintext does not match. */
/* Create another random plaintext as data for signature checking. */
_gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
/* Use the RSA secret function to create a signature of the plaintext. */
secret (signature, plaintext, sk);
/* Use the RSA public function to verify this signature. */
public (decr_plaintext, signature, &pk);
if (mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Signature does not match. */
/* Modify the signature and check that the signing fails. */
mpi_add_ui (signature, signature, 1);
public (decr_plaintext, signature, &pk);
if (!mpi_cmp (decr_plaintext, plaintext))
goto leave; /* Signature matches but should not. */
result = 0; /* All tests succeeded. */
leave:
_gcry_mpi_release (signature);
_gcry_mpi_release (decr_plaintext);
_gcry_mpi_release (ciphertext);
_gcry_mpi_release (plaintext);
return result;
}
/* Callback used by the prime generation to test whether the exponent
is suitable. Returns 0 if the test has been passed. */
static int
check_exponent (void *arg, gcry_mpi_t a)
{
gcry_mpi_t e = arg;
gcry_mpi_t tmp;
int result;
mpi_sub_ui (a, a, 1);
tmp = _gcry_mpi_alloc_like (a);
result = !mpi_gcd(tmp, e, a); /* GCD is not 1. */
_gcry_mpi_release (tmp);
mpi_add_ui (a, a, 1);
return result;
}
/****************
* Generate a key pair with a key of size NBITS.
* USE_E = 0 let Libcgrypt decide what exponent to use.
* = 1 request the use of a "secure" exponent; this is required by some
* specification to be 65537.
* > 2 Use this public exponent. If the given exponent
* is not odd one is internally added to it.
* TRANSIENT_KEY: If true, generate the primes using the standard RNG.
* Returns: 2 structures filled with all needed values
*/
static gpg_err_code_t
generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
int transient_key)
{
gcry_mpi_t p, q; /* the two primes */
gcry_mpi_t d; /* the private key */
gcry_mpi_t u;
gcry_mpi_t t1, t2;
gcry_mpi_t n; /* the public key */
gcry_mpi_t e; /* the exponent */
gcry_mpi_t phi; /* helper: (p-1)(q-1) */
gcry_mpi_t g;
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;
/* Make sure that nbits is even so that we generate p, q of equal size. */
if ( (nbits&1) )
nbits++;
if (use_e == 1) /* Alias for a secure value */
use_e = 65537; /* as demanded by Sphinx. */
/* Public exponent:
In general we use 41 as this is quite fast and more secure than the
commonly used 17. Benchmarking the RSA verify function
with a 1024 bit key yields (2001-11-08):
e=17 0.54 ms
e=41 0.75 ms
e=257 0.95 ms
e=65537 1.80 ms
*/
e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
if (!use_e)
mpi_set_ui (e, 41); /* This is a reasonable secure and fast value */
else
{
use_e |= 1; /* make sure this is odd */
mpi_set_ui (e, use_e);
}
n = mpi_new (nbits);
p = q = NULL;
do
{
/* select two (very secret) primes */
if (p)
_gcry_mpi_release (p);
if (q)
_gcry_mpi_release (q);
if (use_e)
{ /* Do an extra test to ensure that the given exponent is
suitable. */
p = _gcry_generate_secret_prime (nbits/2, random_level,
check_exponent, e);
q = _gcry_generate_secret_prime (nbits/2, random_level,
check_exponent, e);
}
else
{ /* We check the exponent later. */
p = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
q = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL);
}
if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/
mpi_swap(p,q);
/* calculate the modulus */
mpi_mul( n, p, q );
}
while ( mpi_get_nbits(n) != nbits );
/* calculate Euler totient: phi = (p-1)(q-1) */
t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
phi = mpi_snew ( nbits );
g = mpi_snew ( nbits );
f = mpi_snew ( nbits );
mpi_sub_ui( t1, p, 1 );
mpi_sub_ui( t2, q, 1 );
mpi_mul( phi, t1, t2 );
mpi_gcd (g, t1, t2);
mpi_fdiv_q(f, phi, g);
while (!mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
{
if (use_e)
BUG (); /* The prime generator already made sure that we
never can get to here. */
mpi_add_ui (e, e, 2);
}
/* calculate the secret key d = e^-1 mod phi */
d = mpi_snew ( nbits );
mpi_invm (d, e, f );
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
u = mpi_snew ( nbits );
mpi_invm(u, p, q );
if( DBG_CIPHER )
{
log_mpidump(" p= ", p );
log_mpidump(" q= ", q );
log_mpidump("phi= ", phi );
log_mpidump(" g= ", g );
log_mpidump(" f= ", f );
log_mpidump(" n= ", n );
log_mpidump(" e= ", e );
log_mpidump(" d= ", d );
log_mpidump(" u= ", u );
}
_gcry_mpi_release (t1);
_gcry_mpi_release (t2);
_gcry_mpi_release (phi);
_gcry_mpi_release (f);
_gcry_mpi_release (g);
sk->n = n;
sk->e = e;
sk->p = p;
sk->q = q;
sk->d = d;
sk->u = u;
/* Now we can test our keys. */
if (test_keys (sk, nbits - 64))
{
_gcry_mpi_release (sk->n); sk->n = NULL;
_gcry_mpi_release (sk->e); sk->e = NULL;
_gcry_mpi_release (sk->p); sk->p = NULL;
_gcry_mpi_release (sk->q); sk->q = NULL;
_gcry_mpi_release (sk->d); sk->d = NULL;
_gcry_mpi_release (sk->u); sk->u = NULL;
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
return 0;
}
/****************
* Generate a key pair with a key of size NBITS.
* USE_E = 0 let Libcgrypt decide what exponent to use.
* = 1 request the use of a "secure" exponent; this is required by some
* specification to be 65537.
* > 2 Use this public exponent. If the given exponent
* is not odd one is internally added to it.
* TESTPARMS: If set, do not generate but test whether the p,q is probably prime
* Returns key with zeroes to not break code calling this function.
* TRANSIENT_KEY: If true, generate the primes using the standard RNG.
* Returns: 2 structures filled with all needed values
*/
static gpg_err_code_t
generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
gcry_sexp_t testparms, int transient_key)
{
gcry_mpi_t p, q; /* the two primes */
gcry_mpi_t d; /* the private key */
gcry_mpi_t u;
gcry_mpi_t p1, q1;
gcry_mpi_t n; /* the public key */
gcry_mpi_t e; /* the exponent */
gcry_mpi_t g;
gcry_mpi_t minp;
gcry_mpi_t diff, mindiff;
gcry_random_level_t random_level;
unsigned int pbits = nbits/2;
unsigned int i;
int pqswitch;
gpg_err_code_t ec = GPG_ERR_NO_PRIME;
if (nbits < 1024 || (nbits & 0x1FF))
return GPG_ERR_INV_VALUE;
if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072)
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;
if (testparms)
{
/* Parameters to derive the key are given. */
/* Note that we explicitly need to setup the values of tbl
because some compilers (e.g. OpenWatcom, IRIX) don't allow to
initialize a structure with automatic variables. */
struct { const char *name; gcry_mpi_t *value; } tbl[] = {
{ "e" },
{ "p" },
{ "q" },
{ NULL }
};
int idx;
gcry_sexp_t oneparm;
tbl[0].value = &e;
tbl[1].value = &p;
tbl[2].value = &q;
for (idx=0; tbl[idx].name; idx++)
{
oneparm = sexp_find_token (testparms, tbl[idx].name, 0);
if (oneparm)
{
*tbl[idx].value = sexp_nth_mpi (oneparm, 1, GCRYMPI_FMT_USG);
sexp_release (oneparm);
}
}
for (idx=0; tbl[idx].name; idx++)
if (!*tbl[idx].value)
break;
if (tbl[idx].name)
{
/* At least one parameter is missing. */
for (idx=0; tbl[idx].name; idx++)
_gcry_mpi_release (*tbl[idx].value);
return GPG_ERR_MISSING_VALUE;
}
}
else
{
if (use_e < 65537)
use_e = 65537; /* This is the smallest value allowed by FIPS */
e = mpi_alloc ((32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB);
use_e |= 1; /* make sure this is odd */
mpi_set_ui (e, use_e);
p = mpi_snew (pbits);
q = mpi_snew (pbits);
}
n = mpi_new (nbits);
d = mpi_snew (nbits);
u = mpi_snew (nbits);
/* prepare approximate minimum p and q */
minp = mpi_new (pbits);
mpi_set_ui (minp, 0xB504F334);
mpi_lshift (minp, minp, pbits - 32);
/* prepare minimum p and q difference */
diff = mpi_new (pbits);
mindiff = mpi_new (pbits - 99);
mpi_set_ui (mindiff, 1);
mpi_lshift (mindiff, mindiff, pbits - 100);
p1 = mpi_snew (pbits);
q1 = mpi_snew (pbits);
g = mpi_snew (pbits);
retry:
/* generate p and q */
for (i = 0; i < 5 * pbits; i++)
{
ploop:
if (!testparms)
{
_gcry_mpi_randomize (p, pbits, random_level);
}
if (mpi_cmp (p, minp) < 0)
{
if (testparms)
goto err;
goto ploop;
}
mpi_sub_ui (p1, p, 1);
if (mpi_gcd (g, p1, e))
{
if (_gcry_fips186_4_prime_check (p, pbits) != GPG_ERR_NO_ERROR)
{
/* not a prime */
if (testparms)
goto err;
}
else
break;
}
else if (testparms)
goto err;
}
if (i >= 5 * pbits)
goto err;
for (i = 0; i < 5 * pbits; i++)
{
qloop:
if (!testparms)
{
_gcry_mpi_randomize (q, pbits, random_level);
}
if (mpi_cmp (q, minp) < 0)
{
if (testparms)
goto err;
goto qloop;
}
if (mpi_cmp (p, q) > 0)
{
pqswitch = 1;
mpi_sub (diff, p, q);
}
else
{
pqswitch = 0;
mpi_sub (diff, q, p);
}
if (mpi_cmp (diff, mindiff) < 0)
{
if (testparms)
goto err;
goto qloop;
}
mpi_sub_ui (q1, q, 1);
if (mpi_gcd (g, q1, e))
{
if (_gcry_fips186_4_prime_check (q, pbits) != GPG_ERR_NO_ERROR)
{
/* not a prime */
if (testparms)
goto err;
}
else
break;
}
else if (testparms)
goto err;
}
if (i >= 5 * pbits)
goto err;
if (testparms)
{
mpi_clear (p);
mpi_clear (q);
}
else
{
gcry_mpi_t f;
if (pqswitch)
{
gcry_mpi_t tmp;
tmp = p;
p = q;
q = tmp;
}
f = mpi_snew (nbits);
/* calculate the modulus */
mpi_mul (n, p, q);
/* calculate the secret key d = e^1 mod phi */
mpi_gcd (g, p1, q1);
mpi_fdiv_q (f, p1, g);
mpi_mul (f, f, q1);
mpi_invm (d, e, f);
_gcry_mpi_release (f);
if (mpi_get_nbits (d) < pbits)
goto retry;
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
mpi_invm (u, p, q );
}
ec = 0;
if (DBG_CIPHER)
{
log_mpidump(" p= ", p );
log_mpidump(" q= ", q );
log_mpidump(" n= ", n );
log_mpidump(" e= ", e );
log_mpidump(" d= ", d );
log_mpidump(" u= ", u );
}
err:
_gcry_mpi_release (p1);
_gcry_mpi_release (q1);
_gcry_mpi_release (g);
_gcry_mpi_release (minp);
_gcry_mpi_release (mindiff);
_gcry_mpi_release (diff);
sk->n = n;
sk->e = e;
sk->p = p;
sk->q = q;
sk->d = d;
sk->u = u;
/* Now we can test our keys. */
if (ec || (!testparms && test_keys (sk, nbits - 64)))
{
_gcry_mpi_release (sk->n); sk->n = NULL;
_gcry_mpi_release (sk->e); sk->e = NULL;
_gcry_mpi_release (sk->p); sk->p = NULL;
_gcry_mpi_release (sk->q); sk->q = NULL;
_gcry_mpi_release (sk->d); sk->d = NULL;
_gcry_mpi_release (sk->u); sk->u = NULL;
if (!ec)
{
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
}
return ec;
}
/* Helper for generate_x931. */
static gcry_mpi_t
gen_x931_parm_xp (unsigned int nbits)
{
gcry_mpi_t xp;
xp = mpi_snew (nbits);
_gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM);
/* The requirement for Xp is:
sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1
We set the two high order bits to 1 to satisfy the lower bound.
By using mpi_set_highbit we make sure that the upper bound is
satisfied as well. */
mpi_set_highbit (xp, nbits-1);
mpi_set_bit (xp, nbits-2);
gcry_assert ( mpi_get_nbits (xp) == nbits );
return xp;
}
/* Helper for generate_x931. */
static gcry_mpi_t
gen_x931_parm_xi (void)
{
gcry_mpi_t xi;
xi = mpi_snew (101);
_gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM);
mpi_set_highbit (xi, 100);
gcry_assert ( mpi_get_nbits (xi) == 101 );
return xi;
}
/* Variant of the standard key generation code using the algorithm
from X9.31. Using this algorithm has the advantage that the
generation can be made deterministic which is required for CAVS
testing. */
static gpg_err_code_t
generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
gcry_sexp_t deriveparms, int *swapped)
{
gcry_mpi_t p, q; /* The two primes. */
gcry_mpi_t e; /* The public exponent. */
gcry_mpi_t n; /* The public key. */
gcry_mpi_t d; /* The private key */
gcry_mpi_t u; /* The inverse of p and q. */
gcry_mpi_t pm1; /* p - 1 */
gcry_mpi_t qm1; /* q - 1 */
gcry_mpi_t phi; /* Euler totient. */
gcry_mpi_t f, g; /* Helper. */
*swapped = 0;
if (e_value == 1) /* Alias for a secure value. */
e_value = 65537;
/* Point 1 of section 4.1: k = 1024 + 256s with S >= 0 */
if (nbits < 1024 || (nbits % 256))
return GPG_ERR_INV_VALUE;
/* Point 2: 2 <= bitlength(e) < 2^{k-2}
Note that we do not need to check the upper bound because we use
an unsigned long for E and thus there is no way for E to reach
that limit. */
if (e_value < 3)
return GPG_ERR_INV_VALUE;
/* Our implementation requires E to be odd. */
if (!(e_value & 1))
return GPG_ERR_INV_VALUE;
/* Point 3: e > 0 or e 0 if it is to be randomly generated.
We support only a fixed E and thus there is no need for an extra test. */
/* Compute or extract the derive parameters. */
{
gcry_mpi_t xp1 = NULL;
gcry_mpi_t xp2 = NULL;
gcry_mpi_t xp = NULL;
gcry_mpi_t xq1 = NULL;
gcry_mpi_t xq2 = NULL;
gcry_mpi_t xq = NULL;
gcry_mpi_t tmpval;
if (!deriveparms)
{
/* Not given: Generate them. */
xp = gen_x931_parm_xp (nbits/2);
/* Make sure that |xp - xq| > 2^{nbits - 100} holds. */
tmpval = mpi_snew (nbits/2);
do
{
_gcry_mpi_release (xq);
xq = gen_x931_parm_xp (nbits/2);
mpi_sub (tmpval, xp, xq);
}
while (mpi_get_nbits (tmpval) <= (nbits/2 - 100));
_gcry_mpi_release (tmpval);
xp1 = gen_x931_parm_xi ();
xp2 = gen_x931_parm_xi ();
xq1 = gen_x931_parm_xi ();
xq2 = gen_x931_parm_xi ();
}
else
{
/* Parameters to derive the key are given. */
/* Note that we explicitly need to setup the values of tbl
because some compilers (e.g. OpenWatcom, IRIX) don't allow
to initialize a structure with automatic variables. */
struct { const char *name; gcry_mpi_t *value; } tbl[] = {
{ "Xp1" },
{ "Xp2" },
{ "Xp" },
{ "Xq1" },
{ "Xq2" },
{ "Xq" },
{ NULL }
};
int idx;
gcry_sexp_t oneparm;
tbl[0].value = &xp1;
tbl[1].value = &xp2;
tbl[2].value = &xp;
tbl[3].value = &xq1;
tbl[4].value = &xq2;
tbl[5].value = &xq;
for (idx=0; tbl[idx].name; idx++)
{
oneparm = sexp_find_token (deriveparms, tbl[idx].name, 0);
if (oneparm)
{
*tbl[idx].value = sexp_nth_mpi (oneparm, 1, GCRYMPI_FMT_USG);
sexp_release (oneparm);
}
}
for (idx=0; tbl[idx].name; idx++)
if (!*tbl[idx].value)
break;
if (tbl[idx].name)
{
/* At least one parameter is missing. */
for (idx=0; tbl[idx].name; idx++)
_gcry_mpi_release (*tbl[idx].value);
return GPG_ERR_MISSING_VALUE;
}
}
e = mpi_alloc_set_ui (e_value);
/* Find two prime numbers. */
p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL);
q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL);
_gcry_mpi_release (xp); xp = NULL;
_gcry_mpi_release (xp1); xp1 = NULL;
_gcry_mpi_release (xp2); xp2 = NULL;
_gcry_mpi_release (xq); xq = NULL;
_gcry_mpi_release (xq1); xq1 = NULL;
_gcry_mpi_release (xq2); xq2 = NULL;
if (!p || !q)
{
_gcry_mpi_release (p);
_gcry_mpi_release (q);
_gcry_mpi_release (e);
return GPG_ERR_NO_PRIME;
}
}
/* Compute the public modulus. We make sure that p is smaller than
q to allow the use of the CRT. */
if (mpi_cmp (p, q) > 0 )
{
mpi_swap (p, q);
*swapped = 1;
}
n = mpi_new (nbits);
mpi_mul (n, p, q);
/* Compute the Euler totient: phi = (p-1)(q-1) */
pm1 = mpi_snew (nbits/2);
qm1 = mpi_snew (nbits/2);
phi = mpi_snew (nbits);
mpi_sub_ui (pm1, p, 1);
mpi_sub_ui (qm1, q, 1);
mpi_mul (phi, pm1, qm1);
g = mpi_snew (nbits);
gcry_assert (mpi_gcd (g, e, phi));
/* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
mpi_gcd (g, pm1, qm1);
f = pm1; pm1 = NULL;
_gcry_mpi_release (qm1); qm1 = NULL;
mpi_fdiv_q (f, phi, g);
_gcry_mpi_release (phi); phi = NULL;
d = g; g = NULL;
/* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */
mpi_invm (d, e, f);
/* Compute the inverse of p and q. */
u = f; f = NULL;
mpi_invm (u, p, q );
if( DBG_CIPHER )
{
if (*swapped)
log_debug ("p and q are swapped\n");
log_mpidump(" p", p );
log_mpidump(" q", q );
log_mpidump(" n", n );
log_mpidump(" e", e );
log_mpidump(" d", d );
log_mpidump(" u", u );
}
sk->n = n;
sk->e = e;
sk->p = p;
sk->q = q;
sk->d = d;
sk->u = u;
/* Now we can test our keys. */
if (test_keys (sk, nbits - 64))
{
_gcry_mpi_release (sk->n); sk->n = NULL;
_gcry_mpi_release (sk->e); sk->e = NULL;
_gcry_mpi_release (sk->p); sk->p = NULL;
_gcry_mpi_release (sk->q); sk->q = NULL;
_gcry_mpi_release (sk->d); sk->d = NULL;
_gcry_mpi_release (sk->u); sk->u = NULL;
fips_signal_error ("self-test after key generation failed");
return GPG_ERR_SELFTEST_FAILED;
}
return 0;
}
/****************
* Test whether the secret key is valid.
* Returns: true if this is a valid key.
*/
static int
check_secret_key( RSA_secret_key *sk )
{
int rc;
gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
mpi_mul(temp, sk->p, sk->q );
rc = mpi_cmp( temp, sk->n );
mpi_free(temp);
return !rc;
}
/****************
* Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT.
*
* c = m^e mod n
*
* Where c is OUTPUT, m is INPUT and e,n are elements of PKEY.
*/
static void
public(gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *pkey )
{
if( output == input ) /* powm doesn't like output and input the same */
{
gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs(input)*2 );
mpi_powm( x, input, pkey->e, pkey->n );
mpi_set(output, x);
mpi_free(x);
}
else
mpi_powm( output, input, pkey->e, pkey->n );
}
#if 0
static void
stronger_key_check ( RSA_secret_key *skey )
{
gcry_mpi_t t = mpi_alloc_secure ( 0 );
gcry_mpi_t t1 = mpi_alloc_secure ( 0 );
gcry_mpi_t t2 = mpi_alloc_secure ( 0 );
gcry_mpi_t phi = mpi_alloc_secure ( 0 );
/* check that n == p * q */
mpi_mul( t, skey->p, skey->q);
if (mpi_cmp( t, skey->n) )
log_info ( "RSA Oops: n != p * q\n" );
/* check that p is less than q */
if( mpi_cmp( skey->p, skey->q ) > 0 )
{
log_info ("RSA Oops: p >= q - fixed\n");
_gcry_mpi_swap ( skey->p, skey->q);
}
/* check that e divides neither p-1 nor q-1 */
mpi_sub_ui(t, skey->p, 1 );
mpi_fdiv_r(t, t, skey->e );
if ( !mpi_cmp_ui( t, 0) )
log_info ( "RSA Oops: e divides p-1\n" );
mpi_sub_ui(t, skey->q, 1 );
mpi_fdiv_r(t, t, skey->e );
if ( !mpi_cmp_ui( t, 0) )
log_info ( "RSA Oops: e divides q-1\n" );
/* check that d is correct */
mpi_sub_ui( t1, skey->p, 1 );
mpi_sub_ui( t2, skey->q, 1 );
mpi_mul( phi, t1, t2 );
gcry_mpi_gcd(t, t1, t2);
mpi_fdiv_q(t, phi, t);
mpi_invm(t, skey->e, t );
if ( mpi_cmp(t, skey->d ) )
{
log_info ( "RSA Oops: d is wrong - fixed\n");
mpi_set (skey->d, t);
log_printmpi (" fixed d", skey->d);
}
/* check for correctness of u */
mpi_invm(t, skey->p, skey->q );
if ( mpi_cmp(t, skey->u ) )
{
log_info ( "RSA Oops: u is wrong - fixed\n");
mpi_set (skey->u, t);
log_printmpi (" fixed u", skey->u);
}
log_info ( "RSA secret key check finished\n");
mpi_free (t);
mpi_free (t1);
mpi_free (t2);
mpi_free (phi);
}
#endif
/* Secret key operation - standard version.
*
* m = c^d mod n
*/
static void
secret_core_std (gcry_mpi_t M, gcry_mpi_t C,
gcry_mpi_t D, gcry_mpi_t N)
{
mpi_powm (M, C, D, N);
}
/* Secret key operation - using the CRT.
*
* m1 = c ^ (d mod (p-1)) mod p
* m2 = c ^ (d mod (q-1)) mod q
* h = u * (m2 - m1) mod q
* m = m1 + h * p
*/
static void
secret_core_crt (gcry_mpi_t M, gcry_mpi_t C,
gcry_mpi_t D, unsigned int Nlimbs,
gcry_mpi_t P, gcry_mpi_t Q, gcry_mpi_t U)
{
gcry_mpi_t m1 = mpi_alloc_secure ( Nlimbs + 1 );
gcry_mpi_t m2 = mpi_alloc_secure ( Nlimbs + 1 );
gcry_mpi_t h = mpi_alloc_secure ( Nlimbs + 1 );
gcry_mpi_t D_blind = mpi_alloc_secure ( Nlimbs + 1 );
gcry_mpi_t r;
unsigned int r_nbits;
r_nbits = mpi_get_nbits (P) / 4;
if (r_nbits < 96)
r_nbits = 96;
r = mpi_secure_new (r_nbits);
/* d_blind = (d mod (p-1)) + (p-1) * r */
/* m1 = c ^ d_blind mod p */
_gcry_mpi_randomize (r, r_nbits, GCRY_WEAK_RANDOM);
mpi_set_highbit (r, r_nbits - 1);
mpi_sub_ui ( h, P, 1 );
mpi_mul ( D_blind, h, r );
mpi_fdiv_r ( h, D, h );
mpi_add ( D_blind, D_blind, h );
mpi_powm ( m1, C, D_blind, P );
/* d_blind = (d mod (q-1)) + (q-1) * r */
/* m2 = c ^ d_blind mod q */
_gcry_mpi_randomize (r, r_nbits, GCRY_WEAK_RANDOM);
mpi_set_highbit (r, r_nbits - 1);
mpi_sub_ui ( h, Q, 1 );
mpi_mul ( D_blind, h, r );
mpi_fdiv_r ( h, D, h );
mpi_add ( D_blind, D_blind, h );
mpi_powm ( m2, C, D_blind, Q );
mpi_free ( r );
mpi_free ( D_blind );
/* h = u * ( m2 - m1 ) mod q */
mpi_sub ( h, m2, m1 );
if ( mpi_has_sign ( h ) )
mpi_add ( h, h, Q );
mpi_mulm ( h, U, h, Q );
/* m = m1 + h * p */
mpi_mul ( h, h, P );
mpi_add ( M, m1, h );
mpi_free ( h );
mpi_free ( m1 );
mpi_free ( m2 );
}
/* Secret key operation.
* Encrypt INPUT with SKEY and put result into
* OUTPUT. SKEY has the secret key parameters.
*/
static void
secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey )
{
/* Remove superfluous leading zeroes from INPUT. */
mpi_normalize (input);
if (!skey->p || !skey->q || !skey->u)
{
secret_core_std (output, input, skey->d, skey->n);
}
else
{
secret_core_crt (output, input, skey->d, mpi_get_nlimbs (skey->n),
skey->p, skey->q, skey->u);
}
}
static void
secret_blinded (gcry_mpi_t output, gcry_mpi_t input,
RSA_secret_key *sk, unsigned int nbits)
{
gcry_mpi_t r; /* Random number needed for blinding. */
gcry_mpi_t ri; /* Modular multiplicative inverse of r. */
gcry_mpi_t bldata; /* Blinded data to decrypt. */
/* First, we need a random number r between 0 and n - 1, which is
* relatively prime to n (i.e. it is neither p nor q). The random
* number needs to be only unpredictable, thus we employ the
* gcry_create_nonce function by using GCRY_WEAK_RANDOM with
* gcry_mpi_randomize. */
r = mpi_snew (nbits);
ri = mpi_snew (nbits);
bldata = mpi_snew (nbits);
do
{
_gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM);
mpi_mod (r, r, sk->n);
}
while (!mpi_invm (ri, r, sk->n));
/* Do blinding. We calculate: y = (x * r^e) mod n, where r is the
* random number, e is the public exponent, x is the non-blinded
* input data and n is the RSA modulus. */
mpi_powm (bldata, r, sk->e, sk->n);
mpi_mulm (bldata, bldata, input, sk->n);
/* Perform decryption. */
secret (output, bldata, sk);
_gcry_mpi_release (bldata);
/* Undo blinding. Here we calculate: y = (x * r^-1) mod n, where x
* is the blinded decrypted data, ri is the modular multiplicative
* inverse of r and n is the RSA modulus. */
mpi_mulm (output, output, ri, sk->n);
_gcry_mpi_release (r);
_gcry_mpi_release (ri);
}
/*********************************************
************** interface ******************
*********************************************/
static gcry_err_code_t
rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
{
gpg_err_code_t ec;
unsigned int nbits;
unsigned long evalue;
RSA_secret_key sk;
gcry_sexp_t deriveparms;
int flags = 0;
gcry_sexp_t l1;
gcry_sexp_t swap_info = NULL;
memset (&sk, 0, sizeof sk);
ec = _gcry_pk_util_get_nbits (genparms, &nbits);
if (ec)
return ec;
ec = _gcry_pk_util_get_rsa_use_e (genparms, &evalue);
if (ec)
return ec;
/* Parse the optional flags list. */
l1 = sexp_find_token (genparms, "flags", 0);
if (l1)
{
ec = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
sexp_release (l1);
if (ec)
return ec;
}
deriveparms = (genparms?
sexp_find_token (genparms, "derive-parms", 0) : NULL);
if (!deriveparms)
{
/* Parse the optional "use-x931" flag. */
l1 = sexp_find_token (genparms, "use-x931", 0);
if (l1)
{
flags |= PUBKEY_FLAG_USE_X931;
sexp_release (l1);
}
}
if (deriveparms || (flags & PUBKEY_FLAG_USE_X931))
{
int swapped;
ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
sexp_release (deriveparms);
if (!ec && swapped)
ec = sexp_new (&swap_info, "(misc-key-info(p-q-swapped))", 0, 1);
}
else
{
/* Parse the optional "transient-key" flag. */
if (!(flags & PUBKEY_FLAG_TRANSIENT_KEY))
{
l1 = sexp_find_token (genparms, "transient-key", 0);
if (l1)
{
flags |= PUBKEY_FLAG_TRANSIENT_KEY;
sexp_release (l1);
}
}
deriveparms = (genparms? sexp_find_token (genparms, "test-parms", 0)
/**/ : NULL);
/* Generate. */
if (deriveparms || fips_mode())
{
ec = generate_fips (&sk, nbits, evalue, deriveparms,
!!(flags & PUBKEY_FLAG_TRANSIENT_KEY));
}
else
{
ec = generate_std (&sk, nbits, evalue,
!!(flags & PUBKEY_FLAG_TRANSIENT_KEY));
}
sexp_release (deriveparms);
}
if (!ec)
{
ec = sexp_build (r_skey, NULL,
"(key-data"
" (public-key"
" (rsa(n%m)(e%m)))"
" (private-key"
" (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"
" %S)",
sk.n, sk.e,
sk.n, sk.e, sk.d, sk.p, sk.q, sk.u,
swap_info);
}
mpi_free (sk.n);
mpi_free (sk.e);
mpi_free (sk.p);
mpi_free (sk.q);
mpi_free (sk.d);
mpi_free (sk.u);
sexp_release (swap_info);
return ec;
}
static gcry_err_code_t
rsa_check_secret_key (gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
/* To check the key we need the optional parameters. */
rc = sexp_extract_param (keyparms, NULL, "nedpqu",
&sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
NULL);
if (rc)
goto leave;
if (!check_secret_key (&sk))
rc = GPG_ERR_BAD_SECKEY;
leave:
_gcry_mpi_release (sk.n);
_gcry_mpi_release (sk.e);
_gcry_mpi_release (sk.d);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.u);
if (DBG_CIPHER)
log_debug ("rsa_testkey => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_mpi_t data = NULL;
RSA_public_key pk = {NULL, NULL};
gcry_mpi_t ciph = NULL;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
rsa_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_mpidump ("rsa_encrypt data", data);
if (!data || mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "ne", &pk.n, &pk.e, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_mpidump ("rsa_encrypt n", pk.n);
log_mpidump ("rsa_encrypt e", pk.e);
}
/* Do RSA computation and build result. */
ciph = mpi_new (0);
public (ciph, data, &pk);
if (DBG_CIPHER)
log_mpidump ("rsa_encrypt res", ciph);
if ((ctx.flags & PUBKEY_FLAG_FIXEDLEN))
{
/* We need to make sure to return the correct length to avoid
problems with missing leading zeroes. */
unsigned char *em;
size_t emlen = (mpi_get_nbits (pk.n)+7)/8;
rc = _gcry_mpi_to_octet_string (&em, NULL, ciph, emlen);
if (!rc)
{
rc = sexp_build (r_ciph, NULL, "(enc-val(rsa(a%b)))", (int)emlen, em);
xfree (em);
}
}
else
rc = sexp_build (r_ciph, NULL, "(enc-val(rsa(a%m)))", ciph);
leave:
_gcry_mpi_release (ciph);
_gcry_mpi_release (pk.n);
_gcry_mpi_release (pk.e);
_gcry_mpi_release (data);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("rsa_encrypt => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gpg_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_sexp_t l1 = NULL;
gcry_mpi_t data = NULL;
RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
gcry_mpi_t plain = NULL;
unsigned char *unpad = NULL;
size_t unpadlen = 0;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
rsa_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx);
if (rc)
goto leave;
rc = sexp_extract_param (l1, NULL, "a", &data, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printmpi ("rsa_decrypt data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?",
&sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_decrypt n", sk.n);
log_printmpi ("rsa_decrypt e", sk.e);
if (!fips_mode ())
{
log_printmpi ("rsa_decrypt d", sk.d);
log_printmpi ("rsa_decrypt p", sk.p);
log_printmpi ("rsa_decrypt q", sk.q);
log_printmpi ("rsa_decrypt u", sk.u);
}
}
/* Better make sure that there are no superfluous leading zeroes in
the input and it has not been "padded" using multiples of N.
This mitigates side-channel attacks (CVE-2013-4576). */
mpi_normalize (data);
mpi_fdiv_r (data, data, sk.n);
/* Allocate MPI for the plaintext. */
plain = mpi_snew (ctx.nbits);
/* We use blinding by default to mitigate timing attacks which can
be practically mounted over the network as shown by Brumley and
Boney in 2003. */
if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
secret (plain, data, &sk);
else
secret_blinded (plain, data, &sk, ctx.nbits);
if (DBG_CIPHER)
log_printmpi ("rsa_decrypt res", plain);
/* Reverse the encoding and build the s-expression. */
switch (ctx.encoding)
{
case PUBKEY_ENC_PKCS1:
rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
mpi_free (plain);
plain = NULL;
if (!rc)
rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
break;
case PUBKEY_ENC_OAEP:
rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
ctx.nbits, ctx.hash_algo,
plain, ctx.label, ctx.labellen);
mpi_free (plain);
plain = NULL;
if (!rc)
rc = sexp_build (r_plain, NULL, "(value %b)", (int)unpadlen, unpad);
break;
default:
/* Raw format. For backward compatibility we need to assume a
signed mpi by using the sexp format string "%m". */
rc = sexp_build (r_plain, NULL,
(ctx.flags & PUBKEY_FLAG_LEGACYRESULT)
? "%m":"(value %m)", plain);
break;
}
leave:
xfree (unpad);
_gcry_mpi_release (plain);
_gcry_mpi_release (sk.n);
_gcry_mpi_release (sk.e);
_gcry_mpi_release (sk.d);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.u);
_gcry_mpi_release (data);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("rsa_decrypt => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gpg_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_mpi_t data = NULL;
RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
RSA_public_key pk;
gcry_mpi_t sig = NULL;
gcry_mpi_t result = NULL;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
rsa_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printmpi ("rsa_sign data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?",
&sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_sign n", sk.n);
log_printmpi ("rsa_sign e", sk.e);
if (!fips_mode ())
{
log_printmpi ("rsa_sign d", sk.d);
log_printmpi ("rsa_sign p", sk.p);
log_printmpi ("rsa_sign q", sk.q);
log_printmpi ("rsa_sign u", sk.u);
}
}
/* Do RSA computation. */
sig = mpi_new (0);
if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
secret (sig, data, &sk);
else
secret_blinded (sig, data, &sk, ctx.nbits);
if (DBG_CIPHER)
log_printmpi ("rsa_sign res", sig);
/* Check that the created signature is good. This detects a failure
of the CRT algorithm (Lenstra's attack on RSA's use of the CRT). */
result = mpi_new (0);
pk.n = sk.n;
pk.e = sk.e;
public (result, sig, &pk);
if (mpi_cmp (result, data))
{
rc = GPG_ERR_BAD_SIGNATURE;
goto leave;
}
/* Convert the result. */
if ((ctx.flags & PUBKEY_FLAG_FIXEDLEN))
{
/* We need to make sure to return the correct length to avoid
problems with missing leading zeroes. */
unsigned char *em;
size_t emlen = (mpi_get_nbits (sk.n)+7)/8;
rc = _gcry_mpi_to_octet_string (&em, NULL, sig, emlen);
if (!rc)
{
rc = sexp_build (r_sig, NULL, "(sig-val(rsa(s%b)))", (int)emlen, em);
xfree (em);
}
}
else
rc = sexp_build (r_sig, NULL, "(sig-val(rsa(s%M)))", sig);
leave:
_gcry_mpi_release (result);
_gcry_mpi_release (sig);
_gcry_mpi_release (sk.n);
_gcry_mpi_release (sk.e);
_gcry_mpi_release (sk.d);
_gcry_mpi_release (sk.p);
_gcry_mpi_release (sk.q);
_gcry_mpi_release (sk.u);
_gcry_mpi_release (data);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("rsa_sign => %s\n", gpg_strerror (rc));
return rc;
}
static gcry_err_code_t
rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
{
gcry_err_code_t rc;
struct pk_encoding_ctx ctx;
gcry_sexp_t l1 = NULL;
gcry_mpi_t sig = NULL;
gcry_mpi_t data = NULL;
RSA_public_key pk = { NULL, NULL };
gcry_mpi_t result = NULL;
_gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
rsa_get_nbits (keyparms));
/* Extract the data. */
rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printmpi ("rsa_verify data", data);
if (mpi_is_opaque (data))
{
rc = GPG_ERR_INV_DATA;
goto leave;
}
/* Extract the signature value. */
rc = _gcry_pk_util_preparse_sigval (s_sig, rsa_names, &l1, NULL);
if (rc)
goto leave;
rc = sexp_extract_param (l1, NULL, "s", &sig, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
log_printmpi ("rsa_verify sig", sig);
/* Extract the key. */
rc = sexp_extract_param (keyparms, NULL, "ne", &pk.n, &pk.e, NULL);
if (rc)
goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_verify n", pk.n);
log_printmpi ("rsa_verify e", pk.e);
}
/* Do RSA computation and compare. */
result = mpi_new (0);
public (result, sig, &pk);
if (DBG_CIPHER)
log_printmpi ("rsa_verify cmp", result);
if (ctx.verify_cmp)
rc = ctx.verify_cmp (&ctx, result);
else
rc = mpi_cmp (result, data) ? GPG_ERR_BAD_SIGNATURE : 0;
leave:
_gcry_mpi_release (result);
_gcry_mpi_release (pk.n);
_gcry_mpi_release (pk.e);
_gcry_mpi_release (data);
_gcry_mpi_release (sig);
sexp_release (l1);
_gcry_pk_util_free_encoding_ctx (&ctx);
if (DBG_CIPHER)
log_debug ("rsa_verify => %s\n", rc?gpg_strerror (rc):"Good");
return rc;
}
/* Return the number of bits for the key described by PARMS. On error
* 0 is returned. The format of PARMS starts with the algorithm name;
* for example:
*
* (rsa
* (n <mpi>)
* (e <mpi>))
*
* More parameters may be given but we only need N here.
*/
static unsigned int
rsa_get_nbits (gcry_sexp_t parms)
{
gcry_sexp_t l1;
gcry_mpi_t n;
unsigned int nbits;
l1 = sexp_find_token (parms, "n", 1);
if (!l1)
return 0; /* Parameter N not found. */
n = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
sexp_release (l1);
nbits = n? mpi_get_nbits (n) : 0;
_gcry_mpi_release (n);
return nbits;
}
/* Compute a keygrip. MD is the hash context which we are going to
update. KEYPARAM is an S-expression with the key parameters, this
is usually a public key but may also be a secret key. An example
of such an S-expression is:
(rsa
(n #00B...#)
(e #010001#))
PKCS-15 says that for RSA only the modulus should be hashed -
however, it is not clear whether this is meant to use the raw bytes
(assuming this is an unsigned integer) or whether the DER required
0 should be prefixed. We hash the raw bytes. */
static gpg_err_code_t
compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
{
gcry_sexp_t l1;
const char *data;
size_t datalen;
l1 = sexp_find_token (keyparam, "n", 1);
if (!l1)
return GPG_ERR_NO_OBJ;
data = sexp_nth_data (l1, 1, &datalen);
if (!data)
{
sexp_release (l1);
return GPG_ERR_NO_OBJ;
}
_gcry_md_write (md, data, datalen);
sexp_release (l1);
return 0;
}
/*
Self-test section.
*/
static const char *
selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
{
static const char sample_data[] =
"(data (flags pkcs1)"
" (hash sha256 #11223344556677889900aabbccddeeff"
/**/ "102030405060708090a0b0c0d0f01121#))";
static const char sample_data_bad[] =
"(data (flags pkcs1)"
" (hash sha256 #11223344556677889900aabbccddeeff"
/**/ "802030405060708090a0b0c0d0f01121#))";
const char *errtxt = NULL;
gcry_error_t err;
gcry_sexp_t data = NULL;
gcry_sexp_t data_bad = NULL;
gcry_sexp_t sig = NULL;
/* raw signature data reference */
const char ref_data[] =
"6252a19a11e1d5155ed9376036277193d644fa239397fff03e9b92d6f86415d6"
"d30da9273775f290e580d038295ff8ff89522becccfa6ae870bf76b76df402a8"
"54f69347e3db3de8e1e7d4dada281ec556810c7a8ecd0b5f51f9b1c0e7aa7557"
"61aa2b8ba5f811304acc6af0eca41fe49baf33bf34eddaf44e21e036ac7f0b68"
"03cdef1c60021fb7b5b97ebacdd88ab755ce29af568dbc5728cc6e6eff42618d"
"62a0386ca8beed46402bdeeef29b6a3feded906bace411a06a39192bf516ae10"
"67e4320fa8ea113968525f4574d022a3ceeaafdc41079efe1f22cc94bf59d8d3"
"328085da9674857db56de5978a62394aab48aa3b72e23a1b16260cfd9daafe65";
gcry_mpi_t ref_mpi = NULL;
gcry_mpi_t sig_mpi = NULL;
err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
if (!err)
err = sexp_sscan (&data_bad, NULL,
sample_data_bad, strlen (sample_data_bad));
if (err)
{
errtxt = "converting data failed";
goto leave;
}
err = _gcry_pk_sign (&sig, data, skey);
if (err)
{
errtxt = "signing failed";
goto leave;
}
err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
if (err)
{
errtxt = "converting ref_data to mpi failed";
goto leave;
}
err = _gcry_sexp_extract_param(sig, "sig-val!rsa", "s", &sig_mpi, NULL);
if (err)
{
errtxt = "extracting signature data failed";
goto leave;
}
if (mpi_cmp (sig_mpi, ref_mpi))
{
errtxt = "signature does not match reference data";
goto leave;
}
err = _gcry_pk_verify (sig, data, pkey);
if (err)
{
errtxt = "verify failed";
goto leave;
}
err = _gcry_pk_verify (sig, data_bad, pkey);
if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
{
errtxt = "bad signature not detected";
goto leave;
}
leave:
sexp_release (sig);
sexp_release (data_bad);
sexp_release (data);
_gcry_mpi_release (ref_mpi);
_gcry_mpi_release (sig_mpi);
return errtxt;
}
/* Given an S-expression ENCR_DATA of the form:
(enc-val
(rsa
(a a-value)))
as returned by gcry_pk_decrypt, return the the A-VALUE. On error,
return NULL. */
static gcry_mpi_t
extract_a_from_sexp (gcry_sexp_t encr_data)
{
gcry_sexp_t l1, l2, l3;
gcry_mpi_t a_value;
l1 = sexp_find_token (encr_data, "enc-val", 0);
if (!l1)
return NULL;
l2 = sexp_find_token (l1, "rsa", 0);
sexp_release (l1);
if (!l2)
return NULL;
l3 = sexp_find_token (l2, "a", 0);
sexp_release (l2);
if (!l3)
return NULL;
a_value = sexp_nth_mpi (l3, 1, 0);
sexp_release (l3);
return a_value;
}
static const char *
selftest_encr_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
{
const char *errtxt = NULL;
gcry_error_t err;
static const char plaintext[] =
"Jim quickly realized that the beautiful gowns are expensive.";
gcry_sexp_t plain = NULL;
gcry_sexp_t encr = NULL;
gcry_mpi_t ciphertext = NULL;
gcry_sexp_t decr = NULL;
char *decr_plaintext = NULL;
gcry_sexp_t tmplist = NULL;
/* expected result of encrypting the plaintext with sample_secret_key */
static const char ref_data[] =
"18022e2593a402a737caaa93b4c7e750e20ca265452980e1d6b7710fbd3e"
"7dce72be5c2110fb47691cb38f42170ee3b4a37f2498d4a51567d762585e"
"4cb81d04fbc7df4144f8e5eac2d4b8688521b64011f11d7ad53f4c874004"
"819856f2e2a6f83d1c9c4e73ac26089789c14482b0b8d44139133c88c4a5"
"2dba9dd6d6ffc622666b7d129168333d999706af30a2d7d272db7734e5ed"
"fb8c64ea3018af3ad20f4a013a5060cb0f5e72753967bebe294280a6ed0d"
"dbd3c4f11d0a8696e9d32a0dc03deb0b5e49b2cbd1503392642d4e1211f3"
"e8e2ee38abaa3671ccd57fcde8ca76e85fd2cb77c35706a970a213a27352"
"cec92a9604d543ddb5fc478ff50e0622";
gcry_mpi_t ref_mpi = NULL;
/* Put the plaintext into an S-expression. */
err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext);
if (err)
{
errtxt = "converting data failed";
goto leave;
}
/* Encrypt. */
err = _gcry_pk_encrypt (&encr, plain, pkey);
if (err)
{
errtxt = "encrypt failed";
goto leave;
}
err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
if (err)
{
errtxt = "converting encrydata to mpi failed";
goto leave;
}
/* Extraxt the ciphertext from the returned S-expression. */
/*sexp_dump (encr);*/
ciphertext = extract_a_from_sexp (encr);
if (!ciphertext)
{
errtxt = "gcry_pk_decrypt returned garbage";
goto leave;
}
/* Check that the ciphertext does no match the plaintext. */
/* _gcry_log_printmpi ("plaintext", plaintext); */
/* _gcry_log_printmpi ("ciphertxt", ciphertext); */
if (mpi_cmp (ref_mpi, ciphertext))
{
errtxt = "ciphertext doesn't match reference data";
goto leave;
}
/* Decrypt. */
err = _gcry_pk_decrypt (&decr, encr, skey);
if (err)
{
errtxt = "decrypt failed";
goto leave;
}
/* Extract the decrypted data from the S-expression. Note that the
output of gcry_pk_decrypt depends on whether a flags lists occurs
in its input data. Because we passed the output of
gcry_pk_encrypt directly to gcry_pk_decrypt, such a flag value
won't be there as of today. To be prepared for future changes we
take care of it anyway. */
tmplist = sexp_find_token (decr, "value", 0);
if (tmplist)
decr_plaintext = sexp_nth_string (tmplist, 1);
else
decr_plaintext = sexp_nth_string (decr, 0);
if (!decr_plaintext)
{
errtxt = "decrypt returned no plaintext";
goto leave;
}
/* Check that the decrypted plaintext matches the original plaintext. */
if (strcmp (plaintext, decr_plaintext))
{
errtxt = "mismatch";
goto leave;
}
leave:
sexp_release (tmplist);
xfree (decr_plaintext);
sexp_release (decr);
_gcry_mpi_release (ciphertext);
_gcry_mpi_release (ref_mpi);
sexp_release (encr);
sexp_release (plain);
return errtxt;
}
static gpg_err_code_t
selftests_rsa (selftest_report_func_t report)
{
const char *what;
const char *errtxt;
gcry_error_t err;
gcry_sexp_t skey = NULL;
gcry_sexp_t pkey = NULL;
/* Convert the S-expressions into the internal representation. */
what = "convert";
err = sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key));
if (!err)
err = sexp_sscan (&pkey, NULL,
sample_public_key, strlen (sample_public_key));
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "key consistency";
err = _gcry_pk_testkey (skey);
if (err)
{
errtxt = _gcry_strerror (err);
goto failed;
}
what = "sign";
errtxt = selftest_sign_2048 (pkey, skey);
if (errtxt)
goto failed;
what = "encrypt";
errtxt = selftest_encr_2048 (pkey, skey);
if (errtxt)
goto failed;
sexp_release (pkey);
sexp_release (skey);
return 0; /* Succeeded. */
failed:
sexp_release (pkey);
sexp_release (skey);
if (report)
report ("pubkey", GCRY_PK_RSA, 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;
(void)extended;
switch (algo)
{
case GCRY_PK_RSA:
ec = selftests_rsa (report);
break;
default:
ec = GPG_ERR_PUBKEY_ALGO;
break;
}
return ec;
}
gcry_pk_spec_t _gcry_pubkey_spec_rsa =
{
GCRY_PK_RSA, { 0, 1 },
(GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
"RSA", rsa_names,
"ne", "nedpqu", "a", "s", "n",
rsa_generate,
rsa_check_secret_key,
rsa_encrypt,
rsa_decrypt,
rsa_sign,
rsa_verify,
rsa_get_nbits,
run_selftests,
compute_keygrip
};
diff --git a/cipher/salsa20-amd64.S b/cipher/salsa20-amd64.S
index ae8f2715..4c7c3a38 100644
--- a/cipher/salsa20-amd64.S
+++ b/cipher/salsa20-amd64.S
@@ -1,940 +1,940 @@
/* salsa20-amd64.S - AMD64 implementation of Salsa20
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Based on public domain implementation by D. J. Bernstein at
- * http://cr.yp.to/snuffle.html
+ * https://cr.yp.to/snuffle.html
*/
#ifdef __x86_64
#include <config.h>
#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SALSA20)
#include "asm-common-amd64.h"
.text
.align 8
.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
movl 12(%rsi),%r10d
movl %r8d,20(%rdi)
movl %r9d,40(%rdi)
movl %eax,60(%rdi)
movl %r10d,48(%rdi)
cmp $256,%rdx
jb .L_kbits128
.L_kbits256:
movl 16(%rsi),%edx
movl 20(%rsi),%ecx
movl 24(%rsi),%r8d
movl 28(%rsi),%esi
movl %edx,28(%rdi)
movl %ecx,16(%rdi)
movl %r8d,36(%rdi)
movl %esi,56(%rdi)
mov $1634760805,%rsi
mov $857760878,%rdx
mov $2036477234,%rcx
mov $1797285236,%r8
movl %esi,0(%rdi)
movl %edx,4(%rdi)
movl %ecx,8(%rdi)
movl %r8d,12(%rdi)
jmp .L_keysetupdone
.L_kbits128:
movl 0(%rsi),%edx
movl 4(%rsi),%ecx
movl 8(%rsi),%r8d
movl 12(%rsi),%esi
movl %edx,28(%rdi)
movl %ecx,16(%rdi)
movl %r8d,36(%rdi)
movl %esi,56(%rdi)
mov $1634760805,%rsi
mov $824206446,%rdx
mov $2036477238,%rcx
mov $1797285236,%r8
movl %esi,0(%rdi)
movl %edx,4(%rdi)
movl %ecx,8(%rdi)
movl %r8d,12(%rdi)
.L_keysetupdone:
ret
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
mov $0,%rax
movl %r8d,24(%rdi)
movl %esi,44(%rdi)
movl %r9d,32(%rdi)
movl %eax,52(%rdi)
ret
CFI_ENDPROC();
.align 8
.globl _gcry_salsa20_amd64_encrypt_blocks
ELF(.type _gcry_salsa20_amd64_encrypt_blocks,@function;)
_gcry_salsa20_amd64_encrypt_blocks:
/*
* Modifications to original implementation:
* - Number of rounds passing in register %r8 (for Salsa20/12).
* - 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
CFI_DEF_CFA_REGISTER(%r11);
sub $384,%rsp
and $~31,%rsp
mov %rdi,%r8
mov %rsi,%rsi
mov %rdx,%rdi
mov %rcx,%rdx
cmp $0,%rdx
jbe .L_done
.L_start:
cmp $256,%rdx
jb .L_bytes_are_64_128_or_192
movdqa 0(%r8),%xmm0
pshufd $0x55,%xmm0,%xmm1
pshufd $0xaa,%xmm0,%xmm2
pshufd $0xff,%xmm0,%xmm3
pshufd $0x00,%xmm0,%xmm0
movdqa %xmm1,0(%rsp)
movdqa %xmm2,16(%rsp)
movdqa %xmm3,32(%rsp)
movdqa %xmm0,48(%rsp)
movdqa 16(%r8),%xmm0
pshufd $0xaa,%xmm0,%xmm1
pshufd $0xff,%xmm0,%xmm2
pshufd $0x00,%xmm0,%xmm3
pshufd $0x55,%xmm0,%xmm0
movdqa %xmm1,64(%rsp)
movdqa %xmm2,80(%rsp)
movdqa %xmm3,96(%rsp)
movdqa %xmm0,112(%rsp)
movdqa 32(%r8),%xmm0
pshufd $0xff,%xmm0,%xmm1
pshufd $0x55,%xmm0,%xmm2
pshufd $0xaa,%xmm0,%xmm0
movdqa %xmm1,128(%rsp)
movdqa %xmm2,144(%rsp)
movdqa %xmm0,160(%rsp)
movdqa 48(%r8),%xmm0
pshufd $0x00,%xmm0,%xmm1
pshufd $0xaa,%xmm0,%xmm2
pshufd $0xff,%xmm0,%xmm0
movdqa %xmm1,176(%rsp)
movdqa %xmm2,192(%rsp)
movdqa %xmm0,208(%rsp)
.L_bytesatleast256:
movl 32(%r8),%ecx
movl 52(%r8),%r9d
movl %ecx,224(%rsp)
movl %r9d,240(%rsp)
add $1,%ecx
adc $0,%r9d
movl %ecx,4+224(%rsp)
movl %r9d,4+240(%rsp)
add $1,%ecx
adc $0,%r9d
movl %ecx,8+224(%rsp)
movl %r9d,8+240(%rsp)
add $1,%ecx
adc $0,%r9d
movl %ecx,12+224(%rsp)
movl %r9d,12+240(%rsp)
add $1,%ecx
adc $0,%r9d
movl %ecx,32(%r8)
movl %r9d,52(%r8)
movq %rdx,288(%rsp)
mov %rbx,%rdx
movdqa 0(%rsp),%xmm0
movdqa 16(%rsp),%xmm1
movdqa 32(%rsp),%xmm2
movdqa 192(%rsp),%xmm3
movdqa 208(%rsp),%xmm4
movdqa 64(%rsp),%xmm5
movdqa 80(%rsp),%xmm6
movdqa 112(%rsp),%xmm7
movdqa 128(%rsp),%xmm8
movdqa 144(%rsp),%xmm9
movdqa 160(%rsp),%xmm10
movdqa 240(%rsp),%xmm11
movdqa 48(%rsp),%xmm12
movdqa 96(%rsp),%xmm13
movdqa 176(%rsp),%xmm14
movdqa 224(%rsp),%xmm15
.L_mainloop1:
movdqa %xmm1,256(%rsp)
movdqa %xmm2,272(%rsp)
movdqa %xmm13,%xmm1
paddd %xmm12,%xmm1
movdqa %xmm1,%xmm2
pslld $7,%xmm1
pxor %xmm1,%xmm14
psrld $25,%xmm2
pxor %xmm2,%xmm14
movdqa %xmm7,%xmm1
paddd %xmm0,%xmm1
movdqa %xmm1,%xmm2
pslld $7,%xmm1
pxor %xmm1,%xmm11
psrld $25,%xmm2
pxor %xmm2,%xmm11
movdqa %xmm12,%xmm1
paddd %xmm14,%xmm1
movdqa %xmm1,%xmm2
pslld $9,%xmm1
pxor %xmm1,%xmm15
psrld $23,%xmm2
pxor %xmm2,%xmm15
movdqa %xmm0,%xmm1
paddd %xmm11,%xmm1
movdqa %xmm1,%xmm2
pslld $9,%xmm1
pxor %xmm1,%xmm9
psrld $23,%xmm2
pxor %xmm2,%xmm9
movdqa %xmm14,%xmm1
paddd %xmm15,%xmm1
movdqa %xmm1,%xmm2
pslld $13,%xmm1
pxor %xmm1,%xmm13
psrld $19,%xmm2
pxor %xmm2,%xmm13
movdqa %xmm11,%xmm1
paddd %xmm9,%xmm1
movdqa %xmm1,%xmm2
pslld $13,%xmm1
pxor %xmm1,%xmm7
psrld $19,%xmm2
pxor %xmm2,%xmm7
movdqa %xmm15,%xmm1
paddd %xmm13,%xmm1
movdqa %xmm1,%xmm2
pslld $18,%xmm1
pxor %xmm1,%xmm12
psrld $14,%xmm2
pxor %xmm2,%xmm12
movdqa 256(%rsp),%xmm1
movdqa %xmm12,256(%rsp)
movdqa %xmm9,%xmm2
paddd %xmm7,%xmm2
movdqa %xmm2,%xmm12
pslld $18,%xmm2
pxor %xmm2,%xmm0
psrld $14,%xmm12
pxor %xmm12,%xmm0
movdqa %xmm5,%xmm2
paddd %xmm1,%xmm2
movdqa %xmm2,%xmm12
pslld $7,%xmm2
pxor %xmm2,%xmm3
psrld $25,%xmm12
pxor %xmm12,%xmm3
movdqa 272(%rsp),%xmm2
movdqa %xmm0,272(%rsp)
movdqa %xmm6,%xmm0
paddd %xmm2,%xmm0
movdqa %xmm0,%xmm12
pslld $7,%xmm0
pxor %xmm0,%xmm4
psrld $25,%xmm12
pxor %xmm12,%xmm4
movdqa %xmm1,%xmm0
paddd %xmm3,%xmm0
movdqa %xmm0,%xmm12
pslld $9,%xmm0
pxor %xmm0,%xmm10
psrld $23,%xmm12
pxor %xmm12,%xmm10
movdqa %xmm2,%xmm0
paddd %xmm4,%xmm0
movdqa %xmm0,%xmm12
pslld $9,%xmm0
pxor %xmm0,%xmm8
psrld $23,%xmm12
pxor %xmm12,%xmm8
movdqa %xmm3,%xmm0
paddd %xmm10,%xmm0
movdqa %xmm0,%xmm12
pslld $13,%xmm0
pxor %xmm0,%xmm5
psrld $19,%xmm12
pxor %xmm12,%xmm5
movdqa %xmm4,%xmm0
paddd %xmm8,%xmm0
movdqa %xmm0,%xmm12
pslld $13,%xmm0
pxor %xmm0,%xmm6
psrld $19,%xmm12
pxor %xmm12,%xmm6
movdqa %xmm10,%xmm0
paddd %xmm5,%xmm0
movdqa %xmm0,%xmm12
pslld $18,%xmm0
pxor %xmm0,%xmm1
psrld $14,%xmm12
pxor %xmm12,%xmm1
movdqa 256(%rsp),%xmm0
movdqa %xmm1,256(%rsp)
movdqa %xmm4,%xmm1
paddd %xmm0,%xmm1
movdqa %xmm1,%xmm12
pslld $7,%xmm1
pxor %xmm1,%xmm7
psrld $25,%xmm12
pxor %xmm12,%xmm7
movdqa %xmm8,%xmm1
paddd %xmm6,%xmm1
movdqa %xmm1,%xmm12
pslld $18,%xmm1
pxor %xmm1,%xmm2
psrld $14,%xmm12
pxor %xmm12,%xmm2
movdqa 272(%rsp),%xmm12
movdqa %xmm2,272(%rsp)
movdqa %xmm14,%xmm1
paddd %xmm12,%xmm1
movdqa %xmm1,%xmm2
pslld $7,%xmm1
pxor %xmm1,%xmm5
psrld $25,%xmm2
pxor %xmm2,%xmm5
movdqa %xmm0,%xmm1
paddd %xmm7,%xmm1
movdqa %xmm1,%xmm2
pslld $9,%xmm1
pxor %xmm1,%xmm10
psrld $23,%xmm2
pxor %xmm2,%xmm10
movdqa %xmm12,%xmm1
paddd %xmm5,%xmm1
movdqa %xmm1,%xmm2
pslld $9,%xmm1
pxor %xmm1,%xmm8
psrld $23,%xmm2
pxor %xmm2,%xmm8
movdqa %xmm7,%xmm1
paddd %xmm10,%xmm1
movdqa %xmm1,%xmm2
pslld $13,%xmm1
pxor %xmm1,%xmm4
psrld $19,%xmm2
pxor %xmm2,%xmm4
movdqa %xmm5,%xmm1
paddd %xmm8,%xmm1
movdqa %xmm1,%xmm2
pslld $13,%xmm1
pxor %xmm1,%xmm14
psrld $19,%xmm2
pxor %xmm2,%xmm14
movdqa %xmm10,%xmm1
paddd %xmm4,%xmm1
movdqa %xmm1,%xmm2
pslld $18,%xmm1
pxor %xmm1,%xmm0
psrld $14,%xmm2
pxor %xmm2,%xmm0
movdqa 256(%rsp),%xmm1
movdqa %xmm0,256(%rsp)
movdqa %xmm8,%xmm0
paddd %xmm14,%xmm0
movdqa %xmm0,%xmm2
pslld $18,%xmm0
pxor %xmm0,%xmm12
psrld $14,%xmm2
pxor %xmm2,%xmm12
movdqa %xmm11,%xmm0
paddd %xmm1,%xmm0
movdqa %xmm0,%xmm2
pslld $7,%xmm0
pxor %xmm0,%xmm6
psrld $25,%xmm2
pxor %xmm2,%xmm6
movdqa 272(%rsp),%xmm2
movdqa %xmm12,272(%rsp)
movdqa %xmm3,%xmm0
paddd %xmm2,%xmm0
movdqa %xmm0,%xmm12
pslld $7,%xmm0
pxor %xmm0,%xmm13
psrld $25,%xmm12
pxor %xmm12,%xmm13
movdqa %xmm1,%xmm0
paddd %xmm6,%xmm0
movdqa %xmm0,%xmm12
pslld $9,%xmm0
pxor %xmm0,%xmm15
psrld $23,%xmm12
pxor %xmm12,%xmm15
movdqa %xmm2,%xmm0
paddd %xmm13,%xmm0
movdqa %xmm0,%xmm12
pslld $9,%xmm0
pxor %xmm0,%xmm9
psrld $23,%xmm12
pxor %xmm12,%xmm9
movdqa %xmm6,%xmm0
paddd %xmm15,%xmm0
movdqa %xmm0,%xmm12
pslld $13,%xmm0
pxor %xmm0,%xmm11
psrld $19,%xmm12
pxor %xmm12,%xmm11
movdqa %xmm13,%xmm0
paddd %xmm9,%xmm0
movdqa %xmm0,%xmm12
pslld $13,%xmm0
pxor %xmm0,%xmm3
psrld $19,%xmm12
pxor %xmm12,%xmm3
movdqa %xmm15,%xmm0
paddd %xmm11,%xmm0
movdqa %xmm0,%xmm12
pslld $18,%xmm0
pxor %xmm0,%xmm1
psrld $14,%xmm12
pxor %xmm12,%xmm1
movdqa %xmm9,%xmm0
paddd %xmm3,%xmm0
movdqa %xmm0,%xmm12
pslld $18,%xmm0
pxor %xmm0,%xmm2
psrld $14,%xmm12
pxor %xmm12,%xmm2
movdqa 256(%rsp),%xmm12
movdqa 272(%rsp),%xmm0
sub $2,%rdx
ja .L_mainloop1
paddd 48(%rsp),%xmm12
paddd 112(%rsp),%xmm7
paddd 160(%rsp),%xmm10
paddd 208(%rsp),%xmm4
movd %xmm12,%rdx
movd %xmm7,%rcx
movd %xmm10,%r9
movd %xmm4,%rax
pshufd $0x39,%xmm12,%xmm12
pshufd $0x39,%xmm7,%xmm7
pshufd $0x39,%xmm10,%xmm10
pshufd $0x39,%xmm4,%xmm4
xorl 0(%rsi),%edx
xorl 4(%rsi),%ecx
xorl 8(%rsi),%r9d
xorl 12(%rsi),%eax
movl %edx,0(%rdi)
movl %ecx,4(%rdi)
movl %r9d,8(%rdi)
movl %eax,12(%rdi)
movd %xmm12,%rdx
movd %xmm7,%rcx
movd %xmm10,%r9
movd %xmm4,%rax
pshufd $0x39,%xmm12,%xmm12
pshufd $0x39,%xmm7,%xmm7
pshufd $0x39,%xmm10,%xmm10
pshufd $0x39,%xmm4,%xmm4
xorl 64(%rsi),%edx
xorl 68(%rsi),%ecx
xorl 72(%rsi),%r9d
xorl 76(%rsi),%eax
movl %edx,64(%rdi)
movl %ecx,68(%rdi)
movl %r9d,72(%rdi)
movl %eax,76(%rdi)
movd %xmm12,%rdx
movd %xmm7,%rcx
movd %xmm10,%r9
movd %xmm4,%rax
pshufd $0x39,%xmm12,%xmm12
pshufd $0x39,%xmm7,%xmm7
pshufd $0x39,%xmm10,%xmm10
pshufd $0x39,%xmm4,%xmm4
xorl 128(%rsi),%edx
xorl 132(%rsi),%ecx
xorl 136(%rsi),%r9d
xorl 140(%rsi),%eax
movl %edx,128(%rdi)
movl %ecx,132(%rdi)
movl %r9d,136(%rdi)
movl %eax,140(%rdi)
movd %xmm12,%rdx
movd %xmm7,%rcx
movd %xmm10,%r9
movd %xmm4,%rax
xorl 192(%rsi),%edx
xorl 196(%rsi),%ecx
xorl 200(%rsi),%r9d
xorl 204(%rsi),%eax
movl %edx,192(%rdi)
movl %ecx,196(%rdi)
movl %r9d,200(%rdi)
movl %eax,204(%rdi)
paddd 176(%rsp),%xmm14
paddd 0(%rsp),%xmm0
paddd 64(%rsp),%xmm5
paddd 128(%rsp),%xmm8
movd %xmm14,%rdx
movd %xmm0,%rcx
movd %xmm5,%r9
movd %xmm8,%rax
pshufd $0x39,%xmm14,%xmm14
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm5,%xmm5
pshufd $0x39,%xmm8,%xmm8
xorl 16(%rsi),%edx
xorl 20(%rsi),%ecx
xorl 24(%rsi),%r9d
xorl 28(%rsi),%eax
movl %edx,16(%rdi)
movl %ecx,20(%rdi)
movl %r9d,24(%rdi)
movl %eax,28(%rdi)
movd %xmm14,%rdx
movd %xmm0,%rcx
movd %xmm5,%r9
movd %xmm8,%rax
pshufd $0x39,%xmm14,%xmm14
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm5,%xmm5
pshufd $0x39,%xmm8,%xmm8
xorl 80(%rsi),%edx
xorl 84(%rsi),%ecx
xorl 88(%rsi),%r9d
xorl 92(%rsi),%eax
movl %edx,80(%rdi)
movl %ecx,84(%rdi)
movl %r9d,88(%rdi)
movl %eax,92(%rdi)
movd %xmm14,%rdx
movd %xmm0,%rcx
movd %xmm5,%r9
movd %xmm8,%rax
pshufd $0x39,%xmm14,%xmm14
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm5,%xmm5
pshufd $0x39,%xmm8,%xmm8
xorl 144(%rsi),%edx
xorl 148(%rsi),%ecx
xorl 152(%rsi),%r9d
xorl 156(%rsi),%eax
movl %edx,144(%rdi)
movl %ecx,148(%rdi)
movl %r9d,152(%rdi)
movl %eax,156(%rdi)
movd %xmm14,%rdx
movd %xmm0,%rcx
movd %xmm5,%r9
movd %xmm8,%rax
xorl 208(%rsi),%edx
xorl 212(%rsi),%ecx
xorl 216(%rsi),%r9d
xorl 220(%rsi),%eax
movl %edx,208(%rdi)
movl %ecx,212(%rdi)
movl %r9d,216(%rdi)
movl %eax,220(%rdi)
paddd 224(%rsp),%xmm15
paddd 240(%rsp),%xmm11
paddd 16(%rsp),%xmm1
paddd 80(%rsp),%xmm6
movd %xmm15,%rdx
movd %xmm11,%rcx
movd %xmm1,%r9
movd %xmm6,%rax
pshufd $0x39,%xmm15,%xmm15
pshufd $0x39,%xmm11,%xmm11
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm6,%xmm6
xorl 32(%rsi),%edx
xorl 36(%rsi),%ecx
xorl 40(%rsi),%r9d
xorl 44(%rsi),%eax
movl %edx,32(%rdi)
movl %ecx,36(%rdi)
movl %r9d,40(%rdi)
movl %eax,44(%rdi)
movd %xmm15,%rdx
movd %xmm11,%rcx
movd %xmm1,%r9
movd %xmm6,%rax
pshufd $0x39,%xmm15,%xmm15
pshufd $0x39,%xmm11,%xmm11
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm6,%xmm6
xorl 96(%rsi),%edx
xorl 100(%rsi),%ecx
xorl 104(%rsi),%r9d
xorl 108(%rsi),%eax
movl %edx,96(%rdi)
movl %ecx,100(%rdi)
movl %r9d,104(%rdi)
movl %eax,108(%rdi)
movd %xmm15,%rdx
movd %xmm11,%rcx
movd %xmm1,%r9
movd %xmm6,%rax
pshufd $0x39,%xmm15,%xmm15
pshufd $0x39,%xmm11,%xmm11
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm6,%xmm6
xorl 160(%rsi),%edx
xorl 164(%rsi),%ecx
xorl 168(%rsi),%r9d
xorl 172(%rsi),%eax
movl %edx,160(%rdi)
movl %ecx,164(%rdi)
movl %r9d,168(%rdi)
movl %eax,172(%rdi)
movd %xmm15,%rdx
movd %xmm11,%rcx
movd %xmm1,%r9
movd %xmm6,%rax
xorl 224(%rsi),%edx
xorl 228(%rsi),%ecx
xorl 232(%rsi),%r9d
xorl 236(%rsi),%eax
movl %edx,224(%rdi)
movl %ecx,228(%rdi)
movl %r9d,232(%rdi)
movl %eax,236(%rdi)
paddd 96(%rsp),%xmm13
paddd 144(%rsp),%xmm9
paddd 192(%rsp),%xmm3
paddd 32(%rsp),%xmm2
movd %xmm13,%rdx
movd %xmm9,%rcx
movd %xmm3,%r9
movd %xmm2,%rax
pshufd $0x39,%xmm13,%xmm13
pshufd $0x39,%xmm9,%xmm9
pshufd $0x39,%xmm3,%xmm3
pshufd $0x39,%xmm2,%xmm2
xorl 48(%rsi),%edx
xorl 52(%rsi),%ecx
xorl 56(%rsi),%r9d
xorl 60(%rsi),%eax
movl %edx,48(%rdi)
movl %ecx,52(%rdi)
movl %r9d,56(%rdi)
movl %eax,60(%rdi)
movd %xmm13,%rdx
movd %xmm9,%rcx
movd %xmm3,%r9
movd %xmm2,%rax
pshufd $0x39,%xmm13,%xmm13
pshufd $0x39,%xmm9,%xmm9
pshufd $0x39,%xmm3,%xmm3
pshufd $0x39,%xmm2,%xmm2
xorl 112(%rsi),%edx
xorl 116(%rsi),%ecx
xorl 120(%rsi),%r9d
xorl 124(%rsi),%eax
movl %edx,112(%rdi)
movl %ecx,116(%rdi)
movl %r9d,120(%rdi)
movl %eax,124(%rdi)
movd %xmm13,%rdx
movd %xmm9,%rcx
movd %xmm3,%r9
movd %xmm2,%rax
pshufd $0x39,%xmm13,%xmm13
pshufd $0x39,%xmm9,%xmm9
pshufd $0x39,%xmm3,%xmm3
pshufd $0x39,%xmm2,%xmm2
xorl 176(%rsi),%edx
xorl 180(%rsi),%ecx
xorl 184(%rsi),%r9d
xorl 188(%rsi),%eax
movl %edx,176(%rdi)
movl %ecx,180(%rdi)
movl %r9d,184(%rdi)
movl %eax,188(%rdi)
movd %xmm13,%rdx
movd %xmm9,%rcx
movd %xmm3,%r9
movd %xmm2,%rax
xorl 240(%rsi),%edx
xorl 244(%rsi),%ecx
xorl 248(%rsi),%r9d
xorl 252(%rsi),%eax
movl %edx,240(%rdi)
movl %ecx,244(%rdi)
movl %r9d,248(%rdi)
movl %eax,252(%rdi)
movq 288(%rsp),%rdx
sub $256,%rdx
add $256,%rsi
add $256,%rdi
cmp $256,%rdx
jae .L_bytesatleast256
cmp $0,%rdx
jbe .L_done
.L_bytes_are_64_128_or_192:
movq %rdx,288(%rsp)
movdqa 0(%r8),%xmm0
movdqa 16(%r8),%xmm1
movdqa 32(%r8),%xmm2
movdqa 48(%r8),%xmm3
movdqa %xmm1,%xmm4
mov %rbx,%rdx
.L_mainloop2:
paddd %xmm0,%xmm4
movdqa %xmm0,%xmm5
movdqa %xmm4,%xmm6
pslld $7,%xmm4
psrld $25,%xmm6
pxor %xmm4,%xmm3
pxor %xmm6,%xmm3
paddd %xmm3,%xmm5
movdqa %xmm3,%xmm4
movdqa %xmm5,%xmm6
pslld $9,%xmm5
psrld $23,%xmm6
pxor %xmm5,%xmm2
pshufd $0x93,%xmm3,%xmm3
pxor %xmm6,%xmm2
paddd %xmm2,%xmm4
movdqa %xmm2,%xmm5
movdqa %xmm4,%xmm6
pslld $13,%xmm4
psrld $19,%xmm6
pxor %xmm4,%xmm1
pshufd $0x4e,%xmm2,%xmm2
pxor %xmm6,%xmm1
paddd %xmm1,%xmm5
movdqa %xmm3,%xmm4
movdqa %xmm5,%xmm6
pslld $18,%xmm5
psrld $14,%xmm6
pxor %xmm5,%xmm0
pshufd $0x39,%xmm1,%xmm1
pxor %xmm6,%xmm0
paddd %xmm0,%xmm4
movdqa %xmm0,%xmm5
movdqa %xmm4,%xmm6
pslld $7,%xmm4
psrld $25,%xmm6
pxor %xmm4,%xmm1
pxor %xmm6,%xmm1
paddd %xmm1,%xmm5
movdqa %xmm1,%xmm4
movdqa %xmm5,%xmm6
pslld $9,%xmm5
psrld $23,%xmm6
pxor %xmm5,%xmm2
pshufd $0x93,%xmm1,%xmm1
pxor %xmm6,%xmm2
paddd %xmm2,%xmm4
movdqa %xmm2,%xmm5
movdqa %xmm4,%xmm6
pslld $13,%xmm4
psrld $19,%xmm6
pxor %xmm4,%xmm3
pshufd $0x4e,%xmm2,%xmm2
pxor %xmm6,%xmm3
paddd %xmm3,%xmm5
movdqa %xmm1,%xmm4
movdqa %xmm5,%xmm6
pslld $18,%xmm5
psrld $14,%xmm6
pxor %xmm5,%xmm0
pshufd $0x39,%xmm3,%xmm3
pxor %xmm6,%xmm0
paddd %xmm0,%xmm4
movdqa %xmm0,%xmm5
movdqa %xmm4,%xmm6
pslld $7,%xmm4
psrld $25,%xmm6
pxor %xmm4,%xmm3
pxor %xmm6,%xmm3
paddd %xmm3,%xmm5
movdqa %xmm3,%xmm4
movdqa %xmm5,%xmm6
pslld $9,%xmm5
psrld $23,%xmm6
pxor %xmm5,%xmm2
pshufd $0x93,%xmm3,%xmm3
pxor %xmm6,%xmm2
paddd %xmm2,%xmm4
movdqa %xmm2,%xmm5
movdqa %xmm4,%xmm6
pslld $13,%xmm4
psrld $19,%xmm6
pxor %xmm4,%xmm1
pshufd $0x4e,%xmm2,%xmm2
pxor %xmm6,%xmm1
paddd %xmm1,%xmm5
movdqa %xmm3,%xmm4
movdqa %xmm5,%xmm6
pslld $18,%xmm5
psrld $14,%xmm6
pxor %xmm5,%xmm0
pshufd $0x39,%xmm1,%xmm1
pxor %xmm6,%xmm0
paddd %xmm0,%xmm4
movdqa %xmm0,%xmm5
movdqa %xmm4,%xmm6
pslld $7,%xmm4
psrld $25,%xmm6
pxor %xmm4,%xmm1
pxor %xmm6,%xmm1
paddd %xmm1,%xmm5
movdqa %xmm1,%xmm4
movdqa %xmm5,%xmm6
pslld $9,%xmm5
psrld $23,%xmm6
pxor %xmm5,%xmm2
pshufd $0x93,%xmm1,%xmm1
pxor %xmm6,%xmm2
paddd %xmm2,%xmm4
movdqa %xmm2,%xmm5
movdqa %xmm4,%xmm6
pslld $13,%xmm4
psrld $19,%xmm6
pxor %xmm4,%xmm3
pshufd $0x4e,%xmm2,%xmm2
pxor %xmm6,%xmm3
sub $4,%rdx
paddd %xmm3,%xmm5
movdqa %xmm1,%xmm4
movdqa %xmm5,%xmm6
pslld $18,%xmm5
pxor %xmm7,%xmm7
psrld $14,%xmm6
pxor %xmm5,%xmm0
pshufd $0x39,%xmm3,%xmm3
pxor %xmm6,%xmm0
ja .L_mainloop2
paddd 0(%r8),%xmm0
paddd 16(%r8),%xmm1
paddd 32(%r8),%xmm2
paddd 48(%r8),%xmm3
movd %xmm0,%rdx
movd %xmm1,%rcx
movd %xmm2,%rax
movd %xmm3,%r10
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm2,%xmm2
pshufd $0x39,%xmm3,%xmm3
xorl 0(%rsi),%edx
xorl 48(%rsi),%ecx
xorl 32(%rsi),%eax
xorl 16(%rsi),%r10d
movl %edx,0(%rdi)
movl %ecx,48(%rdi)
movl %eax,32(%rdi)
movl %r10d,16(%rdi)
movd %xmm0,%rdx
movd %xmm1,%rcx
movd %xmm2,%rax
movd %xmm3,%r10
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm2,%xmm2
pshufd $0x39,%xmm3,%xmm3
xorl 20(%rsi),%edx
xorl 4(%rsi),%ecx
xorl 52(%rsi),%eax
xorl 36(%rsi),%r10d
movl %edx,20(%rdi)
movl %ecx,4(%rdi)
movl %eax,52(%rdi)
movl %r10d,36(%rdi)
movd %xmm0,%rdx
movd %xmm1,%rcx
movd %xmm2,%rax
movd %xmm3,%r10
pshufd $0x39,%xmm0,%xmm0
pshufd $0x39,%xmm1,%xmm1
pshufd $0x39,%xmm2,%xmm2
pshufd $0x39,%xmm3,%xmm3
xorl 40(%rsi),%edx
xorl 24(%rsi),%ecx
xorl 8(%rsi),%eax
xorl 56(%rsi),%r10d
movl %edx,40(%rdi)
movl %ecx,24(%rdi)
movl %eax,8(%rdi)
movl %r10d,56(%rdi)
movd %xmm0,%rdx
movd %xmm1,%rcx
movd %xmm2,%rax
movd %xmm3,%r10
xorl 60(%rsi),%edx
xorl 44(%rsi),%ecx
xorl 28(%rsi),%eax
xorl 12(%rsi),%r10d
movl %edx,60(%rdi)
movl %ecx,44(%rdi)
movl %eax,28(%rdi)
movl %r10d,12(%rdi)
movq 288(%rsp),%rdx
movl 32(%r8),%ecx
movl 52(%r8),%eax
add $1,%ecx
adc $0,%eax
movl %ecx,32(%r8)
movl %eax,52(%r8)
cmp $64,%rdx
ja .L_bytes_are_128_or_192
.L_done:
CFI_REMEMBER_STATE();
mov %r11,%rax
sub %rsp,%rax
mov %r11,%rsp
CFI_REGISTER(%r11, %rsp)
CFI_DEF_CFA_REGISTER(%rsp)
pop %rbx
CFI_POP(%rbx)
ret
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)*/
#endif /*__x86_64*/
diff --git a/cipher/salsa20-armv7-neon.S b/cipher/salsa20-armv7-neon.S
index 3686e3fa..eff10e87 100644
--- a/cipher/salsa20-armv7-neon.S
+++ b/cipher/salsa20-armv7-neon.S
@@ -1,899 +1,899 @@
/* salsa-armv7-neon.S - ARM NEON implementation of Salsa20 cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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) && defined(USE_SALSA20)
/*
* Based on public domain implementation from SUPERCOP benchmarking framework
* by Peter Schwabe and D. J. Bernstein. Paper about the implementation at:
- * http://cryptojedi.org/papers/#neoncrypto
+ * https://cryptojedi.org/papers/#neoncrypto
*/
.syntax unified
.arm
.fpu neon
.text
.align 2
.globl _gcry_arm_neon_salsa20_encrypt
.type _gcry_arm_neon_salsa20_encrypt,%function;
_gcry_arm_neon_salsa20_encrypt:
/* Modifications:
* - arguments changed to (void *c, const void *m, unsigned int nblks,
* void *ctx, unsigned int rounds) from (void *c, const void *m,
* unsigned long long mlen, const void *n, const void *k)
* - nonce and key read from 'ctx' as well as sigma and counter.
* - read in counter from 'ctx' at the start.
* - update counter in 'ctx' at the end.
* - length is input as number of blocks, so don't handle tail bytes
* (this is done in salsa20.c).
*/
lsl r2,r2,#6
vpush {q4,q5,q6,q7}
mov r12,sp
sub sp,sp,#352
and sp,sp,#0xffffffe0
strd r4,[sp,#0]
strd r6,[sp,#8]
strd r8,[sp,#16]
strd r10,[sp,#24]
str r14,[sp,#224]
str r12,[sp,#228]
str r0,[sp,#232]
str r1,[sp,#236]
str r2,[sp,#240]
ldr r4,[r12,#64]
str r4,[sp,#244]
mov r2,r3
add r3,r2,#48
vld1.8 {q3},[r2]
add r0,r2,#32
add r14,r2,#40
vmov.i64 q3,#0xff
str r14,[sp,#160]
ldrd r8,[r2,#4]
vld1.8 {d0},[r0]
ldrd r4,[r2,#20]
vld1.8 {d8-d9},[r2]!
ldrd r6,[r0,#0]
vmov d4,d9
ldr r0,[r14]
vrev64.i32 d0,d0
ldr r1,[r14,#4]
vld1.8 {d10-d11},[r2]
strd r6,[sp,#32]
sub r2,r2,#16
strd r0,[sp,#40]
vmov d5,d11
strd r8,[sp,#48]
vext.32 d1,d0,d10,#1
strd r4,[sp,#56]
ldr r1,[r2,#0]
vshr.u32 q3,q3,#7
ldr r4,[r2,#12]
vext.32 d3,d11,d9,#1
ldr r11,[r2,#16]
vext.32 d2,d8,d0,#1
ldr r8,[r2,#28]
vext.32 d0,d10,d8,#1
ldr r0,[r3,#0]
add r2,r2,#44
vmov q4,q3
vld1.8 {d6-d7},[r14]
vadd.i64 q3,q3,q4
ldr r5,[r3,#4]
add r12,sp,#256
vst1.8 {d4-d5},[r12,: 128]
ldr r10,[r3,#8]
add r14,sp,#272
vst1.8 {d2-d3},[r14,: 128]
ldr r9,[r3,#12]
vld1.8 {d2-d3},[r3]
strd r0,[sp,#64]
ldr r0,[sp,#240]
strd r4,[sp,#72]
strd r10,[sp,#80]
strd r8,[sp,#88]
nop
cmp r0,#192
blo .L_mlenlowbelow192
.L_mlenatleast192:
ldrd r2,[sp,#48]
vext.32 d7,d6,d6,#1
vmov q8,q1
ldrd r6,[sp,#32]
vld1.8 {d18-d19},[r12,: 128]
vmov q10,q0
str r0,[sp,#240]
vext.32 d4,d7,d19,#1
vmov q11,q8
vext.32 d10,d18,d7,#1
vadd.i64 q3,q3,q4
ldrd r0,[sp,#64]
vld1.8 {d24-d25},[r14,: 128]
vmov d5,d24
add r8,sp,#288
ldrd r4,[sp,#72]
vmov d11,d25
add r9,sp,#304
ldrd r10,[sp,#80]
vst1.8 {d4-d5},[r8,: 128]
strd r2,[sp,#96]
vext.32 d7,d6,d6,#1
vmov q13,q10
strd r6,[sp,#104]
vmov d13,d24
vst1.8 {d10-d11},[r9,: 128]
add r2,sp,#320
vext.32 d12,d7,d19,#1
vmov d15,d25
add r6,sp,#336
ldr r12,[sp,#244]
vext.32 d14,d18,d7,#1
vadd.i64 q3,q3,q4
ldrd r8,[sp,#88]
vst1.8 {d12-d13},[r2,: 128]
ldrd r2,[sp,#56]
vst1.8 {d14-d15},[r6,: 128]
ldrd r6,[sp,#40]
.L_mainloop2:
str r12,[sp,#248]
vadd.i32 q4,q10,q8
vadd.i32 q9,q13,q11
add r12,r0,r2
add r14,r5,r1
vshl.i32 q12,q4,#7
vshl.i32 q14,q9,#7
vshr.u32 q4,q4,#25
vshr.u32 q9,q9,#25
eor r4,r4,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r4,r0
add r14,r7,r5
veor q5,q5,q12
veor q7,q7,q14
veor q4,q5,q4
veor q5,q7,q9
eor r6,r6,r12,ROR #23
eor r3,r3,r14,ROR #23
add r12,r6,r4
str r7,[sp,#116]
add r7,r3,r7
ldr r14,[sp,#108]
vadd.i32 q7,q8,q4
vadd.i32 q9,q11,q5
vshl.i32 q12,q7,#9
vshl.i32 q14,q9,#9
vshr.u32 q7,q7,#23
vshr.u32 q9,q9,#23
veor q2,q2,q12
veor q6,q6,q14
veor q2,q2,q7
veor q6,q6,q9
eor r2,r2,r12,ROR #19
str r2,[sp,#120]
eor r1,r1,r7,ROR #19
ldr r7,[sp,#96]
add r2,r2,r6
str r6,[sp,#112]
add r6,r1,r3
ldr r12,[sp,#104]
vadd.i32 q7,q4,q2
vext.32 q4,q4,q4,#3
vadd.i32 q9,q5,q6
vshl.i32 q12,q7,#13
vext.32 q5,q5,q5,#3
vshl.i32 q14,q9,#13
eor r0,r0,r2,ROR #14
eor r2,r5,r6,ROR #14
str r3,[sp,#124]
add r3,r10,r12
ldr r5,[sp,#100]
add r6,r9,r11
vshr.u32 q7,q7,#19
vshr.u32 q9,q9,#19
veor q10,q10,q12
veor q12,q13,q14
eor r8,r8,r3,ROR #25
eor r3,r5,r6,ROR #25
add r5,r8,r10
add r6,r3,r9
veor q7,q10,q7
veor q9,q12,q9
eor r5,r7,r5,ROR #23
eor r6,r14,r6,ROR #23
add r7,r5,r8
add r14,r6,r3
vadd.i32 q10,q2,q7
vswp d4,d5
vadd.i32 q12,q6,q9
vshl.i32 q13,q10,#18
vswp d12,d13
vshl.i32 q14,q12,#18
eor r7,r12,r7,ROR #19
eor r11,r11,r14,ROR #19
add r12,r7,r5
add r14,r11,r6
vshr.u32 q10,q10,#14
vext.32 q7,q7,q7,#1
vshr.u32 q12,q12,#14
veor q8,q8,q13
vext.32 q9,q9,q9,#1
veor q11,q11,q14
eor r10,r10,r12,ROR #14
eor r9,r9,r14,ROR #14
add r12,r0,r3
add r14,r2,r4
veor q8,q8,q10
veor q10,q11,q12
eor r1,r1,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r1,r0
add r14,r7,r2
vadd.i32 q11,q4,q8
vadd.i32 q12,q5,q10
vshl.i32 q13,q11,#7
vshl.i32 q14,q12,#7
eor r5,r5,r12,ROR #23
eor r6,r6,r14,ROR #23
vshr.u32 q11,q11,#25
vshr.u32 q12,q12,#25
add r12,r5,r1
add r14,r6,r7
veor q7,q7,q13
veor q9,q9,q14
veor q7,q7,q11
veor q9,q9,q12
vadd.i32 q11,q8,q7
vadd.i32 q12,q10,q9
vshl.i32 q13,q11,#9
vshl.i32 q14,q12,#9
eor r3,r3,r12,ROR #19
str r7,[sp,#104]
eor r4,r4,r14,ROR #19
ldr r7,[sp,#112]
add r12,r3,r5
str r6,[sp,#108]
add r6,r4,r6
ldr r14,[sp,#116]
eor r0,r0,r12,ROR #14
str r5,[sp,#96]
eor r5,r2,r6,ROR #14
ldr r2,[sp,#120]
vshr.u32 q11,q11,#23
vshr.u32 q12,q12,#23
veor q2,q2,q13
veor q6,q6,q14
veor q2,q2,q11
veor q6,q6,q12
add r6,r10,r14
add r12,r9,r8
vadd.i32 q11,q7,q2
vext.32 q7,q7,q7,#3
vadd.i32 q12,q9,q6
vshl.i32 q13,q11,#13
vext.32 q9,q9,q9,#3
vshl.i32 q14,q12,#13
vshr.u32 q11,q11,#19
vshr.u32 q12,q12,#19
eor r11,r11,r6,ROR #25
eor r2,r2,r12,ROR #25
add r6,r11,r10
str r3,[sp,#100]
add r3,r2,r9
ldr r12,[sp,#124]
veor q4,q4,q13
veor q5,q5,q14
veor q4,q4,q11
veor q5,q5,q12
eor r6,r7,r6,ROR #23
eor r3,r12,r3,ROR #23
add r7,r6,r11
add r12,r3,r2
vadd.i32 q11,q2,q4
vswp d4,d5
vadd.i32 q12,q6,q5
vshl.i32 q13,q11,#18
vswp d12,d13
vshl.i32 q14,q12,#18
eor r7,r14,r7,ROR #19
eor r8,r8,r12,ROR #19
add r12,r7,r6
add r14,r8,r3
vshr.u32 q11,q11,#14
vext.32 q4,q4,q4,#1
vshr.u32 q12,q12,#14
veor q8,q8,q13
vext.32 q5,q5,q5,#1
veor q10,q10,q14
eor r10,r10,r12,ROR #14
veor q8,q8,q11
eor r9,r9,r14,ROR #14
veor q10,q10,q12
vadd.i32 q11,q7,q8
vadd.i32 q12,q9,q10
add r12,r0,r2
add r14,r5,r1
vshl.i32 q13,q11,#7
vshl.i32 q14,q12,#7
vshr.u32 q11,q11,#25
vshr.u32 q12,q12,#25
eor r4,r4,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r4,r0
add r14,r7,r5
veor q4,q4,q13
veor q5,q5,q14
veor q4,q4,q11
veor q5,q5,q12
eor r6,r6,r12,ROR #23
eor r3,r3,r14,ROR #23
add r12,r6,r4
str r7,[sp,#116]
add r7,r3,r7
ldr r14,[sp,#108]
vadd.i32 q11,q8,q4
vadd.i32 q12,q10,q5
vshl.i32 q13,q11,#9
vshl.i32 q14,q12,#9
vshr.u32 q11,q11,#23
vshr.u32 q12,q12,#23
veor q2,q2,q13
veor q6,q6,q14
veor q2,q2,q11
veor q6,q6,q12
eor r2,r2,r12,ROR #19
str r2,[sp,#120]
eor r1,r1,r7,ROR #19
ldr r7,[sp,#96]
add r2,r2,r6
str r6,[sp,#112]
add r6,r1,r3
ldr r12,[sp,#104]
vadd.i32 q11,q4,q2
vext.32 q4,q4,q4,#3
vadd.i32 q12,q5,q6
vshl.i32 q13,q11,#13
vext.32 q5,q5,q5,#3
vshl.i32 q14,q12,#13
eor r0,r0,r2,ROR #14
eor r2,r5,r6,ROR #14
str r3,[sp,#124]
add r3,r10,r12
ldr r5,[sp,#100]
add r6,r9,r11
vshr.u32 q11,q11,#19
vshr.u32 q12,q12,#19
veor q7,q7,q13
veor q9,q9,q14
eor r8,r8,r3,ROR #25
eor r3,r5,r6,ROR #25
add r5,r8,r10
add r6,r3,r9
veor q7,q7,q11
veor q9,q9,q12
eor r5,r7,r5,ROR #23
eor r6,r14,r6,ROR #23
add r7,r5,r8
add r14,r6,r3
vadd.i32 q11,q2,q7
vswp d4,d5
vadd.i32 q12,q6,q9
vshl.i32 q13,q11,#18
vswp d12,d13
vshl.i32 q14,q12,#18
eor r7,r12,r7,ROR #19
eor r11,r11,r14,ROR #19
add r12,r7,r5
add r14,r11,r6
vshr.u32 q11,q11,#14
vext.32 q7,q7,q7,#1
vshr.u32 q12,q12,#14
veor q8,q8,q13
vext.32 q9,q9,q9,#1
veor q10,q10,q14
eor r10,r10,r12,ROR #14
eor r9,r9,r14,ROR #14
add r12,r0,r3
add r14,r2,r4
veor q8,q8,q11
veor q11,q10,q12
eor r1,r1,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r1,r0
add r14,r7,r2
vadd.i32 q10,q4,q8
vadd.i32 q12,q5,q11
vshl.i32 q13,q10,#7
vshl.i32 q14,q12,#7
eor r5,r5,r12,ROR #23
eor r6,r6,r14,ROR #23
vshr.u32 q10,q10,#25
vshr.u32 q12,q12,#25
add r12,r5,r1
add r14,r6,r7
veor q7,q7,q13
veor q9,q9,q14
veor q7,q7,q10
veor q9,q9,q12
vadd.i32 q10,q8,q7
vadd.i32 q12,q11,q9
vshl.i32 q13,q10,#9
vshl.i32 q14,q12,#9
eor r3,r3,r12,ROR #19
str r7,[sp,#104]
eor r4,r4,r14,ROR #19
ldr r7,[sp,#112]
add r12,r3,r5
str r6,[sp,#108]
add r6,r4,r6
ldr r14,[sp,#116]
eor r0,r0,r12,ROR #14
str r5,[sp,#96]
eor r5,r2,r6,ROR #14
ldr r2,[sp,#120]
vshr.u32 q10,q10,#23
vshr.u32 q12,q12,#23
veor q2,q2,q13
veor q6,q6,q14
veor q2,q2,q10
veor q6,q6,q12
add r6,r10,r14
add r12,r9,r8
vadd.i32 q12,q7,q2
vext.32 q10,q7,q7,#3
vadd.i32 q7,q9,q6
vshl.i32 q14,q12,#13
vext.32 q13,q9,q9,#3
vshl.i32 q9,q7,#13
vshr.u32 q12,q12,#19
vshr.u32 q7,q7,#19
eor r11,r11,r6,ROR #25
eor r2,r2,r12,ROR #25
add r6,r11,r10
str r3,[sp,#100]
add r3,r2,r9
ldr r12,[sp,#124]
veor q4,q4,q14
veor q5,q5,q9
veor q4,q4,q12
veor q7,q5,q7
eor r6,r7,r6,ROR #23
eor r3,r12,r3,ROR #23
add r7,r6,r11
add r12,r3,r2
vadd.i32 q5,q2,q4
vswp d4,d5
vadd.i32 q9,q6,q7
vshl.i32 q12,q5,#18
vswp d12,d13
vshl.i32 q14,q9,#18
eor r7,r14,r7,ROR #19
eor r8,r8,r12,ROR #19
add r12,r7,r6
add r14,r8,r3
vshr.u32 q15,q5,#14
vext.32 q5,q4,q4,#1
vshr.u32 q4,q9,#14
veor q8,q8,q12
vext.32 q7,q7,q7,#1
veor q9,q11,q14
eor r10,r10,r12,ROR #14
ldr r12,[sp,#248]
veor q8,q8,q15
eor r9,r9,r14,ROR #14
veor q11,q9,q4
subs r12,r12,#4
bhi .L_mainloop2
strd r8,[sp,#112]
ldrd r8,[sp,#64]
strd r2,[sp,#120]
ldrd r2,[sp,#96]
add r0,r0,r8
strd r10,[sp,#96]
add r1,r1,r9
ldrd r10,[sp,#48]
ldrd r8,[sp,#72]
add r2,r2,r10
strd r6,[sp,#128]
add r3,r3,r11
ldrd r6,[sp,#104]
ldrd r10,[sp,#32]
ldr r12,[sp,#236]
add r4,r4,r8
add r5,r5,r9
add r6,r6,r10
add r7,r7,r11
cmp r12,#0
beq .L_nomessage1
ldr r8,[r12,#0]
ldr r9,[r12,#4]
ldr r10,[r12,#8]
ldr r11,[r12,#12]
eor r0,r0,r8
ldr r8,[r12,#16]
eor r1,r1,r9
ldr r9,[r12,#20]
eor r2,r2,r10
ldr r10,[r12,#24]
eor r3,r3,r11
ldr r11,[r12,#28]
eor r4,r4,r8
eor r5,r5,r9
eor r6,r6,r10
eor r7,r7,r11
.L_nomessage1:
ldr r14,[sp,#232]
vadd.i32 q4,q8,q1
str r0,[r14,#0]
add r0,sp,#304
str r1,[r14,#4]
vld1.8 {d16-d17},[r0,: 128]
str r2,[r14,#8]
vadd.i32 q5,q8,q5
str r3,[r14,#12]
add r0,sp,#288
str r4,[r14,#16]
vld1.8 {d16-d17},[r0,: 128]
str r5,[r14,#20]
vadd.i32 q9,q10,q0
str r6,[r14,#24]
vadd.i32 q2,q8,q2
str r7,[r14,#28]
vmov.i64 q8,#0xffffffff
ldrd r6,[sp,#128]
vext.32 d20,d8,d10,#1
ldrd r0,[sp,#40]
vext.32 d25,d9,d11,#1
ldrd r2,[sp,#120]
vbif q4,q9,q8
ldrd r4,[sp,#56]
vext.32 d21,d5,d19,#1
add r6,r6,r0
vext.32 d24,d4,d18,#1
add r7,r7,r1
vbif q2,q5,q8
add r2,r2,r4
vrev64.i32 q5,q10
add r3,r3,r5
vrev64.i32 q9,q12
adds r0,r0,#3
vswp d5,d9
adc r1,r1,#0
strd r0,[sp,#40]
ldrd r8,[sp,#112]
ldrd r0,[sp,#88]
ldrd r10,[sp,#96]
ldrd r4,[sp,#80]
add r0,r8,r0
add r1,r9,r1
add r4,r10,r4
add r5,r11,r5
add r8,r14,#64
cmp r12,#0
beq .L_nomessage2
ldr r9,[r12,#32]
ldr r10,[r12,#36]
ldr r11,[r12,#40]
ldr r14,[r12,#44]
eor r6,r6,r9
ldr r9,[r12,#48]
eor r7,r7,r10
ldr r10,[r12,#52]
eor r4,r4,r11
ldr r11,[r12,#56]
eor r5,r5,r14
ldr r14,[r12,#60]
add r12,r12,#64
eor r2,r2,r9
vld1.8 {d20-d21},[r12]!
veor q4,q4,q10
eor r3,r3,r10
vld1.8 {d20-d21},[r12]!
veor q5,q5,q10
eor r0,r0,r11
vld1.8 {d20-d21},[r12]!
veor q2,q2,q10
eor r1,r1,r14
vld1.8 {d20-d21},[r12]!
veor q9,q9,q10
.L_nomessage2:
vst1.8 {d8-d9},[r8]!
vst1.8 {d10-d11},[r8]!
vmov.i64 q4,#0xff
vst1.8 {d4-d5},[r8]!
vst1.8 {d18-d19},[r8]!
str r6,[r8,#-96]
add r6,sp,#336
str r7,[r8,#-92]
add r7,sp,#320
str r4,[r8,#-88]
vadd.i32 q2,q11,q1
vld1.8 {d10-d11},[r6,: 128]
vadd.i32 q5,q5,q7
vld1.8 {d14-d15},[r7,: 128]
vadd.i32 q9,q13,q0
vadd.i32 q6,q7,q6
str r5,[r8,#-84]
vext.32 d14,d4,d10,#1
str r2,[r8,#-80]
vext.32 d21,d5,d11,#1
str r3,[r8,#-76]
vbif q2,q9,q8
str r0,[r8,#-72]
vext.32 d15,d13,d19,#1
vshr.u32 q4,q4,#7
str r1,[r8,#-68]
vext.32 d20,d12,d18,#1
vbif q6,q5,q8
ldr r0,[sp,#240]
vrev64.i32 q5,q7
vrev64.i32 q7,q10
vswp d13,d5
vadd.i64 q3,q3,q4
sub r0,r0,#192
cmp r12,#0
beq .L_nomessage21
vld1.8 {d16-d17},[r12]!
veor q2,q2,q8
vld1.8 {d16-d17},[r12]!
veor q5,q5,q8
vld1.8 {d16-d17},[r12]!
veor q6,q6,q8
vld1.8 {d16-d17},[r12]!
veor q7,q7,q8
.L_nomessage21:
vst1.8 {d4-d5},[r8]!
vst1.8 {d10-d11},[r8]!
vst1.8 {d12-d13},[r8]!
vst1.8 {d14-d15},[r8]!
str r12,[sp,#236]
add r14,sp,#272
add r12,sp,#256
str r8,[sp,#232]
cmp r0,#192
bhs .L_mlenatleast192
.L_mlenlowbelow192:
cmp r0,#0
beq .L_done
b .L_mlenatleast1
.L_nextblock:
sub r0,r0,#64
.L_mlenatleast1:
.L_handleblock:
str r0,[sp,#248]
ldrd r2,[sp,#48]
ldrd r6,[sp,#32]
ldrd r0,[sp,#64]
ldrd r4,[sp,#72]
ldrd r10,[sp,#80]
ldrd r8,[sp,#88]
strd r2,[sp,#96]
strd r6,[sp,#104]
ldrd r2,[sp,#56]
ldrd r6,[sp,#40]
ldr r12,[sp,#244]
.L_mainloop1:
str r12,[sp,#252]
add r12,r0,r2
add r14,r5,r1
eor r4,r4,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r4,r0
add r14,r7,r5
eor r6,r6,r12,ROR #23
eor r3,r3,r14,ROR #23
add r12,r6,r4
str r7,[sp,#132]
add r7,r3,r7
ldr r14,[sp,#104]
eor r2,r2,r12,ROR #19
str r6,[sp,#128]
eor r1,r1,r7,ROR #19
ldr r7,[sp,#100]
add r6,r2,r6
str r2,[sp,#120]
add r2,r1,r3
ldr r12,[sp,#96]
eor r0,r0,r6,ROR #14
str r3,[sp,#124]
eor r2,r5,r2,ROR #14
ldr r3,[sp,#108]
add r5,r10,r14
add r6,r9,r11
eor r8,r8,r5,ROR #25
eor r5,r7,r6,ROR #25
add r6,r8,r10
add r7,r5,r9
eor r6,r12,r6,ROR #23
eor r3,r3,r7,ROR #23
add r7,r6,r8
add r12,r3,r5
eor r7,r14,r7,ROR #19
eor r11,r11,r12,ROR #19
add r12,r7,r6
add r14,r11,r3
eor r10,r10,r12,ROR #14
eor r9,r9,r14,ROR #14
add r12,r0,r5
add r14,r2,r4
eor r1,r1,r12,ROR #25
eor r7,r7,r14,ROR #25
add r12,r1,r0
add r14,r7,r2
eor r6,r6,r12,ROR #23
eor r3,r3,r14,ROR #23
add r12,r6,r1
str r7,[sp,#104]
add r7,r3,r7
ldr r14,[sp,#128]
eor r5,r5,r12,ROR #19
str r3,[sp,#108]
eor r4,r4,r7,ROR #19
ldr r7,[sp,#132]
add r12,r5,r6
str r6,[sp,#96]
add r3,r4,r3
ldr r6,[sp,#120]
eor r0,r0,r12,ROR #14
str r5,[sp,#100]
eor r5,r2,r3,ROR #14
ldr r3,[sp,#124]
add r2,r10,r7
add r12,r9,r8
eor r11,r11,r2,ROR #25
eor r2,r6,r12,ROR #25
add r6,r11,r10
add r12,r2,r9
eor r6,r14,r6,ROR #23
eor r3,r3,r12,ROR #23
add r12,r6,r11
add r14,r3,r2
eor r7,r7,r12,ROR #19
eor r8,r8,r14,ROR #19
add r12,r7,r6
add r14,r8,r3
eor r10,r10,r12,ROR #14
eor r9,r9,r14,ROR #14
ldr r12,[sp,#252]
subs r12,r12,#2
bhi .L_mainloop1
strd r6,[sp,#128]
strd r2,[sp,#120]
strd r10,[sp,#112]
strd r8,[sp,#136]
ldrd r2,[sp,#96]
ldrd r6,[sp,#104]
ldrd r8,[sp,#64]
ldrd r10,[sp,#48]
add r0,r0,r8
add r1,r1,r9
add r2,r2,r10
add r3,r3,r11
ldrd r8,[sp,#72]
ldrd r10,[sp,#32]
add r4,r4,r8
add r5,r5,r9
add r6,r6,r10
add r7,r7,r11
ldr r12,[sp,#236]
cmp r12,#0
beq .L_nomessage10
ldr r8,[r12,#0]
ldr r9,[r12,#4]
ldr r10,[r12,#8]
ldr r11,[r12,#12]
eor r0,r0,r8
ldr r8,[r12,#16]
eor r1,r1,r9
ldr r9,[r12,#20]
eor r2,r2,r10
ldr r10,[r12,#24]
eor r3,r3,r11
ldr r11,[r12,#28]
eor r4,r4,r8
eor r5,r5,r9
eor r6,r6,r10
eor r7,r7,r11
.L_nomessage10:
ldr r14,[sp,#232]
str r0,[r14,#0]
str r1,[r14,#4]
str r2,[r14,#8]
str r3,[r14,#12]
str r4,[r14,#16]
str r5,[r14,#20]
str r6,[r14,#24]
str r7,[r14,#28]
ldrd r6,[sp,#128]
ldrd r10,[sp,#112]
ldrd r0,[sp,#40]
ldrd r4,[sp,#80]
add r6,r6,r0
add r7,r7,r1
add r10,r10,r4
add r11,r11,r5
adds r0,r0,#1
adc r1,r1,#0
strd r0,[sp,#40]
ldrd r2,[sp,#120]
ldrd r8,[sp,#136]
ldrd r4,[sp,#56]
ldrd r0,[sp,#88]
add r2,r2,r4
add r3,r3,r5
add r0,r8,r0
add r1,r9,r1
cmp r12,#0
beq .L_nomessage11
ldr r4,[r12,#32]
ldr r5,[r12,#36]
ldr r8,[r12,#40]
ldr r9,[r12,#44]
eor r6,r6,r4
ldr r4,[r12,#48]
eor r7,r7,r5
ldr r5,[r12,#52]
eor r10,r10,r8
ldr r8,[r12,#56]
eor r11,r11,r9
ldr r9,[r12,#60]
eor r2,r2,r4
eor r3,r3,r5
eor r0,r0,r8
eor r1,r1,r9
add r4,r12,#64
str r4,[sp,#236]
.L_nomessage11:
str r6,[r14,#32]
str r7,[r14,#36]
str r10,[r14,#40]
str r11,[r14,#44]
str r2,[r14,#48]
str r3,[r14,#52]
str r0,[r14,#56]
str r1,[r14,#60]
add r0,r14,#64
str r0,[sp,#232]
ldr r0,[sp,#248]
cmp r0,#64
bhi .L_nextblock
.L_done:
ldr r2,[sp,#160]
ldrd r4,[sp,#0]
ldrd r6,[sp,#8]
ldrd r8,[sp,#16]
ldrd r10,[sp,#24]
ldr r12,[sp,#228]
ldr r14,[sp,#224]
ldrd r0,[sp,#40]
strd r0,[r2]
sub r0,r12,sp
mov sp,r12
vpop {q4,q5,q6,q7}
add r0,r0,#64
bx lr
.size _gcry_arm_neon_salsa20_encrypt,.-_gcry_arm_neon_salsa20_encrypt;
#endif
diff --git a/cipher/salsa20.c b/cipher/salsa20.c
index 5c5e2b54..29f664e0 100644
--- a/cipher/salsa20.c
+++ b/cipher/salsa20.c
@@ -1,599 +1,599 @@
/* salsa20.c - Bernstein's Salsa20 cipher
* Copyright (C) 2012 Simon Josefsson, Niels Möller
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* For a description of the algorithm, see:
- * http://cr.yp.to/snuffle/spec.pdf
- * http://cr.yp.to/snuffle/design.pdf
+ * https://cr.yp.to/snuffle/spec.pdf
+ * https://cr.yp.to/snuffle/design.pdf
*/
/* The code is based on the code in Nettle
(git commit id 9d2d8ddaee35b91a4e1a32ae77cba04bea3480e7)
which in turn is based on
salsa20-ref.c version 20051118
D. J. Bernstein
Public domain.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
/* USE_AMD64 indicates whether to compile with AMD64 code. */
#undef USE_AMD64
#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# define USE_AMD64 1
#endif
/* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */
#undef USE_ARM_NEON_ASM
#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_ARM_NEON_ASM 1
# endif
#endif /*ENABLE_NEON_SUPPORT*/
#define SALSA20_MIN_KEY_SIZE 16 /* Bytes. */
#define SALSA20_MAX_KEY_SIZE 32 /* Bytes. */
#define SALSA20_BLOCK_SIZE 64 /* Bytes. */
#define SALSA20_IV_SIZE 8 /* Bytes. */
#define SALSA20_INPUT_LENGTH 16 /* Bytes. */
/* Number of rounds. The standard uses 20 rounds. In any case the
number of rounds must be even. */
#define SALSA20_ROUNDS 20
#define SALSA20R12_ROUNDS 12
struct SALSA20_context_s;
typedef unsigned int (*salsa20_core_t) (u32 *dst, struct SALSA20_context_s *ctx,
unsigned int rounds);
typedef void (* salsa20_keysetup_t)(struct SALSA20_context_s *ctx,
const byte *key, int keylen);
typedef void (* salsa20_ivsetup_t)(struct SALSA20_context_s *ctx,
const byte *iv);
typedef struct SALSA20_context_s
{
/* Indices 1-4 and 11-14 holds the key (two identical copies for the
shorter key size), indices 0, 5, 10, 15 are constant, indices 6, 7
are the IV, and indices 8, 9 are the block counter:
C K K K
K C I I
B B C K
K K K C
*/
u32 input[SALSA20_INPUT_LENGTH];
u32 pad[SALSA20_INPUT_LENGTH];
unsigned int unused; /* bytes in the pad. */
#ifdef USE_ARM_NEON_ASM
int use_neon;
#endif
salsa20_keysetup_t keysetup;
salsa20_ivsetup_t ivsetup;
salsa20_core_t core;
} SALSA20_context_t;
/* The masking of the right shift is needed to allow n == 0 (using
just 32 - n and 64 - n results in undefined behaviour). Most uses
of these macros use a constant and non-zero rotation count. */
#define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31))))
#define LE_SWAP32(v) le_bswap32(v)
#define LE_READ_UINT32(p) buf_get_le32(p)
static void salsa20_setiv (void *context, const byte *iv, size_t ivlen);
static const char *selftest (void);
#ifdef USE_AMD64
/* Assembly implementations use SystemV ABI, ABI conversion and additional
* stack to store XMM6-XMM15 needed on Win64. */
#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
/* AMD64 assembly implementations of Salsa20. */
void _gcry_salsa20_amd64_keysetup(u32 *ctxinput, const void *key, int keybits)
ASM_FUNC_ABI;
void _gcry_salsa20_amd64_ivsetup(u32 *ctxinput, const void *iv)
ASM_FUNC_ABI;
unsigned int
_gcry_salsa20_amd64_encrypt_blocks(u32 *ctxinput, const void *src, void *dst,
size_t len, int rounds) ASM_FUNC_ABI;
static void
salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen)
{
_gcry_salsa20_amd64_keysetup(ctx->input, key, keylen * 8);
}
static void
salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv)
{
_gcry_salsa20_amd64_ivsetup(ctx->input, iv);
}
static unsigned int
salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds)
{
memset(dst, 0, SALSA20_BLOCK_SIZE);
return _gcry_salsa20_amd64_encrypt_blocks(ctx->input, dst, dst, 1, rounds)
+ ASM_EXTRA_STACK;
}
#else /* USE_AMD64 */
#if 0
# define SALSA20_CORE_DEBUG(i) do { \
unsigned debug_j; \
for (debug_j = 0; debug_j < 16; debug_j++) \
{ \
if (debug_j == 0) \
fprintf(stderr, "%2d:", (i)); \
else if (debug_j % 4 == 0) \
fprintf(stderr, "\n "); \
fprintf(stderr, " %8x", pad[debug_j]); \
} \
fprintf(stderr, "\n"); \
} while (0)
#else
# define SALSA20_CORE_DEBUG(i)
#endif
#define QROUND(x0, x1, x2, x3) \
do { \
x1 ^= ROTL32 ( 7, x0 + x3); \
x2 ^= ROTL32 ( 9, x1 + x0); \
x3 ^= ROTL32 (13, x2 + x1); \
x0 ^= ROTL32 (18, x3 + x2); \
} while(0)
static unsigned int
salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned rounds)
{
u32 pad[SALSA20_INPUT_LENGTH], *src = ctx->input;
unsigned int i;
memcpy (pad, src, sizeof(pad));
for (i = 0; i < rounds; i += 2)
{
SALSA20_CORE_DEBUG (i);
QROUND (pad[0], pad[4], pad[8], pad[12]);
QROUND (pad[5], pad[9], pad[13], pad[1] );
QROUND (pad[10], pad[14], pad[2], pad[6] );
QROUND (pad[15], pad[3], pad[7], pad[11]);
SALSA20_CORE_DEBUG (i+1);
QROUND (pad[0], pad[1], pad[2], pad[3] );
QROUND (pad[5], pad[6], pad[7], pad[4] );
QROUND (pad[10], pad[11], pad[8], pad[9] );
QROUND (pad[15], pad[12], pad[13], pad[14]);
}
SALSA20_CORE_DEBUG (i);
for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
{
u32 t = pad[i] + src[i];
dst[i] = LE_SWAP32 (t);
}
/* Update counter. */
if (!++src[8])
src[9]++;
/* burn_stack */
return ( 3*sizeof (void*) \
+ 2*sizeof (void*) \
+ 64 \
+ sizeof (unsigned int) \
+ sizeof (u32) );
}
#undef QROUND
#undef SALSA20_CORE_DEBUG
static void
salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, 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[5] = 0x3320646e; /* "3 dn" */
ctx->input[10] = 0x79622d32; /* "yb-2" */
ctx->input[15] = 0x6b206574; /* "k et" */
ctx->input[1] = LE_READ_UINT32(key + 0);
ctx->input[2] = LE_READ_UINT32(key + 4);
ctx->input[3] = LE_READ_UINT32(key + 8);
ctx->input[4] = LE_READ_UINT32(key + 12);
if (keylen == SALSA20_MAX_KEY_SIZE) /* 256 bits */
{
ctx->input[11] = LE_READ_UINT32(key + 16);
ctx->input[12] = LE_READ_UINT32(key + 20);
ctx->input[13] = LE_READ_UINT32(key + 24);
ctx->input[14] = LE_READ_UINT32(key + 28);
}
else /* 128 bits */
{
ctx->input[11] = ctx->input[1];
ctx->input[12] = ctx->input[2];
ctx->input[13] = ctx->input[3];
ctx->input[14] = ctx->input[4];
ctx->input[5] -= 0x02000000; /* Change to "1 dn". */
ctx->input[10] += 0x00000004; /* Change to "yb-6". */
}
}
static void salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv)
{
ctx->input[6] = LE_READ_UINT32(iv + 0);
ctx->input[7] = LE_READ_UINT32(iv + 4);
/* Reset the block counter. */
ctx->input[8] = 0;
ctx->input[9] = 0;
}
#endif /*!USE_AMD64*/
#ifdef USE_ARM_NEON_ASM
/* ARM NEON implementation of Salsa20. */
unsigned int
_gcry_arm_neon_salsa20_encrypt(void *c, const void *m, unsigned int nblks,
void *k, unsigned int rounds);
static unsigned int
salsa20_core_neon (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds)
{
return _gcry_arm_neon_salsa20_encrypt(dst, NULL, 1, ctx->input, rounds);
}
static void salsa20_ivsetup_neon(SALSA20_context_t *ctx, const byte *iv)
{
memcpy(ctx->input + 8, iv, 8);
/* Reset the block counter. */
memset(ctx->input + 10, 0, 8);
}
static void
salsa20_keysetup_neon(SALSA20_context_t *ctx, const byte *key, int klen)
{
static const unsigned char sigma32[16] = "expand 32-byte k";
static const unsigned char sigma16[16] = "expand 16-byte k";
if (klen == 16)
{
memcpy (ctx->input, key, 16);
memcpy (ctx->input + 4, key, 16); /* Duplicate 128-bit key. */
memcpy (ctx->input + 12, sigma16, 16);
}
else
{
/* 32-byte key */
memcpy (ctx->input, key, 32);
memcpy (ctx->input + 12, sigma32, 16);
}
}
#endif /*USE_ARM_NEON_ASM*/
static gcry_err_code_t
salsa20_do_setkey (SALSA20_context_t *ctx,
const byte *key, unsigned int keylen)
{
static int initialized;
static const char *selftest_failed;
if (!initialized )
{
initialized = 1;
selftest_failed = selftest ();
if (selftest_failed)
log_error ("SALSA20 selftest failed (%s)\n", selftest_failed );
}
if (selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
if (keylen != SALSA20_MIN_KEY_SIZE
&& keylen != SALSA20_MAX_KEY_SIZE)
return GPG_ERR_INV_KEYLEN;
/* Default ops. */
ctx->keysetup = salsa20_keysetup;
ctx->ivsetup = salsa20_ivsetup;
ctx->core = salsa20_core;
#ifdef USE_ARM_NEON_ASM
ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
if (ctx->use_neon)
{
/* Use ARM NEON ops instead. */
ctx->keysetup = salsa20_keysetup_neon;
ctx->ivsetup = salsa20_ivsetup_neon;
ctx->core = salsa20_core_neon;
}
#endif
ctx->keysetup (ctx, key, keylen);
/* We default to a zero nonce. */
salsa20_setiv (ctx, NULL, 0);
return 0;
}
static gcry_err_code_t
salsa20_setkey (void *context, const byte *key, unsigned int keylen,
gcry_cipher_hd_t hd)
{
SALSA20_context_t *ctx = (SALSA20_context_t *)context;
gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen);
(void)hd;
_gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
return rc;
}
static void
salsa20_setiv (void *context, const byte *iv, size_t ivlen)
{
SALSA20_context_t *ctx = (SALSA20_context_t *)context;
byte tmp[SALSA20_IV_SIZE];
if (iv && ivlen != SALSA20_IV_SIZE)
log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen);
if (!iv || ivlen != SALSA20_IV_SIZE)
memset (tmp, 0, sizeof(tmp));
else
memcpy (tmp, iv, SALSA20_IV_SIZE);
ctx->ivsetup (ctx, tmp);
/* Reset the unused pad bytes counter. */
ctx->unused = 0;
wipememory (tmp, sizeof(tmp));
}
/* Note: This function requires LENGTH > 0. */
static void
salsa20_do_encrypt_stream (SALSA20_context_t *ctx,
byte *outbuf, const byte *inbuf,
size_t length, unsigned rounds)
{
unsigned int nburn, burn = 0;
if (ctx->unused)
{
unsigned char *p = (void*)ctx->pad;
size_t n;
gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE);
n = ctx->unused;
if (n > length)
n = length;
buf_xor (outbuf, inbuf, p + SALSA20_BLOCK_SIZE - ctx->unused, n);
length -= n;
outbuf += n;
inbuf += n;
ctx->unused -= n;
if (!length)
return;
gcry_assert (!ctx->unused);
}
#ifdef USE_AMD64
if (length >= SALSA20_BLOCK_SIZE)
{
size_t nblocks = length / SALSA20_BLOCK_SIZE;
burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf,
nblocks, rounds);
burn += ASM_EXTRA_STACK;
length -= SALSA20_BLOCK_SIZE * nblocks;
outbuf += SALSA20_BLOCK_SIZE * nblocks;
inbuf += SALSA20_BLOCK_SIZE * nblocks;
}
#endif
#ifdef USE_ARM_NEON_ASM
if (ctx->use_neon && length >= SALSA20_BLOCK_SIZE)
{
unsigned int nblocks = length / SALSA20_BLOCK_SIZE;
_gcry_arm_neon_salsa20_encrypt (outbuf, inbuf, nblocks, ctx->input,
rounds);
length -= SALSA20_BLOCK_SIZE * nblocks;
outbuf += SALSA20_BLOCK_SIZE * nblocks;
inbuf += SALSA20_BLOCK_SIZE * nblocks;
}
#endif
while (length > 0)
{
/* Create the next pad and bump the block counter. Note that it
is the user's duty to change to another nonce not later than
after 2^70 processed bytes. */
nburn = ctx->core (ctx->pad, ctx, rounds);
burn = nburn > burn ? nburn : burn;
if (length <= SALSA20_BLOCK_SIZE)
{
buf_xor (outbuf, inbuf, ctx->pad, length);
ctx->unused = SALSA20_BLOCK_SIZE - length;
break;
}
buf_xor (outbuf, inbuf, ctx->pad, SALSA20_BLOCK_SIZE);
length -= SALSA20_BLOCK_SIZE;
outbuf += SALSA20_BLOCK_SIZE;
inbuf += SALSA20_BLOCK_SIZE;
}
_gcry_burn_stack (burn);
}
static void
salsa20_encrypt_stream (void *context,
byte *outbuf, const byte *inbuf, size_t length)
{
SALSA20_context_t *ctx = (SALSA20_context_t *)context;
if (length)
salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS);
}
static void
salsa20r12_encrypt_stream (void *context,
byte *outbuf, const byte *inbuf, size_t length)
{
SALSA20_context_t *ctx = (SALSA20_context_t *)context;
if (length)
salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS);
}
static const char*
selftest (void)
{
byte ctxbuf[sizeof(SALSA20_context_t) + 15];
SALSA20_context_t *ctx;
byte scratch[8+1];
byte buf[256+64+4];
int i;
static byte key_1[] =
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const byte nonce_1[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const byte plaintext_1[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const byte ciphertext_1[] =
{ 0xE3, 0xBE, 0x8F, 0xDD, 0x8B, 0xEC, 0xA2, 0xE3};
/* 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, NULL);
salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
scratch[8] = 0;
salsa20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1))
return "Salsa20 encryption test 1 failed.";
if (scratch[8])
return "Salsa20 wrote too much.";
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))
return "Salsa20 decryption test 1 failed.";
for (i = 0; i < sizeof buf; i++)
buf[i] = i;
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, 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);
salsa20_encrypt_stream (ctx, buf+(sizeof buf)-1, buf+(sizeof buf)-1, 1);
for (i = 0; i < sizeof buf; i++)
if (buf[i] != (byte)i)
return "Salsa20 encryption test 2 failed.";
return NULL;
}
gcry_cipher_spec_t _gcry_cipher_spec_salsa20 =
{
GCRY_CIPHER_SALSA20,
{0, 0}, /* flags */
"SALSA20", /* name */
NULL, /* aliases */
NULL, /* oids */
1, /* blocksize in bytes. */
SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */
sizeof (SALSA20_context_t),
salsa20_setkey,
NULL,
NULL,
salsa20_encrypt_stream,
salsa20_encrypt_stream,
NULL,
NULL,
salsa20_setiv
};
gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12 =
{
GCRY_CIPHER_SALSA20R12,
{0, 0}, /* flags */
"SALSA20R12", /* name */
NULL, /* aliases */
NULL, /* oids */
1, /* blocksize in bytes. */
SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */
sizeof (SALSA20_context_t),
salsa20_setkey,
NULL,
NULL,
salsa20r12_encrypt_stream,
salsa20r12_encrypt_stream,
NULL,
NULL,
salsa20_setiv
};
diff --git a/cipher/scrypt.c b/cipher/scrypt.c
index 13fd1cf0..c38c85a2 100644
--- a/cipher/scrypt.c
+++ b/cipher/scrypt.c
@@ -1,322 +1,322 @@
/* scrypt.c - Scrypt password-based key derivation function.
* Copyright (C) 2012 Simon Josefsson
* Copyright (C) 2013 Christian Grothoff
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Adapted from the nettle, low-level cryptographics library for
* libgcrypt by Christian Grothoff; original license:
*
* Copyright (C) 2012 Simon Josefsson
*
* The nettle 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 nettle 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 nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02111-1301, USA.
*/
#include <config.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "kdf-internal.h"
#include "bufhelp.h"
/* We really need a 64 bit type for this code. */
#define SALSA20_INPUT_LENGTH 16
#define ROTL32(n,x) (((x)<<(n)) | ((x)>>(32-(n))))
/* Reads a 64-bit integer, in network, big-endian, byte order */
#define READ_UINT64(p) buf_get_be64(p)
/* And the other, little-endian, byteorder */
#define LE_READ_UINT64(p) buf_get_le64(p)
#define LE_SWAP32(v) le_bswap32(v)
#define QROUND(x0, x1, x2, x3) do { \
x1 ^= ROTL32(7, x0 + x3); \
x2 ^= ROTL32(9, x1 + x0); \
x3 ^= ROTL32(13, x2 + x1); \
x0 ^= ROTL32(18, x3 + x2); \
} while(0)
static void
salsa20_core (u32 *dst, const u32 *src, unsigned int rounds)
{
u32 x[SALSA20_INPUT_LENGTH];
unsigned i;
assert ( (rounds & 1) == 0);
for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
x[i] = LE_SWAP32(src[i]);
for (i = 0; i < rounds;i += 2)
{
QROUND(x[0], x[4], x[8], x[12]);
QROUND(x[5], x[9], x[13], x[1]);
QROUND(x[10], x[14], x[2], x[6]);
QROUND(x[15], x[3], x[7], x[11]);
QROUND(x[0], x[1], x[2], x[3]);
QROUND(x[5], x[6], x[7], x[4]);
QROUND(x[10], x[11], x[8], x[9]);
QROUND(x[15], x[12], x[13], x[14]);
}
for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
{
u32 t = x[i] + LE_SWAP32(src[i]);
dst[i] = LE_SWAP32(t);
}
}
static void
scrypt_block_mix (u32 r, unsigned char *B, unsigned char *tmp2)
{
u64 i;
unsigned char *X = tmp2;
unsigned char *Y = tmp2 + 64;
#if 0
if (r == 1)
{
for (i = 0; i < 2 * r; i++)
{
size_t j;
printf ("B[%d] = ", (int)i);
for (j = 0; j < 64; j++)
{
if (j && !(j % 16))
printf ("\n ");
printf (" %02x", B[i * 64 + j]);
}
putchar ('\n');
}
}
#endif
/* X = B[2 * r - 1] */
memcpy (X, &B[(2 * r - 1) * 64], 64);
/* for i = 0 to 2 * r - 1 do */
for (i = 0; i <= 2 * r - 1; i++)
{
/* T = X xor B[i] */
buf_xor(X, X, &B[i * 64], 64);
/* X = Salsa (T) */
salsa20_core ((u32*)(void*)X, (u32*)(void*)X, 8);
/* Y[i] = X */
memcpy (&Y[i * 64], X, 64);
}
for (i = 0; i < r; i++)
{
memcpy (&B[i * 64], &Y[2 * i * 64], 64);
memcpy (&B[(r + i) * 64], &Y[(2 * i + 1) * 64], 64);
}
#if 0
if (r==1)
{
for (i = 0; i < 2 * r; i++)
{
size_t j;
printf ("B'[%d] =", (int)i);
for (j = 0; j < 64; j++)
{
if (j && !(j % 16))
printf ("\n ");
printf (" %02x", B[i * 64 + j]);
}
putchar ('\n');
}
}
#endif
}
static void
scrypt_ro_mix (u32 r, unsigned char *B, u64 N,
unsigned char *tmp1, unsigned char *tmp2)
{
unsigned char *X = B, *T = B;
u64 i;
#if 0
if (r == 1)
{
printf ("B = ");
for (i = 0; i < 128 * r; i++)
{
if (i && !(i % 16))
printf ("\n ");
printf (" %02x", B[i]);
}
putchar ('\n');
}
#endif
/* for i = 0 to N - 1 do */
for (i = 0; i <= N - 1; i++)
{
/* V[i] = X */
memcpy (&tmp1[i * 128 * r], X, 128 * r);
/* X = ScryptBlockMix (X) */
scrypt_block_mix (r, X, tmp2);
}
/* for i = 0 to N - 1 do */
for (i = 0; i <= N - 1; i++)
{
u64 j;
/* j = Integerify (X) mod N */
j = LE_READ_UINT64 (&X[128 * r - 64]) % N;
/* T = X xor V[j] */
buf_xor (T, T, &tmp1[j * 128 * r], 128 * r);
/* X = scryptBlockMix (T) */
scrypt_block_mix (r, T, tmp2);
}
#if 0
if (r == 1)
{
printf ("B' =");
for (i = 0; i < 128 * r; i++)
{
if (i && !(i % 16))
printf ("\n ");
printf (" %02x", B[i]);
}
putchar ('\n');
}
#endif
}
/*
*
*/
gcry_err_code_t
_gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
int algo, int subalgo,
const unsigned char *salt, size_t saltlen,
unsigned long iterations,
size_t dkLen, unsigned char *DK)
{
u64 N = subalgo; /* CPU/memory cost parameter. */
u32 r; /* Block size. */
u32 p = iterations; /* Parallelization parameter. */
gpg_err_code_t ec;
u32 i;
unsigned char *B = NULL;
unsigned char *tmp1 = NULL;
unsigned char *tmp2 = NULL;
size_t r128;
size_t nbytes;
if (subalgo < 1 || !iterations)
return GPG_ERR_INV_VALUE;
if (algo == GCRY_KDF_SCRYPT)
r = 8;
else if (algo == 41) /* Hack to allow the use of all test vectors. */
r = 1;
else
return GPG_ERR_UNKNOWN_ALGORITHM;
r128 = r * 128;
if (r128 / 128 != r)
return GPG_ERR_ENOMEM;
nbytes = p * r128;
if (r128 && nbytes / r128 != p)
return GPG_ERR_ENOMEM;
nbytes = N * r128;
if (r128 && nbytes / r128 != N)
return GPG_ERR_ENOMEM;
nbytes = 64 + r128;
if (nbytes < r128)
return GPG_ERR_ENOMEM;
B = xtrymalloc (p * r128);
if (!B)
{
ec = gpg_err_code_from_syserror ();
goto leave;
}
tmp1 = xtrymalloc (N * r128);
if (!tmp1)
{
ec = gpg_err_code_from_syserror ();
goto leave;
}
tmp2 = xtrymalloc (64 + r128);
if (!tmp2)
{
ec = gpg_err_code_from_syserror ();
goto leave;
}
ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, salt, saltlen,
1 /* iterations */, p * r128, B);
for (i = 0; !ec && i < p; i++)
scrypt_ro_mix (r, &B[i * r128], N, tmp1, tmp2);
for (i = 0; !ec && i < p; i++)
ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128,
1 /* iterations */, dkLen, DK);
leave:
xfree (tmp2);
xfree (tmp1);
xfree (B);
return ec;
}
diff --git a/cipher/serpent-armv7-neon.S b/cipher/serpent-armv7-neon.S
index adff6394..d308d542 100644
--- a/cipher/serpent-armv7-neon.S
+++ b/cipher/serpent-armv7-neon.S
@@ -1,1124 +1,1124 @@
/* serpent-armv7-neon.S - ARM/NEON assembly implementation of Serpent cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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)
.text
.syntax unified
.fpu neon
.arm
/* ARM registers */
#define RROUND r0
/* NEON vector registers */
#define RA0 q0
#define RA1 q1
#define RA2 q2
#define RA3 q3
#define RA4 q4
#define RB0 q5
#define RB1 q6
#define RB2 q7
#define RB3 q8
#define RB4 q9
#define RT0 q10
#define RT1 q11
#define RT2 q12
#define RT3 q13
#define RA0d0 d0
#define RA0d1 d1
#define RA1d0 d2
#define RA1d1 d3
#define RA2d0 d4
#define RA2d1 d5
#define RA3d0 d6
#define RA3d1 d7
#define RA4d0 d8
#define RA4d1 d9
#define RB0d0 d10
#define RB0d1 d11
#define RB1d0 d12
#define RB1d1 d13
#define RB2d0 d14
#define RB2d1 d15
#define RB3d0 d16
#define RB3d1 d17
#define RB4d0 d18
#define RB4d1 d19
#define RT0d0 d20
#define RT0d1 d21
#define RT1d0 d22
#define RT1d1 d23
#define RT2d0 d24
#define RT2d1 d25
/**********************************************************************
helper macros
**********************************************************************/
#define transpose_4x4(_q0, _q1, _q2, _q3) \
vtrn.32 _q0, _q1; \
vtrn.32 _q2, _q3; \
vswp _q0##d1, _q2##d0; \
vswp _q1##d1, _q3##d0;
/**********************************************************************
8-way serpent
**********************************************************************/
/*
* These are the S-Boxes of Serpent from following research paper.
*
* D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
* (New York, New York, USA), p. 317–329, National Institute of Standards and
* Technology, 2000.
*
- * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
+ * Paper is also available at: https://www.ii.uib.no/~osvik/pub/aes3.pdf
*
*/
#define SBOX0(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
veor a3, a3, a0; veor b3, b3, b0; vmov a4, a1; vmov b4, b1; \
vand a1, a1, a3; vand b1, b1, b3; veor a4, a4, a2; veor b4, b4, b2; \
veor a1, a1, a0; veor b1, b1, b0; vorr a0, a0, a3; vorr b0, b0, b3; \
veor a0, a0, a4; veor b0, b0, b4; veor a4, a4, a3; veor b4, b4, b3; \
veor a3, a3, a2; veor b3, b3, b2; vorr a2, a2, a1; vorr b2, b2, b1; \
veor a2, a2, a4; veor b2, b2, b4; vmvn a4, a4; vmvn b4, b4; \
vorr a4, a4, a1; vorr b4, b4, b1; veor a1, a1, a3; veor b1, b1, b3; \
veor a1, a1, a4; veor b1, b1, b4; vorr a3, a3, a0; vorr b3, b3, b0; \
veor a1, a1, a3; veor b1, b1, b3; veor a4, a3; veor b4, b3;
#define SBOX0_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmvn a2, a2; vmvn b2, b2; vmov a4, a1; vmov b4, b1; \
vorr a1, a1, a0; vorr b1, b1, b0; vmvn a4, a4; vmvn b4, b4; \
veor a1, a1, a2; veor b1, b1, b2; vorr a2, a2, a4; vorr b2, b2, b4; \
veor a1, a1, a3; veor b1, b1, b3; veor a0, a0, a4; veor b0, b0, b4; \
veor a2, a2, a0; veor b2, b2, b0; vand a0, a0, a3; vand b0, b0, b3; \
veor a4, a4, a0; veor b4, b4, b0; vorr a0, a0, a1; vorr b0, b0, b1; \
veor a0, a0, a2; veor b0, b0, b2; veor a3, a3, a4; veor b3, b3, b4; \
veor a2, a2, a1; veor b2, b2, b1; veor a3, a3, a0; veor b3, b3, b0; \
veor a3, a3, a1; veor b3, b3, b1;\
vand a2, a2, a3; vand b2, b2, b3;\
veor a4, a2; veor b4, b2;
#define SBOX1(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmvn a0, a0; vmvn b0, b0; vmvn a2, a2; vmvn b2, b2; \
vmov a4, a0; vmov b4, b0; vand a0, a0, a1; vand b0, b0, b1; \
veor a2, a2, a0; veor b2, b2, b0; vorr a0, a0, a3; vorr b0, b0, b3; \
veor a3, a3, a2; veor b3, b3, b2; veor a1, a1, a0; veor b1, b1, b0; \
veor a0, a0, a4; veor b0, b0, b4; vorr a4, a4, a1; vorr b4, b4, b1; \
veor a1, a1, a3; veor b1, b1, b3; vorr a2, a2, a0; vorr b2, b2, b0; \
vand a2, a2, a4; vand b2, b2, b4; veor a0, a0, a1; veor b0, b0, b1; \
vand a1, a1, a2; vand b1, b1, b2;\
veor a1, a1, a0; veor b1, b1, b0; vand a0, a0, a2; vand b0, b0, b2; \
veor a0, a4; veor b0, b4;
#define SBOX1_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a1; vmov b4, b1; veor a1, a1, a3; veor b1, b1, b3; \
vand a3, a3, a1; vand b3, b3, b1; veor a4, a4, a2; veor b4, b4, b2; \
veor a3, a3, a0; veor b3, b3, b0; vorr a0, a0, a1; vorr b0, b0, b1; \
veor a2, a2, a3; veor b2, b2, b3; veor a0, a0, a4; veor b0, b0, b4; \
vorr a0, a0, a2; vorr b0, b0, b2; veor a1, a1, a3; veor b1, b1, b3; \
veor a0, a0, a1; veor b0, b0, b1; vorr a1, a1, a3; vorr b1, b1, b3; \
veor a1, a1, a0; veor b1, b1, b0; vmvn a4, a4; vmvn b4, b4; \
veor a4, a4, a1; veor b4, b4, b1; vorr a1, a1, a0; vorr b1, b1, b0; \
veor a1, a1, a0; veor b1, b1, b0;\
vorr a1, a1, a4; vorr b1, b1, b4;\
veor a3, a1; veor b3, b1;
#define SBOX2(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a0; vmov b4, b0; vand a0, a0, a2; vand b0, b0, b2; \
veor a0, a0, a3; veor b0, b0, b3; veor a2, a2, a1; veor b2, b2, b1; \
veor a2, a2, a0; veor b2, b2, b0; vorr a3, a3, a4; vorr b3, b3, b4; \
veor a3, a3, a1; veor b3, b3, b1; veor a4, a4, a2; veor b4, b4, b2; \
vmov a1, a3; vmov b1, b3; vorr a3, a3, a4; vorr b3, b3, b4; \
veor a3, a3, a0; veor b3, b3, b0; vand a0, a0, a1; vand b0, b0, b1; \
veor a4, a4, a0; veor b4, b4, b0; veor a1, a1, a3; veor b1, b1, b3; \
veor a1, a1, a4; veor b1, b1, b4; vmvn a4, a4; vmvn b4, b4;
#define SBOX2_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
veor a2, a2, a3; veor b2, b2, b3; veor a3, a3, a0; veor b3, b3, b0; \
vmov a4, a3; vmov b4, b3; vand a3, a3, a2; vand b3, b3, b2; \
veor a3, a3, a1; veor b3, b3, b1; vorr a1, a1, a2; vorr b1, b1, b2; \
veor a1, a1, a4; veor b1, b1, b4; vand a4, a4, a3; vand b4, b4, b3; \
veor a2, a2, a3; veor b2, b2, b3; vand a4, a4, a0; vand b4, b4, b0; \
veor a4, a4, a2; veor b4, b4, b2; vand a2, a2, a1; vand b2, b2, b1; \
vorr a2, a2, a0; vorr b2, b2, b0; vmvn a3, a3; vmvn b3, b3; \
veor a2, a2, a3; veor b2, b2, b3; veor a0, a0, a3; veor b0, b0, b3; \
vand a0, a0, a1; vand b0, b0, b1; veor a3, a3, a4; veor b3, b3, b4; \
veor a3, a0; veor b3, b0;
#define SBOX3(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a0; vmov b4, b0; vorr a0, a0, a3; vorr b0, b0, b3; \
veor a3, a3, a1; veor b3, b3, b1; vand a1, a1, a4; vand b1, b1, b4; \
veor a4, a4, a2; veor b4, b4, b2; veor a2, a2, a3; veor b2, b2, b3; \
vand a3, a3, a0; vand b3, b3, b0; vorr a4, a4, a1; vorr b4, b4, b1; \
veor a3, a3, a4; veor b3, b3, b4; veor a0, a0, a1; veor b0, b0, b1; \
vand a4, a4, a0; vand b4, b4, b0; veor a1, a1, a3; veor b1, b1, b3; \
veor a4, a4, a2; veor b4, b4, b2; vorr a1, a1, a0; vorr b1, b1, b0; \
veor a1, a1, a2; veor b1, b1, b2; veor a0, a0, a3; veor b0, b0, b3; \
vmov a2, a1; vmov b2, b1; vorr a1, a1, a3; vorr b1, b1, b3; \
veor a1, a0; veor b1, b0;
#define SBOX3_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a2; vmov b4, b2; veor a2, a2, a1; veor b2, b2, b1; \
veor a0, a0, a2; veor b0, b0, b2; vand a4, a4, a2; vand b4, b4, b2; \
veor a4, a4, a0; veor b4, b4, b0; vand a0, a0, a1; vand b0, b0, b1; \
veor a1, a1, a3; veor b1, b1, b3; vorr a3, a3, a4; vorr b3, b3, b4; \
veor a2, a2, a3; veor b2, b2, b3; veor a0, a0, a3; veor b0, b0, b3; \
veor a1, a1, a4; veor b1, b1, b4; vand a3, a3, a2; vand b3, b3, b2; \
veor a3, a3, a1; veor b3, b3, b1; veor a1, a1, a0; veor b1, b1, b0; \
vorr a1, a1, a2; vorr b1, b1, b2; veor a0, a0, a3; veor b0, b0, b3; \
veor a1, a1, a4; veor b1, b1, b4;\
veor a0, a1; veor b0, b1;
#define SBOX4(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
veor a1, a1, a3; veor b1, b1, b3; vmvn a3, a3; vmvn b3, b3; \
veor a2, a2, a3; veor b2, b2, b3; veor a3, a3, a0; veor b3, b3, b0; \
vmov a4, a1; vmov b4, b1; vand a1, a1, a3; vand b1, b1, b3; \
veor a1, a1, a2; veor b1, b1, b2; veor a4, a4, a3; veor b4, b4, b3; \
veor a0, a0, a4; veor b0, b0, b4; vand a2, a2, a4; vand b2, b2, b4; \
veor a2, a2, a0; veor b2, b2, b0; vand a0, a0, a1; vand b0, b0, b1; \
veor a3, a3, a0; veor b3, b3, b0; vorr a4, a4, a1; vorr b4, b4, b1; \
veor a4, a4, a0; veor b4, b4, b0; vorr a0, a0, a3; vorr b0, b0, b3; \
veor a0, a0, a2; veor b0, b0, b2; vand a2, a2, a3; vand b2, b2, b3; \
vmvn a0, a0; vmvn b0, b0; veor a4, a2; veor b4, b2;
#define SBOX4_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a2; vmov b4, b2; vand a2, a2, a3; vand b2, b2, b3; \
veor a2, a2, a1; veor b2, b2, b1; vorr a1, a1, a3; vorr b1, b1, b3; \
vand a1, a1, a0; vand b1, b1, b0; veor a4, a4, a2; veor b4, b4, b2; \
veor a4, a4, a1; veor b4, b4, b1; vand a1, a1, a2; vand b1, b1, b2; \
vmvn a0, a0; vmvn b0, b0; veor a3, a3, a4; veor b3, b3, b4; \
veor a1, a1, a3; veor b1, b1, b3; vand a3, a3, a0; vand b3, b3, b0; \
veor a3, a3, a2; veor b3, b3, b2; veor a0, a0, a1; veor b0, b0, b1; \
vand a2, a2, a0; vand b2, b2, b0; veor a3, a3, a0; veor b3, b3, b0; \
veor a2, a2, a4; veor b2, b2, b4;\
vorr a2, a2, a3; vorr b2, b2, b3; veor a3, a3, a0; veor b3, b3, b0; \
veor a2, a1; veor b2, b1;
#define SBOX5(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
veor a0, a0, a1; veor b0, b0, b1; veor a1, a1, a3; veor b1, b1, b3; \
vmvn a3, a3; vmvn b3, b3; vmov a4, a1; vmov b4, b1; \
vand a1, a1, a0; vand b1, b1, b0; veor a2, a2, a3; veor b2, b2, b3; \
veor a1, a1, a2; veor b1, b1, b2; vorr a2, a2, a4; vorr b2, b2, b4; \
veor a4, a4, a3; veor b4, b4, b3; vand a3, a3, a1; vand b3, b3, b1; \
veor a3, a3, a0; veor b3, b3, b0; veor a4, a4, a1; veor b4, b4, b1; \
veor a4, a4, a2; veor b4, b4, b2; veor a2, a2, a0; veor b2, b2, b0; \
vand a0, a0, a3; vand b0, b0, b3; vmvn a2, a2; vmvn b2, b2; \
veor a0, a0, a4; veor b0, b0, b4; vorr a4, a4, a3; vorr b4, b4, b3; \
veor a2, a4; veor b2, b4;
#define SBOX5_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmvn a1, a1; vmvn b1, b1; vmov a4, a3; vmov b4, b3; \
veor a2, a2, a1; veor b2, b2, b1; vorr a3, a3, a0; vorr b3, b3, b0; \
veor a3, a3, a2; veor b3, b3, b2; vorr a2, a2, a1; vorr b2, b2, b1; \
vand a2, a2, a0; vand b2, b2, b0; veor a4, a4, a3; veor b4, b4, b3; \
veor a2, a2, a4; veor b2, b2, b4; vorr a4, a4, a0; vorr b4, b4, b0; \
veor a4, a4, a1; veor b4, b4, b1; vand a1, a1, a2; vand b1, b1, b2; \
veor a1, a1, a3; veor b1, b1, b3; veor a4, a4, a2; veor b4, b4, b2; \
vand a3, a3, a4; vand b3, b3, b4; veor a4, a4, a1; veor b4, b4, b1; \
veor a3, a3, a4; veor b3, b3, b4; vmvn a4, a4; vmvn b4, b4; \
veor a3, a0; veor b3, b0;
#define SBOX6(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmvn a2, a2; vmvn b2, b2; vmov a4, a3; vmov b4, b3; \
vand a3, a3, a0; vand b3, b3, b0; veor a0, a0, a4; veor b0, b0, b4; \
veor a3, a3, a2; veor b3, b3, b2; vorr a2, a2, a4; vorr b2, b2, b4; \
veor a1, a1, a3; veor b1, b1, b3; veor a2, a2, a0; veor b2, b2, b0; \
vorr a0, a0, a1; vorr b0, b0, b1; veor a2, a2, a1; veor b2, b2, b1; \
veor a4, a4, a0; veor b4, b4, b0; vorr a0, a0, a3; vorr b0, b0, b3; \
veor a0, a0, a2; veor b0, b0, b2; veor a4, a4, a3; veor b4, b4, b3; \
veor a4, a4, a0; veor b4, b4, b0; vmvn a3, a3; vmvn b3, b3; \
vand a2, a2, a4; vand b2, b2, b4;\
veor a2, a3; veor b2, b3;
#define SBOX6_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
veor a0, a0, a2; veor b0, b0, b2; vmov a4, a2; vmov b4, b2; \
vand a2, a2, a0; vand b2, b2, b0; veor a4, a4, a3; veor b4, b4, b3; \
vmvn a2, a2; vmvn b2, b2; veor a3, a3, a1; veor b3, b3, b1; \
veor a2, a2, a3; veor b2, b2, b3; vorr a4, a4, a0; vorr b4, b4, b0; \
veor a0, a0, a2; veor b0, b0, b2; veor a3, a3, a4; veor b3, b3, b4; \
veor a4, a4, a1; veor b4, b4, b1; vand a1, a1, a3; vand b1, b1, b3; \
veor a1, a1, a0; veor b1, b1, b0; veor a0, a0, a3; veor b0, b0, b3; \
vorr a0, a0, a2; vorr b0, b0, b2; veor a3, a3, a1; veor b3, b3, b1; \
veor a4, a0; veor b4, b0;
#define SBOX7(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a1; vmov b4, b1; vorr a1, a1, a2; vorr b1, b1, b2; \
veor a1, a1, a3; veor b1, b1, b3; veor a4, a4, a2; veor b4, b4, b2; \
veor a2, a2, a1; veor b2, b2, b1; vorr a3, a3, a4; vorr b3, b3, b4; \
vand a3, a3, a0; vand b3, b3, b0; veor a4, a4, a2; veor b4, b4, b2; \
veor a3, a3, a1; veor b3, b3, b1; vorr a1, a1, a4; vorr b1, b1, b4; \
veor a1, a1, a0; veor b1, b1, b0; vorr a0, a0, a4; vorr b0, b0, b4; \
veor a0, a0, a2; veor b0, b0, b2; veor a1, a1, a4; veor b1, b1, b4; \
veor a2, a2, a1; veor b2, b2, b1; vand a1, a1, a0; vand b1, b1, b0; \
veor a1, a1, a4; veor b1, b1, b4; vmvn a2, a2; vmvn b2, b2; \
vorr a2, a2, a0; vorr b2, b2, b0;\
veor a4, a2; veor b4, b2;
#define SBOX7_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vmov a4, a2; vmov b4, b2; veor a2, a2, a0; veor b2, b2, b0; \
vand a0, a0, a3; vand b0, b0, b3; vorr a4, a4, a3; vorr b4, b4, b3; \
vmvn a2, a2; vmvn b2, b2; veor a3, a3, a1; veor b3, b3, b1; \
vorr a1, a1, a0; vorr b1, b1, b0; veor a0, a0, a2; veor b0, b0, b2; \
vand a2, a2, a4; vand b2, b2, b4; vand a3, a3, a4; vand b3, b3, b4; \
veor a1, a1, a2; veor b1, b1, b2; veor a2, a2, a0; veor b2, b2, b0; \
vorr a0, a0, a2; vorr b0, b0, b2; veor a4, a4, a1; veor b4, b4, b1; \
veor a0, a0, a3; veor b0, b0, b3; veor a3, a3, a4; veor b3, b3, b4; \
vorr a4, a4, a0; vorr b4, b4, b0; veor a3, a3, a2; veor b3, b3, b2; \
veor a4, a2; veor b4, b2;
/* Apply SBOX number WHICH to to the block. */
#define SBOX(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
SBOX##which (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4)
/* Apply inverse SBOX number WHICH to to the block. */
#define SBOX_INVERSE(which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
SBOX##which##_INVERSE (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4)
/* XOR round key into block state in a0,a1,a2,a3. a4 used as temporary. */
#define BLOCK_XOR_KEY(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vdup.32 RT3, RT0d0[0]; \
vdup.32 RT1, RT0d0[1]; \
vdup.32 RT2, RT0d1[0]; \
vdup.32 RT0, RT0d1[1]; \
veor a0, a0, RT3; veor b0, b0, RT3; \
veor a1, a1, RT1; veor b1, b1, RT1; \
veor a2, a2, RT2; veor b2, b2, RT2; \
veor a3, a3, RT0; veor b3, b3, RT0;
#define BLOCK_LOAD_KEY_ENC() \
vld1.8 {RT0d0, RT0d1}, [RROUND]!;
#define BLOCK_LOAD_KEY_DEC() \
vld1.8 {RT0d0, RT0d1}, [RROUND]; \
sub RROUND, RROUND, #16
/* Apply the linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vshl.u32 a4, a0, #13; vshl.u32 b4, b0, #13; \
vshr.u32 a0, a0, #(32-13); vshr.u32 b0, b0, #(32-13); \
veor a0, a0, a4; veor b0, b0, b4; \
vshl.u32 a4, a2, #3; vshl.u32 b4, b2, #3; \
vshr.u32 a2, a2, #(32-3); vshr.u32 b2, b2, #(32-3); \
veor a2, a2, a4; veor b2, b2, b4; \
veor a1, a0, a1; veor b1, b0, b1; \
veor a1, a2, a1; veor b1, b2, b1; \
vshl.u32 a4, a0, #3; vshl.u32 b4, b0, #3; \
veor a3, a2, a3; veor b3, b2, b3; \
veor a3, a4, a3; veor b3, b4, b3; \
vshl.u32 a4, a1, #1; vshl.u32 b4, b1, #1; \
vshr.u32 a1, a1, #(32-1); vshr.u32 b1, b1, #(32-1); \
veor a1, a1, a4; veor b1, b1, b4; \
vshl.u32 a4, a3, #7; vshl.u32 b4, b3, #7; \
vshr.u32 a3, a3, #(32-7); vshr.u32 b3, b3, #(32-7); \
veor a3, a3, a4; veor b3, b3, b4; \
veor a0, a1, a0; veor b0, b1, b0; \
veor a0, a3, a0; veor b0, b3, b0; \
vshl.u32 a4, a1, #7; vshl.u32 b4, b1, #7; \
veor a2, a3, a2; veor b2, b3, b2; \
veor a2, a4, a2; veor b2, b4, b2; \
vshl.u32 a4, a0, #5; vshl.u32 b4, b0, #5; \
vshr.u32 a0, a0, #(32-5); vshr.u32 b0, b0, #(32-5); \
veor a0, a0, a4; veor b0, b0, b4; \
vshl.u32 a4, a2, #22; vshl.u32 b4, b2, #22; \
vshr.u32 a2, a2, #(32-22); vshr.u32 b2, b2, #(32-22); \
veor a2, a2, a4; veor b2, b2, b4;
/* Apply the inverse linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION_INVERSE(a0, a1, a2, a3, a4, b0, b1, b2, b3, b4) \
vshr.u32 a4, a2, #22; vshr.u32 b4, b2, #22; \
vshl.u32 a2, a2, #(32-22); vshl.u32 b2, b2, #(32-22); \
veor a2, a2, a4; veor b2, b2, b4; \
vshr.u32 a4, a0, #5; vshr.u32 b4, b0, #5; \
vshl.u32 a0, a0, #(32-5); vshl.u32 b0, b0, #(32-5); \
veor a0, a0, a4; veor b0, b0, b4; \
vshl.u32 a4, a1, #7; vshl.u32 b4, b1, #7; \
veor a2, a3, a2; veor b2, b3, b2; \
veor a2, a4, a2; veor b2, b4, b2; \
veor a0, a1, a0; veor b0, b1, b0; \
veor a0, a3, a0; veor b0, b3, b0; \
vshr.u32 a4, a3, #7; vshr.u32 b4, b3, #7; \
vshl.u32 a3, a3, #(32-7); vshl.u32 b3, b3, #(32-7); \
veor a3, a3, a4; veor b3, b3, b4; \
vshr.u32 a4, a1, #1; vshr.u32 b4, b1, #1; \
vshl.u32 a1, a1, #(32-1); vshl.u32 b1, b1, #(32-1); \
veor a1, a1, a4; veor b1, b1, b4; \
vshl.u32 a4, a0, #3; vshl.u32 b4, b0, #3; \
veor a3, a2, a3; veor b3, b2, b3; \
veor a3, a4, a3; veor b3, b4, b3; \
veor a1, a0, a1; veor b1, b0, b1; \
veor a1, a2, a1; veor b1, b2, b1; \
vshr.u32 a4, a2, #3; vshr.u32 b4, b2, #3; \
vshl.u32 a2, a2, #(32-3); vshl.u32 b2, b2, #(32-3); \
veor a2, a2, a4; veor b2, b2, b4; \
vshr.u32 a4, a0, #13; vshr.u32 b4, b0, #13; \
vshl.u32 a0, a0, #(32-13); vshl.u32 b0, b0, #(32-13); \
veor a0, a0, a4; veor b0, b0, b4;
/* Apply a Serpent round to eight parallel blocks. This macro increments
`round'. */
#define ROUND(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_LOAD_KEY_ENC (); \
SBOX (which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
LINEAR_TRANSFORMATION (na0, na1, na2, na3, na4, nb0, nb1, nb2, nb3, nb4);
/* Apply the last Serpent round to eight parallel blocks. This macro increments
`round'. */
#define ROUND_LAST(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_LOAD_KEY_ENC (); \
SBOX (which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, nb0, nb1, nb2, nb3, nb4);
/* Apply an inverse Serpent round to eight parallel blocks. This macro
increments `round'. */
#define ROUND_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
LINEAR_TRANSFORMATION_INVERSE (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, nb0, nb1, nb2, nb3, nb4); \
BLOCK_LOAD_KEY_DEC ();
/* Apply the first inverse Serpent round to eight parallel blocks. This macro
increments `round'. */
#define ROUND_FIRST_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_LOAD_KEY_DEC (); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, nb0, nb1, nb2, nb3, nb4); \
BLOCK_LOAD_KEY_DEC ();
.align 3
.type __serpent_enc_blk8,%function;
__serpent_enc_blk8:
/* input:
* r0: round key pointer
* RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: eight parallel plaintext
* blocks
* output:
* RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: eight parallel
* ciphertext blocks
*/
transpose_4x4(RA0, RA1, RA2, RA3);
BLOCK_LOAD_KEY_ENC ();
transpose_4x4(RB0, RB1, RB2, RB3);
ROUND (0, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (1, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (2, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (3, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (4, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (5, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (6, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND (7, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
ROUND (8, 0, RA4, RA1, RA2, RA0, RA3, RA1, RA3, RA2, RA4, RA0,
RB4, RB1, RB2, RB0, RB3, RB1, RB3, RB2, RB4, RB0);
ROUND (9, 1, RA1, RA3, RA2, RA4, RA0, RA2, RA1, RA4, RA3, RA0,
RB1, RB3, RB2, RB4, RB0, RB2, RB1, RB4, RB3, RB0);
ROUND (10, 2, RA2, RA1, RA4, RA3, RA0, RA4, RA3, RA1, RA0, RA2,
RB2, RB1, RB4, RB3, RB0, RB4, RB3, RB1, RB0, RB2);
ROUND (11, 3, RA4, RA3, RA1, RA0, RA2, RA3, RA1, RA0, RA2, RA4,
RB4, RB3, RB1, RB0, RB2, RB3, RB1, RB0, RB2, RB4);
ROUND (12, 4, RA3, RA1, RA0, RA2, RA4, RA1, RA4, RA3, RA2, RA0,
RB3, RB1, RB0, RB2, RB4, RB1, RB4, RB3, RB2, RB0);
ROUND (13, 5, RA1, RA4, RA3, RA2, RA0, RA4, RA2, RA1, RA3, RA0,
RB1, RB4, RB3, RB2, RB0, RB4, RB2, RB1, RB3, RB0);
ROUND (14, 6, RA4, RA2, RA1, RA3, RA0, RA4, RA2, RA0, RA1, RA3,
RB4, RB2, RB1, RB3, RB0, RB4, RB2, RB0, RB1, RB3);
ROUND (15, 7, RA4, RA2, RA0, RA1, RA3, RA3, RA1, RA2, RA4, RA0,
RB4, RB2, RB0, RB1, RB3, RB3, RB1, RB2, RB4, RB0);
ROUND (16, 0, RA3, RA1, RA2, RA4, RA0, RA1, RA0, RA2, RA3, RA4,
RB3, RB1, RB2, RB4, RB0, RB1, RB0, RB2, RB3, RB4);
ROUND (17, 1, RA1, RA0, RA2, RA3, RA4, RA2, RA1, RA3, RA0, RA4,
RB1, RB0, RB2, RB3, RB4, RB2, RB1, RB3, RB0, RB4);
ROUND (18, 2, RA2, RA1, RA3, RA0, RA4, RA3, RA0, RA1, RA4, RA2,
RB2, RB1, RB3, RB0, RB4, RB3, RB0, RB1, RB4, RB2);
ROUND (19, 3, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA4, RA2, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB4, RB2, RB3);
ROUND (20, 4, RA0, RA1, RA4, RA2, RA3, RA1, RA3, RA0, RA2, RA4,
RB0, RB1, RB4, RB2, RB3, RB1, RB3, RB0, RB2, RB4);
ROUND (21, 5, RA1, RA3, RA0, RA2, RA4, RA3, RA2, RA1, RA0, RA4,
RB1, RB3, RB0, RB2, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND (22, 6, RA3, RA2, RA1, RA0, RA4, RA3, RA2, RA4, RA1, RA0,
RB3, RB2, RB1, RB0, RB4, RB3, RB2, RB4, RB1, RB0);
ROUND (23, 7, RA3, RA2, RA4, RA1, RA0, RA0, RA1, RA2, RA3, RA4,
RB3, RB2, RB4, RB1, RB0, RB0, RB1, RB2, RB3, RB4);
ROUND (24, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (25, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (26, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (27, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (28, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (29, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (30, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND_LAST (31, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
transpose_4x4(RA4, RA1, RA2, RA0);
transpose_4x4(RB4, RB1, RB2, RB0);
bx lr;
.size __serpent_enc_blk8,.-__serpent_enc_blk8;
.align 3
.type __serpent_dec_blk8,%function;
__serpent_dec_blk8:
/* input:
* r0: round key pointer
* 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
*/
add RROUND, RROUND, #(32*16);
transpose_4x4(RA0, RA1, RA2, RA3);
BLOCK_LOAD_KEY_DEC ();
transpose_4x4(RB0, RB1, RB2, RB3);
ROUND_FIRST_INVERSE (31, 7, RA0, RA1, RA2, RA3, RA4,
RA3, RA0, RA1, RA4, RA2,
RB0, RB1, RB2, RB3, RB4,
RB3, RB0, RB1, RB4, RB2);
ROUND_INVERSE (30, 6, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA2, RA4, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB2, RB4, RB3);
ROUND_INVERSE (29, 5, RA0, RA1, RA2, RA4, RA3, RA1, RA3, RA4, RA2, RA0,
RB0, RB1, RB2, RB4, RB3, RB1, RB3, RB4, RB2, RB0);
ROUND_INVERSE (28, 4, RA1, RA3, RA4, RA2, RA0, RA1, RA2, RA4, RA0, RA3,
RB1, RB3, RB4, RB2, RB0, RB1, RB2, RB4, RB0, RB3);
ROUND_INVERSE (27, 3, RA1, RA2, RA4, RA0, RA3, RA4, RA2, RA0, RA1, RA3,
RB1, RB2, RB4, RB0, RB3, RB4, RB2, RB0, RB1, RB3);
ROUND_INVERSE (26, 2, RA4, RA2, RA0, RA1, RA3, RA2, RA3, RA0, RA1, RA4,
RB4, RB2, RB0, RB1, RB3, RB2, RB3, RB0, RB1, RB4);
ROUND_INVERSE (25, 1, RA2, RA3, RA0, RA1, RA4, RA4, RA2, RA1, RA0, RA3,
RB2, RB3, RB0, RB1, RB4, RB4, RB2, RB1, RB0, RB3);
ROUND_INVERSE (24, 0, RA4, RA2, RA1, RA0, RA3, RA4, RA3, RA2, RA0, RA1,
RB4, RB2, RB1, RB0, RB3, RB4, RB3, RB2, RB0, RB1);
ROUND_INVERSE (23, 7, RA4, RA3, RA2, RA0, RA1, RA0, RA4, RA3, RA1, RA2,
RB4, RB3, RB2, RB0, RB1, RB0, RB4, RB3, RB1, RB2);
ROUND_INVERSE (22, 6, RA0, RA4, RA3, RA1, RA2, RA4, RA3, RA2, RA1, RA0,
RB0, RB4, RB3, RB1, RB2, RB4, RB3, RB2, RB1, RB0);
ROUND_INVERSE (21, 5, RA4, RA3, RA2, RA1, RA0, RA3, RA0, RA1, RA2, RA4,
RB4, RB3, RB2, RB1, RB0, RB3, RB0, RB1, RB2, RB4);
ROUND_INVERSE (20, 4, RA3, RA0, RA1, RA2, RA4, RA3, RA2, RA1, RA4, RA0,
RB3, RB0, RB1, RB2, RB4, RB3, RB2, RB1, RB4, RB0);
ROUND_INVERSE (19, 3, RA3, RA2, RA1, RA4, RA0, RA1, RA2, RA4, RA3, RA0,
RB3, RB2, RB1, RB4, RB0, RB1, RB2, RB4, RB3, RB0);
ROUND_INVERSE (18, 2, RA1, RA2, RA4, RA3, RA0, RA2, RA0, RA4, RA3, RA1,
RB1, RB2, RB4, RB3, RB0, RB2, RB0, RB4, RB3, RB1);
ROUND_INVERSE (17, 1, RA2, RA0, RA4, RA3, RA1, RA1, RA2, RA3, RA4, RA0,
RB2, RB0, RB4, RB3, RB1, RB1, RB2, RB3, RB4, RB0);
ROUND_INVERSE (16, 0, RA1, RA2, RA3, RA4, RA0, RA1, RA0, RA2, RA4, RA3,
RB1, RB2, RB3, RB4, RB0, RB1, RB0, RB2, RB4, RB3);
ROUND_INVERSE (15, 7, RA1, RA0, RA2, RA4, RA3, RA4, RA1, RA0, RA3, RA2,
RB1, RB0, RB2, RB4, RB3, RB4, RB1, RB0, RB3, RB2);
ROUND_INVERSE (14, 6, RA4, RA1, RA0, RA3, RA2, RA1, RA0, RA2, RA3, RA4,
RB4, RB1, RB0, RB3, RB2, RB1, RB0, RB2, RB3, RB4);
ROUND_INVERSE (13, 5, RA1, RA0, RA2, RA3, RA4, RA0, RA4, RA3, RA2, RA1,
RB1, RB0, RB2, RB3, RB4, RB0, RB4, RB3, RB2, RB1);
ROUND_INVERSE (12, 4, RA0, RA4, RA3, RA2, RA1, RA0, RA2, RA3, RA1, RA4,
RB0, RB4, RB3, RB2, RB1, RB0, RB2, RB3, RB1, RB4);
ROUND_INVERSE (11, 3, RA0, RA2, RA3, RA1, RA4, RA3, RA2, RA1, RA0, RA4,
RB0, RB2, RB3, RB1, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND_INVERSE (10, 2, RA3, RA2, RA1, RA0, RA4, RA2, RA4, RA1, RA0, RA3,
RB3, RB2, RB1, RB0, RB4, RB2, RB4, RB1, RB0, RB3);
ROUND_INVERSE (9, 1, RA2, RA4, RA1, RA0, RA3, RA3, RA2, RA0, RA1, RA4,
RB2, RB4, RB1, RB0, RB3, RB3, RB2, RB0, RB1, RB4);
ROUND_INVERSE (8, 0, RA3, RA2, RA0, RA1, RA4, RA3, RA4, RA2, RA1, RA0,
RB3, RB2, RB0, RB1, RB4, RB3, RB4, RB2, RB1, RB0);
ROUND_INVERSE (7, 7, RA3, RA4, RA2, RA1, RA0, RA1, RA3, RA4, RA0, RA2,
RB3, RB4, RB2, RB1, RB0, RB1, RB3, RB4, RB0, RB2);
ROUND_INVERSE (6, 6, RA1, RA3, RA4, RA0, RA2, RA3, RA4, RA2, RA0, RA1,
RB1, RB3, RB4, RB0, RB2, RB3, RB4, RB2, RB0, RB1);
ROUND_INVERSE (5, 5, RA3, RA4, RA2, RA0, RA1, RA4, RA1, RA0, RA2, RA3,
RB3, RB4, RB2, RB0, RB1, RB4, RB1, RB0, RB2, RB3);
ROUND_INVERSE (4, 4, RA4, RA1, RA0, RA2, RA3, RA4, RA2, RA0, RA3, RA1,
RB4, RB1, RB0, RB2, RB3, RB4, RB2, RB0, RB3, RB1);
ROUND_INVERSE (3, 3, RA4, RA2, RA0, RA3, RA1, RA0, RA2, RA3, RA4, RA1,
RB4, RB2, RB0, RB3, RB1, RB0, RB2, RB3, RB4, RB1);
ROUND_INVERSE (2, 2, RA0, RA2, RA3, RA4, RA1, RA2, RA1, RA3, RA4, RA0,
RB0, RB2, RB3, RB4, RB1, RB2, RB1, RB3, RB4, RB0);
ROUND_INVERSE (1, 1, RA2, RA1, RA3, RA4, RA0, RA0, RA2, RA4, RA3, RA1,
RB2, RB1, RB3, RB4, RB0, RB0, RB2, RB4, RB3, RB1);
ROUND_INVERSE (0, 0, RA0, RA2, RA4, RA3, RA1, RA0, RA1, RA2, RA3, RA4,
RB0, RB2, RB4, RB3, RB1, RB0, RB1, RB2, RB3, RB4);
transpose_4x4(RA0, RA1, RA2, RA3);
transpose_4x4(RB0, RB1, RB2, RB3);
bx lr;
.size __serpent_dec_blk8,.-__serpent_dec_blk8;
.align 3
.globl _gcry_serpent_neon_ctr_enc
.type _gcry_serpent_neon_ctr_enc,%function;
_gcry_serpent_neon_ctr_enc:
/* input:
* r0: ctx, CTX
* r1: dst (8 blocks)
* r2: src (8 blocks)
* r3: iv
*/
vmov.u8 RT1d0, #0xff; /* u64: -1 */
push {r4,lr};
vadd.u64 RT2d0, RT1d0, RT1d0; /* u64: -2 */
vpush {RA4-RB2};
/* load IV and byteswap */
vld1.8 {RA0}, [r3];
vrev64.u8 RT0, RA0; /* be => le */
ldr r4, [r3, #8];
/* construct IVs */
vsub.u64 RA2d1, RT0d1, RT2d0; /* +2 */
vsub.u64 RA1d1, RT0d1, RT1d0; /* +1 */
cmp r4, #-1;
vsub.u64 RB0d1, RA2d1, RT2d0; /* +4 */
vsub.u64 RA3d1, RA2d1, RT1d0; /* +3 */
ldr r4, [r3, #12];
vsub.u64 RB2d1, RB0d1, RT2d0; /* +6 */
vsub.u64 RB1d1, RB0d1, RT1d0; /* +5 */
vsub.u64 RT2d1, RB2d1, RT2d0; /* +8 */
vsub.u64 RB3d1, RB2d1, RT1d0; /* +7 */
vmov RA1d0, RT0d0;
vmov RA2d0, RT0d0;
vmov RA3d0, RT0d0;
vmov RB0d0, RT0d0;
rev r4, r4;
vmov RB1d0, RT0d0;
vmov RB2d0, RT0d0;
vmov RB3d0, RT0d0;
vmov RT2d0, RT0d0;
/* check need for handling 64-bit overflow and carry */
beq .Ldo_ctr_carry;
.Lctr_carry_done:
/* le => be */
vrev64.u8 RA1, RA1;
vrev64.u8 RA2, RA2;
vrev64.u8 RA3, RA3;
vrev64.u8 RB0, RB0;
vrev64.u8 RT2, RT2;
vrev64.u8 RB1, RB1;
vrev64.u8 RB2, RB2;
vrev64.u8 RB3, RB3;
/* store new IV */
vst1.8 {RT2}, [r3];
bl __serpent_enc_blk8;
vld1.8 {RT0, RT1}, [r2]!;
vld1.8 {RT2, RT3}, [r2]!;
veor RA4, RA4, RT0;
veor RA1, RA1, RT1;
vld1.8 {RT0, RT1}, [r2]!;
veor RA2, RA2, RT2;
veor RA0, RA0, RT3;
vld1.8 {RT2, RT3}, [r2]!;
veor RB4, RB4, RT0;
veor RT0, RT0;
veor RB1, RB1, RT1;
veor RT1, RT1;
veor RB2, RB2, RT2;
veor RT2, RT2;
veor RB0, RB0, RT3;
veor RT3, RT3;
vst1.8 {RA4}, [r1]!;
vst1.8 {RA1}, [r1]!;
veor RA1, RA1;
vst1.8 {RA2}, [r1]!;
veor RA2, RA2;
vst1.8 {RA0}, [r1]!;
veor RA0, RA0;
vst1.8 {RB4}, [r1]!;
veor RB4, RB4;
vst1.8 {RB1}, [r1]!;
vst1.8 {RB2}, [r1]!;
vst1.8 {RB0}, [r1]!;
vpop {RA4-RB2};
/* clear the used registers */
veor RA3, RA3;
veor RB3, RB3;
pop {r4,pc};
.Ldo_ctr_carry:
cmp r4, #-8;
blo .Lctr_carry_done;
beq .Lcarry_RT2;
cmp r4, #-6;
blo .Lcarry_RB3;
beq .Lcarry_RB2;
cmp r4, #-4;
blo .Lcarry_RB1;
beq .Lcarry_RB0;
cmp r4, #-2;
blo .Lcarry_RA3;
beq .Lcarry_RA2;
vsub.u64 RA1d0, RT1d0;
.Lcarry_RA2:
vsub.u64 RA2d0, RT1d0;
.Lcarry_RA3:
vsub.u64 RA3d0, RT1d0;
.Lcarry_RB0:
vsub.u64 RB0d0, RT1d0;
.Lcarry_RB1:
vsub.u64 RB1d0, RT1d0;
.Lcarry_RB2:
vsub.u64 RB2d0, RT1d0;
.Lcarry_RB3:
vsub.u64 RB3d0, RT1d0;
.Lcarry_RT2:
vsub.u64 RT2d0, RT1d0;
b .Lctr_carry_done;
.size _gcry_serpent_neon_ctr_enc,.-_gcry_serpent_neon_ctr_enc;
.align 3
.globl _gcry_serpent_neon_cfb_dec
.type _gcry_serpent_neon_cfb_dec,%function;
_gcry_serpent_neon_cfb_dec:
/* input:
* r0: ctx, CTX
* r1: dst (8 blocks)
* r2: src (8 blocks)
* r3: iv
*/
push {lr};
vpush {RA4-RB2};
/* Load input */
vld1.8 {RA0}, [r3];
vld1.8 {RA1, RA2}, [r2]!;
vld1.8 {RA3}, [r2]!;
vld1.8 {RB0}, [r2]!;
vld1.8 {RB1, RB2}, [r2]!;
vld1.8 {RB3}, [r2]!;
/* Update IV */
vld1.8 {RT0}, [r2]!;
vst1.8 {RT0}, [r3];
mov r3, lr;
sub r2, r2, #(8*16);
bl __serpent_enc_blk8;
vld1.8 {RT0, RT1}, [r2]!;
vld1.8 {RT2, RT3}, [r2]!;
veor RA4, RA4, RT0;
veor RA1, RA1, RT1;
vld1.8 {RT0, RT1}, [r2]!;
veor RA2, RA2, RT2;
veor RA0, RA0, RT3;
vld1.8 {RT2, RT3}, [r2]!;
veor RB4, RB4, RT0;
veor RT0, RT0;
veor RB1, RB1, RT1;
veor RT1, RT1;
veor RB2, RB2, RT2;
veor RT2, RT2;
veor RB0, RB0, RT3;
veor RT3, RT3;
vst1.8 {RA4}, [r1]!;
vst1.8 {RA1}, [r1]!;
veor RA1, RA1;
vst1.8 {RA2}, [r1]!;
veor RA2, RA2;
vst1.8 {RA0}, [r1]!;
veor RA0, RA0;
vst1.8 {RB4}, [r1]!;
veor RB4, RB4;
vst1.8 {RB1}, [r1]!;
vst1.8 {RB2}, [r1]!;
vst1.8 {RB0}, [r1]!;
vpop {RA4-RB2};
/* clear the used registers */
veor RA3, RA3;
veor RB3, RB3;
pop {pc};
.size _gcry_serpent_neon_cfb_dec,.-_gcry_serpent_neon_cfb_dec;
.align 3
.globl _gcry_serpent_neon_cbc_dec
.type _gcry_serpent_neon_cbc_dec,%function;
_gcry_serpent_neon_cbc_dec:
/* input:
* r0: ctx, CTX
* r1: dst (8 blocks)
* r2: src (8 blocks)
* r3: iv
*/
push {lr};
vpush {RA4-RB2};
vld1.8 {RA0, RA1}, [r2]!;
vld1.8 {RA2, RA3}, [r2]!;
vld1.8 {RB0, RB1}, [r2]!;
vld1.8 {RB2, RB3}, [r2]!;
sub r2, r2, #(8*16);
bl __serpent_dec_blk8;
vld1.8 {RB4}, [r3];
vld1.8 {RT0, RT1}, [r2]!;
vld1.8 {RT2, RT3}, [r2]!;
veor RA0, RA0, RB4;
veor RA1, RA1, RT0;
veor RA2, RA2, RT1;
vld1.8 {RT0, RT1}, [r2]!;
veor RA3, RA3, RT2;
veor RB0, RB0, RT3;
vld1.8 {RT2, RT3}, [r2]!;
veor RB1, RB1, RT0;
veor RT0, RT0;
veor RB2, RB2, RT1;
veor RT1, RT1;
veor RB3, RB3, RT2;
veor RT2, RT2;
vst1.8 {RT3}, [r3]; /* store new IV */
veor RT3, RT3;
vst1.8 {RA0, RA1}, [r1]!;
veor RA0, RA0;
veor RA1, RA1;
vst1.8 {RA2, RA3}, [r1]!;
veor RA2, RA2;
vst1.8 {RB0, RB1}, [r1]!;
veor RA3, RA3;
vst1.8 {RB2, RB3}, [r1]!;
veor RB3, RB3;
vpop {RA4-RB2};
/* clear the used registers */
veor RB4, RB4;
pop {pc};
.size _gcry_serpent_neon_cbc_dec,.-_gcry_serpent_neon_cbc_dec;
.align 3
.globl _gcry_serpent_neon_ocb_enc
.type _gcry_serpent_neon_ocb_enc,%function;
_gcry_serpent_neon_ocb_enc:
/* input:
* r0 : ctx, CTX
* r1 : dst (8 blocks)
* r2 : src (8 blocks)
* r3 : offset
* sp+0: checksum
* sp+4: L pointers (void *L[8])
*/
push {r4-r11, ip, lr};
add ip, sp, #(10*4);
vpush {RA4-RB2};
ldm ip, {r4, lr};
vld1.8 {RT0}, [r3];
vld1.8 {RT1}, [r4];
/* Load L pointers */
ldm lr!, {r5, r6, r7, r8};
ldm lr, {r9, r10, r11, ip};
/* 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) */
vld1.8 {RA0, RA1}, [r2]!;
vld1.8 {RA2, RA3}, [r2]!;
vld1.8 {RB0, RB1}, [r2]!;
vld1.8 {RB2, RB3}, [r2];
#define OCB_INPUT(lreg, vreg) \
vld1.8 {RT3}, [lreg]; \
veor RT0, RT3; \
veor RT1, vreg; \
veor vreg, RT0; \
vst1.8 {RT0}, [r1]!;
OCB_INPUT(r5, RA0);
OCB_INPUT(r6, RA1);
OCB_INPUT(r7, RA2);
OCB_INPUT(r8, RA3);
OCB_INPUT(r9, RB0);
OCB_INPUT(r10, RB1);
OCB_INPUT(r11, RB2);
OCB_INPUT(ip, RB3);
#undef OCB_INPUT
sub r1, r1, #(8*16);
vst1.8 {RT0}, [r3];
vst1.8 {RT1}, [r4];
mov r2, r1;
bl __serpent_enc_blk8;
vld1.8 {RT0, RT1}, [r1]!;
veor RT0, RA4, RT0;
veor RT1, RA1, RT1;
vld1.8 {RT2, RT3}, [r1]!;
vst1.8 {RT0, RT1}, [r2]!;
veor RT2, RA2, RT2;
veor RT3, RA0, RT3;
vld1.8 {RT0, RT1}, [r1]!;
vst1.8 {RT2, RT3}, [r2]!;
veor RT0, RB4, RT0;
veor RT1, RB1, RT1;
vld1.8 {RT2, RT3}, [r1]!;
vst1.8 {RT0, RT1}, [r2]!;
veor RT2, RB2, RT2;
veor RT3, RB0, RT3;
vst1.8 {RT2, RT3}, [r2]!;
vpop {RA4-RB2};
/* clear the used registers */
veor RA3, RA3;
veor RB3, RB3;
pop {r4-r11, ip, pc};
.size _gcry_serpent_neon_ocb_enc,.-_gcry_serpent_neon_ocb_enc;
.align 3
.globl _gcry_serpent_neon_ocb_dec
.type _gcry_serpent_neon_ocb_dec,%function;
_gcry_serpent_neon_ocb_dec:
/* input:
* r0 : ctx, CTX
* r1 : dst (8 blocks)
* r2 : src (8 blocks)
* r3 : offset
* sp+0: checksum
* sp+4: L pointers (void *L[8])
*/
push {r4-r11, ip, lr};
add ip, sp, #(10*4);
vpush {RA4-RB2};
ldm ip, {r4, lr};
vld1.8 {RT0}, [r3];
/* Load L pointers */
ldm lr!, {r5, r6, r7, r8};
ldm lr, {r9, r10, r11, ip};
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
/* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
vld1.8 {RA0, RA1}, [r2]!;
vld1.8 {RA2, RA3}, [r2]!;
vld1.8 {RB0, RB1}, [r2]!;
vld1.8 {RB2, RB3}, [r2];
#define OCB_INPUT(lreg, vreg) \
vld1.8 {RT3}, [lreg]; \
veor RT0, RT3; \
veor vreg, RT0; \
vst1.8 {RT0}, [r1]!;
OCB_INPUT(r5, RA0);
OCB_INPUT(r6, RA1);
OCB_INPUT(r7, RA2);
OCB_INPUT(r8, RA3);
OCB_INPUT(r9, RB0);
OCB_INPUT(r10, RB1);
OCB_INPUT(r11, RB2);
OCB_INPUT(ip, RB3);
#undef OCB_INPUT
sub r1, r1, #(8*16);
vst1.8 {RT0}, [r3];
mov r2, r1;
bl __serpent_dec_blk8;
/* Checksum_i = Checksum_{i-1} xor P_i */
vld1.8 {RA4}, [r4];
vld1.8 {RT0, RT1}, [r1]!;
veor RA0, RA0, RT0;
veor RA1, RA1, RT1;
vld1.8 {RT2, RT3}, [r1]!;
veor RA4, RA4, RA0;
vst1.8 {RA0, RA1}, [r2]!;
veor RA4, RA4, RA1;
veor RA2, RA2, RT2;
veor RA3, RA3, RT3;
vld1.8 {RT0, RT1}, [r1]!;
veor RA4, RA4, RA2;
vst1.8 {RA2, RA3}, [r2]!;
veor RA4, RA4, RA3;
veor RB0, RB0, RT0;
veor RB1, RB1, RT1;
vld1.8 {RT2, RT3}, [r1]!;
veor RA4, RA4, RB0;
vst1.8 {RB0, RB1}, [r2]!;
veor RA4, RA4, RB1;
veor RB2, RB2, RT2;
veor RB3, RB3, RT3;
veor RA4, RA4, RB2;
vst1.8 {RB2, RB3}, [r2]!;
veor RA4, RA4, RB3;
vst1.8 {RA4}, [r4];
vpop {RA4-RB2};
/* clear the used registers */
veor RB4, RB4;
pop {r4-r11, ip, pc};
.size _gcry_serpent_neon_ocb_dec,.-_gcry_serpent_neon_ocb_dec;
.align 3
.globl _gcry_serpent_neon_ocb_auth
.type _gcry_serpent_neon_ocb_auth,%function;
_gcry_serpent_neon_ocb_auth:
/* input:
* r0 : ctx, CTX
* r1 : abuf (8 blocks)
* r2 : offset
* r3 : checksum
* sp+0: L pointers (void *L[8])
*/
push {r5-r11, ip, lr};
ldr lr, [sp, #(9*4)];
vpush {RA4-RB2};
vld1.8 {RT0}, [r2];
/* Load L pointers */
ldm lr!, {r5, r6, r7, r8};
ldm lr, {r9, r10, r11, ip};
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
/* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
vld1.8 {RA0, RA1}, [r1]!;
vld1.8 {RA2, RA3}, [r1]!;
vld1.8 {RB0, RB1}, [r1]!;
vld1.8 {RB2, RB3}, [r1];
#define OCB_INPUT(lreg, vreg) \
vld1.8 {RT3}, [lreg]; \
veor RT0, RT3; \
veor vreg, RT0;
OCB_INPUT(r5, RA0);
OCB_INPUT(r6, RA1);
OCB_INPUT(r7, RA2);
OCB_INPUT(r8, RA3);
OCB_INPUT(r9, RB0);
OCB_INPUT(r10, RB1);
OCB_INPUT(r11, RB2);
OCB_INPUT(ip, RB3);
#undef OCB_INPUT
vst1.8 {RT0}, [r2];
bl __serpent_enc_blk8;
/* Checksum_i = Checksum_{i-1} xor P_i */
vld1.8 {RT0}, [r3];
veor RA4, RB4;
veor RA1, RB1;
veor RA2, RB2;
veor RA0, RB0;
veor RA2, RT0;
veor RA1, RA4;
veor RA0, RA2;
veor RA0, RA1;
vst1.8 {RA0}, [r3];
vpop {RA4-RB2};
/* clear the used registers */
veor RA3, RA3;
veor RB3, RB3;
pop {r5-r11, ip, pc};
.size _gcry_serpent_neon_ocb_auth,.-_gcry_serpent_neon_ocb_auth;
#endif
diff --git a/cipher/serpent-avx2-amd64.S b/cipher/serpent-avx2-amd64.S
index 9b17c2bd..5840ca13 100644
--- a/cipher/serpent-avx2-amd64.S
+++ b/cipher/serpent-avx2-amd64.S
@@ -1,1159 +1,1159 @@
/* serpent-avx2-amd64.S - AVX2 implementation of Serpent cipher
*
* Copyright (C) 2013-2015 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/>.
+ * License along with this program; if not, see <https://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(USE_SERPENT) && \
defined(ENABLE_AVX2_SUPPORT)
#include "asm-common-amd64.h"
/* struct serpent_context: */
#define ctx_keys 0
/* register macros */
#define CTX %rdi
/* vector registers */
#define RA0 %ymm0
#define RA1 %ymm1
#define RA2 %ymm2
#define RA3 %ymm3
#define RA4 %ymm4
#define RB0 %ymm5
#define RB1 %ymm6
#define RB2 %ymm7
#define RB3 %ymm8
#define RB4 %ymm9
#define RNOT %ymm10
#define RTMP0 %ymm11
#define RTMP1 %ymm12
#define RTMP2 %ymm13
#define RTMP3 %ymm14
#define RTMP4 %ymm15
#define RNOTx %xmm10
#define RTMP0x %xmm11
#define RTMP1x %xmm12
#define RTMP2x %xmm13
#define RTMP3x %xmm14
#define RTMP4x %xmm15
/**********************************************************************
helper macros
**********************************************************************/
/* vector 32-bit rotation to left */
#define vec_rol(reg, nleft, tmp) \
vpslld $(nleft), reg, tmp; \
vpsrld $(32 - (nleft)), reg, reg; \
vpor tmp, reg, reg;
/* vector 32-bit rotation to right */
#define vec_ror(reg, nright, tmp) \
vec_rol(reg, 32 - nright, tmp)
/* 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;
/**********************************************************************
16-way serpent
**********************************************************************/
/*
* These are the S-Boxes of Serpent from following research paper.
*
* D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
* (New York, New York, USA), p. 317–329, National Institute of Standards and
* Technology, 2000.
*
- * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
+ * Paper is also available at: https://www.ii.uib.no/~osvik/pub/aes3.pdf
*
*/
#define SBOX0(r0, r1, r2, r3, r4) \
vpxor r0, r3, r3; vmovdqa r1, r4; \
vpand r3, r1, r1; vpxor r2, r4, r4; \
vpxor r0, r1, r1; vpor r3, r0, r0; \
vpxor r4, r0, r0; vpxor r3, r4, r4; \
vpxor r2, r3, r3; vpor r1, r2, r2; \
vpxor r4, r2, r2; vpxor RNOT, r4, r4; \
vpor r1, r4, r4; vpxor r3, r1, r1; \
vpxor r4, r1, r1; vpor r0, r3, r3; \
vpxor r3, r1, r1; vpxor r3, r4, r4;
#define SBOX0_INVERSE(r0, r1, r2, r3, r4) \
vpxor RNOT, r2, r2; vmovdqa r1, r4; \
vpor r0, r1, r1; vpxor RNOT, r4, r4; \
vpxor r2, r1, r1; vpor r4, r2, r2; \
vpxor r3, r1, r1; vpxor r4, r0, r0; \
vpxor r0, r2, r2; vpand r3, r0, r0; \
vpxor r0, r4, r4; vpor r1, r0, r0; \
vpxor r2, r0, r0; vpxor r4, r3, r3; \
vpxor r1, r2, r2; vpxor r0, r3, r3; \
vpxor r1, r3, r3; \
vpand r3, r2, r2; \
vpxor r2, r4, r4;
#define SBOX1(r0, r1, r2, r3, r4) \
vpxor RNOT, r0, r0; vpxor RNOT, r2, r2; \
vmovdqa r0, r4; vpand r1, r0, r0; \
vpxor r0, r2, r2; vpor r3, r0, r0; \
vpxor r2, r3, r3; vpxor r0, r1, r1; \
vpxor r4, r0, r0; vpor r1, r4, r4; \
vpxor r3, r1, r1; vpor r0, r2, r2; \
vpand r4, r2, r2; vpxor r1, r0, r0; \
vpand r2, r1, r1; \
vpxor r0, r1, r1; vpand r2, r0, r0; \
vpxor r4, r0, r0;
#define SBOX1_INVERSE(r0, r1, r2, r3, r4) \
vmovdqa r1, r4; vpxor r3, r1, r1; \
vpand r1, r3, r3; vpxor r2, r4, r4; \
vpxor r0, r3, r3; vpor r1, r0, r0; \
vpxor r3, r2, r2; vpxor r4, r0, r0; \
vpor r2, r0, r0; vpxor r3, r1, r1; \
vpxor r1, r0, r0; vpor r3, r1, r1; \
vpxor r0, r1, r1; vpxor RNOT, r4, r4; \
vpxor r1, r4, r4; vpor r0, r1, r1; \
vpxor r0, r1, r1; \
vpor r4, r1, r1; \
vpxor r1, r3, r3;
#define SBOX2(r0, r1, r2, r3, r4) \
vmovdqa r0, r4; vpand r2, r0, r0; \
vpxor r3, r0, r0; vpxor r1, r2, r2; \
vpxor r0, r2, r2; vpor r4, r3, r3; \
vpxor r1, r3, r3; vpxor r2, r4, r4; \
vmovdqa r3, r1; vpor r4, r3, r3; \
vpxor r0, r3, r3; vpand r1, r0, r0; \
vpxor r0, r4, r4; vpxor r3, r1, r1; \
vpxor r4, r1, r1; vpxor RNOT, r4, r4;
#define SBOX2_INVERSE(r0, r1, r2, r3, r4) \
vpxor r3, r2, r2; vpxor r0, r3, r3; \
vmovdqa r3, r4; vpand r2, r3, r3; \
vpxor r1, r3, r3; vpor r2, r1, r1; \
vpxor r4, r1, r1; vpand r3, r4, r4; \
vpxor r3, r2, r2; vpand r0, r4, r4; \
vpxor r2, r4, r4; vpand r1, r2, r2; \
vpor r0, r2, r2; vpxor RNOT, r3, r3; \
vpxor r3, r2, r2; vpxor r3, r0, r0; \
vpand r1, r0, r0; vpxor r4, r3, r3; \
vpxor r0, r3, r3;
#define SBOX3(r0, r1, r2, r3, r4) \
vmovdqa r0, r4; vpor r3, r0, r0; \
vpxor r1, r3, r3; vpand r4, r1, r1; \
vpxor r2, r4, r4; vpxor r3, r2, r2; \
vpand r0, r3, r3; vpor r1, r4, r4; \
vpxor r4, r3, r3; vpxor r1, r0, r0; \
vpand r0, r4, r4; vpxor r3, r1, r1; \
vpxor r2, r4, r4; vpor r0, r1, r1; \
vpxor r2, r1, r1; vpxor r3, r0, r0; \
vmovdqa r1, r2; vpor r3, r1, r1; \
vpxor r0, r1, r1;
#define SBOX3_INVERSE(r0, r1, r2, r3, r4) \
vmovdqa r2, r4; vpxor r1, r2, r2; \
vpxor r2, r0, r0; vpand r2, r4, r4; \
vpxor r0, r4, r4; vpand r1, r0, r0; \
vpxor r3, r1, r1; vpor r4, r3, r3; \
vpxor r3, r2, r2; vpxor r3, r0, r0; \
vpxor r4, r1, r1; vpand r2, r3, r3; \
vpxor r1, r3, r3; vpxor r0, r1, r1; \
vpor r2, r1, r1; vpxor r3, r0, r0; \
vpxor r4, r1, r1; \
vpxor r1, r0, r0;
#define SBOX4(r0, r1, r2, r3, r4) \
vpxor r3, r1, r1; vpxor RNOT, r3, r3; \
vpxor r3, r2, r2; vpxor r0, r3, r3; \
vmovdqa r1, r4; vpand r3, r1, r1; \
vpxor r2, r1, r1; vpxor r3, r4, r4; \
vpxor r4, r0, r0; vpand r4, r2, r2; \
vpxor r0, r2, r2; vpand r1, r0, r0; \
vpxor r0, r3, r3; vpor r1, r4, r4; \
vpxor r0, r4, r4; vpor r3, r0, r0; \
vpxor r2, r0, r0; vpand r3, r2, r2; \
vpxor RNOT, r0, r0; vpxor r2, r4, r4;
#define SBOX4_INVERSE(r0, r1, r2, r3, r4) \
vmovdqa r2, r4; vpand r3, r2, r2; \
vpxor r1, r2, r2; vpor r3, r1, r1; \
vpand r0, r1, r1; vpxor r2, r4, r4; \
vpxor r1, r4, r4; vpand r2, r1, r1; \
vpxor RNOT, r0, r0; vpxor r4, r3, r3; \
vpxor r3, r1, r1; vpand r0, r3, r3; \
vpxor r2, r3, r3; vpxor r1, r0, r0; \
vpand r0, r2, r2; vpxor r0, r3, r3; \
vpxor r4, r2, r2; \
vpor r3, r2, r2; vpxor r0, r3, r3; \
vpxor r1, r2, r2;
#define SBOX5(r0, r1, r2, r3, r4) \
vpxor r1, r0, r0; vpxor r3, r1, r1; \
vpxor RNOT, r3, r3; vmovdqa r1, r4; \
vpand r0, r1, r1; vpxor r3, r2, r2; \
vpxor r2, r1, r1; vpor r4, r2, r2; \
vpxor r3, r4, r4; vpand r1, r3, r3; \
vpxor r0, r3, r3; vpxor r1, r4, r4; \
vpxor r2, r4, r4; vpxor r0, r2, r2; \
vpand r3, r0, r0; vpxor RNOT, r2, r2; \
vpxor r4, r0, r0; vpor r3, r4, r4; \
vpxor r4, r2, r2;
#define SBOX5_INVERSE(r0, r1, r2, r3, r4) \
vpxor RNOT, r1, r1; vmovdqa r3, r4; \
vpxor r1, r2, r2; vpor r0, r3, r3; \
vpxor r2, r3, r3; vpor r1, r2, r2; \
vpand r0, r2, r2; vpxor r3, r4, r4; \
vpxor r4, r2, r2; vpor r0, r4, r4; \
vpxor r1, r4, r4; vpand r2, r1, r1; \
vpxor r3, r1, r1; vpxor r2, r4, r4; \
vpand r4, r3, r3; vpxor r1, r4, r4; \
vpxor r4, r3, r3; vpxor RNOT, r4, r4; \
vpxor r0, r3, r3;
#define SBOX6(r0, r1, r2, r3, r4) \
vpxor RNOT, r2, r2; vmovdqa r3, r4; \
vpand r0, r3, r3; vpxor r4, r0, r0; \
vpxor r2, r3, r3; vpor r4, r2, r2; \
vpxor r3, r1, r1; vpxor r0, r2, r2; \
vpor r1, r0, r0; vpxor r1, r2, r2; \
vpxor r0, r4, r4; vpor r3, r0, r0; \
vpxor r2, r0, r0; vpxor r3, r4, r4; \
vpxor r0, r4, r4; vpxor RNOT, r3, r3; \
vpand r4, r2, r2; \
vpxor r3, r2, r2;
#define SBOX6_INVERSE(r0, r1, r2, r3, r4) \
vpxor r2, r0, r0; vmovdqa r2, r4; \
vpand r0, r2, r2; vpxor r3, r4, r4; \
vpxor RNOT, r2, r2; vpxor r1, r3, r3; \
vpxor r3, r2, r2; vpor r0, r4, r4; \
vpxor r2, r0, r0; vpxor r4, r3, r3; \
vpxor r1, r4, r4; vpand r3, r1, r1; \
vpxor r0, r1, r1; vpxor r3, r0, r0; \
vpor r2, r0, r0; vpxor r1, r3, r3; \
vpxor r0, r4, r4;
#define SBOX7(r0, r1, r2, r3, r4) \
vmovdqa r1, r4; vpor r2, r1, r1; \
vpxor r3, r1, r1; vpxor r2, r4, r4; \
vpxor r1, r2, r2; vpor r4, r3, r3; \
vpand r0, r3, r3; vpxor r2, r4, r4; \
vpxor r1, r3, r3; vpor r4, r1, r1; \
vpxor r0, r1, r1; vpor r4, r0, r0; \
vpxor r2, r0, r0; vpxor r4, r1, r1; \
vpxor r1, r2, r2; vpand r0, r1, r1; \
vpxor r4, r1, r1; vpxor RNOT, r2, r2; \
vpor r0, r2, r2; \
vpxor r2, r4, r4;
#define SBOX7_INVERSE(r0, r1, r2, r3, r4) \
vmovdqa r2, r4; vpxor r0, r2, r2; \
vpand r3, r0, r0; vpor r3, r4, r4; \
vpxor RNOT, r2, r2; vpxor r1, r3, r3; \
vpor r0, r1, r1; vpxor r2, r0, r0; \
vpand r4, r2, r2; vpand r4, r3, r3; \
vpxor r2, r1, r1; vpxor r0, r2, r2; \
vpor r2, r0, r0; vpxor r1, r4, r4; \
vpxor r3, r0, r0; vpxor r4, r3, r3; \
vpor r0, r4, r4; vpxor r2, r3, r3; \
vpxor r2, r4, r4;
/* Apply SBOX number WHICH to to the block. */
#define SBOX(which, r0, r1, r2, r3, r4) \
SBOX##which (r0, r1, r2, r3, r4)
/* Apply inverse SBOX number WHICH to to the block. */
#define SBOX_INVERSE(which, r0, r1, r2, r3, r4) \
SBOX##which##_INVERSE (r0, r1, r2, r3, r4)
/* XOR round key into block state in r0,r1,r2,r3. r4 used as temporary. */
#define BLOCK_XOR_KEY(r0, r1, r2, r3, r4, round) \
vpbroadcastd (ctx_keys + (round) * 16 + 0 * 4)(CTX), r4; \
vpxor r4, r0, r0; \
vpbroadcastd (ctx_keys + (round) * 16 + 1 * 4)(CTX), r4; \
vpxor r4, r1, r1; \
vpbroadcastd (ctx_keys + (round) * 16 + 2 * 4)(CTX), r4; \
vpxor r4, r2, r2; \
vpbroadcastd (ctx_keys + (round) * 16 + 3 * 4)(CTX), r4; \
vpxor r4, r3, r3;
/* Apply the linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION(r0, r1, r2, r3, r4) \
vec_rol(r0, 13, r4); \
vec_rol(r2, 3, r4); \
vpxor r0, r1, r1; \
vpxor r2, r1, r1; \
vpslld $3, r0, r4; \
vpxor r2, r3, r3; \
vpxor r4, r3, r3; \
vec_rol(r1, 1, r4); \
vec_rol(r3, 7, r4); \
vpxor r1, r0, r0; \
vpxor r3, r0, r0; \
vpslld $7, r1, r4; \
vpxor r3, r2, r2; \
vpxor r4, r2, r2; \
vec_rol(r0, 5, r4); \
vec_rol(r2, 22, r4);
/* Apply the inverse linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION_INVERSE(r0, r1, r2, r3, r4) \
vec_ror(r2, 22, r4); \
vec_ror(r0, 5, r4); \
vpslld $7, r1, r4; \
vpxor r3, r2, r2; \
vpxor r4, r2, r2; \
vpxor r1, r0, r0; \
vpxor r3, r0, r0; \
vec_ror(r3, 7, r4); \
vec_ror(r1, 1, r4); \
vpslld $3, r0, r4; \
vpxor r2, r3, r3; \
vpxor r4, r3, r3; \
vpxor r0, r1, r1; \
vpxor r2, r1, r1; \
vec_ror(r2, 3, r4); \
vec_ror(r0, 13, r4);
/* Apply a Serpent round to sixteen parallel blocks. This macro increments
`round'. */
#define ROUND(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round); \
SBOX (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round); \
SBOX (which, b0, b1, b2, b3, b4); \
LINEAR_TRANSFORMATION (na0, na1, na2, na3, na4); \
LINEAR_TRANSFORMATION (nb0, nb1, nb2, nb3, nb4);
/* Apply the last Serpent round to sixteen parallel blocks. This macro
increments `round'. */
#define ROUND_LAST(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round); \
SBOX (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round); \
SBOX (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, ((round) + 1)); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, ((round) + 1));
/* Apply an inverse Serpent round to sixteen parallel blocks. This macro
increments `round'. */
#define ROUND_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
LINEAR_TRANSFORMATION_INVERSE (a0, a1, a2, a3, a4); \
LINEAR_TRANSFORMATION_INVERSE (b0, b1, b2, b3, b4); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round); \
SBOX_INVERSE (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
/* Apply the first inverse Serpent round to sixteen parallel blocks. This macro
increments `round'. */
#define ROUND_FIRST_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, ((round) + 1)); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, ((round) + 1)); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round); \
SBOX_INVERSE (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
.text
.align 8
ELF(.type __serpent_enc_blk16,@function;)
__serpent_enc_blk16:
/* input:
* %rdi: ctx, CTX
* RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
* plaintext blocks
* output:
* RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: sixteen parallel
* ciphertext blocks
*/
CFI_STARTPROC();
vpcmpeqd RNOT, RNOT, RNOT;
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ROUND (0, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (1, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (2, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (3, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (4, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (5, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (6, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND (7, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
ROUND (8, 0, RA4, RA1, RA2, RA0, RA3, RA1, RA3, RA2, RA4, RA0,
RB4, RB1, RB2, RB0, RB3, RB1, RB3, RB2, RB4, RB0);
ROUND (9, 1, RA1, RA3, RA2, RA4, RA0, RA2, RA1, RA4, RA3, RA0,
RB1, RB3, RB2, RB4, RB0, RB2, RB1, RB4, RB3, RB0);
ROUND (10, 2, RA2, RA1, RA4, RA3, RA0, RA4, RA3, RA1, RA0, RA2,
RB2, RB1, RB4, RB3, RB0, RB4, RB3, RB1, RB0, RB2);
ROUND (11, 3, RA4, RA3, RA1, RA0, RA2, RA3, RA1, RA0, RA2, RA4,
RB4, RB3, RB1, RB0, RB2, RB3, RB1, RB0, RB2, RB4);
ROUND (12, 4, RA3, RA1, RA0, RA2, RA4, RA1, RA4, RA3, RA2, RA0,
RB3, RB1, RB0, RB2, RB4, RB1, RB4, RB3, RB2, RB0);
ROUND (13, 5, RA1, RA4, RA3, RA2, RA0, RA4, RA2, RA1, RA3, RA0,
RB1, RB4, RB3, RB2, RB0, RB4, RB2, RB1, RB3, RB0);
ROUND (14, 6, RA4, RA2, RA1, RA3, RA0, RA4, RA2, RA0, RA1, RA3,
RB4, RB2, RB1, RB3, RB0, RB4, RB2, RB0, RB1, RB3);
ROUND (15, 7, RA4, RA2, RA0, RA1, RA3, RA3, RA1, RA2, RA4, RA0,
RB4, RB2, RB0, RB1, RB3, RB3, RB1, RB2, RB4, RB0);
ROUND (16, 0, RA3, RA1, RA2, RA4, RA0, RA1, RA0, RA2, RA3, RA4,
RB3, RB1, RB2, RB4, RB0, RB1, RB0, RB2, RB3, RB4);
ROUND (17, 1, RA1, RA0, RA2, RA3, RA4, RA2, RA1, RA3, RA0, RA4,
RB1, RB0, RB2, RB3, RB4, RB2, RB1, RB3, RB0, RB4);
ROUND (18, 2, RA2, RA1, RA3, RA0, RA4, RA3, RA0, RA1, RA4, RA2,
RB2, RB1, RB3, RB0, RB4, RB3, RB0, RB1, RB4, RB2);
ROUND (19, 3, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA4, RA2, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB4, RB2, RB3);
ROUND (20, 4, RA0, RA1, RA4, RA2, RA3, RA1, RA3, RA0, RA2, RA4,
RB0, RB1, RB4, RB2, RB3, RB1, RB3, RB0, RB2, RB4);
ROUND (21, 5, RA1, RA3, RA0, RA2, RA4, RA3, RA2, RA1, RA0, RA4,
RB1, RB3, RB0, RB2, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND (22, 6, RA3, RA2, RA1, RA0, RA4, RA3, RA2, RA4, RA1, RA0,
RB3, RB2, RB1, RB0, RB4, RB3, RB2, RB4, RB1, RB0);
ROUND (23, 7, RA3, RA2, RA4, RA1, RA0, RA0, RA1, RA2, RA3, RA4,
RB3, RB2, RB4, RB1, RB0, RB0, RB1, RB2, RB3, RB4);
ROUND (24, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (25, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (26, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (27, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (28, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (29, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (30, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND_LAST (31, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
transpose_4x4(RA4, RA1, RA2, RA0, RA3, RTMP0, RTMP1);
transpose_4x4(RB4, RB1, RB2, RB0, RB3, RTMP0, RTMP1);
ret;
CFI_ENDPROC();
ELF(.size __serpent_enc_blk16,.-__serpent_enc_blk16;)
.align 8
ELF(.type __serpent_dec_blk16,@function;)
__serpent_dec_blk16:
/* input:
* %rdi: ctx, CTX
* RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
* ciphertext blocks
* output:
* RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
* plaintext blocks
*/
CFI_STARTPROC();
vpcmpeqd RNOT, RNOT, RNOT;
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ROUND_FIRST_INVERSE (31, 7, RA0, RA1, RA2, RA3, RA4,
RA3, RA0, RA1, RA4, RA2,
RB0, RB1, RB2, RB3, RB4,
RB3, RB0, RB1, RB4, RB2);
ROUND_INVERSE (30, 6, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA2, RA4, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB2, RB4, RB3);
ROUND_INVERSE (29, 5, RA0, RA1, RA2, RA4, RA3, RA1, RA3, RA4, RA2, RA0,
RB0, RB1, RB2, RB4, RB3, RB1, RB3, RB4, RB2, RB0);
ROUND_INVERSE (28, 4, RA1, RA3, RA4, RA2, RA0, RA1, RA2, RA4, RA0, RA3,
RB1, RB3, RB4, RB2, RB0, RB1, RB2, RB4, RB0, RB3);
ROUND_INVERSE (27, 3, RA1, RA2, RA4, RA0, RA3, RA4, RA2, RA0, RA1, RA3,
RB1, RB2, RB4, RB0, RB3, RB4, RB2, RB0, RB1, RB3);
ROUND_INVERSE (26, 2, RA4, RA2, RA0, RA1, RA3, RA2, RA3, RA0, RA1, RA4,
RB4, RB2, RB0, RB1, RB3, RB2, RB3, RB0, RB1, RB4);
ROUND_INVERSE (25, 1, RA2, RA3, RA0, RA1, RA4, RA4, RA2, RA1, RA0, RA3,
RB2, RB3, RB0, RB1, RB4, RB4, RB2, RB1, RB0, RB3);
ROUND_INVERSE (24, 0, RA4, RA2, RA1, RA0, RA3, RA4, RA3, RA2, RA0, RA1,
RB4, RB2, RB1, RB0, RB3, RB4, RB3, RB2, RB0, RB1);
ROUND_INVERSE (23, 7, RA4, RA3, RA2, RA0, RA1, RA0, RA4, RA3, RA1, RA2,
RB4, RB3, RB2, RB0, RB1, RB0, RB4, RB3, RB1, RB2);
ROUND_INVERSE (22, 6, RA0, RA4, RA3, RA1, RA2, RA4, RA3, RA2, RA1, RA0,
RB0, RB4, RB3, RB1, RB2, RB4, RB3, RB2, RB1, RB0);
ROUND_INVERSE (21, 5, RA4, RA3, RA2, RA1, RA0, RA3, RA0, RA1, RA2, RA4,
RB4, RB3, RB2, RB1, RB0, RB3, RB0, RB1, RB2, RB4);
ROUND_INVERSE (20, 4, RA3, RA0, RA1, RA2, RA4, RA3, RA2, RA1, RA4, RA0,
RB3, RB0, RB1, RB2, RB4, RB3, RB2, RB1, RB4, RB0);
ROUND_INVERSE (19, 3, RA3, RA2, RA1, RA4, RA0, RA1, RA2, RA4, RA3, RA0,
RB3, RB2, RB1, RB4, RB0, RB1, RB2, RB4, RB3, RB0);
ROUND_INVERSE (18, 2, RA1, RA2, RA4, RA3, RA0, RA2, RA0, RA4, RA3, RA1,
RB1, RB2, RB4, RB3, RB0, RB2, RB0, RB4, RB3, RB1);
ROUND_INVERSE (17, 1, RA2, RA0, RA4, RA3, RA1, RA1, RA2, RA3, RA4, RA0,
RB2, RB0, RB4, RB3, RB1, RB1, RB2, RB3, RB4, RB0);
ROUND_INVERSE (16, 0, RA1, RA2, RA3, RA4, RA0, RA1, RA0, RA2, RA4, RA3,
RB1, RB2, RB3, RB4, RB0, RB1, RB0, RB2, RB4, RB3);
ROUND_INVERSE (15, 7, RA1, RA0, RA2, RA4, RA3, RA4, RA1, RA0, RA3, RA2,
RB1, RB0, RB2, RB4, RB3, RB4, RB1, RB0, RB3, RB2);
ROUND_INVERSE (14, 6, RA4, RA1, RA0, RA3, RA2, RA1, RA0, RA2, RA3, RA4,
RB4, RB1, RB0, RB3, RB2, RB1, RB0, RB2, RB3, RB4);
ROUND_INVERSE (13, 5, RA1, RA0, RA2, RA3, RA4, RA0, RA4, RA3, RA2, RA1,
RB1, RB0, RB2, RB3, RB4, RB0, RB4, RB3, RB2, RB1);
ROUND_INVERSE (12, 4, RA0, RA4, RA3, RA2, RA1, RA0, RA2, RA3, RA1, RA4,
RB0, RB4, RB3, RB2, RB1, RB0, RB2, RB3, RB1, RB4);
ROUND_INVERSE (11, 3, RA0, RA2, RA3, RA1, RA4, RA3, RA2, RA1, RA0, RA4,
RB0, RB2, RB3, RB1, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND_INVERSE (10, 2, RA3, RA2, RA1, RA0, RA4, RA2, RA4, RA1, RA0, RA3,
RB3, RB2, RB1, RB0, RB4, RB2, RB4, RB1, RB0, RB3);
ROUND_INVERSE (9, 1, RA2, RA4, RA1, RA0, RA3, RA3, RA2, RA0, RA1, RA4,
RB2, RB4, RB1, RB0, RB3, RB3, RB2, RB0, RB1, RB4);
ROUND_INVERSE (8, 0, RA3, RA2, RA0, RA1, RA4, RA3, RA4, RA2, RA1, RA0,
RB3, RB2, RB0, RB1, RB4, RB3, RB4, RB2, RB1, RB0);
ROUND_INVERSE (7, 7, RA3, RA4, RA2, RA1, RA0, RA1, RA3, RA4, RA0, RA2,
RB3, RB4, RB2, RB1, RB0, RB1, RB3, RB4, RB0, RB2);
ROUND_INVERSE (6, 6, RA1, RA3, RA4, RA0, RA2, RA3, RA4, RA2, RA0, RA1,
RB1, RB3, RB4, RB0, RB2, RB3, RB4, RB2, RB0, RB1);
ROUND_INVERSE (5, 5, RA3, RA4, RA2, RA0, RA1, RA4, RA1, RA0, RA2, RA3,
RB3, RB4, RB2, RB0, RB1, RB4, RB1, RB0, RB2, RB3);
ROUND_INVERSE (4, 4, RA4, RA1, RA0, RA2, RA3, RA4, RA2, RA0, RA3, RA1,
RB4, RB1, RB0, RB2, RB3, RB4, RB2, RB0, RB3, RB1);
ROUND_INVERSE (3, 3, RA4, RA2, RA0, RA3, RA1, RA0, RA2, RA3, RA4, RA1,
RB4, RB2, RB0, RB3, RB1, RB0, RB2, RB3, RB4, RB1);
ROUND_INVERSE (2, 2, RA0, RA2, RA3, RA4, RA1, RA2, RA1, RA3, RA4, RA0,
RB0, RB2, RB3, RB4, RB1, RB2, RB1, RB3, RB4, RB0);
ROUND_INVERSE (1, 1, RA2, RA1, RA3, RA4, RA0, RA0, RA2, RA4, RA3, RA1,
RB2, RB1, RB3, RB4, RB0, RB0, RB2, RB4, RB3, RB1);
ROUND_INVERSE (0, 0, RA0, RA2, RA4, RA3, RA1, RA0, RA1, RA2, RA3, RA4,
RB0, RB2, RB4, RB3, RB1, RB0, RB1, RB2, RB3, RB4);
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ret;
CFI_ENDPROC();
ELF(.size __serpent_dec_blk16,.-__serpent_dec_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_serpent_avx2_ctr_enc
ELF(.type _gcry_serpent_avx2_ctr_enc,@function;)
_gcry_serpent_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 __serpent_enc_blk16;
vpxor (0 * 32)(%rdx), RA4, RA4;
vpxor (1 * 32)(%rdx), RA1, RA1;
vpxor (2 * 32)(%rdx), RA2, RA2;
vpxor (3 * 32)(%rdx), RA0, RA0;
vpxor (4 * 32)(%rdx), RB4, RB4;
vpxor (5 * 32)(%rdx), RB1, RB1;
vpxor (6 * 32)(%rdx), RB2, RB2;
vpxor (7 * 32)(%rdx), RB0, RB0;
vmovdqu RA4, (0 * 32)(%rsi);
vmovdqu RA1, (1 * 32)(%rsi);
vmovdqu RA2, (2 * 32)(%rsi);
vmovdqu RA0, (3 * 32)(%rsi);
vmovdqu RB4, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RB2, (6 * 32)(%rsi);
vmovdqu RB0, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_ctr_enc,.-_gcry_serpent_avx2_ctr_enc;)
.align 8
.globl _gcry_serpent_avx2_cbc_dec
ELF(.type _gcry_serpent_avx2_cbc_dec,@function;)
_gcry_serpent_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 __serpent_dec_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;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_cbc_dec,.-_gcry_serpent_avx2_cbc_dec;)
.align 8
.globl _gcry_serpent_avx2_cfb_dec
ELF(.type _gcry_serpent_avx2_cfb_dec,@function;)
_gcry_serpent_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 __serpent_enc_blk16;
vpxor (0 * 32)(%rdx), RA4, RA4;
vpxor (1 * 32)(%rdx), RA1, RA1;
vpxor (2 * 32)(%rdx), RA2, RA2;
vpxor (3 * 32)(%rdx), RA0, RA0;
vpxor (4 * 32)(%rdx), RB4, RB4;
vpxor (5 * 32)(%rdx), RB1, RB1;
vpxor (6 * 32)(%rdx), RB2, RB2;
vpxor (7 * 32)(%rdx), RB0, RB0;
vmovdqu RA4, (0 * 32)(%rsi);
vmovdqu RA1, (1 * 32)(%rsi);
vmovdqu RA2, (2 * 32)(%rsi);
vmovdqu RA0, (3 * 32)(%rsi);
vmovdqu RB4, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RB2, (6 * 32)(%rsi);
vmovdqu RB0, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_cfb_dec,.-_gcry_serpent_avx2_cfb_dec;)
.align 8
.globl _gcry_serpent_avx2_ocb_enc
ELF(.type _gcry_serpent_avx2_ocb_enc,@function;)
_gcry_serpent_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 __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;
vpxor (2 * 32)(%rsi), RA2, RA2;
vpxor (3 * 32)(%rsi), RA0, RA0;
vpxor (4 * 32)(%rsi), RB4, RB4;
vpxor (5 * 32)(%rsi), RB1, RB1;
vpxor (6 * 32)(%rsi), RB2, RB2;
vpxor (7 * 32)(%rsi), RB0, RB0;
vmovdqu RA4, (0 * 32)(%rsi);
vmovdqu RA1, (1 * 32)(%rsi);
vmovdqu RA2, (2 * 32)(%rsi);
vmovdqu RA0, (3 * 32)(%rsi);
vmovdqu RB4, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RB2, (6 * 32)(%rsi);
vmovdqu RB0, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_ocb_enc,.-_gcry_serpent_avx2_ocb_enc;)
.align 8
.globl _gcry_serpent_avx2_ocb_dec
ELF(.type _gcry_serpent_avx2_ocb_dec,@function;)
_gcry_serpent_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 __serpent_dec_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;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_ocb_dec,.-_gcry_serpent_avx2_ocb_dec;)
.align 8
.globl _gcry_serpent_avx2_ocb_auth
ELF(.type _gcry_serpent_avx2_ocb_auth,@function;)
_gcry_serpent_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 __serpent_enc_blk16;
addq $(4 * 8), %rsp;
CFI_ADJUST_CFA_OFFSET(-4 * 8);
vpxor RA4, RB4, RA4;
vpxor RA1, RB1, RA1;
vpxor RA2, RB2, RA2;
vpxor RA0, RB0, RA0;
vpxor RA4, RA1, RA1;
vpxor RA2, RA0, RA0;
vpxor RA1, RA0, RTMP1;
vextracti128 $1, RTMP1, RNOTx;
vpxor (%rcx), RTMP1x, RTMP1x;
vpxor RNOTx, RTMP1x, RTMP1x;
vmovdqu RTMP1x, (%rcx);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_avx2_ocb_auth,.-_gcry_serpent_avx2_ocb_auth;)
.align 16
/* For CTR-mode IV byteswap */
.Lbswap128_mask:
.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#endif /*defined(USE_SERPENT) && defined(ENABLE_AVX2_SUPPORT)*/
#endif /*__x86_64*/
diff --git a/cipher/serpent-sse2-amd64.S b/cipher/serpent-sse2-amd64.S
index 39cba002..5c57daa0 100644
--- a/cipher/serpent-sse2-amd64.S
+++ b/cipher/serpent-sse2-amd64.S
@@ -1,1211 +1,1211 @@
/* serpent-sse2-amd64.S - SSE2 implementation of Serpent cipher
*
* Copyright (C) 2013-2015 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/>.
+ * License along with this program; if not, see <https://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(USE_SERPENT)
#include "asm-common-amd64.h"
/* struct serpent_context: */
#define ctx_keys 0
/* register macros */
#define CTX %rdi
/* vector registers */
#define RA0 %xmm0
#define RA1 %xmm1
#define RA2 %xmm2
#define RA3 %xmm3
#define RA4 %xmm4
#define RB0 %xmm5
#define RB1 %xmm6
#define RB2 %xmm7
#define RB3 %xmm8
#define RB4 %xmm9
#define RNOT %xmm10
#define RTMP0 %xmm11
#define RTMP1 %xmm12
#define RTMP2 %xmm13
/**********************************************************************
helper macros
**********************************************************************/
/* vector 32-bit rotation to left */
#define vec_rol(reg, nleft, tmp) \
movdqa reg, tmp; \
pslld $(nleft), tmp; \
psrld $(32 - (nleft)), reg; \
por tmp, reg;
/* vector 32-bit rotation to right */
#define vec_ror(reg, nright, tmp) \
vec_rol(reg, 32 - nright, tmp)
/* 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;
/* 128-bit wide byte swap */
#define pbswap(xreg, t0) \
/* reorder 32-bit words, [a,b,c,d] => [d,c,b,a] */ \
pshufd $0x1b, xreg, xreg; \
/* reorder high&low 16-bit words, [d0,d1,c0,c1] => [d1,d0,c1,c0] */ \
pshuflw $0xb1, xreg, xreg; \
pshufhw $0xb1, xreg, xreg; \
/* reorder bytes in 16-bit words */ \
movdqa xreg, t0; \
psrlw $8, t0; \
psllw $8, xreg; \
por t0, xreg;
/**********************************************************************
8-way serpent
**********************************************************************/
/*
* These are the S-Boxes of Serpent from following research paper.
*
* D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
* (New York, New York, USA), p. 317–329, National Institute of Standards and
* Technology, 2000.
*
- * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
+ * Paper is also available at: https://www.ii.uib.no/~osvik/pub/aes3.pdf
*
*/
#define SBOX0(r0, r1, r2, r3, r4) \
pxor r0, r3; movdqa r1, r4; \
pand r3, r1; pxor r2, r4; \
pxor r0, r1; por r3, r0; \
pxor r4, r0; pxor r3, r4; \
pxor r2, r3; por r1, r2; \
pxor r4, r2; pxor RNOT, r4; \
por r1, r4; pxor r3, r1; \
pxor r4, r1; por r0, r3; \
pxor r3, r1; pxor r3, r4;
#define SBOX0_INVERSE(r0, r1, r2, r3, r4) \
pxor RNOT, r2; movdqa r1, r4; \
por r0, r1; pxor RNOT, r4; \
pxor r2, r1; por r4, r2; \
pxor r3, r1; pxor r4, r0; \
pxor r0, r2; pand r3, r0; \
pxor r0, r4; por r1, r0; \
pxor r2, r0; pxor r4, r3; \
pxor r1, r2; pxor r0, r3; \
pxor r1, r3; \
pand r3, r2; \
pxor r2, r4;
#define SBOX1(r0, r1, r2, r3, r4) \
pxor RNOT, r0; pxor RNOT, r2; \
movdqa r0, r4; pand r1, r0; \
pxor r0, r2; por r3, r0; \
pxor r2, r3; pxor r0, r1; \
pxor r4, r0; por r1, r4; \
pxor r3, r1; por r0, r2; \
pand r4, r2; pxor r1, r0; \
pand r2, r1; \
pxor r0, r1; pand r2, r0; \
pxor r4, r0;
#define SBOX1_INVERSE(r0, r1, r2, r3, r4) \
movdqa r1, r4; pxor r3, r1; \
pand r1, r3; pxor r2, r4; \
pxor r0, r3; por r1, r0; \
pxor r3, r2; pxor r4, r0; \
por r2, r0; pxor r3, r1; \
pxor r1, r0; por r3, r1; \
pxor r0, r1; pxor RNOT, r4; \
pxor r1, r4; por r0, r1; \
pxor r0, r1; \
por r4, r1; \
pxor r1, r3;
#define SBOX2(r0, r1, r2, r3, r4) \
movdqa r0, r4; pand r2, r0; \
pxor r3, r0; pxor r1, r2; \
pxor r0, r2; por r4, r3; \
pxor r1, r3; pxor r2, r4; \
movdqa r3, r1; por r4, r3; \
pxor r0, r3; pand r1, r0; \
pxor r0, r4; pxor r3, r1; \
pxor r4, r1; pxor RNOT, r4;
#define SBOX2_INVERSE(r0, r1, r2, r3, r4) \
pxor r3, r2; pxor r0, r3; \
movdqa r3, r4; pand r2, r3; \
pxor r1, r3; por r2, r1; \
pxor r4, r1; pand r3, r4; \
pxor r3, r2; pand r0, r4; \
pxor r2, r4; pand r1, r2; \
por r0, r2; pxor RNOT, r3; \
pxor r3, r2; pxor r3, r0; \
pand r1, r0; pxor r4, r3; \
pxor r0, r3;
#define SBOX3(r0, r1, r2, r3, r4) \
movdqa r0, r4; por r3, r0; \
pxor r1, r3; pand r4, r1; \
pxor r2, r4; pxor r3, r2; \
pand r0, r3; por r1, r4; \
pxor r4, r3; pxor r1, r0; \
pand r0, r4; pxor r3, r1; \
pxor r2, r4; por r0, r1; \
pxor r2, r1; pxor r3, r0; \
movdqa r1, r2; por r3, r1; \
pxor r0, r1;
#define SBOX3_INVERSE(r0, r1, r2, r3, r4) \
movdqa r2, r4; pxor r1, r2; \
pxor r2, r0; pand r2, r4; \
pxor r0, r4; pand r1, r0; \
pxor r3, r1; por r4, r3; \
pxor r3, r2; pxor r3, r0; \
pxor r4, r1; pand r2, r3; \
pxor r1, r3; pxor r0, r1; \
por r2, r1; pxor r3, r0; \
pxor r4, r1; \
pxor r1, r0;
#define SBOX4(r0, r1, r2, r3, r4) \
pxor r3, r1; pxor RNOT, r3; \
pxor r3, r2; pxor r0, r3; \
movdqa r1, r4; pand r3, r1; \
pxor r2, r1; pxor r3, r4; \
pxor r4, r0; pand r4, r2; \
pxor r0, r2; pand r1, r0; \
pxor r0, r3; por r1, r4; \
pxor r0, r4; por r3, r0; \
pxor r2, r0; pand r3, r2; \
pxor RNOT, r0; pxor r2, r4;
#define SBOX4_INVERSE(r0, r1, r2, r3, r4) \
movdqa r2, r4; pand r3, r2; \
pxor r1, r2; por r3, r1; \
pand r0, r1; pxor r2, r4; \
pxor r1, r4; pand r2, r1; \
pxor RNOT, r0; pxor r4, r3; \
pxor r3, r1; pand r0, r3; \
pxor r2, r3; pxor r1, r0; \
pand r0, r2; pxor r0, r3; \
pxor r4, r2; \
por r3, r2; pxor r0, r3; \
pxor r1, r2;
#define SBOX5(r0, r1, r2, r3, r4) \
pxor r1, r0; pxor r3, r1; \
pxor RNOT, r3; movdqa r1, r4; \
pand r0, r1; pxor r3, r2; \
pxor r2, r1; por r4, r2; \
pxor r3, r4; pand r1, r3; \
pxor r0, r3; pxor r1, r4; \
pxor r2, r4; pxor r0, r2; \
pand r3, r0; pxor RNOT, r2; \
pxor r4, r0; por r3, r4; \
pxor r4, r2;
#define SBOX5_INVERSE(r0, r1, r2, r3, r4) \
pxor RNOT, r1; movdqa r3, r4; \
pxor r1, r2; por r0, r3; \
pxor r2, r3; por r1, r2; \
pand r0, r2; pxor r3, r4; \
pxor r4, r2; por r0, r4; \
pxor r1, r4; pand r2, r1; \
pxor r3, r1; pxor r2, r4; \
pand r4, r3; pxor r1, r4; \
pxor r4, r3; pxor RNOT, r4; \
pxor r0, r3;
#define SBOX6(r0, r1, r2, r3, r4) \
pxor RNOT, r2; movdqa r3, r4; \
pand r0, r3; pxor r4, r0; \
pxor r2, r3; por r4, r2; \
pxor r3, r1; pxor r0, r2; \
por r1, r0; pxor r1, r2; \
pxor r0, r4; por r3, r0; \
pxor r2, r0; pxor r3, r4; \
pxor r0, r4; pxor RNOT, r3; \
pand r4, r2; \
pxor r3, r2;
#define SBOX6_INVERSE(r0, r1, r2, r3, r4) \
pxor r2, r0; movdqa r2, r4; \
pand r0, r2; pxor r3, r4; \
pxor RNOT, r2; pxor r1, r3; \
pxor r3, r2; por r0, r4; \
pxor r2, r0; pxor r4, r3; \
pxor r1, r4; pand r3, r1; \
pxor r0, r1; pxor r3, r0; \
por r2, r0; pxor r1, r3; \
pxor r0, r4;
#define SBOX7(r0, r1, r2, r3, r4) \
movdqa r1, r4; por r2, r1; \
pxor r3, r1; pxor r2, r4; \
pxor r1, r2; por r4, r3; \
pand r0, r3; pxor r2, r4; \
pxor r1, r3; por r4, r1; \
pxor r0, r1; por r4, r0; \
pxor r2, r0; pxor r4, r1; \
pxor r1, r2; pand r0, r1; \
pxor r4, r1; pxor RNOT, r2; \
por r0, r2; \
pxor r2, r4;
#define SBOX7_INVERSE(r0, r1, r2, r3, r4) \
movdqa r2, r4; pxor r0, r2; \
pand r3, r0; por r3, r4; \
pxor RNOT, r2; pxor r1, r3; \
por r0, r1; pxor r2, r0; \
pand r4, r2; pand r4, r3; \
pxor r2, r1; pxor r0, r2; \
por r2, r0; pxor r1, r4; \
pxor r3, r0; pxor r4, r3; \
por r0, r4; pxor r2, r3; \
pxor r2, r4;
/* Apply SBOX number WHICH to to the block. */
#define SBOX(which, r0, r1, r2, r3, r4) \
SBOX##which (r0, r1, r2, r3, r4)
/* Apply inverse SBOX number WHICH to to the block. */
#define SBOX_INVERSE(which, r0, r1, r2, r3, r4) \
SBOX##which##_INVERSE (r0, r1, r2, r3, r4)
/* XOR round key into block state in r0,r1,r2,r3. r4 used as temporary. */
#define BLOCK_XOR_KEY(r0, r1, r2, r3, r4, round) \
pbroadcastd ((ctx_keys + (round) * 16 + 0 * 4)(CTX), r4); \
pxor r4, r0; \
pbroadcastd ((ctx_keys + (round) * 16 + 1 * 4)(CTX), r4); \
pxor r4, r1; \
pbroadcastd ((ctx_keys + (round) * 16 + 2 * 4)(CTX), r4); \
pxor r4, r2; \
pbroadcastd ((ctx_keys + (round) * 16 + 3 * 4)(CTX), r4); \
pxor r4, r3;
/* Apply the linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION(r0, r1, r2, r3, r4) \
vec_rol(r0, 13, r4); \
vec_rol(r2, 3, r4); \
pxor r0, r1; \
pxor r2, r1; \
movdqa r0, r4; \
pslld $3, r4; \
pxor r2, r3; \
pxor r4, r3; \
vec_rol(r1, 1, r4); \
vec_rol(r3, 7, r4); \
pxor r1, r0; \
pxor r3, r0; \
movdqa r1, r4; \
pslld $7, r4; \
pxor r3, r2; \
pxor r4, r2; \
vec_rol(r0, 5, r4); \
vec_rol(r2, 22, r4);
/* Apply the inverse linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION_INVERSE(r0, r1, r2, r3, r4) \
vec_ror(r2, 22, r4); \
vec_ror(r0, 5, r4); \
movdqa r1, r4; \
pslld $7, r4; \
pxor r3, r2; \
pxor r4, r2; \
pxor r1, r0; \
pxor r3, r0; \
vec_ror(r3, 7, r4); \
vec_ror(r1, 1, r4); \
movdqa r0, r4; \
pslld $3, r4; \
pxor r2, r3; \
pxor r4, r3; \
pxor r0, r1; \
pxor r2, r1; \
vec_ror(r2, 3, r4); \
vec_ror(r0, 13, r4);
/* Apply a Serpent round to eight parallel blocks. This macro increments
`round'. */
#define ROUND(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round); \
SBOX (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round); \
SBOX (which, b0, b1, b2, b3, b4); \
LINEAR_TRANSFORMATION (na0, na1, na2, na3, na4); \
LINEAR_TRANSFORMATION (nb0, nb1, nb2, nb3, nb4);
/* Apply the last Serpent round to eight parallel blocks. This macro increments
`round'. */
#define ROUND_LAST(round, which, a0, a1, a2, a3, a4, na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, round); \
SBOX (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, round); \
SBOX (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, ((round) + 1)); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, ((round) + 1));
/* Apply an inverse Serpent round to eight parallel blocks. This macro
increments `round'. */
#define ROUND_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
LINEAR_TRANSFORMATION_INVERSE (a0, a1, a2, a3, a4); \
LINEAR_TRANSFORMATION_INVERSE (b0, b1, b2, b3, b4); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round); \
SBOX_INVERSE (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
/* Apply the first inverse Serpent round to eight parallel blocks. This macro
increments `round'. */
#define ROUND_FIRST_INVERSE(round, which, a0, a1, a2, a3, a4, \
na0, na1, na2, na3, na4, \
b0, b1, b2, b3, b4, \
nb0, nb1, nb2, nb3, nb4) \
BLOCK_XOR_KEY (a0, a1, a2, a3, a4, ((round) + 1)); \
BLOCK_XOR_KEY (b0, b1, b2, b3, b4, ((round) + 1)); \
SBOX_INVERSE (which, a0, a1, a2, a3, a4); \
BLOCK_XOR_KEY (na0, na1, na2, na3, na4, round); \
SBOX_INVERSE (which, b0, b1, b2, b3, b4); \
BLOCK_XOR_KEY (nb0, nb1, nb2, nb3, nb4, round);
.text
.align 8
ELF(.type __serpent_enc_blk8,@function;)
__serpent_enc_blk8:
/* input:
* %rdi: ctx, CTX
* RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: eight parallel plaintext
* blocks
* output:
* RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: eight parallel
* ciphertext blocks
*/
CFI_STARTPROC();
pcmpeqd RNOT, RNOT;
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ROUND (0, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (1, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (2, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (3, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (4, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (5, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (6, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND (7, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
ROUND (8, 0, RA4, RA1, RA2, RA0, RA3, RA1, RA3, RA2, RA4, RA0,
RB4, RB1, RB2, RB0, RB3, RB1, RB3, RB2, RB4, RB0);
ROUND (9, 1, RA1, RA3, RA2, RA4, RA0, RA2, RA1, RA4, RA3, RA0,
RB1, RB3, RB2, RB4, RB0, RB2, RB1, RB4, RB3, RB0);
ROUND (10, 2, RA2, RA1, RA4, RA3, RA0, RA4, RA3, RA1, RA0, RA2,
RB2, RB1, RB4, RB3, RB0, RB4, RB3, RB1, RB0, RB2);
ROUND (11, 3, RA4, RA3, RA1, RA0, RA2, RA3, RA1, RA0, RA2, RA4,
RB4, RB3, RB1, RB0, RB2, RB3, RB1, RB0, RB2, RB4);
ROUND (12, 4, RA3, RA1, RA0, RA2, RA4, RA1, RA4, RA3, RA2, RA0,
RB3, RB1, RB0, RB2, RB4, RB1, RB4, RB3, RB2, RB0);
ROUND (13, 5, RA1, RA4, RA3, RA2, RA0, RA4, RA2, RA1, RA3, RA0,
RB1, RB4, RB3, RB2, RB0, RB4, RB2, RB1, RB3, RB0);
ROUND (14, 6, RA4, RA2, RA1, RA3, RA0, RA4, RA2, RA0, RA1, RA3,
RB4, RB2, RB1, RB3, RB0, RB4, RB2, RB0, RB1, RB3);
ROUND (15, 7, RA4, RA2, RA0, RA1, RA3, RA3, RA1, RA2, RA4, RA0,
RB4, RB2, RB0, RB1, RB3, RB3, RB1, RB2, RB4, RB0);
ROUND (16, 0, RA3, RA1, RA2, RA4, RA0, RA1, RA0, RA2, RA3, RA4,
RB3, RB1, RB2, RB4, RB0, RB1, RB0, RB2, RB3, RB4);
ROUND (17, 1, RA1, RA0, RA2, RA3, RA4, RA2, RA1, RA3, RA0, RA4,
RB1, RB0, RB2, RB3, RB4, RB2, RB1, RB3, RB0, RB4);
ROUND (18, 2, RA2, RA1, RA3, RA0, RA4, RA3, RA0, RA1, RA4, RA2,
RB2, RB1, RB3, RB0, RB4, RB3, RB0, RB1, RB4, RB2);
ROUND (19, 3, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA4, RA2, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB4, RB2, RB3);
ROUND (20, 4, RA0, RA1, RA4, RA2, RA3, RA1, RA3, RA0, RA2, RA4,
RB0, RB1, RB4, RB2, RB3, RB1, RB3, RB0, RB2, RB4);
ROUND (21, 5, RA1, RA3, RA0, RA2, RA4, RA3, RA2, RA1, RA0, RA4,
RB1, RB3, RB0, RB2, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND (22, 6, RA3, RA2, RA1, RA0, RA4, RA3, RA2, RA4, RA1, RA0,
RB3, RB2, RB1, RB0, RB4, RB3, RB2, RB4, RB1, RB0);
ROUND (23, 7, RA3, RA2, RA4, RA1, RA0, RA0, RA1, RA2, RA3, RA4,
RB3, RB2, RB4, RB1, RB0, RB0, RB1, RB2, RB3, RB4);
ROUND (24, 0, RA0, RA1, RA2, RA3, RA4, RA1, RA4, RA2, RA0, RA3,
RB0, RB1, RB2, RB3, RB4, RB1, RB4, RB2, RB0, RB3);
ROUND (25, 1, RA1, RA4, RA2, RA0, RA3, RA2, RA1, RA0, RA4, RA3,
RB1, RB4, RB2, RB0, RB3, RB2, RB1, RB0, RB4, RB3);
ROUND (26, 2, RA2, RA1, RA0, RA4, RA3, RA0, RA4, RA1, RA3, RA2,
RB2, RB1, RB0, RB4, RB3, RB0, RB4, RB1, RB3, RB2);
ROUND (27, 3, RA0, RA4, RA1, RA3, RA2, RA4, RA1, RA3, RA2, RA0,
RB0, RB4, RB1, RB3, RB2, RB4, RB1, RB3, RB2, RB0);
ROUND (28, 4, RA4, RA1, RA3, RA2, RA0, RA1, RA0, RA4, RA2, RA3,
RB4, RB1, RB3, RB2, RB0, RB1, RB0, RB4, RB2, RB3);
ROUND (29, 5, RA1, RA0, RA4, RA2, RA3, RA0, RA2, RA1, RA4, RA3,
RB1, RB0, RB4, RB2, RB3, RB0, RB2, RB1, RB4, RB3);
ROUND (30, 6, RA0, RA2, RA1, RA4, RA3, RA0, RA2, RA3, RA1, RA4,
RB0, RB2, RB1, RB4, RB3, RB0, RB2, RB3, RB1, RB4);
ROUND_LAST (31, 7, RA0, RA2, RA3, RA1, RA4, RA4, RA1, RA2, RA0, RA3,
RB0, RB2, RB3, RB1, RB4, RB4, RB1, RB2, RB0, RB3);
transpose_4x4(RA4, RA1, RA2, RA0, RA3, RTMP0, RTMP1);
transpose_4x4(RB4, RB1, RB2, RB0, RB3, RTMP0, RTMP1);
ret;
CFI_ENDPROC();
ELF(.size __serpent_enc_blk8,.-__serpent_enc_blk8;)
.align 8
ELF(.type __serpent_dec_blk8,@function;)
__serpent_dec_blk8:
/* input:
* %rdi: ctx, 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();
pcmpeqd RNOT, RNOT;
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ROUND_FIRST_INVERSE (31, 7, RA0, RA1, RA2, RA3, RA4,
RA3, RA0, RA1, RA4, RA2,
RB0, RB1, RB2, RB3, RB4,
RB3, RB0, RB1, RB4, RB2);
ROUND_INVERSE (30, 6, RA3, RA0, RA1, RA4, RA2, RA0, RA1, RA2, RA4, RA3,
RB3, RB0, RB1, RB4, RB2, RB0, RB1, RB2, RB4, RB3);
ROUND_INVERSE (29, 5, RA0, RA1, RA2, RA4, RA3, RA1, RA3, RA4, RA2, RA0,
RB0, RB1, RB2, RB4, RB3, RB1, RB3, RB4, RB2, RB0);
ROUND_INVERSE (28, 4, RA1, RA3, RA4, RA2, RA0, RA1, RA2, RA4, RA0, RA3,
RB1, RB3, RB4, RB2, RB0, RB1, RB2, RB4, RB0, RB3);
ROUND_INVERSE (27, 3, RA1, RA2, RA4, RA0, RA3, RA4, RA2, RA0, RA1, RA3,
RB1, RB2, RB4, RB0, RB3, RB4, RB2, RB0, RB1, RB3);
ROUND_INVERSE (26, 2, RA4, RA2, RA0, RA1, RA3, RA2, RA3, RA0, RA1, RA4,
RB4, RB2, RB0, RB1, RB3, RB2, RB3, RB0, RB1, RB4);
ROUND_INVERSE (25, 1, RA2, RA3, RA0, RA1, RA4, RA4, RA2, RA1, RA0, RA3,
RB2, RB3, RB0, RB1, RB4, RB4, RB2, RB1, RB0, RB3);
ROUND_INVERSE (24, 0, RA4, RA2, RA1, RA0, RA3, RA4, RA3, RA2, RA0, RA1,
RB4, RB2, RB1, RB0, RB3, RB4, RB3, RB2, RB0, RB1);
ROUND_INVERSE (23, 7, RA4, RA3, RA2, RA0, RA1, RA0, RA4, RA3, RA1, RA2,
RB4, RB3, RB2, RB0, RB1, RB0, RB4, RB3, RB1, RB2);
ROUND_INVERSE (22, 6, RA0, RA4, RA3, RA1, RA2, RA4, RA3, RA2, RA1, RA0,
RB0, RB4, RB3, RB1, RB2, RB4, RB3, RB2, RB1, RB0);
ROUND_INVERSE (21, 5, RA4, RA3, RA2, RA1, RA0, RA3, RA0, RA1, RA2, RA4,
RB4, RB3, RB2, RB1, RB0, RB3, RB0, RB1, RB2, RB4);
ROUND_INVERSE (20, 4, RA3, RA0, RA1, RA2, RA4, RA3, RA2, RA1, RA4, RA0,
RB3, RB0, RB1, RB2, RB4, RB3, RB2, RB1, RB4, RB0);
ROUND_INVERSE (19, 3, RA3, RA2, RA1, RA4, RA0, RA1, RA2, RA4, RA3, RA0,
RB3, RB2, RB1, RB4, RB0, RB1, RB2, RB4, RB3, RB0);
ROUND_INVERSE (18, 2, RA1, RA2, RA4, RA3, RA0, RA2, RA0, RA4, RA3, RA1,
RB1, RB2, RB4, RB3, RB0, RB2, RB0, RB4, RB3, RB1);
ROUND_INVERSE (17, 1, RA2, RA0, RA4, RA3, RA1, RA1, RA2, RA3, RA4, RA0,
RB2, RB0, RB4, RB3, RB1, RB1, RB2, RB3, RB4, RB0);
ROUND_INVERSE (16, 0, RA1, RA2, RA3, RA4, RA0, RA1, RA0, RA2, RA4, RA3,
RB1, RB2, RB3, RB4, RB0, RB1, RB0, RB2, RB4, RB3);
ROUND_INVERSE (15, 7, RA1, RA0, RA2, RA4, RA3, RA4, RA1, RA0, RA3, RA2,
RB1, RB0, RB2, RB4, RB3, RB4, RB1, RB0, RB3, RB2);
ROUND_INVERSE (14, 6, RA4, RA1, RA0, RA3, RA2, RA1, RA0, RA2, RA3, RA4,
RB4, RB1, RB0, RB3, RB2, RB1, RB0, RB2, RB3, RB4);
ROUND_INVERSE (13, 5, RA1, RA0, RA2, RA3, RA4, RA0, RA4, RA3, RA2, RA1,
RB1, RB0, RB2, RB3, RB4, RB0, RB4, RB3, RB2, RB1);
ROUND_INVERSE (12, 4, RA0, RA4, RA3, RA2, RA1, RA0, RA2, RA3, RA1, RA4,
RB0, RB4, RB3, RB2, RB1, RB0, RB2, RB3, RB1, RB4);
ROUND_INVERSE (11, 3, RA0, RA2, RA3, RA1, RA4, RA3, RA2, RA1, RA0, RA4,
RB0, RB2, RB3, RB1, RB4, RB3, RB2, RB1, RB0, RB4);
ROUND_INVERSE (10, 2, RA3, RA2, RA1, RA0, RA4, RA2, RA4, RA1, RA0, RA3,
RB3, RB2, RB1, RB0, RB4, RB2, RB4, RB1, RB0, RB3);
ROUND_INVERSE (9, 1, RA2, RA4, RA1, RA0, RA3, RA3, RA2, RA0, RA1, RA4,
RB2, RB4, RB1, RB0, RB3, RB3, RB2, RB0, RB1, RB4);
ROUND_INVERSE (8, 0, RA3, RA2, RA0, RA1, RA4, RA3, RA4, RA2, RA1, RA0,
RB3, RB2, RB0, RB1, RB4, RB3, RB4, RB2, RB1, RB0);
ROUND_INVERSE (7, 7, RA3, RA4, RA2, RA1, RA0, RA1, RA3, RA4, RA0, RA2,
RB3, RB4, RB2, RB1, RB0, RB1, RB3, RB4, RB0, RB2);
ROUND_INVERSE (6, 6, RA1, RA3, RA4, RA0, RA2, RA3, RA4, RA2, RA0, RA1,
RB1, RB3, RB4, RB0, RB2, RB3, RB4, RB2, RB0, RB1);
ROUND_INVERSE (5, 5, RA3, RA4, RA2, RA0, RA1, RA4, RA1, RA0, RA2, RA3,
RB3, RB4, RB2, RB0, RB1, RB4, RB1, RB0, RB2, RB3);
ROUND_INVERSE (4, 4, RA4, RA1, RA0, RA2, RA3, RA4, RA2, RA0, RA3, RA1,
RB4, RB1, RB0, RB2, RB3, RB4, RB2, RB0, RB3, RB1);
ROUND_INVERSE (3, 3, RA4, RA2, RA0, RA3, RA1, RA0, RA2, RA3, RA4, RA1,
RB4, RB2, RB0, RB3, RB1, RB0, RB2, RB3, RB4, RB1);
ROUND_INVERSE (2, 2, RA0, RA2, RA3, RA4, RA1, RA2, RA1, RA3, RA4, RA0,
RB0, RB2, RB3, RB4, RB1, RB2, RB1, RB3, RB4, RB0);
ROUND_INVERSE (1, 1, RA2, RA1, RA3, RA4, RA0, RA0, RA2, RA4, RA3, RA1,
RB2, RB1, RB3, RB4, RB0, RB0, RB2, RB4, RB3, RB1);
ROUND_INVERSE (0, 0, RA0, RA2, RA4, RA3, RA1, RA0, RA1, RA2, RA3, RA4,
RB0, RB2, RB4, RB3, RB1, RB0, RB1, RB2, RB3, RB4);
transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
ret;
CFI_ENDPROC();
ELF(.size __serpent_dec_blk8,.-__serpent_dec_blk8;)
.align 8
.globl _gcry_serpent_sse2_ctr_enc
ELF(.type _gcry_serpent_sse2_ctr_enc,@function;)
_gcry_serpent_sse2_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (8 blocks)
* %rdx: src (8 blocks)
* %rcx: iv (big endian, 128bit)
*/
CFI_STARTPROC();
/* load IV and byteswap */
movdqu (%rcx), RA0;
movdqa RA0, RTMP0;
pbswap(RTMP0, RTMP1); /* be => le */
pcmpeqd RNOT, RNOT;
psrldq $8, RNOT; /* low: -1, high: 0 */
movdqa RNOT, RTMP2;
paddq RTMP2, RTMP2; /* low: -2, high: 0 */
/* construct IVs */
movdqa RTMP0, RTMP1;
psubq RNOT, RTMP0; /* +1 */
movdqa RTMP0, RA1;
psubq RTMP2, RTMP1; /* +2 */
movdqa RTMP1, RA2;
psubq RTMP2, RTMP0; /* +3 */
movdqa RTMP0, RA3;
psubq RTMP2, RTMP1; /* +4 */
movdqa RTMP1, RB0;
psubq RTMP2, RTMP0; /* +5 */
movdqa RTMP0, RB1;
psubq RTMP2, RTMP1; /* +6 */
movdqa RTMP1, RB2;
psubq RTMP2, RTMP0; /* +7 */
movdqa RTMP0, RB3;
psubq RTMP2, RTMP1; /* +8 */
/* check need for handling 64-bit overflow and carry */
cmpl $0xffffffff, 8(%rcx);
jne .Lno_ctr_carry;
movl 12(%rcx), %eax;
bswapl %eax;
cmpl $-8, %eax;
jb .Lno_ctr_carry;
pslldq $8, RNOT; /* low: 0, high: -1 */
je .Lcarry_RTMP0;
cmpl $-6, %eax;
jb .Lcarry_RB3;
je .Lcarry_RB2;
cmpl $-4, %eax;
jb .Lcarry_RB1;
je .Lcarry_RB0;
cmpl $-2, %eax;
jb .Lcarry_RA3;
je .Lcarry_RA2;
psubq RNOT, RA1;
.Lcarry_RA2:
psubq RNOT, RA2;
.Lcarry_RA3:
psubq RNOT, RA3;
.Lcarry_RB0:
psubq RNOT, RB0;
.Lcarry_RB1:
psubq RNOT, RB1;
.Lcarry_RB2:
psubq RNOT, RB2;
.Lcarry_RB3:
psubq RNOT, RB3;
.Lcarry_RTMP0:
psubq RNOT, RTMP1;
.Lno_ctr_carry:
/* le => be */
pbswap(RA1, RTMP0);
pbswap(RA2, RTMP0);
pbswap(RA3, RTMP0);
pbswap(RB0, RTMP0);
pbswap(RB1, RTMP0);
pbswap(RB2, RTMP0);
pbswap(RB3, RTMP0);
pbswap(RTMP1, RTMP0);
/* store new IV */
movdqu RTMP1, (%rcx);
call __serpent_enc_blk8;
pxor_u((0 * 16)(%rdx), RA4, RTMP0);
pxor_u((1 * 16)(%rdx), RA1, RTMP0);
pxor_u((2 * 16)(%rdx), RA2, RTMP0);
pxor_u((3 * 16)(%rdx), RA0, RTMP0);
pxor_u((4 * 16)(%rdx), RB4, RTMP0);
pxor_u((5 * 16)(%rdx), RB1, RTMP0);
pxor_u((6 * 16)(%rdx), RB2, RTMP0);
pxor_u((7 * 16)(%rdx), RB0, RTMP0);
movdqu RA4, (0 * 16)(%rsi);
movdqu RA1, (1 * 16)(%rsi);
movdqu RA2, (2 * 16)(%rsi);
movdqu RA0, (3 * 16)(%rsi);
movdqu RB4, (4 * 16)(%rsi);
movdqu RB1, (5 * 16)(%rsi);
movdqu RB2, (6 * 16)(%rsi);
movdqu RB0, (7 * 16)(%rsi);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_ctr_enc,.-_gcry_serpent_sse2_ctr_enc;)
.align 8
.globl _gcry_serpent_sse2_cbc_dec
ELF(.type _gcry_serpent_sse2_cbc_dec,@function;)
_gcry_serpent_sse2_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (8 blocks)
* %rdx: src (8 blocks)
* %rcx: iv
*/
CFI_STARTPROC();
movdqu (0 * 16)(%rdx), RA0;
movdqu (1 * 16)(%rdx), RA1;
movdqu (2 * 16)(%rdx), RA2;
movdqu (3 * 16)(%rdx), RA3;
movdqu (4 * 16)(%rdx), RB0;
movdqu (5 * 16)(%rdx), RB1;
movdqu (6 * 16)(%rdx), RB2;
movdqu (7 * 16)(%rdx), RB3;
call __serpent_dec_blk8;
movdqu (7 * 16)(%rdx), RNOT;
pxor_u((%rcx), RA0, RTMP0);
pxor_u((0 * 16)(%rdx), RA1, RTMP0);
pxor_u((1 * 16)(%rdx), RA2, RTMP0);
pxor_u((2 * 16)(%rdx), RA3, RTMP0);
pxor_u((3 * 16)(%rdx), RB0, RTMP0);
pxor_u((4 * 16)(%rdx), RB1, RTMP0);
pxor_u((5 * 16)(%rdx), RB2, RTMP0);
pxor_u((6 * 16)(%rdx), RB3, RTMP0);
movdqu RNOT, (%rcx); /* store new IV */
movdqu RA0, (0 * 16)(%rsi);
movdqu RA1, (1 * 16)(%rsi);
movdqu RA2, (2 * 16)(%rsi);
movdqu RA3, (3 * 16)(%rsi);
movdqu RB0, (4 * 16)(%rsi);
movdqu RB1, (5 * 16)(%rsi);
movdqu RB2, (6 * 16)(%rsi);
movdqu RB3, (7 * 16)(%rsi);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_cbc_dec,.-_gcry_serpent_sse2_cbc_dec;)
.align 8
.globl _gcry_serpent_sse2_cfb_dec
ELF(.type _gcry_serpent_sse2_cfb_dec,@function;)
_gcry_serpent_sse2_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (8 blocks)
* %rdx: src (8 blocks)
* %rcx: iv
*/
CFI_STARTPROC();
/* Load input */
movdqu (%rcx), RA0;
movdqu 0 * 16(%rdx), RA1;
movdqu 1 * 16(%rdx), RA2;
movdqu 2 * 16(%rdx), RA3;
movdqu 3 * 16(%rdx), RB0;
movdqu 4 * 16(%rdx), RB1;
movdqu 5 * 16(%rdx), RB2;
movdqu 6 * 16(%rdx), RB3;
/* Update IV */
movdqu 7 * 16(%rdx), RNOT;
movdqu RNOT, (%rcx);
call __serpent_enc_blk8;
pxor_u((0 * 16)(%rdx), RA4, RTMP0);
pxor_u((1 * 16)(%rdx), RA1, RTMP0);
pxor_u((2 * 16)(%rdx), RA2, RTMP0);
pxor_u((3 * 16)(%rdx), RA0, RTMP0);
pxor_u((4 * 16)(%rdx), RB4, RTMP0);
pxor_u((5 * 16)(%rdx), RB1, RTMP0);
pxor_u((6 * 16)(%rdx), RB2, RTMP0);
pxor_u((7 * 16)(%rdx), RB0, RTMP0);
movdqu RA4, (0 * 16)(%rsi);
movdqu RA1, (1 * 16)(%rsi);
movdqu RA2, (2 * 16)(%rsi);
movdqu RA0, (3 * 16)(%rsi);
movdqu RB4, (4 * 16)(%rsi);
movdqu RB1, (5 * 16)(%rsi);
movdqu RB2, (6 * 16)(%rsi);
movdqu RB0, (7 * 16)(%rsi);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_cfb_dec,.-_gcry_serpent_sse2_cfb_dec;)
.align 8
.globl _gcry_serpent_sse2_ocb_enc
ELF(.type _gcry_serpent_sse2_ocb_enc,@function;)
_gcry_serpent_sse2_ocb_enc:
/* input:
* %rdi: ctx, 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;
movdqu (%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) \
movdqu (n * 16)(%rdx), xreg; \
movdqu (lreg), RNOT; \
pxor RNOT, RTMP0; \
pxor xreg, RTMP1; \
pxor RTMP0, xreg; \
movdqu 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
movdqu RTMP0, (%rcx);
movdqu RTMP1, (%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 __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);
pxor_u((2 * 16)(%rsi), RA2, RTMP0);
pxor_u((3 * 16)(%rsi), RA0, RTMP0);
pxor_u((4 * 16)(%rsi), RB4, RTMP0);
pxor_u((5 * 16)(%rsi), RB1, RTMP0);
pxor_u((6 * 16)(%rsi), RB2, RTMP0);
pxor_u((7 * 16)(%rsi), RB0, RTMP0);
movdqu RA4, (0 * 16)(%rsi);
movdqu RA1, (1 * 16)(%rsi);
movdqu RA2, (2 * 16)(%rsi);
movdqu RA0, (3 * 16)(%rsi);
movdqu RB4, (4 * 16)(%rsi);
movdqu RB1, (5 * 16)(%rsi);
movdqu RB2, (6 * 16)(%rsi);
movdqu RB0, (7 * 16)(%rsi);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_ocb_enc,.-_gcry_serpent_sse2_ocb_enc;)
.align 8
.globl _gcry_serpent_sse2_ocb_dec
ELF(.type _gcry_serpent_sse2_ocb_dec,@function;)
_gcry_serpent_sse2_ocb_dec:
/* input:
* %rdi: ctx, 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) \
movdqu (n * 16)(%rdx), xreg; \
movdqu (lreg), RNOT; \
pxor RNOT, RTMP0; \
pxor RTMP0, xreg; \
movdqu 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
movdqu RTMP0, (%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 __serpent_dec_blk8;
addq $(4 * 8), %rsp;
CFI_ADJUST_CFA_OFFSET(-4 * 8);
movdqu (%r8), RTMP0;
pxor_u((0 * 16)(%rsi), RA0, RTMP1);
pxor_u((1 * 16)(%rsi), RA1, RTMP1);
pxor_u((2 * 16)(%rsi), RA2, RTMP1);
pxor_u((3 * 16)(%rsi), RA3, RTMP1);
pxor_u((4 * 16)(%rsi), RB0, RTMP1);
pxor_u((5 * 16)(%rsi), RB1, RTMP1);
pxor_u((6 * 16)(%rsi), RB2, RTMP1);
pxor_u((7 * 16)(%rsi), RB3, RTMP1);
/* Checksum_i = Checksum_{i-1} xor P_i */
movdqu RA0, (0 * 16)(%rsi);
pxor RA0, RTMP0;
movdqu RA1, (1 * 16)(%rsi);
pxor RA1, RTMP0;
movdqu RA2, (2 * 16)(%rsi);
pxor RA2, RTMP0;
movdqu RA3, (3 * 16)(%rsi);
pxor RA3, RTMP0;
movdqu RB0, (4 * 16)(%rsi);
pxor RB0, RTMP0;
movdqu RB1, (5 * 16)(%rsi);
pxor RB1, RTMP0;
movdqu RB2, (6 * 16)(%rsi);
pxor RB2, RTMP0;
movdqu RB3, (7 * 16)(%rsi);
pxor RB3, RTMP0;
movdqu RTMP0, (%r8);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_ocb_dec,.-_gcry_serpent_sse2_ocb_dec;)
.align 8
.globl _gcry_serpent_sse2_ocb_auth
ELF(.type _gcry_serpent_sse2_ocb_auth,@function;)
_gcry_serpent_sse2_ocb_auth:
/* input:
* %rdi: ctx, 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);
movdqu (%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) \
movdqu (n * 16)(%rsi), xreg; \
movdqu (lreg), RNOT; \
pxor RNOT, RTMP0; \
pxor RTMP0, 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
movdqu RTMP0, (%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 __serpent_enc_blk8;
addq $(4 * 8), %rsp;
CFI_ADJUST_CFA_OFFSET(-4 * 8);
movdqu (%rcx), RTMP0;
pxor RB4, RA4;
pxor RB1, RA1;
pxor RB2, RA2;
pxor RB0, RA0;
pxor RTMP0, RA2;
pxor RA4, RA1;
pxor RA2, RA0;
pxor RA1, RA0;
movdqu RA0, (%rcx);
/* clear the used registers */
pxor RA0, RA0;
pxor RA1, RA1;
pxor RA2, RA2;
pxor RA3, RA3;
pxor RA4, RA4;
pxor RB0, RB0;
pxor RB1, RB1;
pxor RB2, RB2;
pxor RB3, RB3;
pxor RB4, RB4;
pxor RTMP0, RTMP0;
pxor RTMP1, RTMP1;
pxor RTMP2, RTMP2;
pxor RNOT, RNOT;
ret;
CFI_ENDPROC();
ELF(.size _gcry_serpent_sse2_ocb_auth,.-_gcry_serpent_sse2_ocb_auth;)
#endif /*defined(USE_SERPENT)*/
#endif /*__x86_64*/
diff --git a/cipher/serpent.c b/cipher/serpent.c
index 71d843d0..4a20f7dd 100644
--- a/cipher/serpent.c
+++ b/cipher/serpent.c
@@ -1,1789 +1,1789 @@
/* serpent.c - Implementation of the Serpent encryption algorithm.
* Copyright (C) 2003, 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.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bithelp.h"
#include "bufhelp.h"
#include "cipher-internal.h"
#include "cipher-selftest.h"
/* USE_SSE2 indicates whether to compile with AMD64 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_AVX2 indicates whether to compile with AMD64 AVX2 code. */
#undef USE_AVX2
#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# if defined(ENABLE_AVX2_SUPPORT)
# define USE_AVX2 1
# endif
#endif
/* USE_NEON indicates whether to enable ARM NEON assembly code. */
#undef USE_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
# endif
#endif /*ENABLE_NEON_SUPPORT*/
/* Number of rounds per Serpent encrypt/decrypt operation. */
#define ROUNDS 32
/* Magic number, used during generating of the subkeys. */
#define PHI 0x9E3779B9
/* Serpent works on 128 bit blocks. */
typedef u32 serpent_block_t[4];
/* Serpent key, provided by the user. If the original key is shorter
than 256 bits, it is padded. */
typedef u32 serpent_key_t[8];
/* The key schedule consists of 33 128 bit subkeys. */
typedef u32 serpent_subkeys_t[ROUNDS + 1][4];
/* A Serpent context. */
typedef struct serpent_context
{
serpent_subkeys_t keys; /* Generated subkeys. */
#ifdef USE_AVX2
int use_avx2;
#endif
#ifdef USE_NEON
int use_neon;
#endif
} serpent_context_t;
/* Assembly implementations use SystemV ABI, ABI conversion and additional
* stack to store XMM6-XMM15 needed on Win64. */
#undef ASM_FUNC_ABI
#if defined(USE_SSE2) || defined(USE_AVX2)
# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
# define ASM_FUNC_ABI __attribute__((sysv_abi))
# else
# define ASM_FUNC_ABI
# endif
#endif
#ifdef USE_SSE2
/* Assembler implementations of Serpent using SSE2. Process 8 block in
parallel.
*/
extern void _gcry_serpent_sse2_ctr_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *ctr) ASM_FUNC_ABI;
extern void _gcry_serpent_sse2_cbc_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_serpent_sse2_cfb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_serpent_sse2_ocb_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[8]) ASM_FUNC_ABI;
extern void _gcry_serpent_sse2_ocb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[8]) ASM_FUNC_ABI;
extern void _gcry_serpent_sse2_ocb_auth(serpent_context_t *ctx,
const unsigned char *abuf,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[8]) ASM_FUNC_ABI;
#endif
#ifdef USE_AVX2
/* Assembler implementations of Serpent using AVX2. Process 16 block in
parallel.
*/
extern void _gcry_serpent_avx2_ctr_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *ctr) ASM_FUNC_ABI;
extern void _gcry_serpent_avx2_cbc_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_serpent_avx2_cfb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv) ASM_FUNC_ABI;
extern void _gcry_serpent_avx2_ocb_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
extern void _gcry_serpent_avx2_ocb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
extern void _gcry_serpent_avx2_ocb_auth(serpent_context_t *ctx,
const unsigned char *abuf,
unsigned char *offset,
unsigned char *checksum,
const u64 Ls[16]) ASM_FUNC_ABI;
#endif
#ifdef USE_NEON
/* Assembler implementations of Serpent using ARM NEON. Process 8 block in
parallel.
*/
extern void _gcry_serpent_neon_ctr_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *ctr);
extern void _gcry_serpent_neon_cbc_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv);
extern void _gcry_serpent_neon_cfb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *iv);
extern void _gcry_serpent_neon_ocb_enc(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const void *Ls[8]);
extern void _gcry_serpent_neon_ocb_dec(serpent_context_t *ctx,
unsigned char *out,
const unsigned char *in,
unsigned char *offset,
unsigned char *checksum,
const void *Ls[8]);
extern void _gcry_serpent_neon_ocb_auth(serpent_context_t *ctx,
const unsigned char *abuf,
unsigned char *offset,
unsigned char *checksum,
const void *Ls[8]);
#endif
/* A prototype. */
static const char *serpent_test (void);
/*
* These are the S-Boxes of Serpent from following research paper.
*
* D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
* (New York, New York, USA), p. 317–329, National Institute of Standards and
* Technology, 2000.
*
- * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
+ * Paper is also available at: https://www.ii.uib.no/~osvik/pub/aes3.pdf
*
*/
#define SBOX0(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r3 ^= r0; r4 = r1; \
r1 &= r3; r4 ^= r2; \
r1 ^= r0; r0 |= r3; \
r0 ^= r4; r4 ^= r3; \
r3 ^= r2; r2 |= r1; \
r2 ^= r4; r4 = ~r4; \
r4 |= r1; r1 ^= r3; \
r1 ^= r4; r3 |= r0; \
r1 ^= r3; r4 ^= r3; \
\
w = r1; x = r4; y = r2; z = r0; \
}
#define SBOX0_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r2 = ~r2; r4 = r1; \
r1 |= r0; r4 = ~r4; \
r1 ^= r2; r2 |= r4; \
r1 ^= r3; r0 ^= r4; \
r2 ^= r0; r0 &= r3; \
r4 ^= r0; r0 |= r1; \
r0 ^= r2; r3 ^= r4; \
r2 ^= r1; r3 ^= r0; \
r3 ^= r1; \
r2 &= r3; \
r4 ^= r2; \
\
w = r0; x = r4; y = r1; z = r3; \
}
#define SBOX1(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r0 = ~r0; r2 = ~r2; \
r4 = r0; r0 &= r1; \
r2 ^= r0; r0 |= r3; \
r3 ^= r2; r1 ^= r0; \
r0 ^= r4; r4 |= r1; \
r1 ^= r3; r2 |= r0; \
r2 &= r4; r0 ^= r1; \
r1 &= r2; \
r1 ^= r0; r0 &= r2; \
r0 ^= r4; \
\
w = r2; x = r0; y = r3; z = r1; \
}
#define SBOX1_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r1; r1 ^= r3; \
r3 &= r1; r4 ^= r2; \
r3 ^= r0; r0 |= r1; \
r2 ^= r3; r0 ^= r4; \
r0 |= r2; r1 ^= r3; \
r0 ^= r1; r1 |= r3; \
r1 ^= r0; r4 = ~r4; \
r4 ^= r1; r1 |= r0; \
r1 ^= r0; \
r1 |= r4; \
r3 ^= r1; \
\
w = r4; x = r0; y = r3; z = r2; \
}
#define SBOX2(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r0; r0 &= r2; \
r0 ^= r3; r2 ^= r1; \
r2 ^= r0; r3 |= r4; \
r3 ^= r1; r4 ^= r2; \
r1 = r3; r3 |= r4; \
r3 ^= r0; r0 &= r1; \
r4 ^= r0; r1 ^= r3; \
r1 ^= r4; r4 = ~r4; \
\
w = r2; x = r3; y = r1; z = r4; \
}
#define SBOX2_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r2 ^= r3; r3 ^= r0; \
r4 = r3; r3 &= r2; \
r3 ^= r1; r1 |= r2; \
r1 ^= r4; r4 &= r3; \
r2 ^= r3; r4 &= r0; \
r4 ^= r2; r2 &= r1; \
r2 |= r0; r3 = ~r3; \
r2 ^= r3; r0 ^= r3; \
r0 &= r1; r3 ^= r4; \
r3 ^= r0; \
\
w = r1; x = r4; y = r2; z = r3; \
}
#define SBOX3(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r0; r0 |= r3; \
r3 ^= r1; r1 &= r4; \
r4 ^= r2; r2 ^= r3; \
r3 &= r0; r4 |= r1; \
r3 ^= r4; r0 ^= r1; \
r4 &= r0; r1 ^= r3; \
r4 ^= r2; r1 |= r0; \
r1 ^= r2; r0 ^= r3; \
r2 = r1; r1 |= r3; \
r1 ^= r0; \
\
w = r1; x = r2; y = r3; z = r4; \
}
#define SBOX3_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r2; r2 ^= r1; \
r0 ^= r2; r4 &= r2; \
r4 ^= r0; r0 &= r1; \
r1 ^= r3; r3 |= r4; \
r2 ^= r3; r0 ^= r3; \
r1 ^= r4; r3 &= r2; \
r3 ^= r1; r1 ^= r0; \
r1 |= r2; r0 ^= r3; \
r1 ^= r4; \
r0 ^= r1; \
\
w = r2; x = r1; y = r3; z = r0; \
}
#define SBOX4(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r1 ^= r3; r3 = ~r3; \
r2 ^= r3; r3 ^= r0; \
r4 = r1; r1 &= r3; \
r1 ^= r2; r4 ^= r3; \
r0 ^= r4; r2 &= r4; \
r2 ^= r0; r0 &= r1; \
r3 ^= r0; r4 |= r1; \
r4 ^= r0; r0 |= r3; \
r0 ^= r2; r2 &= r3; \
r0 = ~r0; r4 ^= r2; \
\
w = r1; x = r4; y = r0; z = r3; \
}
#define SBOX4_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r2; r2 &= r3; \
r2 ^= r1; r1 |= r3; \
r1 &= r0; r4 ^= r2; \
r4 ^= r1; r1 &= r2; \
r0 = ~r0; r3 ^= r4; \
r1 ^= r3; r3 &= r0; \
r3 ^= r2; r0 ^= r1; \
r2 &= r0; r3 ^= r0; \
r2 ^= r4; \
r2 |= r3; r3 ^= r0; \
r2 ^= r1; \
\
w = r0; x = r3; y = r2; z = r4; \
}
#define SBOX5(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r0 ^= r1; r1 ^= r3; \
r3 = ~r3; r4 = r1; \
r1 &= r0; r2 ^= r3; \
r1 ^= r2; r2 |= r4; \
r4 ^= r3; r3 &= r1; \
r3 ^= r0; r4 ^= r1; \
r4 ^= r2; r2 ^= r0; \
r0 &= r3; r2 = ~r2; \
r0 ^= r4; r4 |= r3; \
r2 ^= r4; \
\
w = r1; x = r3; y = r0; z = r2; \
}
#define SBOX5_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r1 = ~r1; r4 = r3; \
r2 ^= r1; r3 |= r0; \
r3 ^= r2; r2 |= r1; \
r2 &= r0; r4 ^= r3; \
r2 ^= r4; r4 |= r0; \
r4 ^= r1; r1 &= r2; \
r1 ^= r3; r4 ^= r2; \
r3 &= r4; r4 ^= r1; \
r3 ^= r4; r4 = ~r4; \
r3 ^= r0; \
\
w = r1; x = r4; y = r3; z = r2; \
}
#define SBOX6(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r2 = ~r2; r4 = r3; \
r3 &= r0; r0 ^= r4; \
r3 ^= r2; r2 |= r4; \
r1 ^= r3; r2 ^= r0; \
r0 |= r1; r2 ^= r1; \
r4 ^= r0; r0 |= r3; \
r0 ^= r2; r4 ^= r3; \
r4 ^= r0; r3 = ~r3; \
r2 &= r4; \
r2 ^= r3; \
\
w = r0; x = r1; y = r4; z = r2; \
}
#define SBOX6_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r0 ^= r2; r4 = r2; \
r2 &= r0; r4 ^= r3; \
r2 = ~r2; r3 ^= r1; \
r2 ^= r3; r4 |= r0; \
r0 ^= r2; r3 ^= r4; \
r4 ^= r1; r1 &= r3; \
r1 ^= r0; r0 ^= r3; \
r0 |= r2; r3 ^= r1; \
r4 ^= r0; \
\
w = r1; x = r2; y = r4; z = r3; \
}
#define SBOX7(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r1; r1 |= r2; \
r1 ^= r3; r4 ^= r2; \
r2 ^= r1; r3 |= r4; \
r3 &= r0; r4 ^= r2; \
r3 ^= r1; r1 |= r4; \
r1 ^= r0; r0 |= r4; \
r0 ^= r2; r1 ^= r4; \
r2 ^= r1; r1 &= r0; \
r1 ^= r4; r2 = ~r2; \
r2 |= r0; \
r4 ^= r2; \
\
w = r4; x = r3; y = r1; z = r0; \
}
#define SBOX7_INVERSE(r0, r1, r2, r3, w, x, y, z) \
{ \
u32 r4; \
\
r4 = r2; r2 ^= r0; \
r0 &= r3; r4 |= r3; \
r2 = ~r2; r3 ^= r1; \
r1 |= r0; r0 ^= r2; \
r2 &= r4; r3 &= r4; \
r1 ^= r2; r2 ^= r0; \
r0 |= r2; r4 ^= r1; \
r0 ^= r3; r3 ^= r4; \
r4 |= r0; r3 ^= r2; \
r4 ^= r2; \
\
w = r3; x = r0; y = r1; z = r4; \
}
/* XOR BLOCK1 into BLOCK0. */
#define BLOCK_XOR(block0, block1) \
{ \
block0[0] ^= block1[0]; \
block0[1] ^= block1[1]; \
block0[2] ^= block1[2]; \
block0[3] ^= block1[3]; \
}
/* Copy BLOCK_SRC to BLOCK_DST. */
#define BLOCK_COPY(block_dst, block_src) \
{ \
block_dst[0] = block_src[0]; \
block_dst[1] = block_src[1]; \
block_dst[2] = block_src[2]; \
block_dst[3] = block_src[3]; \
}
/* Apply SBOX number WHICH to to the block found in ARRAY0, writing
the output to the block found in ARRAY1. */
#define SBOX(which, array0, array1) \
SBOX##which (array0[0], array0[1], array0[2], array0[3], \
array1[0], array1[1], array1[2], array1[3]);
/* Apply inverse SBOX number WHICH to to the block found in ARRAY0, writing
the output to the block found in ARRAY1. */
#define SBOX_INVERSE(which, array0, array1) \
SBOX##which##_INVERSE (array0[0], array0[1], array0[2], array0[3], \
array1[0], array1[1], array1[2], array1[3]);
/* Apply the linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION(block) \
{ \
block[0] = rol (block[0], 13); \
block[2] = rol (block[2], 3); \
block[1] = block[1] ^ block[0] ^ block[2]; \
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
block[1] = rol (block[1], 1); \
block[3] = rol (block[3], 7); \
block[0] = block[0] ^ block[1] ^ block[3]; \
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
block[0] = rol (block[0], 5); \
block[2] = rol (block[2], 22); \
}
/* Apply the inverse linear transformation to BLOCK. */
#define LINEAR_TRANSFORMATION_INVERSE(block) \
{ \
block[2] = ror (block[2], 22); \
block[0] = ror (block[0] , 5); \
block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
block[0] = block[0] ^ block[1] ^ block[3]; \
block[3] = ror (block[3], 7); \
block[1] = ror (block[1], 1); \
block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
block[1] = block[1] ^ block[0] ^ block[2]; \
block[2] = ror (block[2], 3); \
block[0] = ror (block[0], 13); \
}
/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage.
This macro increments `round'. */
#define ROUND(which, subkeys, block, block_tmp) \
{ \
BLOCK_XOR (block, subkeys[round]); \
round++; \
SBOX (which, block, block_tmp); \
LINEAR_TRANSFORMATION (block_tmp); \
BLOCK_COPY (block, block_tmp); \
}
/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
storage. The result will be stored in BLOCK_TMP. This macro
increments `round'. */
#define ROUND_LAST(which, subkeys, block, block_tmp) \
{ \
BLOCK_XOR (block, subkeys[round]); \
round++; \
SBOX (which, block, block_tmp); \
BLOCK_XOR (block_tmp, subkeys[round]); \
round++; \
}
/* Apply an inverse Serpent round to BLOCK, using the SBOX number
WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as
temporary storage. This macro increments `round'. */
#define ROUND_INVERSE(which, subkey, block, block_tmp) \
{ \
LINEAR_TRANSFORMATION_INVERSE (block); \
SBOX_INVERSE (which, block, block_tmp); \
BLOCK_XOR (block_tmp, subkey[round]); \
round--; \
BLOCK_COPY (block, block_tmp); \
}
/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
storage. The result will be stored in BLOCK_TMP. This macro
increments `round'. */
#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
{ \
BLOCK_XOR (block, subkeys[round]); \
round--; \
SBOX_INVERSE (which, block, block_tmp); \
BLOCK_XOR (block_tmp, subkeys[round]); \
round--; \
}
/* Convert the user provided key KEY of KEY_LENGTH bytes into the
internally used format. */
static void
serpent_key_prepare (const byte *key, unsigned int key_length,
serpent_key_t key_prepared)
{
int i;
/* Copy key. */
key_length /= 4;
for (i = 0; i < key_length; i++)
key_prepared[i] = buf_get_le32 (key + i * 4);
if (i < 8)
{
/* Key must be padded according to the Serpent
specification. */
key_prepared[i] = 0x00000001;
for (i++; i < 8; i++)
key_prepared[i] = 0;
}
}
/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */
static void
serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
{
u32 w[8]; /* The `prekey'. */
u32 ws[4];
u32 wt[4];
/* Initialize with key values. */
w[0] = key[0];
w[1] = key[1];
w[2] = key[2];
w[3] = key[3];
w[4] = key[4];
w[5] = key[5];
w[6] = key[6];
w[7] = key[7];
/* Expand to intermediate key using the affine recurrence. */
#define EXPAND_KEY4(wo, r) \
wo[0] = w[(r+0)%8] = \
rol (w[(r+0)%8] ^ w[(r+3)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ PHI ^ (r+0), 11); \
wo[1] = w[(r+1)%8] = \
rol (w[(r+1)%8] ^ w[(r+4)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ PHI ^ (r+1), 11); \
wo[2] = w[(r+2)%8] = \
rol (w[(r+2)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ w[(r+1)%8] ^ PHI ^ (r+2), 11); \
wo[3] = w[(r+3)%8] = \
rol (w[(r+3)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ w[(r+2)%8] ^ PHI ^ (r+3), 11);
#define EXPAND_KEY(r) \
EXPAND_KEY4(ws, (r)); \
EXPAND_KEY4(wt, (r + 4));
/* Calculate subkeys via S-Boxes, in bitslice mode. */
EXPAND_KEY (0); SBOX (3, ws, subkeys[0]); SBOX (2, wt, subkeys[1]);
EXPAND_KEY (8); SBOX (1, ws, subkeys[2]); SBOX (0, wt, subkeys[3]);
EXPAND_KEY (16); SBOX (7, ws, subkeys[4]); SBOX (6, wt, subkeys[5]);
EXPAND_KEY (24); SBOX (5, ws, subkeys[6]); SBOX (4, wt, subkeys[7]);
EXPAND_KEY (32); SBOX (3, ws, subkeys[8]); SBOX (2, wt, subkeys[9]);
EXPAND_KEY (40); SBOX (1, ws, subkeys[10]); SBOX (0, wt, subkeys[11]);
EXPAND_KEY (48); SBOX (7, ws, subkeys[12]); SBOX (6, wt, subkeys[13]);
EXPAND_KEY (56); SBOX (5, ws, subkeys[14]); SBOX (4, wt, subkeys[15]);
EXPAND_KEY (64); SBOX (3, ws, subkeys[16]); SBOX (2, wt, subkeys[17]);
EXPAND_KEY (72); SBOX (1, ws, subkeys[18]); SBOX (0, wt, subkeys[19]);
EXPAND_KEY (80); SBOX (7, ws, subkeys[20]); SBOX (6, wt, subkeys[21]);
EXPAND_KEY (88); SBOX (5, ws, subkeys[22]); SBOX (4, wt, subkeys[23]);
EXPAND_KEY (96); SBOX (3, ws, subkeys[24]); SBOX (2, wt, subkeys[25]);
EXPAND_KEY (104); SBOX (1, ws, subkeys[26]); SBOX (0, wt, subkeys[27]);
EXPAND_KEY (112); SBOX (7, ws, subkeys[28]); SBOX (6, wt, subkeys[29]);
EXPAND_KEY (120); SBOX (5, ws, subkeys[30]); SBOX (4, wt, subkeys[31]);
EXPAND_KEY4 (ws, 128); SBOX (3, ws, subkeys[32]);
wipememory (ws, sizeof (ws));
wipememory (wt, sizeof (wt));
wipememory (w, sizeof (w));
}
/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
static void
serpent_setkey_internal (serpent_context_t *context,
const byte *key, unsigned int key_length)
{
serpent_key_t key_prepared;
serpent_key_prepare (key, key_length, key_prepared);
serpent_subkeys_generate (key_prepared, context->keys);
#ifdef USE_AVX2
context->use_avx2 = 0;
if ((_gcry_get_hw_features () & HWF_INTEL_AVX2))
{
context->use_avx2 = 1;
}
#endif
#ifdef USE_NEON
context->use_neon = 0;
if ((_gcry_get_hw_features () & HWF_ARM_NEON))
{
context->use_neon = 1;
}
#endif
wipememory (key_prepared, sizeof(key_prepared));
}
/* 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,
gcry_cipher_hd_t hd)
{
serpent_context_t *context = ctx;
static const char *serpent_test_ret;
static int serpent_init_done;
gcry_err_code_t ret = GPG_ERR_NO_ERROR;
(void)hd;
if (! serpent_init_done)
{
/* Execute a self-test the first time, Serpent is used. */
serpent_init_done = 1;
serpent_test_ret = serpent_test ();
if (serpent_test_ret)
log_error ("Serpent test failure: %s\n", serpent_test_ret);
}
if (serpent_test_ret)
ret = GPG_ERR_SELFTEST_FAILED;
else
serpent_setkey_internal (context, key, key_length);
return ret;
}
static void
serpent_encrypt_internal (serpent_context_t *context,
const byte *input, byte *output)
{
serpent_block_t b, b_next;
int round = 0;
b[0] = buf_get_le32 (input + 0);
b[1] = buf_get_le32 (input + 4);
b[2] = buf_get_le32 (input + 8);
b[3] = buf_get_le32 (input + 12);
ROUND (0, context->keys, b, b_next);
ROUND (1, context->keys, b, b_next);
ROUND (2, context->keys, b, b_next);
ROUND (3, context->keys, b, b_next);
ROUND (4, context->keys, b, b_next);
ROUND (5, context->keys, b, b_next);
ROUND (6, context->keys, b, b_next);
ROUND (7, context->keys, b, b_next);
ROUND (0, context->keys, b, b_next);
ROUND (1, context->keys, b, b_next);
ROUND (2, context->keys, b, b_next);
ROUND (3, context->keys, b, b_next);
ROUND (4, context->keys, b, b_next);
ROUND (5, context->keys, b, b_next);
ROUND (6, context->keys, b, b_next);
ROUND (7, context->keys, b, b_next);
ROUND (0, context->keys, b, b_next);
ROUND (1, context->keys, b, b_next);
ROUND (2, context->keys, b, b_next);
ROUND (3, context->keys, b, b_next);
ROUND (4, context->keys, b, b_next);
ROUND (5, context->keys, b, b_next);
ROUND (6, context->keys, b, b_next);
ROUND (7, context->keys, b, b_next);
ROUND (0, context->keys, b, b_next);
ROUND (1, context->keys, b, b_next);
ROUND (2, context->keys, b, b_next);
ROUND (3, context->keys, b, b_next);
ROUND (4, context->keys, b, b_next);
ROUND (5, context->keys, b, b_next);
ROUND (6, context->keys, b, b_next);
ROUND_LAST (7, context->keys, b, b_next);
buf_put_le32 (output + 0, b_next[0]);
buf_put_le32 (output + 4, b_next[1]);
buf_put_le32 (output + 8, b_next[2]);
buf_put_le32 (output + 12, b_next[3]);
}
static void
serpent_decrypt_internal (serpent_context_t *context,
const byte *input, byte *output)
{
serpent_block_t b, b_next;
int round = ROUNDS;
b_next[0] = buf_get_le32 (input + 0);
b_next[1] = buf_get_le32 (input + 4);
b_next[2] = buf_get_le32 (input + 8);
b_next[3] = buf_get_le32 (input + 12);
ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
ROUND_INVERSE (6, context->keys, b, b_next);
ROUND_INVERSE (5, context->keys, b, b_next);
ROUND_INVERSE (4, context->keys, b, b_next);
ROUND_INVERSE (3, context->keys, b, b_next);
ROUND_INVERSE (2, context->keys, b, b_next);
ROUND_INVERSE (1, context->keys, b, b_next);
ROUND_INVERSE (0, context->keys, b, b_next);
ROUND_INVERSE (7, context->keys, b, b_next);
ROUND_INVERSE (6, context->keys, b, b_next);
ROUND_INVERSE (5, context->keys, b, b_next);
ROUND_INVERSE (4, context->keys, b, b_next);
ROUND_INVERSE (3, context->keys, b, b_next);
ROUND_INVERSE (2, context->keys, b, b_next);
ROUND_INVERSE (1, context->keys, b, b_next);
ROUND_INVERSE (0, context->keys, b, b_next);
ROUND_INVERSE (7, context->keys, b, b_next);
ROUND_INVERSE (6, context->keys, b, b_next);
ROUND_INVERSE (5, context->keys, b, b_next);
ROUND_INVERSE (4, context->keys, b, b_next);
ROUND_INVERSE (3, context->keys, b, b_next);
ROUND_INVERSE (2, context->keys, b, b_next);
ROUND_INVERSE (1, context->keys, b, b_next);
ROUND_INVERSE (0, context->keys, b, b_next);
ROUND_INVERSE (7, context->keys, b, b_next);
ROUND_INVERSE (6, context->keys, b, b_next);
ROUND_INVERSE (5, context->keys, b, b_next);
ROUND_INVERSE (4, context->keys, b, b_next);
ROUND_INVERSE (3, context->keys, b, b_next);
ROUND_INVERSE (2, context->keys, b, b_next);
ROUND_INVERSE (1, context->keys, b, b_next);
ROUND_INVERSE (0, context->keys, b, b_next);
buf_put_le32 (output + 0, b_next[0]);
buf_put_le32 (output + 4, b_next[1]);
buf_put_le32 (output + 8, b_next[2]);
buf_put_le32 (output + 12, b_next[3]);
}
static unsigned int
serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
{
serpent_context_t *context = ctx;
serpent_encrypt_internal (context, buffer_in, buffer_out);
return /*burn_stack*/ (2 * sizeof (serpent_block_t));
}
static unsigned int
serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
{
serpent_context_t *context = ctx;
serpent_decrypt_internal (context, buffer_in, buffer_out);
return /*burn_stack*/ (2 * sizeof (serpent_block_t));
}
/* 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
_gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
serpent_context_t *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned char tmpbuf[sizeof(serpent_block_t)];
int burn_stack_depth = 2 * sizeof (serpent_block_t);
#ifdef USE_AVX2
if (ctx->use_avx2)
{
int did_use_avx2 = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_serpent_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
nblocks -= 16;
outbuf += 16 * sizeof(serpent_block_t);
inbuf += 16 * sizeof(serpent_block_t);
did_use_avx2 = 1;
}
if (did_use_avx2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic/sse2 code to handle smaller chunks... */
/* TODO: use caching instead? */
}
#endif
#ifdef USE_SSE2
{
int did_use_sse2 = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_sse2_ctr_enc(ctx, outbuf, inbuf, ctr);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_sse2 = 1;
}
if (did_use_sse2)
{
/* serpent-sse2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
/* TODO: use caching instead? */
}
#endif
#ifdef USE_NEON
if (ctx->use_neon)
{
int did_use_neon = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_neon_ctr_enc(ctx, outbuf, inbuf, ctr);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_neon = 1;
}
if (did_use_neon)
{
/* serpent-neon assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
/* TODO: use caching instead? */
}
#endif
for ( ;nblocks; nblocks-- )
{
/* Encrypt the counter. */
serpent_encrypt_internal(ctx, ctr, tmpbuf);
/* XOR the input with the encrypted counter and store in output. */
cipher_block_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t));
outbuf += sizeof(serpent_block_t);
inbuf += sizeof(serpent_block_t);
/* Increment the counter. */
cipher_block_add(ctr, 1, sizeof(serpent_block_t));
}
wipememory(tmpbuf, sizeof(tmpbuf));
_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. */
void
_gcry_serpent_cbc_dec(void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
serpent_context_t *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
unsigned char savebuf[sizeof(serpent_block_t)];
int burn_stack_depth = 2 * sizeof (serpent_block_t);
#ifdef USE_AVX2
if (ctx->use_avx2)
{
int did_use_avx2 = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_serpent_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
nblocks -= 16;
outbuf += 16 * sizeof(serpent_block_t);
inbuf += 16 * sizeof(serpent_block_t);
did_use_avx2 = 1;
}
if (did_use_avx2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic/sse2 code to handle smaller chunks... */
}
#endif
#ifdef USE_SSE2
{
int did_use_sse2 = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_sse2_cbc_dec(ctx, outbuf, inbuf, iv);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_sse2 = 1;
}
if (did_use_sse2)
{
/* serpent-sse2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_NEON
if (ctx->use_neon)
{
int did_use_neon = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_neon_cbc_dec(ctx, outbuf, inbuf, iv);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_neon = 1;
}
if (did_use_neon)
{
/* serpent-neon assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
for ( ;nblocks; nblocks-- )
{
/* INBUF is needed later and it may be identical to OUTBUF, so store
the intermediate result to SAVEBUF. */
serpent_decrypt_internal (ctx, inbuf, savebuf);
cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf,
sizeof(serpent_block_t));
inbuf += sizeof(serpent_block_t);
outbuf += sizeof(serpent_block_t);
}
wipememory(savebuf, sizeof(savebuf));
_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. */
void
_gcry_serpent_cfb_dec(void *context, unsigned char *iv,
void *outbuf_arg, const void *inbuf_arg,
size_t nblocks)
{
serpent_context_t *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
int burn_stack_depth = 2 * sizeof (serpent_block_t);
#ifdef USE_AVX2
if (ctx->use_avx2)
{
int did_use_avx2 = 0;
/* Process data in 16 block chunks. */
while (nblocks >= 16)
{
_gcry_serpent_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
nblocks -= 16;
outbuf += 16 * sizeof(serpent_block_t);
inbuf += 16 * sizeof(serpent_block_t);
did_use_avx2 = 1;
}
if (did_use_avx2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic/sse2 code to handle smaller chunks... */
}
#endif
#ifdef USE_SSE2
{
int did_use_sse2 = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_sse2_cfb_dec(ctx, outbuf, inbuf, iv);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_sse2 = 1;
}
if (did_use_sse2)
{
/* serpent-sse2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_NEON
if (ctx->use_neon)
{
int did_use_neon = 0;
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
_gcry_serpent_neon_cfb_dec(ctx, outbuf, inbuf, iv);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_neon = 1;
}
if (did_use_neon)
{
/* serpent-neon assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
for ( ;nblocks; nblocks-- )
{
serpent_encrypt_internal(ctx, iv, iv);
cipher_block_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t));
outbuf += sizeof(serpent_block_t);
inbuf += sizeof(serpent_block_t);
}
_gcry_burn_stack(burn_stack_depth);
}
/* Bulk encryption/decryption of complete blocks in OCB mode. */
size_t
_gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
const void *inbuf_arg, size_t nblocks, int encrypt)
{
#if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
serpent_context_t *ctx = (void *)&c->context.c;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
int burn_stack_depth = 2 * sizeof (serpent_block_t);
u64 blkn = c->u_mode.ocb.data_nblocks;
#else
(void)c;
(void)outbuf_arg;
(void)inbuf_arg;
(void)encrypt;
#endif
#ifdef USE_AVX2
if (ctx->use_avx2)
{
int did_use_avx2 = 0;
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_serpent_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
else
_gcry_serpent_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
nblocks -= 16;
outbuf += 16 * sizeof(serpent_block_t);
inbuf += 16 * sizeof(serpent_block_t);
did_use_avx2 = 1;
}
}
if (did_use_avx2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_SSE2
{
int did_use_sse2 = 0;
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];
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_serpent_sse2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
else
_gcry_serpent_sse2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_sse2 = 1;
}
}
if (did_use_sse2)
{
/* serpent-sse2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_NEON
if (ctx->use_neon)
{
int did_use_neon = 0;
const void *Ls[8];
unsigned int n = 8 - (blkn % 8);
const void **l;
if (nblocks >= 8)
{
Ls[(0 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(1 + n) % 8] = c->u_mode.ocb.L[1];
Ls[(2 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(3 + n) % 8] = c->u_mode.ocb.L[2];
Ls[(4 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(5 + n) % 8] = c->u_mode.ocb.L[1];
Ls[(6 + n) % 8] = c->u_mode.ocb.L[0];
l = &Ls[(7 + n) % 8];
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
blkn += 8;
*l = ocb_get_l(c, blkn - blkn % 8);
if (encrypt)
_gcry_serpent_neon_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
else
_gcry_serpent_neon_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
c->u_ctr.ctr, Ls);
nblocks -= 8;
outbuf += 8 * sizeof(serpent_block_t);
inbuf += 8 * sizeof(serpent_block_t);
did_use_neon = 1;
}
}
if (did_use_neon)
{
/* serpent-neon assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
c->u_mode.ocb.data_nblocks = blkn;
if (burn_stack_depth)
_gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
#endif
return nblocks;
}
/* Bulk authentication of complete blocks in OCB mode. */
size_t
_gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
size_t nblocks)
{
#if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
serpent_context_t *ctx = (void *)&c->context.c;
const unsigned char *abuf = abuf_arg;
int burn_stack_depth = 2 * sizeof(serpent_block_t);
u64 blkn = c->u_mode.ocb.aad_nblocks;
#else
(void)c;
(void)abuf_arg;
#endif
#ifdef USE_AVX2
if (ctx->use_avx2)
{
int did_use_avx2 = 0;
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_serpent_avx2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
c->u_mode.ocb.aad_sum, Ls);
nblocks -= 16;
abuf += 16 * sizeof(serpent_block_t);
did_use_avx2 = 1;
}
}
if (did_use_avx2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_SSE2
{
int did_use_sse2 = 0;
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];
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_serpent_sse2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
c->u_mode.ocb.aad_sum, Ls);
nblocks -= 8;
abuf += 8 * sizeof(serpent_block_t);
did_use_sse2 = 1;
}
}
if (did_use_sse2)
{
/* serpent-avx2 assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#ifdef USE_NEON
if (ctx->use_neon)
{
int did_use_neon = 0;
const void *Ls[8];
unsigned int n = 8 - (blkn % 8);
const void **l;
if (nblocks >= 8)
{
Ls[(0 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(1 + n) % 8] = c->u_mode.ocb.L[1];
Ls[(2 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(3 + n) % 8] = c->u_mode.ocb.L[2];
Ls[(4 + n) % 8] = c->u_mode.ocb.L[0];
Ls[(5 + n) % 8] = c->u_mode.ocb.L[1];
Ls[(6 + n) % 8] = c->u_mode.ocb.L[0];
l = &Ls[(7 + n) % 8];
/* Process data in 8 block chunks. */
while (nblocks >= 8)
{
blkn += 8;
*l = ocb_get_l(c, blkn - blkn % 8);
_gcry_serpent_neon_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
c->u_mode.ocb.aad_sum, Ls);
nblocks -= 8;
abuf += 8 * sizeof(serpent_block_t);
did_use_neon = 1;
}
}
if (did_use_neon)
{
/* serpent-neon assembly code does not use stack */
if (nblocks == 0)
burn_stack_depth = 0;
}
/* Use generic code to handle smaller chunks... */
}
#endif
#if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
c->u_mode.ocb.aad_nblocks = blkn;
if (burn_stack_depth)
_gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
#endif
return nblocks;
}
/* Run the self-tests for SERPENT-CTR-128, tests IV increment of bulk CTR
encryption. Returns NULL on success. */
static const char*
selftest_ctr_128 (void)
{
const int nblocks = 16+8+1;
const int blocksize = sizeof(serpent_block_t);
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);
}
/* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption.
Returns NULL on success. */
static const char*
selftest_cbc_128 (void)
{
const int nblocks = 16+8+2;
const int blocksize = sizeof(serpent_block_t);
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);
}
/* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption.
Returns NULL on success. */
static const char*
selftest_cfb_128 (void)
{
const int nblocks = 16+8+2;
const int blocksize = sizeof(serpent_block_t);
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 test. */
static const char *
serpent_test (void)
{
serpent_context_t context;
unsigned char scratch[16];
unsigned int i;
const char *r;
static struct test
{
int key_length;
unsigned char key[32];
unsigned char text_plain[16];
unsigned char text_cipher[16];
} test_data[] =
{
{
16,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E",
"\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D"
},
{
24,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E",
"\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9"
},
{
32,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E",
"\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B"
},
{
32,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
"\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C"
},
{
0
},
};
for (i = 0; test_data[i].key_length; i++)
{
serpent_setkey_internal (&context, test_data[i].key,
test_data[i].key_length);
serpent_encrypt_internal (&context, test_data[i].text_plain, scratch);
if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
switch (test_data[i].key_length)
{
case 16:
return "Serpent-128 test encryption failed.";
case 24:
return "Serpent-192 test encryption failed.";
case 32:
return "Serpent-256 test encryption failed.";
}
serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch);
if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
switch (test_data[i].key_length)
{
case 16:
return "Serpent-128 test decryption failed.";
case 24:
return "Serpent-192 test decryption failed.";
case 32:
return "Serpent-256 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 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 },
{"1.3.6.1.4.1.11591.13.2.3", GCRY_CIPHER_MODE_OFB },
{"1.3.6.1.4.1.11591.13.2.4", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
static 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 },
{"1.3.6.1.4.1.11591.13.2.23", GCRY_CIPHER_MODE_OFB },
{"1.3.6.1.4.1.11591.13.2.24", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
static 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 },
{"1.3.6.1.4.1.11591.13.2.43", GCRY_CIPHER_MODE_OFB },
{"1.3.6.1.4.1.11591.13.2.44", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
static const char *serpent128_aliases[] =
{
"SERPENT",
"SERPENT-128",
NULL
};
static const char *serpent192_aliases[] =
{
"SERPENT-192",
NULL
};
static const char *serpent256_aliases[] =
{
"SERPENT-256",
NULL
};
gcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
{
GCRY_CIPHER_SERPENT128, {0, 0},
"SERPENT128", serpent128_aliases, serpent128_oids, 16, 128,
sizeof (serpent_context_t),
serpent_setkey, serpent_encrypt, serpent_decrypt
};
gcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
{
GCRY_CIPHER_SERPENT192, {0, 0},
"SERPENT192", serpent192_aliases, serpent192_oids, 16, 192,
sizeof (serpent_context_t),
serpent_setkey, serpent_encrypt, serpent_decrypt
};
gcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
{
GCRY_CIPHER_SERPENT256, {0, 0},
"SERPENT256", serpent256_aliases, serpent256_oids, 16, 256,
sizeof (serpent_context_t),
serpent_setkey, serpent_encrypt, serpent_decrypt
};
diff --git a/cipher/sha1-armv7-neon.S b/cipher/sha1-armv7-neon.S
index 61cc541c..3da106ac 100644
--- a/cipher/sha1-armv7-neon.S
+++ b/cipher/sha1-armv7-neon.S
@@ -1,526 +1,526 @@
/* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
* Copyright (C) 2013-2014 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/>.
+ * License along with this program; if not, see <https://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) && defined(USE_SHA1)
.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
/* Context structure */
#define state_h0 0
#define state_h1 4
#define state_h2 8
#define state_h3 12
#define state_h4 16
/* Constants */
#define K1 0x5A827999
#define K2 0x6ED9EBA1
#define K3 0x8F1BBCDC
#define K4 0xCA62C1D6
.align 4
gcry_sha1_armv7_neon_K_VEC:
.LK_VEC:
.LK1: .long K1, K1, K1, K1
.LK2: .long K2, K2, K2, K2
.LK3: .long K3, K3, K3, K3
.LK4: .long K4, K4, K4, K4
/* Register macros */
#define RSTATE r0
#define RDATA r1
#define RNBLKS r2
#define ROLDSTACK r3
#define RWK lr
#define _a r4
#define _b r5
#define _c r6
#define _d r7
#define _e r8
#define RT0 r9
#define RT1 r10
#define RT2 r11
#define RT3 r12
#define W0 q0
#define W1 q1
#define W2 q2
#define W3 q3
#define W4 q4
#define W5 q5
#define W6 q6
#define W7 q7
#define tmp0 q8
#define tmp1 q9
#define tmp2 q10
#define tmp3 q11
#define qK1 q12
#define qK2 q13
#define qK3 q14
#define qK4 q15
/* Round function macros. */
#define WK_offs(i) (((i) & 15) * 4)
#define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
ldr RT3, [sp, WK_offs(i)]; \
pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
bic RT0, d, b; \
add e, e, a, ror #(32 - 5); \
and RT1, c, b; \
pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
add RT0, RT0, RT3; \
add e, e, RT1; \
ror b, #(32 - 30); \
pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
add e, e, RT0;
#define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
ldr RT3, [sp, WK_offs(i)]; \
pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
eor RT0, d, b; \
add e, e, a, ror #(32 - 5); \
eor RT0, RT0, c; \
pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
add e, e, RT3; \
ror b, #(32 - 30); \
pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
add e, e, RT0; \
#define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
ldr RT3, [sp, WK_offs(i)]; \
pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
eor RT0, b, c; \
and RT1, b, c; \
add e, e, a, ror #(32 - 5); \
pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
and RT0, RT0, d; \
add RT1, RT1, RT3; \
add e, e, RT0; \
ror b, #(32 - 30); \
pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
add e, e, RT1;
#define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
_R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
#define _R(a,b,c,d,e,f,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
_R_##f(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
#define R(a,b,c,d,e,f,i) \
_R_##f(a,b,c,d,e,i,dummy,dummy,dummy,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
#define dummy(...)
/* Input expansion macros. */
/********* Precalc macros for rounds 0-15 *************************************/
#define W_PRECALC_00_15() \
add RWK, sp, #(WK_offs(0)); \
\
vld1.32 {tmp0, tmp1}, [RDATA]!; \
vrev32.8 W0, tmp0; /* big => little */ \
vld1.32 {tmp2, tmp3}, [RDATA]!; \
vadd.u32 tmp0, W0, curK; \
vrev32.8 W7, tmp1; /* big => little */ \
vrev32.8 W6, tmp2; /* big => little */ \
vadd.u32 tmp1, W7, curK; \
vrev32.8 W5, tmp3; /* big => little */ \
vadd.u32 tmp2, W6, curK; \
vst1.32 {tmp0, tmp1}, [RWK]!; \
vadd.u32 tmp3, W5, curK; \
vst1.32 {tmp2, tmp3}, [RWK]; \
#define WPRECALC_00_15_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vld1.32 {tmp0, tmp1}, [RDATA]!; \
#define WPRECALC_00_15_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
add RWK, sp, #(WK_offs(0)); \
#define WPRECALC_00_15_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vrev32.8 W0, tmp0; /* big => little */ \
#define WPRECALC_00_15_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vld1.32 {tmp2, tmp3}, [RDATA]!; \
#define WPRECALC_00_15_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp0, W0, curK; \
#define WPRECALC_00_15_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vrev32.8 W7, tmp1; /* big => little */ \
#define WPRECALC_00_15_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vrev32.8 W6, tmp2; /* big => little */ \
#define WPRECALC_00_15_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp1, W7, curK; \
#define WPRECALC_00_15_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vrev32.8 W5, tmp3; /* big => little */ \
#define WPRECALC_00_15_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp2, W6, curK; \
#define WPRECALC_00_15_10(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vst1.32 {tmp0, tmp1}, [RWK]!; \
#define WPRECALC_00_15_11(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp3, W5, curK; \
#define WPRECALC_00_15_12(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vst1.32 {tmp2, tmp3}, [RWK]; \
/********* Precalc macros for rounds 16-31 ************************************/
#define WPRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor tmp0, tmp0; \
vext.8 W, W_m16, W_m12, #8; \
#define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
add RWK, sp, #(WK_offs(i)); \
vext.8 tmp0, W_m04, tmp0, #4; \
#define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor tmp0, tmp0, W_m16; \
veor.32 W, W, W_m08; \
#define WPRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor tmp1, tmp1; \
veor W, W, tmp0; \
#define WPRECALC_16_31_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vshl.u32 tmp0, W, #1; \
#define WPRECALC_16_31_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vext.8 tmp1, tmp1, W, #(16-12); \
vshr.u32 W, W, #31; \
#define WPRECALC_16_31_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vorr tmp0, tmp0, W; \
vshr.u32 W, tmp1, #30; \
#define WPRECALC_16_31_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vshl.u32 tmp1, tmp1, #2; \
#define WPRECALC_16_31_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor tmp0, tmp0, W; \
#define WPRECALC_16_31_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor W, tmp0, tmp1; \
#define WPRECALC_16_31_10(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp0, W, curK; \
#define WPRECALC_16_31_11(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vst1.32 {tmp0}, [RWK];
/********* Precalc macros for rounds 32-79 ************************************/
#define WPRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor W, W_m28; \
#define WPRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vext.8 tmp0, W_m08, W_m04, #8; \
#define WPRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor W, W_m16; \
#define WPRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
veor W, tmp0; \
#define WPRECALC_32_79_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
add RWK, sp, #(WK_offs(i&~3)); \
#define WPRECALC_32_79_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vshl.u32 tmp1, W, #2; \
#define WPRECALC_32_79_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vshr.u32 tmp0, W, #30; \
#define WPRECALC_32_79_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vorr W, tmp0, tmp1; \
#define WPRECALC_32_79_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vadd.u32 tmp0, W, curK; \
#define WPRECALC_32_79_9(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
vst1.32 {tmp0}, [RWK];
/* Other functional macros */
#define CLEAR_REG(reg) veor reg, reg;
/*
* Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
*
* unsigned int
* _gcry_sha1_transform_armv7_neon (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.align 3
.globl _gcry_sha1_transform_armv7_neon
.type _gcry_sha1_transform_armv7_neon,%function;
_gcry_sha1_transform_armv7_neon:
/* input:
* r0: ctx, CTX
* r1: data (64*nblks bytes)
* r2: nblks
*/
cmp RNBLKS, #0;
beq .Ldo_nothing;
push {r4-r12, lr};
GET_DATA_POINTER(RT3, .LK_VEC, _a);
vpush {q4-q7};
mov ROLDSTACK, sp;
/* Align stack. */
sub sp, #(16*4);
and sp, #(~(16-1));
vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
/* Get the values of the chaining variables. */
ldm RSTATE, {_a-_e};
vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
#undef curK
#define curK qK1
/* Precalc 0-15. */
W_PRECALC_00_15();
b .Loop;
.ltorg
.Loop:
/* Transform 0-15 + Precalc 16-31. */
_R( _a, _b, _c, _d, _e, F1, 0, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 16, W4, W5, W6, W7, W0, _, _, _ );
_R( _e, _a, _b, _c, _d, F1, 1, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 16, W4, W5, W6, W7, W0, _, _, _ );
_R( _d, _e, _a, _b, _c, F1, 2, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16, W4, W5, W6, W7, W0, _, _, _ );
_R( _c, _d, _e, _a, _b, F1, 3, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16, W4, W5, W6, W7, W0, _, _, _ );
#undef curK
#define curK qK2
_R( _b, _c, _d, _e, _a, F1, 4, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20, W3, W4, W5, W6, W7, _, _, _ );
_R( _a, _b, _c, _d, _e, F1, 5, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20, W3, W4, W5, W6, W7, _, _, _ );
_R( _e, _a, _b, _c, _d, F1, 6, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20, W3, W4, W5, W6, W7, _, _, _ );
_R( _d, _e, _a, _b, _c, F1, 7, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,20, W3, W4, W5, W6, W7, _, _, _ );
_R( _c, _d, _e, _a, _b, F1, 8, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 24, W2, W3, W4, W5, W6, _, _, _ );
_R( _b, _c, _d, _e, _a, F1, 9, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 24, W2, W3, W4, W5, W6, _, _, _ );
_R( _a, _b, _c, _d, _e, F1, 10, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 24, W2, W3, W4, W5, W6, _, _, _ );
_R( _e, _a, _b, _c, _d, F1, 11, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,24, W2, W3, W4, W5, W6, _, _, _ );
_R( _d, _e, _a, _b, _c, F1, 12, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 28, W1, W2, W3, W4, W5, _, _, _ );
_R( _c, _d, _e, _a, _b, F1, 13, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 28, W1, W2, W3, W4, W5, _, _, _ );
_R( _b, _c, _d, _e, _a, F1, 14, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 28, W1, W2, W3, W4, W5, _, _, _ );
_R( _a, _b, _c, _d, _e, F1, 15, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,28, W1, W2, W3, W4, W5, _, _, _ );
/* Transform 16-63 + Precalc 32-79. */
_R( _e, _a, _b, _c, _d, F1, 16, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _d, _e, _a, _b, _c, F1, 17, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 32, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _b, _c, _d, _e, _a, F1, 19, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 32, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _a, _b, _c, _d, _e, F2, 20, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _e, _a, _b, _c, _d, F2, 21, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 36, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _c, _d, _e, _a, _b, F2, 23, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 36, W7, W0, W1, W2, W3, W4, W5, W6);
#undef curK
#define curK qK3
_R( _b, _c, _d, _e, _a, F2, 24, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _a, _b, _c, _d, _e, F2, 25, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 40, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _d, _e, _a, _b, _c, F2, 27, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 40, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _c, _d, _e, _a, _b, F2, 28, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _b, _c, _d, _e, _a, F2, 29, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 44, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _e, _a, _b, _c, _d, F2, 31, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 44, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _d, _e, _a, _b, _c, F2, 32, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48, W4, W5, W6, W7, W0, W1, W2, W3);
_R( _c, _d, _e, _a, _b, F2, 33, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48, W4, W5, W6, W7, W0, W1, W2, W3);
_R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 48, W4, W5, W6, W7, W0, W1, W2, W3);
_R( _a, _b, _c, _d, _e, F2, 35, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 48, W4, W5, W6, W7, W0, W1, W2, W3);
_R( _e, _a, _b, _c, _d, F2, 36, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52, W3, W4, W5, W6, W7, W0, W1, W2);
_R( _d, _e, _a, _b, _c, F2, 37, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52, W3, W4, W5, W6, W7, W0, W1, W2);
_R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 52, W3, W4, W5, W6, W7, W0, W1, W2);
_R( _b, _c, _d, _e, _a, F2, 39, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 52, W3, W4, W5, W6, W7, W0, W1, W2);
_R( _a, _b, _c, _d, _e, F3, 40, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56, W2, W3, W4, W5, W6, W7, W0, W1);
_R( _e, _a, _b, _c, _d, F3, 41, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56, W2, W3, W4, W5, W6, W7, W0, W1);
_R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 56, W2, W3, W4, W5, W6, W7, W0, W1);
_R( _c, _d, _e, _a, _b, F3, 43, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 56, W2, W3, W4, W5, W6, W7, W0, W1);
#undef curK
#define curK qK4
_R( _b, _c, _d, _e, _a, F3, 44, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60, W1, W2, W3, W4, W5, W6, W7, W0);
_R( _a, _b, _c, _d, _e, F3, 45, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60, W1, W2, W3, W4, W5, W6, W7, W0);
_R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 60, W1, W2, W3, W4, W5, W6, W7, W0);
_R( _d, _e, _a, _b, _c, F3, 47, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 60, W1, W2, W3, W4, W5, W6, W7, W0);
_R( _c, _d, _e, _a, _b, F3, 48, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _b, _c, _d, _e, _a, F3, 49, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 64, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _e, _a, _b, _c, _d, F3, 51, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 64, W0, W1, W2, W3, W4, W5, W6, W7);
_R( _d, _e, _a, _b, _c, F3, 52, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _c, _d, _e, _a, _b, F3, 53, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 68, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _a, _b, _c, _d, _e, F3, 55, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 68, W7, W0, W1, W2, W3, W4, W5, W6);
_R( _e, _a, _b, _c, _d, F3, 56, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _d, _e, _a, _b, _c, F3, 57, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 72, W6, W7, W0, W1, W2, W3, W4, W5);
_R( _b, _c, _d, _e, _a, F3, 59, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 72, W6, W7, W0, W1, W2, W3, W4, W5);
subs RNBLKS, #1;
_R( _a, _b, _c, _d, _e, F4, 60, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _e, _a, _b, _c, _d, F4, 61, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 76, W5, W6, W7, W0, W1, W2, W3, W4);
_R( _c, _d, _e, _a, _b, F4, 63, WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 76, W5, W6, W7, W0, W1, W2, W3, W4);
beq .Lend;
/* Transform 64-79 + Precalc 0-15 of next block. */
#undef curK
#define curK qK1
_R( _b, _c, _d, _e, _a, F4, 64, WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _a, _b, _c, _d, _e, F4, 65, WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _e, _a, _b, _c, _d, F4, 66, WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _d, _e, _a, _b, _c, F4, 67, WPRECALC_00_15_3, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _c, _d, _e, _a, _b, F4, 68, dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _b, _c, _d, _e, _a, F4, 69, dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _a, _b, _c, _d, _e, F4, 70, WPRECALC_00_15_4, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _e, _a, _b, _c, _d, F4, 71, WPRECALC_00_15_5, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _d, _e, _a, _b, _c, F4, 72, dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _c, _d, _e, _a, _b, F4, 73, dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _b, _c, _d, _e, _a, F4, 74, WPRECALC_00_15_6, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _a, _b, _c, _d, _e, F4, 75, WPRECALC_00_15_7, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _e, _a, _b, _c, _d, F4, 76, WPRECALC_00_15_8, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _d, _e, _a, _b, _c, F4, 77, WPRECALC_00_15_9, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _c, _d, _e, _a, _b, F4, 78, WPRECALC_00_15_10, dummy, dummy, _, _, _, _, _, _, _, _, _ );
_R( _b, _c, _d, _e, _a, F4, 79, WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );
/* Update the chaining variables. */
ldm RSTATE, {RT0-RT3};
add _a, RT0;
ldr RT0, [RSTATE, #state_h4];
add _b, RT1;
add _c, RT2;
add _d, RT3;
add _e, RT0;
stm RSTATE, {_a-_e};
b .Loop;
.ltorg
.Lend:
/* Transform 64-79 + Clear XMM registers. */
R( _b, _c, _d, _e, _a, F4, 64 );
R( _a, _b, _c, _d, _e, F4, 65 ); CLEAR_REG(tmp0);
R( _e, _a, _b, _c, _d, F4, 66 ); CLEAR_REG(tmp1);
R( _d, _e, _a, _b, _c, F4, 67 ); CLEAR_REG(W0);
R( _c, _d, _e, _a, _b, F4, 68 ); CLEAR_REG(W1);
R( _b, _c, _d, _e, _a, F4, 69 ); CLEAR_REG(W2);
R( _a, _b, _c, _d, _e, F4, 70 ); CLEAR_REG(W3);
R( _e, _a, _b, _c, _d, F4, 71 ); CLEAR_REG(W4);
R( _d, _e, _a, _b, _c, F4, 72 ); CLEAR_REG(W5);
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( _b, _c, _d, _e, _a, F4, 79 );
mov sp, ROLDSTACK;
/* Update the chaining variables. */
ldm RSTATE, {RT0-RT3};
add _a, RT0;
ldr RT0, [RSTATE, #state_h4];
add _b, RT1;
add _c, RT2;
add _d, RT3;
vpop {q4-q7};
add _e, RT0;
stm RSTATE, {_a-_e};
/* burn_stack */
mov r0, #(16*4 + 16*4 + 15);
pop {r4-r12, pc};
.Ldo_nothing:
mov r0, #0;
bx lr
.size _gcry_sha1_transform_armv7_neon,.-_gcry_sha1_transform_armv7_neon;
#endif
diff --git a/cipher/sha1-armv8-aarch32-ce.S b/cipher/sha1-armv8-aarch32-ce.S
index bf2b233b..f3771402 100644
--- a/cipher/sha1-armv8-aarch32-ce.S
+++ b/cipher/sha1-armv8-aarch32-ce.S
@@ -1,220 +1,220 @@
/* sha1-armv8-aarch32-ce.S - ARM/CE accelerated SHA-1 transform function
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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_AARCH32_CRYPTO) && defined(USE_SHA1)
.syntax unified
.arch armv8-a
.fpu crypto-neon-fp-armv8
.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 */
#define K1 0x5A827999
#define K2 0x6ED9EBA1
#define K3 0x8F1BBCDC
#define K4 0xCA62C1D6
.align 4
gcry_sha1_aarch32_ce_K_VEC:
.LK_VEC:
.LK1: .long K1, K1, K1, K1
.LK2: .long K2, K2, K2, K2
.LK3: .long K3, K3, K3, K3
.LK4: .long K4, K4, K4, K4
/* Register macros */
#define qH4 q0
#define sH4 s0
#define qH0123 q1
#define qABCD q2
#define qE0 q3
#define qE1 q4
#define qT0 q5
#define qT1 q6
#define qW0 q8
#define qW1 q9
#define qW2 q10
#define qW3 q11
#define qK1 q12
#define qK2 q13
#define qK3 q14
#define qK4 q15
/* Round macros */
#define _(...) /*_*/
#define do_add(dst, src0, src1) vadd.u32 dst, src0, src1;
#define do_sha1su0(w0,w1,w2) sha1su0.32 w0,w1,w2;
#define do_sha1su1(w0,w3) sha1su1.32 w0,w3;
#define do_rounds(f, e0, e1, t, k, w0, w1, w2, w3, add_fn, sha1su0_fn, sha1su1_fn) \
sha1su1_fn( w3, w2 ); \
sha1h.32 e0, qABCD; \
sha1##f.32 qABCD, e1, t; \
add_fn( t, w2, k ); \
sha1su0_fn( w0, w1, w2 );
/* Other functional macros */
#define CLEAR_REG(reg) veor reg, reg;
/*
* unsigned int
* _gcry_sha1_transform_armv8_ce (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.align 3
.globl _gcry_sha1_transform_armv8_ce
.type _gcry_sha1_transform_armv8_ce,%function;
_gcry_sha1_transform_armv8_ce:
/* input:
* r0: ctx, CTX
* r1: data (64*nblks bytes)
* r2: nblks
*/
cmp r2, #0;
push {r4,lr};
beq .Ldo_nothing;
vpush {q4-q7};
GET_DATA_POINTER(r4, .LK_VEC, lr);
veor qH4, qH4
vld1.32 {qH0123}, [r0] /* load h0,h1,h2,h3 */
vld1.32 {qK1-qK2}, [r4]! /* load K1,K2 */
vldr sH4, [r0, #16] /* load h4 */
vld1.32 {qK3-qK4}, [r4] /* load K3,K4 */
vld1.8 {qW0-qW1}, [r1]!
vmov qABCD, qH0123
vld1.8 {qW2-qW3}, [r1]!
vrev32.8 qW0, qW0
vrev32.8 qW1, qW1
vrev32.8 qW2, qW2
do_add(qT0, qW0, qK1)
vrev32.8 qW3, qW3
do_add(qT1, qW1, qK1)
.Loop:
do_rounds(c, qE1, qH4, qT0, qK1, qW0, qW1, qW2, qW3, do_add, do_sha1su0, _)
subs r2, r2, #1
do_rounds(c, qE0, qE1, qT1, qK1, qW1, qW2, qW3, qW0, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, qE1, qE0, qT0, qK1, qW2, qW3, qW0, qW1, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, qE0, qE1, qT1, qK2, qW3, qW0, qW1, qW2, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, qE1, qE0, qT0, qK2, qW0, qW1, qW2, qW3, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE0, qE1, qT1, qK2, qW1, qW2, qW3, qW0, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE1, qE0, qT0, qK2, qW2, qW3, qW0, qW1, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE0, qE1, qT1, qK2, qW3, qW0, qW1, qW2, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE1, qE0, qT0, qK3, qW0, qW1, qW2, qW3, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE0, qE1, qT1, qK3, qW1, qW2, qW3, qW0, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, qE1, qE0, qT0, qK3, qW2, qW3, qW0, qW1, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, qE0, qE1, qT1, qK3, qW3, qW0, qW1, qW2, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, qE1, qE0, qT0, qK3, qW0, qW1, qW2, qW3, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, qE0, qE1, qT1, qK4, qW1, qW2, qW3, qW0, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, qE1, qE0, qT0, qK4, qW2, qW3, qW0, qW1, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, qE0, qE1, qT1, qK4, qW3, qW0, qW1, qW2, do_add, do_sha1su0, do_sha1su1)
beq .Lend
vld1.8 {qW0-qW1}, [r1]! /* preload */
do_rounds(p, qE1, qE0, qT0, qK4, _ , _ , qW2, qW3, do_add, _, do_sha1su1)
vrev32.8 qW0, qW0
vld1.8 {qW2}, [r1]!
vrev32.8 qW1, qW1
do_rounds(p, qE0, qE1, qT1, qK4, _ , _ , qW3, _ , do_add, _, _)
vld1.8 {qW3}, [r1]!
vrev32.8 qW2, qW2
do_rounds(p, qE1, qE0, qT0, _, _, _, _, _, _, _, _)
vrev32.8 qW3, qW3
do_rounds(p, qE0, qE1, qT1, _, _, _, _, _, _, _, _)
do_add(qT0, qW0, qK1)
vadd.u32 qH4, qE0
vadd.u32 qABCD, qH0123
do_add(qT1, qW1, qK1)
vmov qH0123, qABCD
b .Loop
.Lend:
do_rounds(p, qE1, qE0, qT0, qK4, _ , _ , qW2, qW3, do_add, _, do_sha1su1)
do_rounds(p, qE0, qE1, qT1, qK4, _ , _ , qW3, _ , do_add, _, _)
do_rounds(p, qE1, qE0, qT0, _, _, _, _, _, _, _, _)
do_rounds(p, qE0, qE1, qT1, _, _, _, _, _, _, _, _)
vadd.u32 qH4, qE0
vadd.u32 qH0123, qABCD
CLEAR_REG(qW0)
CLEAR_REG(qW1)
CLEAR_REG(qW2)
CLEAR_REG(qW3)
CLEAR_REG(qABCD)
CLEAR_REG(qE1)
CLEAR_REG(qE0)
vstr sH4, [r0, #16] /* store h4 */
vst1.32 {qH0123}, [r0] /* store h0,h1,h2,h3 */
CLEAR_REG(qH0123)
CLEAR_REG(qH4)
vpop {q4-q7}
.Ldo_nothing:
mov r0, #0
pop {r4,pc}
.size _gcry_sha1_transform_armv8_ce,.-_gcry_sha1_transform_armv8_ce;
#endif
diff --git a/cipher/sha1-armv8-aarch64-ce.S b/cipher/sha1-armv8-aarch64-ce.S
index 223268ca..e2b35f95 100644
--- a/cipher/sha1-armv8-aarch64-ce.S
+++ b/cipher/sha1-armv8-aarch64-ce.S
@@ -1,201 +1,201 @@
/* sha1-armv8-aarch64-ce.S - ARM/CE accelerated SHA-1 transform function
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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) && defined(USE_SHA1)
.cpu generic+simd+crypto
.text
/* Constants */
#define K1 0x5A827999
#define K2 0x6ED9EBA1
#define K3 0x8F1BBCDC
#define K4 0xCA62C1D6
.align 4
gcry_sha1_aarch64_ce_K_VEC:
.LK_VEC:
.LK1: .long K1, K1, K1, K1
.LK2: .long K2, K2, K2, K2
.LK3: .long K3, K3, K3, K3
.LK4: .long K4, K4, K4, K4
/* Register macros */
#define sH4 s0
#define vH4 v0
#define vH0123 v1
#define qABCD q2
#define sABCD s2
#define vABCD v2
#define sE0 s3
#define vE0 v3
#define sE1 s4
#define vE1 v4
#define vT0 v5
#define vT1 v6
#define vW0 v16
#define vW1 v17
#define vW2 v18
#define vW3 v19
#define vK1 v20
#define vK2 v21
#define vK3 v22
#define vK4 v23
/* Round macros */
#define _(...) /*_*/
#define do_add(dst, src0, src1) add dst.4s, src0.4s, src1.4s;
#define do_sha1su0(w0,w1,w2) sha1su0 w0.4s,w1.4s,w2.4s;
#define do_sha1su1(w0,w3) sha1su1 w0.4s,w3.4s;
#define do_rounds(f, e0, e1, t, k, w0, w1, w2, w3, add_fn, sha1su0_fn, sha1su1_fn) \
sha1su1_fn( v##w3, v##w2 ); \
sha1h e0, sABCD; \
sha1##f qABCD, e1, v##t.4s; \
add_fn( v##t, v##w2, v##k ); \
sha1su0_fn( v##w0, v##w1, v##w2 );
/* Other functional macros */
#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
/*
* unsigned int
* _gcry_sha1_transform_armv8_ce (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.align 3
.globl _gcry_sha1_transform_armv8_ce
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;
GET_DATA_POINTER(x4, .LK_VEC);
ld1 {vH0123.4s}, [x0] /* load h0,h1,h2,h3 */
ld1 {vK1.4s-vK4.4s}, [x4] /* load K1,K2,K3,K4 */
ldr sH4, [x0, #16] /* load h4 */
ld1 {vW0.16b-vW3.16b}, [x1], #64
mov vABCD.16b, vH0123.16b
rev32 vW0.16b, vW0.16b
rev32 vW1.16b, vW1.16b
rev32 vW2.16b, vW2.16b
do_add(vT0, vW0, vK1)
rev32 vW3.16b, vW3.16b
do_add(vT1, vW1, vK1)
.Loop:
do_rounds(c, sE1, sH4, T0, K1, W0, W1, W2, W3, do_add, do_sha1su0, _)
sub x2, x2, #1
do_rounds(c, sE0, sE1, T1, K1, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, sE1, sE0, T0, K1, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, sE0, sE1, T1, K2, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
do_rounds(c, sE1, sE0, T0, K2, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE0, sE1, T1, K2, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE1, sE0, T0, K2, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE0, sE1, T1, K2, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE1, sE0, T0, K3, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE0, sE1, T1, K3, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, sE1, sE0, T0, K3, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, sE0, sE1, T1, K3, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, sE1, sE0, T0, K3, W0, W1, W2, W3, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, sE0, sE1, T1, K4, W1, W2, W3, W0, do_add, do_sha1su0, do_sha1su1)
do_rounds(m, sE1, sE0, T0, K4, W2, W3, W0, W1, do_add, do_sha1su0, do_sha1su1)
do_rounds(p, sE0, sE1, T1, K4, W3, W0, W1, W2, do_add, do_sha1su0, do_sha1su1)
cbz x2, .Lend
ld1 {vW0.16b-vW1.16b}, [x1], #32 /* preload */
do_rounds(p, sE1, sE0, T0, K4, _ , _ , W2, W3, do_add, _, do_sha1su1)
rev32 vW0.16b, vW0.16b
ld1 {vW2.16b}, [x1], #16
rev32 vW1.16b, vW1.16b
do_rounds(p, sE0, sE1, T1, K4, _ , _ , W3, _ , do_add, _, _)
ld1 {vW3.16b}, [x1], #16
rev32 vW2.16b, vW2.16b
do_rounds(p, sE1, sE0, T0, _, _, _, _, _, _, _, _)
rev32 vW3.16b, vW3.16b
do_rounds(p, sE0, sE1, T1, _, _, _, _, _, _, _, _)
do_add(vT0, vW0, vK1)
add vH4.2s, vH4.2s, vE0.2s
add vABCD.4s, vABCD.4s, vH0123.4s
do_add(vT1, vW1, vK1)
mov vH0123.16b, vABCD.16b
b .Loop
.Lend:
do_rounds(p, sE1, sE0, T0, K4, _ , _ , W2, W3, do_add, _, do_sha1su1)
do_rounds(p, sE0, sE1, T1, K4, _ , _ , W3, _ , do_add, _, _)
do_rounds(p, sE1, sE0, T0, _, _, _, _, _, _, _, _)
do_rounds(p, sE0, sE1, T1, _, _, _, _, _, _, _, _)
add vH4.2s, vH4.2s, vE0.2s
add vH0123.4s, vH0123.4s, vABCD.4s
CLEAR_REG(vW0)
CLEAR_REG(vW1)
CLEAR_REG(vW2)
CLEAR_REG(vW3)
CLEAR_REG(vABCD)
CLEAR_REG(vE1)
CLEAR_REG(vE0)
str sH4, [x0, #16] /* store h4 */
st1 {vH0123.4s}, [x0] /* store h0,h1,h2,h3 */
CLEAR_REG(vH0123)
CLEAR_REG(vH4)
.Ldo_nothing:
mov x0, #0
ret
CFI_ENDPROC();
ELF(.size _gcry_sha1_transform_armv8_ce,.-_gcry_sha1_transform_armv8_ce;)
#endif
diff --git a/cipher/sha1-avx-amd64.S b/cipher/sha1-avx-amd64.S
index 85876ad4..93b14003 100644
--- a/cipher/sha1-avx-amd64.S
+++ b/cipher/sha1-avx-amd64.S
@@ -1,429 +1,429 @@
/* sha1-avx-amd64.S - Intel AVX accelerated SHA-1 transform function
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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
+ * https://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_AVX) && 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 */
.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
/* 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 RT0 %esi
#define RT1 %ebp
#define Wtmp0 %xmm0
#define Wtmp1 %xmm1
#define W0 %xmm2
#define W1 %xmm3
#define W2 %xmm4
#define W3 %xmm5
#define W4 %xmm6
#define W5 %xmm7
#define W6 %xmm8
#define W7 %xmm9
#define BSWAP_REG %xmm10
/* Round function macros. */
#define WK(i) (((i) & 15) * 4)(%rsp)
#define R_F1(a,b,c,d,e,i) \
movl c, RT0; \
addl WK(i), e; \
xorl d, RT0; \
movl a, RT1; \
andl b, RT0; \
shldl $30, b, b; \
xorl d, RT0; \
leal (RT0,e), e; \
shldl $5, RT1, RT1; \
addl RT1, e;
#define R_F2(a,b,c,d,e,i) \
movl c, RT0; \
addl WK(i), e; \
xorl b, RT0; \
shldl $30, b, b; \
xorl d, RT0; \
movl a, RT1; \
leal (RT0,e), e; \
shldl $5, RT1, RT1; \
addl RT1, e;
#define R_F3(a,b,c,d,e,i) \
movl c, RT0; \
movl b, RT1; \
xorl b, RT0; \
andl c, RT1; \
andl d, RT0; \
addl RT1, e; \
addl WK(i), e; \
shldl $30, b, b; \
movl a, RT1; \
leal (RT0,e), e; \
shldl $5, RT1, RT1; \
addl RT1, e;
#define R_F4(a,b,c,d,e,i) R_F2(a,b,c,d,e,i)
#define R(a,b,c,d,e,f,i) \
R_##f(a,b,c,d,e,i)
/* Input expansion macros. */
#define W_PRECALC_00_15_0(i, W, tmp0) \
vmovdqu (4*(i))(RDATA), tmp0;
#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) rRIP, W, tmp0;
#define W_PRECALC_00_15_3(i, W, tmp0) \
vmovdqa tmp0, 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) \
vpxor W, tmp0, tmp0; \
vpxor tmp1, tmp0, W; \
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) \
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) \
vpor W, tmp0, W; \
vpaddd (.LK_XMM + ((i)/20)*16) rRIP, W, tmp0; \
vmovdqa tmp0, WK((i)&~3);
/*
* Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
*
* unsigned int
* _gcry_sha1_transform_amd64_avx (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.globl _gcry_sha1_transform_amd64_avx
ELF(.type _gcry_sha1_transform_amd64_avx,@function)
.align 16
_gcry_sha1_transform_amd64_avx:
/* input:
* %rdi: ctx, CTX
* %rsi: data (64*nblks bytes)
* %rdx: nblks
*/
CFI_STARTPROC();
xorl %eax, %eax;
cmpq $0, %rdx;
jz .Lret;
vzeroupper;
movq %rdx, RNBLKS;
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;
/* 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;
vmovdqa .Lbswap_shufb_ctl rRIP, BSWAP_REG;
/* 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_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_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_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_3(15, W5, Wtmp0);
.align 8
.Loop:
addq $64, RDATA;
/* Transform 0-15 + Precalc 16-31. */
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( 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( 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( 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);
/* 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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);
decq RNBLKS;
jz .Lend;
/* 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( 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( 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( 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);
R( b, c, d, e, a, F4, 79 ); W_PRECALC_00_15_3(15, W5, Wtmp0);
/* 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 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 );
R( d, e, a, b, c, F4, 67 );
R( c, d, e, a, b, F4, 68 );
R( b, c, d, e, a, F4, 69 );
R( a, b, c, d, e, F4, 70 );
R( e, a, b, c, d, F4, 71 );
R( d, e, a, b, c, F4, 72 );
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 ); 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;
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 %rbp;
CFI_POP(%rbp);
popq %rbx;
CFI_POP(%rbx);
/* stack already burned */
xorl %eax, %eax;
.Lret:
ret;
CFI_ENDPROC();
ELF(.size _gcry_sha1_transform_amd64_avx,
.-_gcry_sha1_transform_amd64_avx;)
#endif
#endif
diff --git a/cipher/sha1-avx-bmi2-amd64.S b/cipher/sha1-avx-bmi2-amd64.S
index 5dfcdca9..4867bfcc 100644
--- a/cipher/sha1-avx-bmi2-amd64.S
+++ b/cipher/sha1-avx-bmi2-amd64.S
@@ -1,441 +1,441 @@
/* sha1-avx-bmi2-amd64.S - Intel AVX/BMI2 accelerated SHA-1 transform function
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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
+ * https://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(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 */
.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 %esi
#define b %edi
#define c %ebp
#define d %edx
#define e %ecx
#define ne %ebx
#define RT0 %eax
#define RT1 %r12d
#define Wtmp0 %xmm0
#define Wtmp1 %xmm1
#define W0 %xmm2
#define W1 %xmm3
#define W2 %xmm4
#define W3 %xmm5
#define W4 %xmm6
#define W5 %xmm7
#define W6 %xmm8
#define W7 %xmm9
#define BSWAP_REG %xmm10
#define K1 %xmm11
#define K2 %xmm12
#define K3 %xmm13
#define K4 %xmm14
/* Round function macros. */
#define WK(i) (((i) & 15) * 4)(%rsp)
#define R_F1(a,b,c,d,e,i) \
movl c, RT0; \
andn d, b, RT1; \
addl WK(i), e; \
andl b, RT0; \
rorxl $2, b, b; \
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; \
addl WK(i), e; \
xorl b, RT0; \
rorxl $2, b, b; \
xorl d, RT0; \
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; \
rorxl $2, b, b; \
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 R(a,b,c,d,e,f,i) \
R_##f(a,b,c,d,e,i)
/* Input expansion macros. */
#define W_PRECALC_00_15_0(i, W, tmp0) \
vmovdqu (4*(i))(RDATA), 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, 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, 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, WK((i)&~3);
/*
* Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
*
* unsigned int
* _gcry_sha1_transform_amd64_avx_bmi2 (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.globl _gcry_sha1_transform_amd64_avx_bmi2
ELF(.type _gcry_sha1_transform_amd64_avx_bmi2,@function)
.align 16
_gcry_sha1_transform_amd64_avx_bmi2:
/* input:
* %rdi: ctx, CTX
* %rsi: data (64*nblks bytes)
* %rdx: nblks
*/
CFI_STARTPROC();
xorl %eax, %eax;
cmpq $0, %rdx;
jz .Lret;
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 $(16*4), %rsp;
andq $(~31), %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;
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, 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);
.align 8
.Loop:
addq $64, RDATA;
/* Transform 0-15 + Precalc 16-31. */
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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, K4);
decq RNBLKS;
jz .Lend;
/* 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, 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, 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, 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, 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;
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 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 );
R( d, e, a, b, c, F4, 67 );
R( c, d, e, a, b, F4, 68 );
R( b, c, d, e, a, F4, 69 );
R( a, b, c, d, e, F4, 70 );
R( e, a, b, c, d, F4, 71 );
R( d, e, a, b, c, F4, 72 );
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 ); 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;
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;
.Lret:
ret;
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
index 93863230..7c4e8e82 100644
--- a/cipher/sha1-avx2-bmi2-amd64.S
+++ b/cipher/sha1-avx2-bmi2-amd64.S
@@ -1,573 +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/>.
+ * License along with this program; if not, see <https://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
+ * https://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;
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
index d7e3d4f8..5bf52f25 100644
--- a/cipher/sha1-intel-shaext.c
+++ b/cipher/sha1-intel-shaext.c
@@ -1,288 +1,288 @@
/* 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/>.
+ * License along with this program; if not, see <https://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
/* 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
_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 */
diff --git a/cipher/sha1-ssse3-amd64.S b/cipher/sha1-ssse3-amd64.S
index 7e32b0f4..ef6abd92 100644
--- a/cipher/sha1-ssse3-amd64.S
+++ b/cipher/sha1-ssse3-amd64.S
@@ -1,437 +1,437 @@
/* sha1-ssse3-amd64.S - Intel SSSE3 accelerated SHA-1 transform function
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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
+ * https://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_SSSE3) && 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 */
.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
/* 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 RT0 %esi
#define RT1 %ebp
#define Wtmp0 %xmm0
#define Wtmp1 %xmm1
#define W0 %xmm2
#define W1 %xmm3
#define W2 %xmm4
#define W3 %xmm5
#define W4 %xmm6
#define W5 %xmm7
#define W6 %xmm8
#define W7 %xmm9
#define BSWAP_REG %xmm10
/* Round function macros. */
#define WK(i) (((i) & 15) * 4)(%rsp)
#define R_F1(a,b,c,d,e,i) \
movl c, RT0; \
addl WK(i), e; \
xorl d, RT0; \
movl a, RT1; \
andl b, RT0; \
roll $30, b; \
xorl d, RT0; \
leal (RT0,e), e; \
roll $5, RT1; \
addl RT1, e;
#define R_F2(a,b,c,d,e,i) \
movl c, RT0; \
addl WK(i), e; \
xorl b, RT0; \
roll $30, b; \
xorl d, RT0; \
movl a, RT1; \
leal (RT0,e), e; \
roll $5, RT1; \
addl RT1, e;
#define R_F3(a,b,c,d,e,i) \
movl c, RT0; \
movl b, RT1; \
xorl b, RT0; \
andl c, RT1; \
andl d, RT0; \
addl RT1, e; \
addl WK(i), e; \
roll $30, b; \
movl a, RT1; \
leal (RT0,e), e; \
roll $5, RT1; \
addl RT1, e;
#define R_F4(a,b,c,d,e,i) R_F2(a,b,c,d,e,i)
#define R(a,b,c,d,e,f,i) \
R_##f(a,b,c,d,e,i)
/* Input expansion macros. */
#define W_PRECALC_00_15_0(i, W, tmp0) \
movdqu (4*(i))(RDATA), tmp0;
#define W_PRECALC_00_15_1(i, W, tmp0) \
pshufb BSWAP_REG, tmp0; \
movdqa tmp0, W;
#define W_PRECALC_00_15_2(i, W, tmp0) \
paddd (.LK_XMM + ((i)/20)*16) rRIP, tmp0;
#define W_PRECALC_00_15_3(i, W, tmp0) \
movdqa tmp0, WK(i&~3);
#define W_PRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
movdqa W_m12, W; \
palignr $8, W_m16, W; \
movdqa W_m04, tmp0; \
psrldq $4, tmp0; \
pxor W_m08, W;
#define W_PRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
pxor W_m16, tmp0; \
pxor tmp0, W; \
movdqa W, tmp1; \
movdqa W, tmp0; \
pslldq $12, tmp1;
#define W_PRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
psrld $31, W; \
pslld $1, tmp0; \
por W, tmp0; \
movdqa tmp1, W; \
psrld $30, tmp1; \
pslld $2, W;
#define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
pxor W, tmp0; \
pxor tmp1, tmp0; \
movdqa tmp0, W; \
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) \
movdqa W_m04, tmp0; \
pxor W_m28, W; \
palignr $8, W_m08, tmp0;
#define W_PRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
pxor W_m16, W; \
pxor tmp0, W; \
movdqa W, tmp0;
#define W_PRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
psrld $30, W; \
pslld $2, tmp0; \
por W, 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) rRIP, tmp0; \
movdqa tmp0, WK((i)&~3);
#define CLEAR_REG(reg) pxor reg, reg;
/*
* Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
*
* unsigned int
* _gcry_sha1_transform_amd64_ssse3 (void *ctx, const unsigned char *data,
* size_t nblks)
*/
.globl _gcry_sha1_transform_amd64_ssse3
ELF(.type _gcry_sha1_transform_amd64_ssse3,@function)
.align 16
_gcry_sha1_transform_amd64_ssse3:
/* input:
* %rdi: ctx, CTX
* %rsi: data (64*nblks bytes)
* %rdx: nblks
*/
CFI_STARTPROC();
xorl %eax, %eax;
cmpq $0, %rdx;
jz .Lret;
movq %rdx, RNBLKS;
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;
/* 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;
movdqa .Lbswap_shufb_ctl rRIP, BSWAP_REG;
/* 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_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_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_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_3(15, W5, Wtmp0);
.align 8
.Loop:
addq $64, RDATA;
/* Transform 0-15 + Precalc 16-31. */
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( 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( 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( 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);
/* 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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( 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);
decq RNBLKS;
jz .Lend;
/* 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( 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( 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( 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);
R( b, c, d, e, a, F4, 79 ); W_PRECALC_00_15_3(15, W5, Wtmp0);
/* 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:
/* 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);
R( d, e, a, b, c, F4, 67 ); CLEAR_REG(W0);
R( c, d, e, a, b, F4, 68 ); CLEAR_REG(W1);
R( b, c, d, e, a, F4, 69 ); CLEAR_REG(W2);
R( a, b, c, d, e, F4, 70 ); CLEAR_REG(W3);
R( e, a, b, c, d, F4, 71 ); CLEAR_REG(W4);
R( d, e, a, b, c, F4, 72 ); CLEAR_REG(W5);
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 ); 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 */
vmovdqa Wtmp0, (3*16)(%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 %rbp;
CFI_POP(%rbp);
popq %rbx;
CFI_POP(%rbx);
/* stack already burned */
xorl %eax, %eax;
.Lret:
ret;
CFI_ENDPROC();
ELF(.size _gcry_sha1_transform_amd64_ssse3,
.-_gcry_sha1_transform_amd64_ssse3;)
#endif
#endif
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 23aceef3..b5d93fdc 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -1,709 +1,709 @@
/* sha1.c - SHA1 hash function
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Test vectors:
*
* "abc"
* A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D
*
* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
* 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "g10lib.h"
#include "bithelp.h"
#include "bufhelp.h"
#include "cipher.h"
#include "sha1.h"
/* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
#undef USE_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_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_BMI2 indicates whether to compile with Intel AVX/BMI2 code. */
#undef USE_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_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
# 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
# endif
#endif
/* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly
* code. */
#undef USE_ARM_CE
#ifdef ENABLE_ARM_CRYPTO_SUPPORT
# if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
&& defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO)
# define USE_ARM_CE 1
# elif defined(__AARCH64EL__) \
&& defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
# define USE_ARM_CE 1
# 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. */
/* #if __GNUC__ >= 2 */
/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % __alignof__ (u32))) */
/* #else */
/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */
/* #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
static unsigned int
do_transform_generic (void *c, const unsigned char *data, size_t nblks);
static void
sha1_init (void *context, unsigned int flags)
{
SHA1_CONTEXT *hd = context;
unsigned int features = _gcry_get_hw_features ();
(void)flags;
hd->h0 = 0x67452301;
hd->h1 = 0xefcdab89;
hd->h2 = 0x98badcfe;
hd->h3 = 0x10325476;
hd->h4 = 0xc3d2e1f0;
hd->bctx.nblocks = 0;
hd->bctx.nblocks_high = 0;
hd->bctx.count = 0;
hd->bctx.blocksize = 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
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. */
if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
hd->bctx.bwrite = do_sha1_transform_amd64_avx;
#endif
#ifdef USE_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
if ((features & HWF_ARM_NEON) != 0)
hd->bctx.bwrite = do_sha1_transform_armv7_neon;
#endif
#ifdef USE_ARM_CE
if ((features & HWF_ARM_SHA1) != 0)
hd->bctx.bwrite = do_sha1_transform_armv8_ce;
#endif
(void)features;
}
/*
* Initialize the context HD. This is used to prepare the use of
* _gcry_sha1_mixblock. WARNING: This is a special purpose function
* for exclusive use by random-csprng.c.
*/
void
_gcry_sha1_mixblock_init (SHA1_CONTEXT *hd)
{
sha1_init (hd, 0);
}
/* Round function macros. */
#define K1 0x5A827999L
#define K2 0x6ED9EBA1L
#define K3 0x8F1BBCDCL
#define K4 0xCA62C1D6L
#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) )
#define F2(x,y,z) ( x ^ y ^ z )
#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) )
#define F4(x,y,z) ( x ^ y ^ z )
#define M(i) ( tm = x[ i &0x0f] \
^ x[(i-14)&0x0f] \
^ x[(i-8) &0x0f] \
^ x[(i-3) &0x0f], \
(x[i&0x0f] = rol(tm, 1)))
#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \
+ f( b, c, d ) \
+ k \
+ m; \
b = rol( b, 30 ); \
} while(0)
/*
* Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA.
*/
static unsigned int
do_transform_generic (void *ctx, const unsigned char *data, size_t nblks)
{
SHA1_CONTEXT *hd = ctx;
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))
/* Get the values of the chaining variables. */
a = hd->h0;
b = hd->h1;
c = hd->h2;
d = hd->h3;
e = hd->h4;
/* Transform. */
R( a, b, c, d, e, F1, K1, I( 0) );
R( e, a, b, c, d, F1, K1, I( 1) );
R( d, e, a, b, c, F1, K1, I( 2) );
R( c, d, e, a, b, F1, K1, I( 3) );
R( b, c, d, e, a, F1, K1, I( 4) );
R( a, b, c, d, e, F1, K1, I( 5) );
R( e, a, b, c, d, F1, K1, I( 6) );
R( d, e, a, b, c, F1, K1, I( 7) );
R( c, d, e, a, b, F1, K1, I( 8) );
R( b, c, d, e, a, F1, K1, I( 9) );
R( a, b, c, d, e, F1, K1, I(10) );
R( e, a, b, c, d, F1, K1, I(11) );
R( d, e, a, b, c, F1, K1, I(12) );
R( c, d, e, a, b, F1, K1, I(13) );
R( b, c, d, e, a, F1, K1, I(14) );
R( a, b, c, d, e, F1, K1, I(15) );
R( e, a, b, c, d, F1, K1, M(16) );
R( d, e, a, b, c, F1, K1, M(17) );
R( c, d, e, a, b, F1, K1, M(18) );
R( b, c, d, e, a, F1, K1, M(19) );
R( a, b, c, d, e, F2, K2, M(20) );
R( e, a, b, c, d, F2, K2, M(21) );
R( d, e, a, b, c, F2, K2, M(22) );
R( c, d, e, a, b, F2, K2, M(23) );
R( b, c, d, e, a, F2, K2, M(24) );
R( a, b, c, d, e, F2, K2, M(25) );
R( e, a, b, c, d, F2, K2, M(26) );
R( d, e, a, b, c, F2, K2, M(27) );
R( c, d, e, a, b, F2, K2, M(28) );
R( b, c, d, e, a, F2, K2, M(29) );
R( a, b, c, d, e, F2, K2, M(30) );
R( e, a, b, c, d, F2, K2, M(31) );
R( d, e, a, b, c, F2, K2, M(32) );
R( c, d, e, a, b, F2, K2, M(33) );
R( b, c, d, e, a, F2, K2, M(34) );
R( a, b, c, d, e, F2, K2, M(35) );
R( e, a, b, c, d, F2, K2, M(36) );
R( d, e, a, b, c, F2, K2, M(37) );
R( c, d, e, a, b, F2, K2, M(38) );
R( b, c, d, e, a, F2, K2, M(39) );
R( a, b, c, d, e, F3, K3, M(40) );
R( e, a, b, c, d, F3, K3, M(41) );
R( d, e, a, b, c, F3, K3, M(42) );
R( c, d, e, a, b, F3, K3, M(43) );
R( b, c, d, e, a, F3, K3, M(44) );
R( a, b, c, d, e, F3, K3, M(45) );
R( e, a, b, c, d, F3, K3, M(46) );
R( d, e, a, b, c, F3, K3, M(47) );
R( c, d, e, a, b, F3, K3, M(48) );
R( b, c, d, e, a, F3, K3, M(49) );
R( a, b, c, d, e, F3, K3, M(50) );
R( e, a, b, c, d, F3, K3, M(51) );
R( d, e, a, b, c, F3, K3, M(52) );
R( c, d, e, a, b, F3, K3, M(53) );
R( b, c, d, e, a, F3, K3, M(54) );
R( a, b, c, d, e, F3, K3, M(55) );
R( e, a, b, c, d, F3, K3, M(56) );
R( d, e, a, b, c, F3, K3, M(57) );
R( c, d, e, a, b, F3, K3, M(58) );
R( b, c, d, e, a, F3, K3, M(59) );
R( a, b, c, d, e, F4, K4, M(60) );
R( e, a, b, c, d, F4, K4, M(61) );
R( d, e, a, b, c, F4, K4, M(62) );
R( c, d, e, a, b, F4, K4, M(63) );
R( b, c, d, e, a, F4, K4, M(64) );
R( a, b, c, d, e, F4, K4, M(65) );
R( e, a, b, c, d, F4, K4, M(66) );
R( d, e, a, b, c, F4, K4, M(67) );
R( c, d, e, a, b, F4, K4, M(68) );
R( b, c, d, e, a, F4, K4, M(69) );
R( a, b, c, d, e, F4, K4, M(70) );
R( e, a, b, c, d, F4, K4, M(71) );
R( d, e, a, b, c, F4, K4, M(72) );
R( c, d, e, a, b, F4, K4, M(73) );
R( b, c, d, e, a, F4, K4, M(74) );
R( a, b, c, d, e, F4, K4, M(75) );
R( e, a, b, c, d, F4, K4, M(76) );
R( d, e, a, b, c, F4, K4, M(77) );
R( c, d, e, a, b, F4, K4, M(78) );
R( b, c, d, e, a, F4, K4, M(79) );
/* Update the chaining variables. */
hd->h0 += a;
hd->h1 += b;
hd->h2 += c;
hd->h3 += d;
hd->h4 += e;
data += 64;
}
while (--nblks);
return 88+4*sizeof(void*);
}
/*
* Apply the SHA-1 transform function on the buffer BLOCKOF64BYTE
* which must have a length 64 bytes. BLOCKOF64BYTE must be 32-bit
* aligned. Updates the 20 bytes in BLOCKOF64BYTE with its mixed
* content. Returns the number of bytes which should be burned on the
* stack. You need to use _gcry_sha1_mixblock_init to initialize the
* context.
* WARNING: This is a special purpose function for exclusive use by
* random-csprng.c.
*/
unsigned int
_gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte)
{
u32 *p = blockof64byte;
unsigned int nburn;
nburn = (*hd->bctx.bwrite) (hd, blockof64byte, 1);
p[0] = hd->h0;
p[1] = hd->h1;
p[2] = hd->h2;
p[3] = hd->h3;
p[4] = hd->h4;
return nburn;
}
/* The routine final 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: 20 bytes representing the digest.
*/
static void
sha1_final(void *context)
{
SHA1_CONTEXT *hd = context;
u32 t, th, msb, lsb;
unsigned char *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);
hd->bctx.count = 56;
/* 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);
hd->bctx.count = 64 + 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);
#undef X
_gcry_burn_stack (burn);
}
static unsigned char *
sha1_read( void *context )
{
SHA1_CONTEXT *hd = context;
return hd->bctx.buf;
}
/****************
* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 20 bytes.
*/
void
_gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA1_CONTEXT hd;
sha1_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha1_final (&hd);
memcpy (outbuf, hd.bctx.buf, 20);
}
/* Variant of the above shortcut function using a multiple buffers. */
void
_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SHA1_CONTEXT hd;
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);
}
/*
Self-test section.
*/
static gpg_err_code_t
selftests_sha1 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
what = "short string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA1, 0,
"abc", 3,
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E"
"\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA1, 0,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE"
"\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", 20);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA1, 1,
NULL, 0,
"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E"
"\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", 20);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", GCRY_MD_SHA1, 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;
default:
ec = GPG_ERR_DIGEST_ALGO;
break;
}
return ec;
}
static 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[] =
{
/* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */
{ "1.2.840.113549.1.1.5" },
/* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/
{ "1.2.840.10040.4.3" },
/* from NIST's OIW (sha1) */
{ "1.3.14.3.2.26" },
/* from NIST OIW (sha-1WithRSAEncryption) */
{ "1.3.14.3.2.29" },
/* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */
{ "1.2.840.10045.4.1" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sha1 =
{
GCRY_MD_SHA1, {0, 1},
"SHA1", asn, DIM (asn), oid_spec_sha1, 20,
sha1_init, _gcry_md_block_write, sha1_final, sha1_read, NULL,
_gcry_sha1_hash_buffer, _gcry_sha1_hash_buffers,
sizeof (SHA1_CONTEXT),
run_selftests
};
diff --git a/cipher/sha1.h b/cipher/sha1.h
index acf764ba..9be78735 100644
--- a/cipher/sha1.h
+++ b/cipher/sha1.h
@@ -1,35 +1,35 @@
/* sha1.h - SHA-1 context definition
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_SHA1_H
#define GCRY_SHA1_H
#include "hash-common.h"
/* 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;
} SHA1_CONTEXT;
void _gcry_sha1_mixblock_init (SHA1_CONTEXT *hd);
unsigned int _gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte);
#endif /*GCRY_SHA1_H*/
diff --git a/cipher/sha256-armv8-aarch32-ce.S b/cipher/sha256-armv8-aarch32-ce.S
index 2b17ab1b..29d3f23f 100644
--- a/cipher/sha256-armv8-aarch32-ce.S
+++ b/cipher/sha256-armv8-aarch32-ce.S
@@ -1,231 +1,231 @@
/* sha256-armv8-aarch32-ce.S - ARM/CE accelerated SHA-256 transform function
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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_AARCH32_CRYPTO) && defined(USE_SHA256)
.syntax unified
.arch armv8-a
.fpu crypto-neon-fp-armv8
.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_sha256_aarch32_ce_K:
.LK:
.long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
.long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
.long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
.long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
.long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
.long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
.long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
.long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
.long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
.long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
.long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
.long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
.long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
.long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
.long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
.long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/* Register macros */
#define qH0123 q0
#define qH4567 q1
#define qABCD0 q2
#define qABCD1 q3
#define qEFGH q4
#define qT0 q5
#define qT1 q6
#define qW0 q8
#define qW1 q9
#define qW2 q10
#define qW3 q11
#define qK0 q12
#define qK1 q13
#define qK2 q14
#define qK3 q15
/* Round macros */
#define _(...) /*_*/
#define do_loadk(nk0, nk1) vld1.32 {nk0-nk1},[lr]!;
#define do_add(a, b) vadd.u32 a, a, b;
#define do_sha256su0(w0, w1) sha256su0.32 w0, w1;
#define do_sha256su1(w0, w2, w3) sha256su1.32 w0, w2, w3;
#define do_rounds(k, nk0, nk1, w0, w1, w2, w3, loadk_fn, add_fn, su0_fn, su1_fn) \
loadk_fn( nk0, nk1 ); \
su0_fn( w0, w1 ); \
vmov qABCD1, qABCD0; \
sha256h.32 qABCD0, qEFGH, k; \
sha256h2.32 qEFGH, qABCD1, k; \
add_fn( nk0, w2 ); \
su1_fn( w0, w2, w3 );
/* Other functional macros */
#define CLEAR_REG(reg) veor reg, reg;
/*
* unsigned int
* _gcry_sha256_transform_armv8_ce (u32 state[8], const void *input_data,
* size_t num_blks)
*/
.align 3
.globl _gcry_sha256_transform_armv8_ce
.type _gcry_sha256_transform_armv8_ce,%function;
_gcry_sha256_transform_armv8_ce:
/* input:
* r0: ctx, CTX
* r1: data (64*nblks bytes)
* r2: nblks
*/
cmp r2, #0;
push {r4,lr};
beq .Ldo_nothing;
vpush {q4-q7};
GET_DATA_POINTER(r4, .LK, lr);
mov lr, r4
vld1.32 {qH0123-qH4567}, [r0] /* load state */
vld1.8 {qW0-qW1}, [r1]!
do_loadk(qK0, qK1)
vld1.8 {qW2-qW3}, [r1]!
vmov qABCD0, qH0123
vmov qEFGH, qH4567
vrev32.8 qW0, qW0
vrev32.8 qW1, qW1
vrev32.8 qW2, qW2
do_add(qK0, qW0)
vrev32.8 qW3, qW3
do_add(qK1, qW1)
.Loop:
do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
subs r2,r2,#1
do_rounds(qK1, qK3, _ , qW1, qW2, qW3, qW0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(qK3, qK1, _ , qW3, qW0, qW1, qW2, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(qK1, qK3, _ , qW1, qW2, qW3, qW0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(qK3, qK1, _ , qW3, qW0, qW1, qW2, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(qK0, qK2, qK3, qW0, qW1, qW2, qW3, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(qK1, qK3, _ , qW1, qW2, qW3, qW0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(qK2, qK0, qK1, qW2, qW3, qW0, qW1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(qK3, qK1, _ , qW3, qW0, qW1, qW2, _ , do_add, do_sha256su0, do_sha256su1)
beq .Lend
do_rounds(qK0, qK2, qK3, qW0, _ , qW2, qW3, do_loadk, do_add, _, _)
vld1.8 {qW0}, [r1]!
mov lr, r4
do_rounds(qK1, qK3, _ , qW1, _ , qW3, _ , _ , do_add, _, _)
vld1.8 {qW1}, [r1]!
vrev32.8 qW0, qW0
do_rounds(qK2, qK0, qK1, qW2, _ , qW0, _ , do_loadk, do_add, _, _)
vrev32.8 qW1, qW1
vld1.8 {qW2}, [r1]!
do_rounds(qK3, qK1, _ , qW3, _ , qW1, _ , _ , do_add, _, _)
vld1.8 {qW3}, [r1]!
vadd.u32 qH0123, qABCD0
vadd.u32 qH4567, qEFGH
vrev32.8 qW2, qW2
vmov qABCD0, qH0123
vrev32.8 qW3, qW3
vmov qEFGH, qH4567
b .Loop
.Lend:
do_rounds(qK0, qK2, qK3, qW0, _ , qW2, qW3, do_loadk, do_add, _, _)
do_rounds(qK1, qK3, _ , qW1, _ , qW3, _ , _ , do_add, _, _)
do_rounds(qK2, _ , _ , qW2, _ , _ , _ , _ , _, _, _)
do_rounds(qK3, _ , _ , qW3, _ , _ , _ , _ , _, _, _)
CLEAR_REG(qW0)
CLEAR_REG(qW1)
CLEAR_REG(qW2)
CLEAR_REG(qW3)
CLEAR_REG(qK0)
CLEAR_REG(qK1)
CLEAR_REG(qK2)
CLEAR_REG(qK3)
vadd.u32 qH0123, qABCD0
vadd.u32 qH4567, qEFGH
CLEAR_REG(qABCD0)
CLEAR_REG(qABCD1)
CLEAR_REG(qEFGH)
vst1.32 {qH0123-qH4567}, [r0] /* store state */
CLEAR_REG(qH0123)
CLEAR_REG(qH4567)
vpop {q4-q7}
.Ldo_nothing:
mov r0, #0
pop {r4,pc}
.size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;
#endif
diff --git a/cipher/sha256-armv8-aarch64-ce.S b/cipher/sha256-armv8-aarch64-ce.S
index f57cae29..3c53de1d 100644
--- a/cipher/sha256-armv8-aarch64-ce.S
+++ b/cipher/sha256-armv8-aarch64-ce.S
@@ -1,215 +1,215 @@
/* sha256-armv8-aarch64-ce.S - ARM/CE accelerated SHA-256 transform function
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://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) && defined(USE_SHA256)
.cpu generic+simd+crypto
.text
/* Constants */
.align 4
gcry_sha256_aarch64_ce_K:
.LK:
.long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
.long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
.long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
.long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
.long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
.long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
.long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
.long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
.long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
.long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
.long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
.long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
.long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
.long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
.long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
.long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/* Register macros */
#define vH0123 v0
#define vH4567 v1
#define vABCD0 v2
#define qABCD0 q2
#define vABCD1 v3
#define qABCD1 q3
#define vEFGH v4
#define qEFGH q4
#define vT0 v5
#define vT1 v6
#define vW0 v16
#define vW1 v17
#define vW2 v18
#define vW3 v19
#define vK0 v20
#define vK1 v21
#define vK2 v22
#define vK3 v23
/* Round macros */
#define _(...) /*_*/
#define do_loadk(nk0, nk1) ld1 {nk0.16b-nk1.16b},[x3],#32;
#define do_add(a, b) add a.4s, a.4s, b.4s;
#define do_sha256su0(w0, w1) sha256su0 w0.4s, w1.4s;
#define do_sha256su1(w0, w2, w3) sha256su1 w0.4s, w2.4s, w3.4s;
#define do_rounds(k, nk0, nk1, w0, w1, w2, w3, loadk_fn, add_fn, su0_fn, su1_fn) \
loadk_fn( v##nk0, v##nk1 ); \
su0_fn( v##w0, v##w1 ); \
mov vABCD1.16b, vABCD0.16b; \
sha256h qABCD0, qEFGH, v##k.4s; \
sha256h2 qEFGH, qABCD1, v##k.4s; \
add_fn( v##nk0, v##w2 ); \
su1_fn( v##w0, v##w2, v##w3 );
/* Other functional macros */
#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
/*
* unsigned int
* _gcry_sha256_transform_armv8_ce (u32 state[8], const void *input_data,
* size_t num_blks)
*/
.align 3
.globl _gcry_sha256_transform_armv8_ce
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;
GET_DATA_POINTER(x3, .LK);
mov x4, x3
ld1 {vH0123.4s-vH4567.4s}, [x0] /* load state */
ld1 {vW0.16b-vW1.16b}, [x1], #32
do_loadk(vK0, vK1)
ld1 {vW2.16b-vW3.16b}, [x1], #32
mov vABCD0.16b, vH0123.16b
mov vEFGH.16b, vH4567.16b
rev32 vW0.16b, vW0.16b
rev32 vW1.16b, vW1.16b
rev32 vW2.16b, vW2.16b
do_add(vK0, vW0)
rev32 vW3.16b, vW3.16b
do_add(vK1, vW1)
.Loop:
do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
sub x2,x2,#1
do_rounds(K1, K3, _ , W1, W2, W3, W0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(K3, K1, _ , W3, W0, W1, W2, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(K1, K3, _ , W1, W2, W3, W0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(K3, K1, _ , W3, W0, W1, W2, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(K1, K3, _ , W1, W2, W3, W0, _ , do_add, do_sha256su0, do_sha256su1)
do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
do_rounds(K3, K1, _ , W3, W0, W1, W2, _ , do_add, do_sha256su0, do_sha256su1)
cbz x2, .Lend
do_rounds(K0, K2, K3, W0, _ , W2, W3, do_loadk, do_add, _, _)
ld1 {vW0.16b}, [x1], #16
mov x3, x4
do_rounds(K1, K3, _ , W1, _ , W3, _ , _ , do_add, _, _)
ld1 {vW1.16b}, [x1], #16
rev32 vW0.16b, vW0.16b
do_rounds(K2, K0, K1, W2, _ , W0, _ , do_loadk, do_add, _, _)
rev32 vW1.16b, vW1.16b
ld1 {vW2.16b}, [x1], #16
do_rounds(K3, K1, _ , W3, _ , W1, _ , _ , do_add, _, _)
ld1 {vW3.16b}, [x1], #16
do_add(vH0123, vABCD0)
do_add(vH4567, vEFGH)
rev32 vW2.16b, vW2.16b
mov vABCD0.16b, vH0123.16b
rev32 vW3.16b, vW3.16b
mov vEFGH.16b, vH4567.16b
b .Loop
.Lend:
do_rounds(K0, K2, K3, W0, _ , W2, W3, do_loadk, do_add, _, _)
do_rounds(K1, K3, _ , W1, _ , W3, _ , _ , do_add, _, _)
do_rounds(K2, _ , _ , W2, _ , _ , _ , _ , _, _, _)
do_rounds(K3, _ , _ , W3, _ , _ , _ , _ , _, _, _)
CLEAR_REG(vW0)
CLEAR_REG(vW1)
CLEAR_REG(vW2)
CLEAR_REG(vW3)
CLEAR_REG(vK0)
CLEAR_REG(vK1)
CLEAR_REG(vK2)
CLEAR_REG(vK3)
do_add(vH0123, vABCD0)
do_add(vH4567, vEFGH)
CLEAR_REG(vABCD0)
CLEAR_REG(vABCD1)
CLEAR_REG(vEFGH)
st1 {vH0123.4s-vH4567.4s}, [x0] /* store state */
CLEAR_REG(vH0123)
CLEAR_REG(vH4567)
.Ldo_nothing:
mov x0, #0
ret
CFI_ENDPROC();
ELF(.size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;)
#endif
diff --git a/cipher/sha256-avx-amd64.S b/cipher/sha256-avx-amd64.S
index 77143ff0..f2d83876 100644
--- a/cipher/sha256-avx-amd64.S
+++ b/cipher/sha256-avx-amd64.S
@@ -1,532 +1,532 @@
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This code is described in an Intel White-Paper:
; "Fast SHA-256 Implementations on Intel Architecture Processors"
;
-; To find it, surf to http://www.intel.com/p/en_US/embedded
+; To find it, surf to https://www.intel.com/p/en_US/embedded
; and search for that title.
; The paper is expected to be released roughly at the end of April, 2012
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This code schedules 1 blocks at a time, with 4 lanes per block
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/
/*
* Conversion to GAS assembly and integration to libgcrypt
* by Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* Note: Based on the SSSE3 implementation.
*/
#ifdef __x86_64
#include <config.h>
#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
defined(HAVE_GCC_INLINE_ASM_AVX) && defined(USE_SHA256)
#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 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
/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
/* 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
/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
X0 = xmm4
X1 = xmm5
X2 = xmm6
X3 = xmm7
XTMP0 = xmm0
XTMP1 = xmm1
XTMP2 = xmm2
XTMP3 = xmm3
XTMP4 = xmm8
XFER = xmm9
SHUF_00BA = xmm10 /* shuffle xBxA -> 00BA */
SHUF_DC00 = xmm11 /* shuffle xDxC -> DC00 */
BYTE_FLIP_MASK = xmm12
NUM_BLKS = rdx /* 3rd arg */
CTX = rsi /* 2nd arg */
INP = rdi /* 1st arg */
SRND = rdi /* clobbers INP */
c = ecx
d = r8d
e = edx
TBL = rbp
a = eax
b = ebx
f = r9d
g = r10d
h = r11d
y0 = r13d
y1 = r14d
y2 = r15d
#define _INP_END_SIZE 8
#define _INP_SIZE 8
#define _XFER_SIZE 8
#define _XMM_SAVE_SIZE 0
/* STACK_SIZE plus pushes must be an odd multiple of 8 */
#define _ALIGN_SIZE 8
#define _INP_END 0
#define _INP (_INP_END + _INP_END_SIZE)
#define _XFER (_INP + _INP_SIZE)
#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) */
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) */
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) */
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) */
lea h, [h + y0] /* h = h + S1 + CH + k + w + S0 + MAJ */
ROTATE_ARGS
rotate_Xs
.endm
/* 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) */
lea h, [h + y0] /* h = h + S1 + CH + k + w + S0 + MAJ */
ROTATE_ARGS
.endm
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; void sha256_avx(void *input_data, UINT32 digest[8], UINT64 num_blks)
;; arg 1 : pointer to input data
;; arg 2 : pointer to digest
;; arg 3 : Num blocks
*/
.text
.globl _gcry_sha256_transform_amd64_avx
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
add NUM_BLKS, INP /* pointer to end of data */
mov [rsp + _INP_END], NUM_BLKS
/* load initial digest */
mov a,[4*0 + CTX]
mov b,[4*1 + CTX]
mov c,[4*2 + CTX]
mov d,[4*3 + CTX]
mov e,[4*4 + CTX]
mov f,[4*5 + CTX]
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]
.Loop0:
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
mov [rsp + _INP], INP
/* schedule 48 input dwords, by doing 3 rounds of 16 each */
mov SRND, 3
.align 16
.Loop1:
vpaddd XFER, X0, [TBL + 0*16]
vmovdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
vpaddd XFER, X0, [TBL + 1*16]
vmovdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
vpaddd XFER, X0, [TBL + 2*16]
vmovdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
vpaddd XFER, X0, [TBL + 3*16]
vmovdqa [rsp + _XFER], XFER
add TBL, 4*16
FOUR_ROUNDS_AND_SCHED
sub SRND, 1
jne .Loop1
mov SRND, 2
.Loop2:
vpaddd X0, X0, [TBL + 0*16]
vmovdqa [rsp + _XFER], X0
DO_ROUND 0
DO_ROUND 1
DO_ROUND 2
DO_ROUND 3
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
vmovdqa X0, X2
vmovdqa X1, X3
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
mov INP, [rsp + _INP]
add INP, 64
cmp INP, [rsp + _INP_END]
jne .Loop0
.Ldone_hash:
vzeroall
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)
ret
CFI_ENDPROC()
.align 16
.LK256:
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.LPSHUFFLE_BYTE_FLIP_MASK: .octa 0x0c0d0e0f08090a0b0405060700010203
/* shuffle xBxA -> 00BA */
.L_SHUF_00BA: .octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
/* shuffle xDxC -> DC00 */
.L_SHUF_DC00: .octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
#endif
#endif
diff --git a/cipher/sha256-avx2-bmi2-amd64.S b/cipher/sha256-avx2-bmi2-amd64.S
index 52be1a07..49a3994e 100644
--- a/cipher/sha256-avx2-bmi2-amd64.S
+++ b/cipher/sha256-avx2-bmi2-amd64.S
@@ -1,575 +1,575 @@
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This code is described in an Intel White-Paper:
; "Fast SHA-256 Implementations on Intel Architecture Processors"
;
-; To find it, surf to http://www.intel.com/p/en_US/embedded
+; To find it, surf to https://www.intel.com/p/en_US/embedded
; and search for that title.
; The paper is expected to be released roughly at the end of April, 2012
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This code schedules 2 blocks at a time, with 4 lanes per block
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/
/*
* Conversion to GAS assembly and integration to libgcrypt
* by Jussi Kivilinna <jussi.kivilinna@iki.fi>
*/
#ifdef __x86_64
#include <config.h>
#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
defined(HAVE_GCC_INLINE_ASM_AVX2) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
defined(USE_SHA256)
#include "asm-common-amd64.h"
.intel_syntax noprefix
#define VMOVDQ vmovdqu /* ; assume buffers not aligned */
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
X0 = ymm4
X1 = ymm5
X2 = ymm6
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 ONE_ROUND_PART1 XFER
/* 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, [\XFER]
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]
.endm
.macro ONE_ROUND_PART2
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]
.endm
.macro ONE_ROUND XFER
ONE_ROUND_PART1 \XFER
ONE_ROUND_PART2
.endm
.macro FOUR_ROUNDS_AND_SCHED XFER, XFEROUT
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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+\XFER
vmovdqa [rsp + _XFER + \XFEROUT], XFER
ONE_ROUND_PART2
ROTATE_ARGS
rotate_Xs
.endm
.macro DO_4ROUNDS XFER
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
ONE_ROUND 0*4+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
ONE_ROUND 1*4+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
ONE_ROUND 2*4+\XFER
ROTATE_ARGS
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
ONE_ROUND 3*4+\XFER
ROTATE_ARGS
.endm
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; void sha256_rorx(void *input_data, UINT32 digest[8], UINT64 num_blks)
;; arg 1 : pointer to input data
;; arg 2 : pointer to digest
;; arg 3 : Num blocks
*/
.text
.globl _gcry_sha256_transform_amd64_avx2
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, ~63
mov [rsp + _RSP], rax
CFI_CFA_ON_STACK(_RSP, 6 * 8)
shl NUM_BLKS, 6 /* convert to bytes */
lea NUM_BLKS, [NUM_BLKS + INP - 64] /* pointer to last block */
mov [rsp + _INP_END], NUM_BLKS
/* ; load initial digest */
mov a,[4*0 + CTX]
mov b,[4*1 + CTX]
mov c,[4*2 + CTX]
mov d,[4*3 + CTX]
mov e,[4*4 + CTX]
mov f,[4*5 + CTX]
mov g,[4*6 + CTX]
mov h,[4*7 + CTX]
mov [rsp + _CTX], CTX
.Loop0:
lea TBL, [.LK256 ADD_RIP]
/* ; Load first 16 dwords from two blocks */
VMOVDQ XTMP0, [INP + 0*32]
VMOVDQ XTMP1, [INP + 1*32]
VMOVDQ XTMP2, [INP + 2*32]
VMOVDQ XTMP3, [INP + 3*32]
/* ; byte swap data */
vpshufb XTMP0, XTMP0, BYTE_FLIP_MASK
vpshufb XTMP1, XTMP1, BYTE_FLIP_MASK
vpshufb XTMP2, XTMP2, BYTE_FLIP_MASK
vpshufb XTMP3, XTMP3, BYTE_FLIP_MASK
/* ; transpose data into high/low halves */
vperm2i128 X0, XTMP0, XTMP2, 0x20
vperm2i128 X1, XTMP0, XTMP2, 0x31
vperm2i128 X2, XTMP1, XTMP3, 0x20
vperm2i128 X3, XTMP1, XTMP3, 0x31
.Last_block_enter:
add INP, 64
mov [rsp + _INP], INP
/* ; 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:
FOUR_ROUNDS_AND_SCHED rsp + _XFER + SRND + 0*32, SRND + 4*32
FOUR_ROUNDS_AND_SCHED rsp + _XFER + SRND + 1*32, SRND + 5*32
FOUR_ROUNDS_AND_SCHED rsp + _XFER + SRND + 2*32, SRND + 6*32
FOUR_ROUNDS_AND_SCHED rsp + _XFER + SRND + 3*32, SRND + 7*32
add SRND, 4*32
cmp SRND, 3 * 4*32
jb .Loop1
/* ; Do last 16 rounds with no scheduling */
DO_4ROUNDS rsp + _XFER + (3*4*32 + 0*32)
DO_4ROUNDS rsp + _XFER + (3*4*32 + 1*32)
DO_4ROUNDS rsp + _XFER + (3*4*32 + 2*32)
DO_4ROUNDS rsp + _XFER + (3*4*32 + 3*32)
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
cmp INP, [rsp + _INP_END]
ja .Ldone_hash
/* ;;; Do second block using previously scheduled results */
xor SRND, SRND
.align 16
.Loop3:
DO_4ROUNDS rsp + _XFER + SRND + 0*32 + 16
DO_4ROUNDS rsp + _XFER + SRND + 1*32 + 16
add SRND, 2*32
cmp SRND, 4 * 4*32
jb .Loop3
mov CTX, [rsp + _CTX]
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
cmp INP, [rsp + _INP_END]
jb .Loop0
ja .Ldone_hash
.Ldo_last_block:
/* ;;; do last block */
lea TBL, [.LK256 ADD_RIP]
VMOVDQ XWORD0, [INP + 0*16]
VMOVDQ XWORD1, [INP + 1*16]
VMOVDQ XWORD2, [INP + 2*16]
VMOVDQ XWORD3, [INP + 3*16]
vpshufb XWORD0, XWORD0, X_BYTE_FLIP_MASK
vpshufb XWORD1, XWORD1, X_BYTE_FLIP_MASK
vpshufb XWORD2, XWORD2, X_BYTE_FLIP_MASK
vpshufb XWORD3, XWORD3, X_BYTE_FLIP_MASK
jmp .Last_block_enter
.Lonly_one_block:
/* ; load initial digest */
mov a,[4*0 + CTX]
mov b,[4*1 + CTX]
mov c,[4*2 + CTX]
mov d,[4*3 + CTX]
mov e,[4*4 + CTX]
mov f,[4*5 + CTX]
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
jmp .Ldo_last_block
.Ldone_hash:
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)
.Lnowork:
ret
CFI_ENDPROC()
.align 64
.LK256:
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.LPSHUFFLE_BYTE_FLIP_MASK:
.octa 0x0c0d0e0f08090a0b0405060700010203,0x0c0d0e0f08090a0b0405060700010203
/* shuffle xBxA -> 00BA */
.L_SHUF_00BA:
.octa 0xFFFFFFFFFFFFFFFF0b0a090803020100,0xFFFFFFFFFFFFFFFF0b0a090803020100
/* shuffle xDxC -> DC00 */
.L_SHUF_DC00:
.octa 0x0b0a090803020100FFFFFFFFFFFFFFFF,0x0b0a090803020100FFFFFFFFFFFFFFFF
#endif
#endif
diff --git a/cipher/sha256-intel-shaext.c b/cipher/sha256-intel-shaext.c
index 2eda42d8..1f62a17d 100644
--- a/cipher/sha256-intel-shaext.c
+++ b/cipher/sha256-intel-shaext.c
@@ -1,359 +1,359 @@
/* 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/>.
+ * License along with this program; if not, see <https://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
/* 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
_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-ssse3-amd64.S b/cipher/sha256-ssse3-amd64.S
index 0fb94c1b..e1f235f7 100644
--- a/cipher/sha256-ssse3-amd64.S
+++ b/cipher/sha256-ssse3-amd64.S
@@ -1,553 +1,553 @@
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This code is described in an Intel White-Paper:
; "Fast SHA-256 Implementations on Intel Architecture Processors"
;
-; To find it, surf to http://www.intel.com/p/en_US/embedded
+; To find it, surf to https://www.intel.com/p/en_US/embedded
; and search for that title.
; The paper is expected to be released roughly at the end of April, 2012
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This code schedules 1 blocks at a time, with 4 lanes per block
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
*/
/*
* Conversion to GAS assembly and integration to libgcrypt
* by Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* Note: original implementation was named as SHA256-SSE4. However, only SSSE3
* is required.
*/
#ifdef __x86_64
#include <config.h>
#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA256)
#include "asm-common-amd64.h"
.intel_syntax noprefix
#define MOVDQ movdqu /* assume buffers not aligned */
/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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
/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
/* 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
/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
X0 = xmm4
X1 = xmm5
X2 = xmm6
X3 = xmm7
XTMP0 = xmm0
XTMP1 = xmm1
XTMP2 = xmm2
XTMP3 = xmm3
XTMP4 = xmm8
XFER = xmm9
SHUF_00BA = xmm10 /* shuffle xBxA -> 00BA */
SHUF_DC00 = xmm11 /* shuffle xDxC -> DC00 */
BYTE_FLIP_MASK = xmm12
NUM_BLKS = rdx /* 3rd arg */
CTX = rsi /* 2nd arg */
INP = rdi /* 1st arg */
SRND = rdi /* clobbers INP */
c = ecx
d = r8d
e = edx
TBL = rbp
a = eax
b = ebx
f = r9d
g = r10d
h = r11d
y0 = r13d
y1 = r14d
y2 = r15d
#define _INP_END_SIZE 8
#define _INP_SIZE 8
#define _XFER_SIZE 8
#define _XMM_SAVE_SIZE 0
/* STACK_SIZE plus pushes must be an odd multiple of 8 */
#define _ALIGN_SIZE 8
#define _INP_END 0
#define _INP (_INP_END + _INP_END_SIZE)
#define _XFER (_INP + _INP_SIZE)
#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) */
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) */
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) */
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) */
lea h, [h + y0] /* h = h + S1 + CH + k + w + S0 + MAJ */
ROTATE_ARGS
rotate_Xs
.endm
/* 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) */
lea h, [h + y0] /* h = h + S1 + CH + k + w + S0 + MAJ */
ROTATE_ARGS
.endm
/*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; void sha256_sse4(void *input_data, UINT32 digest[8], UINT64 num_blks)
;; arg 1 : pointer to input data
;; arg 2 : pointer to digest
;; arg 3 : Num blocks
*/
.text
.globl _gcry_sha256_transform_amd64_ssse3
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
add NUM_BLKS, INP /* pointer to end of data */
mov [rsp + _INP_END], NUM_BLKS
/* load initial digest */
mov a,[4*0 + CTX]
mov b,[4*1 + CTX]
mov c,[4*2 + CTX]
mov d,[4*3 + CTX]
mov e,[4*4 + CTX]
mov f,[4*5 + CTX]
mov g,[4*6 + CTX]
mov h,[4*7 + CTX]
movdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP]
movdqa SHUF_00BA, [.L_SHUF_00BA ADD_RIP]
movdqa SHUF_DC00, [.L_SHUF_DC00 ADD_RIP]
.Loop0:
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
mov [rsp + _INP], INP
/* schedule 48 input dwords, by doing 3 rounds of 16 each */
mov SRND, 3
.align 16
.Loop1:
movdqa XFER, [TBL + 0*16]
paddd XFER, X0
movdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
movdqa XFER, [TBL + 1*16]
paddd XFER, X0
movdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
movdqa XFER, [TBL + 2*16]
paddd XFER, X0
movdqa [rsp + _XFER], XFER
FOUR_ROUNDS_AND_SCHED
movdqa XFER, [TBL + 3*16]
paddd XFER, X0
movdqa [rsp + _XFER], XFER
add TBL, 4*16
FOUR_ROUNDS_AND_SCHED
sub SRND, 1
jne .Loop1
mov SRND, 2
.Loop2:
paddd X0, [TBL + 0*16]
movdqa [rsp + _XFER], X0
DO_ROUND 0
DO_ROUND 1
DO_ROUND 2
DO_ROUND 3
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
movdqa X0, X2
movdqa X1, X3
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
mov INP, [rsp + _INP]
add INP, 64
cmp INP, [rsp + _INP_END]
jne .Loop0
pxor xmm0, xmm0
pxor xmm1, xmm1
pxor xmm2, xmm2
pxor xmm3, xmm3
pxor xmm4, xmm4
pxor xmm5, xmm5
pxor xmm6, xmm6
pxor xmm7, xmm7
pxor xmm8, xmm8
pxor xmm9, xmm9
pxor xmm10, xmm10
pxor xmm11, xmm11
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)
ret
CFI_ENDPROC()
.align 16
.LK256:
.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
.long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
.long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.LPSHUFFLE_BYTE_FLIP_MASK: .octa 0x0c0d0e0f08090a0b0405060700010203
/* shuffle xBxA -> 00BA */
.L_SHUF_00BA: .octa 0xFFFFFFFFFFFFFFFF0b0a090803020100
/* shuffle xDxC -> DC00 */
.L_SHUF_DC00: .octa 0x0b0a090803020100FFFFFFFFFFFFFFFF
#endif
#endif
diff --git a/cipher/sha256.c b/cipher/sha256.c
index 6c683348..216ae813 100644
--- a/cipher/sha256.c
+++ b/cipher/sha256.c
@@ -1,774 +1,774 @@
/* sha256.c - SHA256 hash function
* Copyright (C) 2003, 2006, 2008, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Test vectors:
"abc"
SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7
SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525
SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1
"a" one million times
SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67
SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0
*/
#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_SSSE3 indicates whether to compile with Intel SSSE3 code. */
#undef USE_SSSE3
#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# define USE_SSSE3 1
#endif
/* 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_INTEL_SYNTAX_PLATFORM_AS) && \
(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/BMI2 code. */
#undef USE_AVX2
#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \
defined(HAVE_GCC_INLINE_ASM_BMI2) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# 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
#ifdef ENABLE_ARM_CRYPTO_SUPPORT
# if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
&& defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO)
# define USE_ARM_CE 1
# elif defined(__AARCH64EL__) \
&& defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \
&& defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
# define USE_ARM_CE 1
# endif
#endif
typedef struct {
gcry_md_block_ctx_t bctx;
u32 h0,h1,h2,h3,h4,h5,h6,h7;
} 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 _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->h0, nblks)
+ ASM_EXTRA_STACK;
}
#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;
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->h0, nblks)
+ ASM_EXTRA_STACK;
}
#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;
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->h0, 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->h0, data, nblks);
}
#endif
#ifdef USE_ARM_CE
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->h0, data, nblks);
}
#endif
static unsigned int
do_transform_generic (void *ctx, const unsigned char *data, size_t nblks);
static void
sha256_init (void *context, unsigned int flags)
{
SHA256_CONTEXT *hd = context;
unsigned int features = _gcry_get_hw_features ();
(void)flags;
hd->h0 = 0x6a09e667;
hd->h1 = 0xbb67ae85;
hd->h2 = 0x3c6ef372;
hd->h3 = 0xa54ff53a;
hd->h4 = 0x510e527f;
hd->h5 = 0x9b05688c;
hd->h6 = 0x1f83d9ab;
hd->h7 = 0x5be0cd19;
hd->bctx.nblocks = 0;
hd->bctx.nblocks_high = 0;
hd->bctx.count = 0;
hd->bctx.blocksize = 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
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. */
if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
hd->bctx.bwrite = do_sha256_transform_amd64_avx;
#endif
#ifdef USE_AVX2
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
if ((features & HWF_ARM_SHA2) != 0)
hd->bctx.bwrite = do_sha256_transform_armv8_ce;
#endif
(void)features;
}
static void
sha224_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->bctx.nblocks = 0;
hd->bctx.nblocks_high = 0;
hd->bctx.count = 0;
hd->bctx.blocksize = 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
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. */
if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
hd->bctx.bwrite = do_sha256_transform_amd64_avx;
#endif
#ifdef USE_AVX2
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
if ((features & HWF_ARM_SHA2) != 0)
hd->bctx.bwrite = do_sha256_transform_armv8_ce;
#endif
(void)features;
}
/*
Transform the message X which consists of 16 32-bit-words. See FIPS
180-2 for details. */
#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)
/* (4.2) same as SHA-1's F1. */
#define Cho(x, y, z) (z ^ (x & (y ^ z)))
/* (4.3) same as SHA-1's F3 */
#define Maj(x, y, z) ((x & y) + (z & (x ^ y)))
/* (4.4) */
#define Sum0(x) (ror (x, 2) ^ ror (x, 13) ^ ror (x, 22))
/* (4.5) */
#define Sum1(x) (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25))
/* Message expansion */
#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */
#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */
#define I(i) ( w[i] = buf_get_be32(data + i * 4) )
#define W(i) ( w[i&0x0f] = S1(w[(i-2) &0x0f]) \
+ w[(i-7) &0x0f] \
+ S0(w[(i-15)&0x0f]) \
+ w[(i-16)&0x0f] )
static unsigned int
do_transform_generic (void *ctx, const unsigned char *data, size_t nblks)
{
SHA256_CONTEXT *hd = ctx;
static const u32 K[64] = {
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
};
do
{
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;
data += 64;
}
while (--nblks);
return 26*4 + 32 + 3 * sizeof(void*);
}
#undef S0
#undef S1
#undef R
/*
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
sha256_final(void *context)
{
SHA256_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);
hd->bctx.count = 56;
/* 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);
hd->bctx.count = 64 + 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
_gcry_burn_stack (burn);
}
static byte *
sha256_read (void *context)
{
SHA256_CONTEXT *hd = context;
return hd->bctx.buf;
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 32 bytes. */
void
_gcry_sha256_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA256_CONTEXT hd;
sha256_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha256_final (&hd);
memcpy (outbuf, hd.bctx.buf, 32);
}
/* Variant of the above shortcut function using multiple buffers. */
void
_gcry_sha256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SHA256_CONTEXT hd;
sha256_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);
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 28 bytes. */
static void
_gcry_sha224_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA256_CONTEXT hd;
sha224_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha256_final (&hd);
memcpy (outbuf, hd.bctx.buf, 28);
}
/* Variant of the above shortcut function using multiple buffers. */
static void
_gcry_sha224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SHA256_CONTEXT hd;
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, 28);
}
/*
Self-test section.
*/
static gpg_err_code_t
selftests_sha224 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
what = "short string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA224, 0,
"abc", 3,
"\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3"
"\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA224, 0,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
"\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50"
"\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA224, 1,
NULL, 0,
"\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b"
"\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67", 28);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", GCRY_MD_SHA224, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
static gpg_err_code_t
selftests_sha256 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
what = "short string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA256, 0,
"abc", 3,
"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
"\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA256, 0,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
"\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1",
32);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA256, 1,
NULL, 0,
"\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
"\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0",
32);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", GCRY_MD_SHA256, 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_SHA224:
ec = selftests_sha224 (extended, report);
break;
case GCRY_MD_SHA256:
ec = selftests_sha256 (extended, report);
break;
default:
ec = GPG_ERR_DIGEST_ALGO;
break;
}
return ec;
}
static 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[] =
{
/* From RFC3874, Section 4 */
{ "2.16.840.1.101.3.4.2.4" },
{ NULL },
};
static 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[] =
{
/* 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" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sha224 =
{
GCRY_MD_SHA224, {0, 1},
"SHA224", asn224, DIM (asn224), oid_spec_sha224, 28,
sha224_init, _gcry_md_block_write, sha256_final, sha256_read, NULL,
_gcry_sha224_hash_buffer, _gcry_sha224_hash_buffers,
sizeof (SHA256_CONTEXT),
run_selftests
};
gcry_md_spec_t _gcry_digest_spec_sha256 =
{
GCRY_MD_SHA256, {0, 1},
"SHA256", asn256, DIM (asn256), oid_spec_sha256, 32,
sha256_init, _gcry_md_block_write, sha256_final, sha256_read, NULL,
_gcry_sha256_hash_buffer, _gcry_sha256_hash_buffers,
sizeof (SHA256_CONTEXT),
run_selftests
};
diff --git a/cipher/sha512-arm.S b/cipher/sha512-arm.S
index 94ec0141..684d7261 100644
--- a/cipher/sha512-arm.S
+++ b/cipher/sha512-arm.S
@@ -1,464 +1,464 @@
/* sha512-arm.S - ARM assembly implementation of SHA-512 transform
*
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.arm
/* structure of SHA512_CONTEXT */
#define hd_a 0
#define hd_b ((hd_a) + 8)
#define hd_c ((hd_b) + 8)
#define hd_d ((hd_c) + 8)
#define hd_e ((hd_d) + 8)
#define hd_f ((hd_e) + 8)
#define hd_g ((hd_f) + 8)
#define hd_h ((hd_g) + 8)
/* register macros */
#define RK %r2
#define RElo %r0
#define REhi %r1
#define RT1lo %r3
#define RT1hi %r4
#define RT2lo %r5
#define RT2hi %r6
#define RWlo %r7
#define RWhi %r8
#define RT3lo %r9
#define RT3hi %r10
#define RT4lo %r11
#define RT4hi %ip
#define RRND %lr
/* variable offsets in stack */
#define ctx (0)
#define data ((ctx) + 4)
#define nblks ((data) + 4)
#define _a ((nblks) + 4)
#define _b ((_a) + 8)
#define _c ((_b) + 8)
#define _d ((_c) + 8)
#define _e ((_d) + 8)
#define _f ((_e) + 8)
#define _g ((_f) + 8)
#define _h ((_g) + 8)
#define w(i) ((_h) + 8 + ((i) % 16) * 8)
#define STACK_MAX (w(15) + 8)
/* helper macros */
#define ldr_unaligned_be(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 3)]; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 0)]; \
orr rout, rout, rtmp, lsl #24;
#ifdef __ARMEL__
/* bswap on little-endian */
#ifdef HAVE_ARM_ARCH_V6
#define be_to_host(reg, rtmp) \
rev reg, reg;
#else
#define be_to_host(reg, rtmp) \
eor rtmp, reg, reg, ror #16; \
mov rtmp, rtmp, lsr #8; \
bic rtmp, rtmp, #65280; \
eor reg, rtmp, reg, ror #8;
#endif
#else
/* nop on big-endian */
#define be_to_host(reg, rtmp) /*_*/
#endif
#define host_to_host(x, y) /*_*/
#define read_u64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, convert, rtmp) \
ldr lo0, [rin, #((offs) + 0 * 8 + 4)]; \
ldr hi0, [rin, #((offs) + 0 * 8 + 0)]; \
ldr lo1, [rin, #((offs) + 1 * 8 + 4)]; \
ldr hi1, [rin, #((offs) + 1 * 8 + 0)]; \
ldr lo2, [rin, #((offs) + 2 * 8 + 4)]; \
convert(lo0, rtmp); \
ldr hi2, [rin, #((offs) + 2 * 8 + 0)]; \
convert(hi0, rtmp); \
ldr lo3, [rin, #((offs) + 3 * 8 + 4)]; \
convert(lo1, rtmp); \
ldr hi3, [rin, #((offs) + 3 * 8 + 0)]; \
convert(hi1, rtmp); \
convert(lo2, rtmp); \
convert(hi2, rtmp); \
convert(lo3, rtmp); \
convert(hi3, rtmp);
#define read_be64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, rtmp0) \
read_u64_aligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, be_to_host, rtmp0)
/* need to handle unaligned reads by byte reads */
#define read_be64_unaligned_4(rin, offs, lo0, hi0, lo1, hi1, lo2, hi2, lo3, hi3, rtmp0) \
ldr_unaligned_be(lo0, rin, (offs) + 0 * 8 + 4, rtmp0); \
ldr_unaligned_be(hi0, rin, (offs) + 0 * 8 + 0, rtmp0); \
ldr_unaligned_be(lo1, rin, (offs) + 1 * 8 + 4, rtmp0); \
ldr_unaligned_be(hi1, rin, (offs) + 1 * 8 + 0, rtmp0); \
ldr_unaligned_be(lo2, rin, (offs) + 2 * 8 + 4, rtmp0); \
ldr_unaligned_be(hi2, rin, (offs) + 2 * 8 + 0, rtmp0); \
ldr_unaligned_be(lo3, rin, (offs) + 3 * 8 + 4, rtmp0); \
ldr_unaligned_be(hi3, rin, (offs) + 3 * 8 + 0, rtmp0);
/***********************************************************************
* ARM assembly implementation of sha512 transform
***********************************************************************/
/* Round function */
#define R(_a,_b,_c,_d,_e,_f,_g,_h,W,wi) \
/* Message expansion, t1 = _h + w[i] */ \
W(_a,_h,wi); \
\
/* w = Sum1(_e) */ \
mov RWlo, RElo, lsr#14; \
ldm RK!, {RT2lo-RT2hi}; \
mov RWhi, REhi, lsr#14; \
eor RWlo, RWlo, RElo, lsr#18; \
eor RWhi, RWhi, REhi, lsr#18; \
ldr RT3lo, [%sp, #(_f)]; \
adds RT1lo, RT2lo; /* t1 += K */ \
ldr RT3hi, [%sp, #(_f) + 4]; \
adc RT1hi, RT2hi; \
ldr RT4lo, [%sp, #(_g)]; \
eor RWlo, RWlo, RElo, lsl#23; \
ldr RT4hi, [%sp, #(_g) + 4]; \
eor RWhi, RWhi, REhi, lsl#23; \
eor RWlo, RWlo, REhi, lsl#18; \
eor RWhi, RWhi, RElo, lsl#18; \
eor RWlo, RWlo, REhi, lsl#14; \
eor RWhi, RWhi, RElo, lsl#14; \
eor RWlo, RWlo, REhi, lsr#9; \
eor RWhi, RWhi, RElo, lsr#9; \
\
/* Cho(_e,_f,_g) => (_e & _f) ^ (~_e & _g) */ \
adds RT1lo, RWlo; /* t1 += Sum1(_e) */ \
and RT3lo, RT3lo, RElo; \
adc RT1hi, RWhi; \
and RT3hi, RT3hi, REhi; \
bic RT4lo, RT4lo, RElo; \
bic RT4hi, RT4hi, REhi; \
eor RT3lo, RT3lo, RT4lo; \
eor RT3hi, RT3hi, RT4hi; \
\
/* Load D */ \
/* t1 += Cho(_e,_f,_g) */ \
ldr RElo, [%sp, #(_d)]; \
adds RT1lo, RT3lo; \
ldr REhi, [%sp, #(_d) + 4]; \
adc RT1hi, RT3hi; \
\
/* Load A */ \
ldr RT3lo, [%sp, #(_a)]; \
\
/* _d += t1 */ \
adds RElo, RT1lo; \
ldr RT3hi, [%sp, #(_a) + 4]; \
adc REhi, RT1hi; \
\
/* Store D */ \
str RElo, [%sp, #(_d)]; \
\
/* t2 = Sum0(_a) */ \
mov RT2lo, RT3lo, lsr#28; \
str REhi, [%sp, #(_d) + 4]; \
mov RT2hi, RT3hi, lsr#28; \
ldr RWlo, [%sp, #(_b)]; \
eor RT2lo, RT2lo, RT3lo, lsl#30; \
ldr RWhi, [%sp, #(_b) + 4]; \
eor RT2hi, RT2hi, RT3hi, lsl#30; \
eor RT2lo, RT2lo, RT3lo, lsl#25; \
eor RT2hi, RT2hi, RT3hi, lsl#25; \
eor RT2lo, RT2lo, RT3hi, lsl#4; \
eor RT2hi, RT2hi, RT3lo, lsl#4; \
eor RT2lo, RT2lo, RT3hi, lsr#2; \
eor RT2hi, RT2hi, RT3lo, lsr#2; \
eor RT2lo, RT2lo, RT3hi, lsr#7; \
eor RT2hi, RT2hi, RT3lo, lsr#7; \
\
/* t2 += t1 */ \
adds RT2lo, RT1lo; \
ldr RT1lo, [%sp, #(_c)]; \
adc RT2hi, RT1hi; \
\
/* Maj(_a,_b,_c) => ((_a & _b) ^ (_c & (_a ^ _b))) */ \
ldr RT1hi, [%sp, #(_c) + 4]; \
and RT4lo, RWlo, RT3lo; \
and RT4hi, RWhi, RT3hi; \
eor RWlo, RWlo, RT3lo; \
eor RWhi, RWhi, RT3hi; \
and RWlo, RWlo, RT1lo; \
and RWhi, RWhi, RT1hi; \
eor RWlo, RWlo, RT4lo; \
eor RWhi, RWhi, RT4hi; \
/* Message expansion */
#define W_0_63(_a,_h,i) \
ldr RT3lo, [%sp, #(w(i-2))]; \
adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */ \
ldr RT3hi, [%sp, #(w(i-2)) + 4]; \
adc RT2hi, RWhi; \
/* nw = S1(w[i-2]) */ \
ldr RT1lo, [%sp, #(_h)]; /* Load H */ \
mov RWlo, RT3lo, lsr#19; \
str RT2lo, [%sp, #(_a)]; \
eor RWlo, RWlo, RT3lo, lsl#3; \
ldr RT1hi, [%sp, #(_h) + 4]; \
mov RWhi, RT3hi, lsr#19; \
ldr RT2lo, [%sp, #(w(i-7))]; \
eor RWhi, RWhi, RT3hi, lsl#3; \
str RT2hi, [%sp, #(_a) + 4]; \
eor RWlo, RWlo, RT3lo, lsr#6; \
ldr RT2hi, [%sp, #(w(i-7)) + 4]; \
eor RWhi, RWhi, RT3hi, lsr#6; \
eor RWlo, RWlo, RT3hi, lsl#13; \
eor RWhi, RWhi, RT3lo, lsl#13; \
eor RWlo, RWlo, RT3hi, lsr#29; \
eor RWhi, RWhi, RT3lo, lsr#29; \
ldr RT3lo, [%sp, #(w(i-15))]; \
eor RWlo, RWlo, RT3hi, lsl#26; \
ldr RT3hi, [%sp, #(w(i-15)) + 4]; \
\
adds RT2lo, RWlo; /* nw += w[i-7] */ \
ldr RWlo, [%sp, #(w(i-16))]; \
adc RT2hi, RWhi; \
mov RT4lo, RT3lo, lsr#1; /* S0(w[i-15]) */ \
ldr RWhi, [%sp, #(w(i-16)) + 4]; \
mov RT4hi, RT3hi, lsr#1; \
adds RT2lo, RWlo; /* nw += w[i-16] */ \
eor RT4lo, RT4lo, RT3lo, lsr#8; \
eor RT4hi, RT4hi, RT3hi, lsr#8; \
eor RT4lo, RT4lo, RT3lo, lsr#7; \
eor RT4hi, RT4hi, RT3hi, lsr#7; \
eor RT4lo, RT4lo, RT3hi, lsl#31; \
eor RT4hi, RT4hi, RT3lo, lsl#31; \
eor RT4lo, RT4lo, RT3hi, lsl#24; \
eor RT4hi, RT4hi, RT3lo, lsl#24; \
eor RT4lo, RT4lo, RT3hi, lsl#25; \
adc RT2hi, RWhi; \
\
/* nw += S0(w[i-15]) */ \
adds RT2lo, RT4lo; \
adc RT2hi, RT4hi; \
\
/* w[0] = nw */ \
str RT2lo, [%sp, #(w(i))]; \
adds RT1lo, RWlo; \
str RT2hi, [%sp, #(w(i)) + 4]; \
adc RT1hi, RWhi;
#define W_64_79(_a,_h,i) \
adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */ \
ldr RWlo, [%sp, #(w(i-16))]; \
adc RT2hi, RWhi; \
ldr RWhi, [%sp, #(w(i-16)) + 4]; \
ldr RT1lo, [%sp, #(_h)]; /* Load H */ \
ldr RT1hi, [%sp, #(_h) + 4]; \
str RT2lo, [%sp, #(_a)]; \
str RT2hi, [%sp, #(_a) + 4]; \
adds RT1lo, RWlo; \
adc RT1hi, RWhi;
.align 3
.globl _gcry_sha512_transform_arm
.type _gcry_sha512_transform_arm,%function;
_gcry_sha512_transform_arm:
/* Input:
* %r0: SHA512_CONTEXT
* %r1: data
* %r2: u64 k[] constants
* %r3: nblks
*/
push {%r4-%r11, %ip, %lr};
sub %sp, %sp, #STACK_MAX;
movs RWlo, %r3;
str %r0, [%sp, #(ctx)];
beq .Ldone;
.Loop_blocks:
str RWlo, [%sp, #nblks];
/* Load context to stack */
add RWhi, %sp, #(_a);
ldm %r0!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
ldm %r0, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
stm RWhi, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
/* Load input to w[16] */
/* test if data is unaligned */
tst %r1, #3;
beq 1f;
/* unaligned load */
add RWhi, %sp, #(w(0));
read_be64_unaligned_4(%r1, 0 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_unaligned_4(%r1, 4 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_unaligned_4(%r1, 8 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_unaligned_4(%r1, 12 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
b 2f;
1:
/* aligned load */
add RWhi, %sp, #(w(0));
read_be64_aligned_4(%r1, 0 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_aligned_4(%r1, 4 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_aligned_4(%r1, 8 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
stm RWhi!, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
read_be64_aligned_4(%r1, 12 * 8, RT1lo, RT1hi, RT2lo, RT2hi, RT3lo, RT3hi, RT4lo, RT4hi, RWlo);
2:
add %r1, #(16 * 8);
stm RWhi, {RT1lo,RT1hi,RT2lo,RT2hi,RT3lo,RT3hi,RT4lo,RT4hi}
str %r1, [%sp, #(data)];
/* preload E & A */
ldr RElo, [%sp, #(_e)];
ldr REhi, [%sp, #(_e) + 4];
mov RWlo, #0;
ldr RT2lo, [%sp, #(_a)];
mov RRND, #(80-16);
ldr RT2hi, [%sp, #(_a) + 4];
mov RWhi, #0;
.Loop_rounds:
R(_a, _b, _c, _d, _e, _f, _g, _h, W_0_63, 16);
R(_h, _a, _b, _c, _d, _e, _f, _g, W_0_63, 17);
R(_g, _h, _a, _b, _c, _d, _e, _f, W_0_63, 18);
R(_f, _g, _h, _a, _b, _c, _d, _e, W_0_63, 19);
R(_e, _f, _g, _h, _a, _b, _c, _d, W_0_63, 20);
R(_d, _e, _f, _g, _h, _a, _b, _c, W_0_63, 21);
R(_c, _d, _e, _f, _g, _h, _a, _b, W_0_63, 22);
R(_b, _c, _d, _e, _f, _g, _h, _a, W_0_63, 23);
R(_a, _b, _c, _d, _e, _f, _g, _h, W_0_63, 24);
R(_h, _a, _b, _c, _d, _e, _f, _g, W_0_63, 25);
R(_g, _h, _a, _b, _c, _d, _e, _f, W_0_63, 26);
R(_f, _g, _h, _a, _b, _c, _d, _e, W_0_63, 27);
R(_e, _f, _g, _h, _a, _b, _c, _d, W_0_63, 28);
R(_d, _e, _f, _g, _h, _a, _b, _c, W_0_63, 29);
R(_c, _d, _e, _f, _g, _h, _a, _b, W_0_63, 30);
R(_b, _c, _d, _e, _f, _g, _h, _a, W_0_63, 31);
subs RRND, #16;
bne .Loop_rounds;
R(_a, _b, _c, _d, _e, _f, _g, _h, W_64_79, 16);
R(_h, _a, _b, _c, _d, _e, _f, _g, W_64_79, 17);
R(_g, _h, _a, _b, _c, _d, _e, _f, W_64_79, 18);
R(_f, _g, _h, _a, _b, _c, _d, _e, W_64_79, 19);
R(_e, _f, _g, _h, _a, _b, _c, _d, W_64_79, 20);
R(_d, _e, _f, _g, _h, _a, _b, _c, W_64_79, 21);
R(_c, _d, _e, _f, _g, _h, _a, _b, W_64_79, 22);
R(_b, _c, _d, _e, _f, _g, _h, _a, W_64_79, 23);
R(_a, _b, _c, _d, _e, _f, _g, _h, W_64_79, 24);
R(_h, _a, _b, _c, _d, _e, _f, _g, W_64_79, 25);
R(_g, _h, _a, _b, _c, _d, _e, _f, W_64_79, 26);
R(_f, _g, _h, _a, _b, _c, _d, _e, W_64_79, 27);
R(_e, _f, _g, _h, _a, _b, _c, _d, W_64_79, 28);
R(_d, _e, _f, _g, _h, _a, _b, _c, W_64_79, 29);
R(_c, _d, _e, _f, _g, _h, _a, _b, W_64_79, 30);
R(_b, _c, _d, _e, _f, _g, _h, _a, W_64_79, 31);
ldr %r0, [%sp, #(ctx)];
adds RT2lo, RWlo; /* _h = t2 + Maj(_a,_b,_c) */
ldr %r1, [%sp, #(data)];
adc RT2hi, RWhi;
ldm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi}
adds RT1lo, RT2lo;
ldr RT2lo, [%sp, #(_b + 0)];
adc RT1hi, RT2hi;
ldr RT2hi, [%sp, #(_b + 4)];
adds RWlo, RT2lo;
ldr RT2lo, [%sp, #(_c + 0)];
adc RWhi, RT2hi;
ldr RT2hi, [%sp, #(_c + 4)];
adds RT3lo, RT2lo;
ldr RT2lo, [%sp, #(_d + 0)];
adc RT3hi, RT2hi;
ldr RT2hi, [%sp, #(_d + 4)];
adds RT4lo, RT2lo;
ldr RT2lo, [%sp, #(_e + 0)];
adc RT4hi, RT2hi;
stm %r0!, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi}
ldr RT2hi, [%sp, #(_e + 4)];
ldm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi}
adds RT1lo, RT2lo;
ldr RT2lo, [%sp, #(_f + 0)];
adc RT1hi, RT2hi;
ldr RT2hi, [%sp, #(_f + 4)];
adds RWlo, RT2lo;
ldr RT2lo, [%sp, #(_g + 0)];
adc RWhi, RT2hi;
ldr RT2hi, [%sp, #(_g + 4)];
adds RT3lo, RT2lo;
ldr RT2lo, [%sp, #(_h + 0)];
adc RT3hi, RT2hi;
ldr RT2hi, [%sp, #(_h + 4)];
adds RT4lo, RT2lo;
adc RT4hi, RT2hi;
stm %r0, {RT1lo,RT1hi,RWlo,RWhi,RT3lo,RT3hi,RT4lo,RT4hi}
sub %r0, %r0, #(4 * 8);
ldr RWlo, [%sp, #nblks];
sub RK, #(80 * 8);
subs RWlo, #1;
bne .Loop_blocks;
.Ldone:
mov %r0, #STACK_MAX;
__out:
add %sp, %sp, #STACK_MAX;
pop {%r4-%r11, %ip, %pc};
.size _gcry_sha512_transform_arm,.-_gcry_sha512_transform_arm;
#endif
#endif
diff --git a/cipher/sha512-armv7-neon.S b/cipher/sha512-armv7-neon.S
index 6596f2cd..2c804ca9 100644
--- a/cipher/sha512-armv7-neon.S
+++ b/cipher/sha512-armv7-neon.S
@@ -1,450 +1,450 @@
/* sha512-armv7-neon.S - ARM/NEON assembly implementation of SHA-512 transform
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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)
.text
.syntax unified
.fpu neon
.arm
/* structure of SHA512_CONTEXT */
#define hd_a 0
#define hd_b ((hd_a) + 8)
#define hd_c ((hd_b) + 8)
#define hd_d ((hd_c) + 8)
#define hd_e ((hd_d) + 8)
#define hd_f ((hd_e) + 8)
#define hd_g ((hd_f) + 8)
/* register macros */
#define RK %r2
#define RA d0
#define RB d1
#define RC d2
#define RD d3
#define RE d4
#define RF d5
#define RG d6
#define RH d7
#define RT0 d8
#define RT1 d9
#define RT2 d10
#define RT3 d11
#define RT4 d12
#define RT5 d13
#define RT6 d14
#define RT7 d15
#define RT01q q4
#define RT23q q5
#define RT45q q6
#define RT67q q7
#define RW0 d16
#define RW1 d17
#define RW2 d18
#define RW3 d19
#define RW4 d20
#define RW5 d21
#define RW6 d22
#define RW7 d23
#define RW8 d24
#define RW9 d25
#define RW10 d26
#define RW11 d27
#define RW12 d28
#define RW13 d29
#define RW14 d30
#define RW15 d31
#define RW01q q8
#define RW23q q9
#define RW45q q10
#define RW67q q11
#define RW89q q12
#define RW1011q q13
#define RW1213q q14
#define RW1415q q15
/***********************************************************************
* ARM assembly implementation of sha512 transform
***********************************************************************/
#define rounds2_0_63(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, rw01q, rw2, rw23q, rw1415q, rw9, rw10, interleave_op, arg1) \
/* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
vshr.u64 RT2, re, #14; \
vshl.u64 RT3, re, #64 - 14; \
interleave_op(arg1); \
vshr.u64 RT4, re, #18; \
vshl.u64 RT5, re, #64 - 18; \
vld1.64 {RT0}, [RK]!; \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, re, #41; \
vshl.u64 RT5, re, #64 - 41; \
vadd.u64 RT0, RT0, rw0; \
veor.64 RT23q, RT23q, RT45q; \
vmov.64 RT7, re; \
veor.64 RT1, RT2, RT3; \
vbsl.64 RT7, rf, rg; \
\
vadd.u64 RT1, RT1, rh; \
vshr.u64 RT2, ra, #28; \
vshl.u64 RT3, ra, #64 - 28; \
vadd.u64 RT1, RT1, RT0; \
vshr.u64 RT4, ra, #34; \
vshl.u64 RT5, ra, #64 - 34; \
vadd.u64 RT1, RT1, RT7; \
\
/* h = Sum0 (a) + Maj (a, b, c); */ \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, ra, #39; \
vshl.u64 RT5, ra, #64 - 39; \
veor.64 RT0, ra, rb; \
veor.64 RT23q, RT23q, RT45q; \
vbsl.64 RT0, rc, rb; \
vadd.u64 rd, rd, RT1; /* d+=t1; */ \
veor.64 rh, RT2, RT3; \
\
/* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
vshr.u64 RT2, rd, #14; \
vshl.u64 RT3, rd, #64 - 14; \
vadd.u64 rh, rh, RT0; \
vshr.u64 RT4, rd, #18; \
vshl.u64 RT5, rd, #64 - 18; \
vadd.u64 rh, rh, RT1; /* h+=t1; */ \
vld1.64 {RT0}, [RK]!; \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, rd, #41; \
vshl.u64 RT5, rd, #64 - 41; \
vadd.u64 RT0, RT0, rw1; \
veor.64 RT23q, RT23q, RT45q; \
vmov.64 RT7, rd; \
veor.64 RT1, RT2, RT3; \
vbsl.64 RT7, re, rf; \
\
vadd.u64 RT1, RT1, rg; \
vshr.u64 RT2, rh, #28; \
vshl.u64 RT3, rh, #64 - 28; \
vadd.u64 RT1, RT1, RT0; \
vshr.u64 RT4, rh, #34; \
vshl.u64 RT5, rh, #64 - 34; \
vadd.u64 RT1, RT1, RT7; \
\
/* g = Sum0 (h) + Maj (h, a, b); */ \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, rh, #39; \
vshl.u64 RT5, rh, #64 - 39; \
veor.64 RT0, rh, ra; \
veor.64 RT23q, RT23q, RT45q; \
vbsl.64 RT0, rb, ra; \
vadd.u64 rc, rc, RT1; /* c+=t1; */ \
veor.64 rg, RT2, RT3; \
\
/* w[0] += S1 (w[14]) + w[9] + S0 (w[1]); */ \
/* w[1] += S1 (w[15]) + w[10] + S0 (w[2]); */ \
\
/**** S0(w[1:2]) */ \
\
/* w[0:1] += w[9:10] */ \
/* RT23q = rw1:rw2 */ \
vext.u64 RT23q, rw01q, rw23q, #1; \
vadd.u64 rw0, rw9; \
vadd.u64 rg, rg, RT0; \
vadd.u64 rw1, rw10;\
vadd.u64 rg, rg, RT1; /* g+=t1; */ \
\
vshr.u64 RT45q, RT23q, #1; \
vshl.u64 RT67q, RT23q, #64 - 1; \
vshr.u64 RT01q, RT23q, #8; \
veor.u64 RT45q, RT45q, RT67q; \
vshl.u64 RT67q, RT23q, #64 - 8; \
veor.u64 RT45q, RT45q, RT01q; \
vshr.u64 RT01q, RT23q, #7; \
veor.u64 RT45q, RT45q, RT67q; \
\
/**** S1(w[14:15]) */ \
vshr.u64 RT23q, rw1415q, #6; \
veor.u64 RT01q, RT01q, RT45q; \
vshr.u64 RT45q, rw1415q, #19; \
vshl.u64 RT67q, rw1415q, #64 - 19; \
veor.u64 RT23q, RT23q, RT45q; \
vshr.u64 RT45q, rw1415q, #61; \
veor.u64 RT23q, RT23q, RT67q; \
vshl.u64 RT67q, rw1415q, #64 - 61; \
veor.u64 RT23q, RT23q, RT45q; \
vadd.u64 rw01q, RT01q; /* w[0:1] += S(w[1:2]) */ \
veor.u64 RT01q, RT23q, RT67q;
#define vadd_RT01q(rw01q) \
/* w[0:1] += S(w[14:15]) */ \
vadd.u64 rw01q, RT01q;
#define dummy(_) /*_*/
#define rounds2_64_79(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, interleave_op1, arg1, interleave_op2, arg2) \
/* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
vshr.u64 RT2, re, #14; \
vshl.u64 RT3, re, #64 - 14; \
interleave_op1(arg1); \
vshr.u64 RT4, re, #18; \
vshl.u64 RT5, re, #64 - 18; \
interleave_op2(arg2); \
vld1.64 {RT0}, [RK]!; \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, re, #41; \
vshl.u64 RT5, re, #64 - 41; \
vadd.u64 RT0, RT0, rw0; \
veor.64 RT23q, RT23q, RT45q; \
vmov.64 RT7, re; \
veor.64 RT1, RT2, RT3; \
vbsl.64 RT7, rf, rg; \
\
vadd.u64 RT1, RT1, rh; \
vshr.u64 RT2, ra, #28; \
vshl.u64 RT3, ra, #64 - 28; \
vadd.u64 RT1, RT1, RT0; \
vshr.u64 RT4, ra, #34; \
vshl.u64 RT5, ra, #64 - 34; \
vadd.u64 RT1, RT1, RT7; \
\
/* h = Sum0 (a) + Maj (a, b, c); */ \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, ra, #39; \
vshl.u64 RT5, ra, #64 - 39; \
veor.64 RT0, ra, rb; \
veor.64 RT23q, RT23q, RT45q; \
vbsl.64 RT0, rc, rb; \
vadd.u64 rd, rd, RT1; /* d+=t1; */ \
veor.64 rh, RT2, RT3; \
\
/* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
vshr.u64 RT2, rd, #14; \
vshl.u64 RT3, rd, #64 - 14; \
vadd.u64 rh, rh, RT0; \
vshr.u64 RT4, rd, #18; \
vshl.u64 RT5, rd, #64 - 18; \
vadd.u64 rh, rh, RT1; /* h+=t1; */ \
vld1.64 {RT0}, [RK]!; \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, rd, #41; \
vshl.u64 RT5, rd, #64 - 41; \
vadd.u64 RT0, RT0, rw1; \
veor.64 RT23q, RT23q, RT45q; \
vmov.64 RT7, rd; \
veor.64 RT1, RT2, RT3; \
vbsl.64 RT7, re, rf; \
\
vadd.u64 RT1, RT1, rg; \
vshr.u64 RT2, rh, #28; \
vshl.u64 RT3, rh, #64 - 28; \
vadd.u64 RT1, RT1, RT0; \
vshr.u64 RT4, rh, #34; \
vshl.u64 RT5, rh, #64 - 34; \
vadd.u64 RT1, RT1, RT7; \
\
/* g = Sum0 (h) + Maj (h, a, b); */ \
veor.64 RT23q, RT23q, RT45q; \
vshr.u64 RT4, rh, #39; \
vshl.u64 RT5, rh, #64 - 39; \
veor.64 RT0, rh, ra; \
veor.64 RT23q, RT23q, RT45q; \
vbsl.64 RT0, rb, ra; \
vadd.u64 rc, rc, RT1; /* c+=t1; */ \
veor.64 rg, RT2, RT3;
#define vadd_rg_RT0(rg) \
vadd.u64 rg, rg, RT0;
#define vadd_rg_RT1(rg) \
vadd.u64 rg, rg, RT1; /* g+=t1; */
.align 3
.globl _gcry_sha512_transform_armv7_neon
.type _gcry_sha512_transform_armv7_neon,%function;
_gcry_sha512_transform_armv7_neon:
/* Input:
* %r0: SHA512_CONTEXT
* %r1: data
* %r2: u64 k[] constants
* %r3: nblks
*/
push {%lr};
mov %lr, #0;
/* Load context to d0-d7 */
vld1.64 {RA-RD}, [%r0]!;
vld1.64 {RE-RH}, [%r0];
sub %r0, #(4*8);
/* Load input to w[16], d16-d31 */
/* NOTE: Assumes that on ARMv7 unaligned accesses are always allowed. */
vld1.64 {RW0-RW3}, [%r1]!;
vld1.64 {RW4-RW7}, [%r1]!;
vld1.64 {RW8-RW11}, [%r1]!;
vld1.64 {RW12-RW15}, [%r1]!;
#ifdef __ARMEL__
/* byteswap */
vrev64.8 RW01q, RW01q;
vrev64.8 RW23q, RW23q;
vrev64.8 RW45q, RW45q;
vrev64.8 RW67q, RW67q;
vrev64.8 RW89q, RW89q;
vrev64.8 RW1011q, RW1011q;
vrev64.8 RW1213q, RW1213q;
vrev64.8 RW1415q, RW1415q;
#endif
/* EABI says that d8-d15 must be preserved by callee. */
vpush {RT0-RT7};
.Loop:
rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2, RW23q, RW1415q, RW9, RW10, dummy, _);
b .Lenter_rounds;
.Loop_rounds:
rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2, RW23q, RW1415q, RW9, RW10, vadd_RT01q, RW1415q);
.Lenter_rounds:
rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3, RW23q, RW4, RW45q, RW01q, RW11, RW12, vadd_RT01q, RW01q);
rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5, RW45q, RW6, RW67q, RW23q, RW13, RW14, vadd_RT01q, RW23q);
rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7, RW67q, RW8, RW89q, RW45q, RW15, RW0, vadd_RT01q, RW45q);
rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9, RW89q, RW10, RW1011q, RW67q, RW1, RW2, vadd_RT01q, RW67q);
rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11, RW1011q, RW12, RW1213q, RW89q, RW3, RW4, vadd_RT01q, RW89q);
add %lr, #16;
rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, RW1213q, RW14, RW1415q, RW1011q, RW5, RW6, vadd_RT01q, RW1011q);
cmp %lr, #64;
rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, RW1415q, RW0, RW01q, RW1213q, RW7, RW8, vadd_RT01q, RW1213q);
bne .Loop_rounds;
subs %r3, #1;
rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, vadd_RT01q, RW1415q, dummy, _);
rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3, vadd_rg_RT0, RG, vadd_rg_RT1, RG);
beq .Lhandle_tail;
vld1.64 {RW0-RW3}, [%r1]!;
rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5, vadd_rg_RT0, RE, vadd_rg_RT1, RE);
rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7, vadd_rg_RT0, RC, vadd_rg_RT1, RC);
#ifdef __ARMEL__
vrev64.8 RW01q, RW01q;
vrev64.8 RW23q, RW23q;
#endif
vld1.64 {RW4-RW7}, [%r1]!;
rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9, vadd_rg_RT0, RA, vadd_rg_RT1, RA);
rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11, vadd_rg_RT0, RG, vadd_rg_RT1, RG);
#ifdef __ARMEL__
vrev64.8 RW45q, RW45q;
vrev64.8 RW67q, RW67q;
#endif
vld1.64 {RW8-RW11}, [%r1]!;
rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, vadd_rg_RT0, RE, vadd_rg_RT1, RE);
rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, vadd_rg_RT0, RC, vadd_rg_RT1, RC);
#ifdef __ARMEL__
vrev64.8 RW89q, RW89q;
vrev64.8 RW1011q, RW1011q;
#endif
vld1.64 {RW12-RW15}, [%r1]!;
vadd_rg_RT0(RA);
vadd_rg_RT1(RA);
/* Load context */
vld1.64 {RT0-RT3}, [%r0]!;
vld1.64 {RT4-RT7}, [%r0];
sub %r0, #(4*8);
#ifdef __ARMEL__
vrev64.8 RW1213q, RW1213q;
vrev64.8 RW1415q, RW1415q;
#endif
vadd.u64 RA, RT0;
vadd.u64 RB, RT1;
vadd.u64 RC, RT2;
vadd.u64 RD, RT3;
vadd.u64 RE, RT4;
vadd.u64 RF, RT5;
vadd.u64 RG, RT6;
vadd.u64 RH, RT7;
/* Store the first half of context */
vst1.64 {RA-RD}, [%r0]!;
sub RK, $(8*80);
vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
mov %lr, #0;
sub %r0, #(4*8);
b .Loop;
.ltorg
.Lhandle_tail:
rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5, vadd_rg_RT0, RE, vadd_rg_RT1, RE);
rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7, vadd_rg_RT0, RC, vadd_rg_RT1, RC);
rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9, vadd_rg_RT0, RA, vadd_rg_RT1, RA);
rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11, vadd_rg_RT0, RG, vadd_rg_RT1, RG);
rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, vadd_rg_RT0, RE, vadd_rg_RT1, RE);
rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, vadd_rg_RT0, RC, vadd_rg_RT1, RC);
/* Load context to d16-d23 */
vld1.64 {RW0-RW3}, [%r0]!;
vadd_rg_RT0(RA);
vld1.64 {RW4-RW7}, [%r0];
vadd_rg_RT1(RA);
sub %r0, #(4*8);
vadd.u64 RA, RW0;
vadd.u64 RB, RW1;
vadd.u64 RC, RW2;
vadd.u64 RD, RW3;
vadd.u64 RE, RW4;
vadd.u64 RF, RW5;
vadd.u64 RG, RW6;
vadd.u64 RH, RW7;
/* Store the first half of context */
vst1.64 {RA-RD}, [%r0]!;
/* Clear used registers */
/* d16-d31 */
veor.u64 RW01q, RW01q;
veor.u64 RW23q, RW23q;
veor.u64 RW45q, RW45q;
veor.u64 RW67q, 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;
/* 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;
eor %r0, %r0;
pop {%pc};
.size _gcry_sha512_transform_armv7_neon,.-_gcry_sha512_transform_armv7_neon;
#endif
diff --git a/cipher/sha512.c b/cipher/sha512.c
index 1a808f88..5f1a9ba6 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -1,1172 +1,1172 @@
/* sha512.c - SHA384 and SHA512 hash functions
* Copyright (C) 2003, 2008, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Test vectors from FIPS-180-2:
*
* "abc"
* 384:
* CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163
* 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7
* 512:
* DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A
* 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F
*
* "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
* 384:
* 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2
* 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039
* 512:
* 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018
* 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909
*
* "a" x 1000000
* 384:
* 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852
* 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985
* 512:
* E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB
* DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B
*/
#include <config.h>
#include <string.h>
#include "g10lib.h"
#include "bithelp.h"
#include "bufhelp.h"
#include "cipher.h"
#include "hash-common.h"
/* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */
#undef USE_ARM_NEON_ASM
#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_ARM_NEON_ASM 1
# endif
#endif /*ENABLE_NEON_SUPPORT*/
/* USE_ARM_ASM indicates whether to enable ARM assembly code. */
#undef USE_ARM_ASM
#if defined(__ARMEL__) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS)
# define USE_ARM_ASM 1
#endif
/* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
#undef USE_SSSE3
#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# define USE_SSSE3 1
#endif
/* 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_INTEL_SYNTAX_PLATFORM_AS) && \
(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/rorx code. */
#undef USE_AVX2
#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \
defined(HAVE_GCC_INLINE_ASM_BMI2) && \
defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
(defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
# define USE_AVX2 1
#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;
} SHA512_CONTEXT;
static const u64 k[] =
{
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)
};
/* 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_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 + 4 * sizeof(void *))
# else
# define ASM_FUNC_ABI
# define ASM_EXTRA_STACK 0
# endif
#endif
#ifdef USE_ARM_NEON_ASM
unsigned int _gcry_sha512_transform_armv7_neon (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_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_armv7_neon (&hd->state, data, k, nblks);
}
#else
static unsigned int
do_transform_generic (void *context, const unsigned char *data, size_t nblks);
#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 = 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 ((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
(void)features;
}
static void
sha512_init (void *context, unsigned int flags)
{
SHA512_CONTEXT *ctx = context;
SHA512_STATE *hd = &ctx->state;
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);
sha512_init_common (ctx, flags);
}
static void
sha384_init (void *context, unsigned int flags)
{
SHA512_CONTEXT *ctx = context;
SHA512_STATE *hd = &ctx->state;
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);
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->h0 = U64_C(0x22312194fc2bf72c);
hd->h1 = U64_C(0x9f555fa3c84c64c2);
hd->h2 = U64_C(0x2393b86b6f53b151);
hd->h3 = U64_C(0x963877195940eabd);
hd->h4 = U64_C(0x96283ee2a88effe3);
hd->h5 = U64_C(0xbe5e1e2553863992);
hd->h6 = U64_C(0x2b0199fc2c85b8aa);
hd->h7 = 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->h0 = U64_C(0x8c3d37c819544da2);
hd->h1 = U64_C(0x73e1996689dcd4d6);
hd->h2 = U64_C(0x1dfab7ae32ff9c82);
hd->h3 = U64_C(0x679dd514582f9fcf);
hd->h4 = U64_C(0x0f6d2b697bd44da8);
hd->h5 = U64_C(0x77e36f7304c48942);
hd->h6 = U64_C(0x3f9d85a86a1d36c8);
hd->h7 = 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;
do
{
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;
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->h0 += a;
hd->h1 += b;
hd->h2 += c;
hd->h3 += d;
hd->h4 += e;
hd->h5 += f;
hd->h6 += g;
hd->h7 += h;
data += 128;
}
while (--nblks);
return (8 + 16) * sizeof(u64) + sizeof(u32) + 3 * sizeof(void*);
}
#endif /*!USE_ARM_ASM*/
/* The routine final 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: 64 bytes representing the digest. When used for sha384,
* we take the leftmost 48 of those bytes.
*/
static void
sha512_final (void *context)
{
SHA512_CONTEXT *hd = context;
unsigned int stack_burn_depth;
u64 t, th, msb, lsb;
byte *p;
t = hd->bctx.nblocks;
/* if (sizeof t == sizeof hd->bctx.nblocks) */
th = hd->bctx.nblocks_high;
/* else */
/* th = hd->bctx.nblocks >> 64; In case we ever use u128 */
/* multiply by 128 to make a byte count */
lsb = t << 7;
msb = (th << 7) | (t >> 57);
/* 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 >> 61;
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);
hd->bctx.count = 112;
}
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);
stack_burn_depth = (*hd->bctx.bwrite) (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)
X (0);
X (1);
X (2);
X (3);
X (4);
X (5);
/* Note that these last two chunks are included even for SHA384.
We just ignore them. */
X (6);
X (7);
#undef X
}
static byte *
sha512_read (void *context)
{
SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context;
return hd->bctx.buf;
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 64 bytes. */
void
_gcry_sha512_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA512_CONTEXT hd;
sha512_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha512_final (&hd);
memcpy (outbuf, hd.bctx.buf, 64);
}
/* Variant of the above shortcut function using multiple buffers. */
void
_gcry_sha512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SHA512_CONTEXT hd;
sha512_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);
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 48 bytes. */
static void
_gcry_sha384_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA512_CONTEXT hd;
sha384_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha512_final (&hd);
memcpy (outbuf, hd.bctx.buf, 48);
}
/* Variant of the above shortcut function using multiple buffers. */
static void
_gcry_sha384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SHA512_CONTEXT hd;
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, 48);
}
/* Shortcut functions which puts the hash value of the supplied buffer
* into outbuf which must have a size of 32 bytes. */
static void
_gcry_sha512_256_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA512_CONTEXT hd;
sha512_256_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha512_final (&hd);
memcpy (outbuf, hd.bctx.buf, 32);
}
/* Variant of the above shortcut function using multiple buffers. */
static void
_gcry_sha512_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
SHA512_CONTEXT hd;
sha512_256_init (&hd, 0);
for (;iovcnt > 0; iov++, iovcnt--)
_gcry_md_block_write (&hd,
(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
* into outbuf which must have a size of 28 bytes. */
static void
_gcry_sha512_224_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA512_CONTEXT hd;
sha512_224_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sha512_final (&hd);
memcpy (outbuf, hd.bctx.buf, 28);
}
/* Variant of the above shortcut function using multiple buffers. */
static void
_gcry_sha512_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov,
int iovcnt)
{
SHA512_CONTEXT hd;
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);
}
/*
Self-test section.
*/
static gpg_err_code_t
selftests_sha384 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
what = "short string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA384, 0,
"abc", 3,
"\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
"\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
"\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA384, 0,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
"\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47"
"\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12"
"\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39",
48);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA384, 1,
NULL, 0,
"\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C"
"\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B"
"\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85",
48);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", GCRY_MD_SHA384, what, errtxt);
return GPG_ERR_SELFTEST_FAILED;
}
static gpg_err_code_t
selftests_sha512 (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, 0,
"abc", 3,
"\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31"
"\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A"
"\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD"
"\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64);
if (errtxt)
goto failed;
if (extended)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA512, 0,
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
"\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F"
"\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18"
"\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A"
"\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09",
64);
if (errtxt)
goto failed;
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA512, 1,
NULL, 0,
"\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63"
"\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB"
"\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B"
"\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B",
64);
if (errtxt)
goto failed;
}
return 0; /* Succeeded. */
failed:
if (report)
report ("digest", GCRY_MD_SHA512, what, errtxt);
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
run_selftests (int algo, int extended, selftest_report_func_t report)
{
gpg_err_code_t ec;
switch (algo)
{
case GCRY_MD_SHA384:
ec = selftests_sha384 (extended, report);
break;
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;
}
return ec;
}
static 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[] =
{
{ "2.16.840.1.101.3.4.2.3" },
/* PKCS#1 sha512WithRSAEncryption */
{ "1.2.840.113549.1.1.13" },
{ NULL }
};
gcry_md_spec_t _gcry_digest_spec_sha512 =
{
GCRY_MD_SHA512, {0, 1},
"SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
sha512_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
_gcry_sha512_hash_buffer, _gcry_sha512_hash_buffers,
sizeof (SHA512_CONTEXT),
run_selftests
};
static 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[] =
{
{ "2.16.840.1.101.3.4.2.2" },
/* PKCS#1 sha384WithRSAEncryption */
{ "1.2.840.113549.1.1.12" },
/* SHA384WithECDSA: RFC 7427 (A.3.3.) */
{ "1.2.840.10045.4.3.3" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sha384 =
{
GCRY_MD_SHA384, {0, 1},
"SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
sha384_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
_gcry_sha384_hash_buffer, _gcry_sha384_hash_buffers,
sizeof (SHA512_CONTEXT),
run_selftests
};
static byte sha512_256_asn[] = { 0x30 };
static gcry_md_oid_spec_t oid_spec_sha512_256[] =
{
{ "2.16.840.1.101.3.4.2.6" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sha512_256 =
{
GCRY_MD_SHA512_256, {0, 1},
"SHA512_256", sha512_256_asn, DIM (sha512_256_asn), oid_spec_sha512_256, 32,
sha512_256_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
_gcry_sha512_256_hash_buffer, _gcry_sha512_256_hash_buffers,
sizeof (SHA512_CONTEXT),
run_selftests
};
static byte sha512_224_asn[] = { 0x30 };
static gcry_md_oid_spec_t oid_spec_sha512_224[] =
{
{ "2.16.840.1.101.3.4.2.5" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sha512_224 =
{
GCRY_MD_SHA512_224, {0, 1},
"SHA512_224", sha512_224_asn, DIM (sha512_224_asn), oid_spec_sha512_224, 28,
sha512_224_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
_gcry_sha512_224_hash_buffer, _gcry_sha512_224_hash_buffers,
sizeof (SHA512_CONTEXT),
run_selftests
};
diff --git a/cipher/sm3.c b/cipher/sm3.c
index b6f0ab28..7ed21838 100644
--- a/cipher/sm3.c
+++ b/cipher/sm3.c
@@ -1,473 +1,473 @@
/* 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/>.
+ * License along with this program; if not, see <https://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"
typedef struct {
gcry_md_block_ctx_t bctx;
u32 h0,h1,h2,h3,h4,h5,h6,h7;
} SM3_CONTEXT;
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->h0 = 0x7380166f;
hd->h1 = 0x4914b2b9;
hd->h2 = 0x172442d7;
hd->h3 = 0xda8a0600;
hd->h4 = 0xa96f30bc;
hd->h5 = 0x163138aa;
hd->h6 = 0xe38dee4d;
hd->h7 = 0xb0fb0e4e;
hd->bctx.nblocks = 0;
hd->bctx.nblocks_high = 0;
hd->bctx.count = 0;
hd->bctx.blocksize = 64;
hd->bctx.bwrite = transform;
(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->h0;
b = hd->h1;
c = hd->h2;
d = hd->h3;
e = hd->h4;
f = hd->h5;
g = hd->h6;
h = hd->h7;
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->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 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);
hd->bctx.count = 56;
/* 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);
hd->bctx.count = 64 + 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
_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
* into outbuf which must have a size of 32 bytes. */
void
_gcry_sm3_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SM3_CONTEXT hd;
sm3_init (&hd, 0);
_gcry_md_block_write (&hd, buffer, length);
sm3_final (&hd);
memcpy (outbuf, hd.bctx.buf, 32);
}
/* Variant of the above shortcut function using multiple buffers. */
void
_gcry_sm3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
{
SM3_CONTEXT hd;
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);
}
/*
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 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 gcry_md_oid_spec_t oid_spec_sm3[] =
{
/* China Electronics Standardization Instutute,
OID White paper (2015), Table 6 */
{ "1.2.156.10197.401" },
{ NULL },
};
gcry_md_spec_t _gcry_digest_spec_sm3 =
{
GCRY_MD_SM3, {0, 0},
"SM3", asn_sm3, DIM (asn_sm3), oid_spec_sm3, 32,
sm3_init, _gcry_md_block_write, sm3_final, sm3_read, NULL,
_gcry_sm3_hash_buffer, _gcry_sm3_hash_buffers,
sizeof (SM3_CONTEXT),
run_selftests
};
diff --git a/cipher/stribog.c b/cipher/stribog.c
index 26787247..5e7ca1e3 100644
--- a/cipher/stribog.c
+++ b/cipher/stribog.c
@@ -1,1360 +1,1360 @@
/* stribog.c - GOST R 34.11-2012 (Stribog) hash function
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#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"
typedef struct
{
gcry_md_block_ctx_t bctx;
union
{
u64 h[8];
unsigned char result[64];
};
u64 N[8];
u64 Sigma[8];
} STRIBOG_CONTEXT;
/* Pre-computed results of multiplication of bytes on A and reordered with
Pi[]. */
static const u64 stribog_table[8][256] =
{
/* 0 */
{ U64_C(0xd01f715b5c7ef8e6), U64_C(0x16fa240980778325),
U64_C(0xa8a42e857ee049c8), U64_C(0x6ac1068fa186465b),
U64_C(0x6e417bd7a2e9320b), U64_C(0x665c8167a437daab),
U64_C(0x7666681aa89617f6), U64_C(0x4b959163700bdcf5),
U64_C(0xf14be6b78df36248), U64_C(0xc585bd689a625cff),
U64_C(0x9557d7fca67d82cb), U64_C(0x89f0b969af6dd366),
U64_C(0xb0833d48749f6c35), U64_C(0xa1998c23b1ecbc7c),
U64_C(0x8d70c431ac02a736), U64_C(0xd6dfbc2fd0a8b69e),
U64_C(0x37aeb3e551fa198b), U64_C(0x0b7d128a40b5cf9c),
U64_C(0x5a8f2008b5780cbc), U64_C(0xedec882284e333e5),
U64_C(0xd25fc177d3c7c2ce), U64_C(0x5e0f5d50b61778ec),
U64_C(0x1d873683c0c24cb9), U64_C(0xad040bcbb45d208c),
U64_C(0x2f89a0285b853c76), U64_C(0x5732fff6791b8d58),
U64_C(0x3e9311439ef6ec3f), U64_C(0xc9183a809fd3c00f),
U64_C(0x83adf3f5260a01ee), U64_C(0xa6791941f4e8ef10),
U64_C(0x103ae97d0ca1cd5d), U64_C(0x2ce948121dee1b4a),
U64_C(0x39738421dbf2bf53), U64_C(0x093da2a6cf0cf5b4),
U64_C(0xcd9847d89cbcb45f), U64_C(0xf9561c078b2d8ae8),
U64_C(0x9c6a755a6971777f), U64_C(0xbc1ebaa0712ef0c5),
U64_C(0x72e61542abf963a6), U64_C(0x78bb5fde229eb12e),
U64_C(0x14ba94250fceb90d), U64_C(0x844d6697630e5282),
U64_C(0x98ea08026a1e032f), U64_C(0xf06bbea144217f5c),
U64_C(0xdb6263d11ccb377a), U64_C(0x641c314b2b8ee083),
U64_C(0x320e96ab9b4770cf), U64_C(0x1ee7deb986a96b85),
U64_C(0xe96cf57a878c47b5), U64_C(0xfdd6615f8842feb8),
U64_C(0xc83862965601dd1b), U64_C(0x2ea9f83e92572162),
U64_C(0xf876441142ff97fc), U64_C(0xeb2c455608357d9d),
U64_C(0x5612a7e0b0c9904c), U64_C(0x6c01cbfb2d500823),
U64_C(0x4548a6a7fa037a2d), U64_C(0xabc4c6bf388b6ef4),
U64_C(0xbade77d4fdf8bebd), U64_C(0x799b07c8eb4cac3a),
U64_C(0x0c9d87e805b19cf0), U64_C(0xcb588aac106afa27),
U64_C(0xea0c1d40c1e76089), U64_C(0x2869354a1e816f1a),
U64_C(0xff96d17307fbc490), U64_C(0x9f0a9d602f1a5043),
U64_C(0x96373fc6e016a5f7), U64_C(0x5292dab8b3a6e41c),
U64_C(0x9b8ae0382c752413), U64_C(0x4f15ec3b7364a8a5),
U64_C(0x3fb349555724f12b), U64_C(0xc7c50d4415db66d7),
U64_C(0x92b7429ee379d1a7), U64_C(0xd37f99611a15dfda),
U64_C(0x231427c05e34a086), U64_C(0xa439a96d7b51d538),
U64_C(0xb403401077f01865), U64_C(0xdda2aea5901d7902),
U64_C(0x0a5d4a9c8967d288), U64_C(0xc265280adf660f93),
U64_C(0x8bb0094520d4e94e), U64_C(0x2a29856691385532),
U64_C(0x42a833c5bf072941), U64_C(0x73c64d54622b7eb2),
U64_C(0x07e095624504536c), U64_C(0x8a905153e906f45a),
U64_C(0x6f6123c16b3b2f1f), U64_C(0xc6e55552dc097bc3),
U64_C(0x4468feb133d16739), U64_C(0xe211e7f0c7398829),
U64_C(0xa2f96419f7879b40), U64_C(0x19074bdbc3ad38e9),
U64_C(0xf4ebc3f9474e0b0c), U64_C(0x43886bd376d53455),
U64_C(0xd8028beb5aa01046), U64_C(0x51f23282f5cdc320),
U64_C(0xe7b1c2be0d84e16d), U64_C(0x081dfab006dee8a0),
U64_C(0x3b33340d544b857b), U64_C(0x7f5bcabc679ae242),
U64_C(0x0edd37c48a08a6d8), U64_C(0x81ed43d9a9b33bc6),
U64_C(0xb1a3655ebd4d7121), U64_C(0x69a1eeb5e7ed6167),
U64_C(0xf6ab73d5c8f73124), U64_C(0x1a67a3e185c61fd5),
U64_C(0x2dc91004d43c065e), U64_C(0x0240b02c8fb93a28),
U64_C(0x90f7f2b26cc0eb8f), U64_C(0x3cd3a16f114fd617),
U64_C(0xaae49ea9f15973e0), U64_C(0x06c0cd748cd64e78),
U64_C(0xda423bc7d5192a6e), U64_C(0xc345701c16b41287),
U64_C(0x6d2193ede4821537), U64_C(0xfcf639494190e3ac),
U64_C(0x7c3b228621f1c57e), U64_C(0xfb16ac2b0494b0c0),
U64_C(0xbf7e529a3745d7f9), U64_C(0x6881b6a32e3f7c73),
U64_C(0xca78d2bad9b8e733), U64_C(0xbbfe2fc2342aa3a9),
U64_C(0x0dbddffecc6381e4), U64_C(0x70a6a56e2440598e),
U64_C(0xe4d12a844befc651), U64_C(0x8c509c2765d0ba22),
U64_C(0xee8c6018c28814d9), U64_C(0x17da7c1f49a59e31),
U64_C(0x609c4c1328e194d3), U64_C(0xb3e3d57232f44b09),
U64_C(0x91d7aaa4a512f69b), U64_C(0x0ffd6fd243dabbcc),
U64_C(0x50d26a943c1fde34), U64_C(0x6be15e9968545b4f),
U64_C(0x94778fea6faf9fdf), U64_C(0x2b09dd7058ea4826),
U64_C(0x677cd9716de5c7bf), U64_C(0x49d5214fffb2e6dd),
U64_C(0x0360e83a466b273c), U64_C(0x1fc786af4f7b7691),
U64_C(0xa0b9d435783ea168), U64_C(0xd49f0c035f118cb6),
U64_C(0x01205816c9d21d14), U64_C(0xac2453dd7d8f3d98),
U64_C(0x545217cc3f70aa64), U64_C(0x26b4028e9489c9c2),
U64_C(0xdec2469fd6765e3e), U64_C(0x04807d58036f7450),
U64_C(0xe5f17292823ddb45), U64_C(0xf30b569b024a5860),
U64_C(0x62dcfc3fa758aefb), U64_C(0xe84cad6c4e5e5aa1),
U64_C(0xccb81fce556ea94b), U64_C(0x53b282ae7a74f908),
U64_C(0x1b47fbf74c1402c1), U64_C(0x368eebf39828049f),
U64_C(0x7afbeff2ad278b06), U64_C(0xbe5e0a8cfe97caed),
U64_C(0xcfd8f7f413058e77), U64_C(0xf78b2bc301252c30),
U64_C(0x4d555c17fcdd928d), U64_C(0x5f2f05467fc565f8),
U64_C(0x24f4b2a21b30f3ea), U64_C(0x860dd6bbecb768aa),
U64_C(0x4c750401350f8f99), U64_C(0x0000000000000000),
U64_C(0xecccd0344d312ef1), U64_C(0xb5231806be220571),
U64_C(0xc105c030990d28af), U64_C(0x653c695de25cfd97),
U64_C(0x159acc33c61ca419), U64_C(0xb89ec7f872418495),
U64_C(0xa9847693b73254dc), U64_C(0x58cf90243ac13694),
U64_C(0x59efc832f3132b80), U64_C(0x5c4fed7c39ae42c4),
U64_C(0x828dabe3efd81cfa), U64_C(0xd13f294d95ace5f2),
U64_C(0x7d1b7a90e823d86a), U64_C(0xb643f03cf849224d),
U64_C(0x3df3f979d89dcb03), U64_C(0x7426d836272f2dde),
U64_C(0xdfe21e891fa4432a), U64_C(0x3a136c1b9d99986f),
U64_C(0xfa36f43dcd46add4), U64_C(0xc025982650df35bb),
U64_C(0x856d3e81aadc4f96), U64_C(0xc4a5e57e53b041eb),
U64_C(0x4708168b75ba4005), U64_C(0xaf44bbe73be41aa4),
U64_C(0x971767d029c4b8e3), U64_C(0xb9be9feebb939981),
U64_C(0x215497ecd18d9aae), U64_C(0x316e7e91dd2c57f3),
U64_C(0xcef8afe2dad79363), U64_C(0x3853dc371220a247),
U64_C(0x35ee03c9de4323a3), U64_C(0xe6919aa8c456fc79),
U64_C(0xe05157dc4880b201), U64_C(0x7bdbb7e464f59612),
U64_C(0x127a59518318f775), U64_C(0x332ecebd52956ddb),
U64_C(0x8f30741d23bb9d1e), U64_C(0xd922d3fd93720d52),
U64_C(0x7746300c61440ae2), U64_C(0x25d4eab4d2e2eefe),
U64_C(0x75068020eefd30ca), U64_C(0x135a01474acaea61),
U64_C(0x304e268714fe4ae7), U64_C(0xa519f17bb283c82c),
U64_C(0xdc82f6b359cf6416), U64_C(0x5baf781e7caa11a8),
U64_C(0xb2c38d64fb26561d), U64_C(0x34ce5bdf17913eb7),
U64_C(0x5d6fb56af07c5fd0), U64_C(0x182713cd0a7f25fd),
U64_C(0x9e2ac576e6c84d57), U64_C(0x9aaab82ee5a73907),
U64_C(0xa3d93c0f3e558654), U64_C(0x7e7b92aaae48ff56),
U64_C(0x872d8ead256575be), U64_C(0x41c8dbfff96c0e7d),
U64_C(0x99ca5014a3cc1e3b), U64_C(0x40e883e930be1369),
U64_C(0x1ca76e95091051ad), U64_C(0x4e35b42dbab6b5b1),
U64_C(0x05a0254ecabd6944), U64_C(0xe1710fca8152af15),
U64_C(0xf22b0e8dcb984574), U64_C(0xb763a82a319b3f59),
U64_C(0x63fca4296e8ab3ef), U64_C(0x9d4a2d4ca0a36a6b),
U64_C(0xe331bfe60eeb953d), U64_C(0xd5bf541596c391a2),
U64_C(0xf5cb9bef8e9c1618), U64_C(0x46284e9dbc685d11),
U64_C(0x2074cffa185f87ba), U64_C(0xbd3ee2b6b8fcedd1),
U64_C(0xae64e3f1f23607b0), U64_C(0xfeb68965ce29d984),
U64_C(0x55724fdaf6a2b770), U64_C(0x29496d5cd753720e),
U64_C(0xa75941573d3af204), U64_C(0x8e102c0bea69800a),
U64_C(0x111ab16bc573d049), U64_C(0xd7ffe439197aab8a),
U64_C(0xefac380e0b5a09cd), U64_C(0x48f579593660fbc9),
U64_C(0x22347fd697e6bd92), U64_C(0x61bc1405e13389c7),
U64_C(0x4ab5c975b9d9c1e1), U64_C(0x80cd1bcf606126d2),
U64_C(0x7186fd78ed92449a), U64_C(0x93971a882aabccb3),
U64_C(0x88d0e17f66bfce72), U64_C(0x27945a985d5bd4d6) },
/* 1 */
{ U64_C(0xde553f8c05a811c8), U64_C(0x1906b59631b4f565),
U64_C(0x436e70d6b1964ff7), U64_C(0x36d343cb8b1e9d85),
U64_C(0x843dfacc858aab5a), U64_C(0xfdfc95c299bfc7f9),
U64_C(0x0f634bdea1d51fa2), U64_C(0x6d458b3b76efb3cd),
U64_C(0x85c3f77cf8593f80), U64_C(0x3c91315fbe737cb2),
U64_C(0x2148b03366ace398), U64_C(0x18f8b8264c6761bf),
U64_C(0xc830c1c495c9fb0f), U64_C(0x981a76102086a0aa),
U64_C(0xaa16012142f35760), U64_C(0x35cc54060c763cf6),
U64_C(0x42907d66cc45db2d), U64_C(0x8203d44b965af4bc),
U64_C(0x3d6f3cefc3a0e868), U64_C(0xbc73ff69d292bda7),
U64_C(0x8722ed0102e20a29), U64_C(0x8f8185e8cd34deb7),
U64_C(0x9b0561dda7ee01d9), U64_C(0x5335a0193227fad6),
U64_C(0xc9cecc74e81a6fd5), U64_C(0x54f5832e5c2431ea),
U64_C(0x99e47ba05d553470), U64_C(0xf7bee756acd226ce),
U64_C(0x384e05a5571816fd), U64_C(0xd1367452a47d0e6a),
U64_C(0xf29fde1c386ad85b), U64_C(0x320c77316275f7ca),
U64_C(0xd0c879e2d9ae9ab0), U64_C(0xdb7406c69110ef5d),
U64_C(0x45505e51a2461011), U64_C(0xfc029872e46c5323),
U64_C(0xfa3cb6f5f7bc0cc5), U64_C(0x031f17cd8768a173),
U64_C(0xbd8df2d9af41297d), U64_C(0x9d3b4f5ab43e5e3f),
U64_C(0x4071671b36feee84), U64_C(0x716207e7d3e3b83d),
U64_C(0x48d20ff2f9283a1a), U64_C(0x27769eb4757cbc7e),
U64_C(0x5c56ebc793f2e574), U64_C(0xa48b474f9ef5dc18),
U64_C(0x52cbada94ff46e0c), U64_C(0x60c7da982d8199c6),
U64_C(0x0e9d466edc068b78), U64_C(0x4eec2175eaf865fc),
U64_C(0x550b8e9e21f7a530), U64_C(0x6b7ba5bc653fec2b),
U64_C(0x5eb7f1ba6949d0dd), U64_C(0x57ea94e3db4c9099),
U64_C(0xf640eae6d101b214), U64_C(0xdd4a284182c0b0bb),
U64_C(0xff1d8fbf6304f250), U64_C(0xb8accb933bf9d7e8),
U64_C(0xe8867c478eb68c4d), U64_C(0x3f8e2692391bddc1),
U64_C(0xcb2fd60912a15a7c), U64_C(0xaec935dbab983d2f),
U64_C(0xf55ffd2b56691367), U64_C(0x80e2ce366ce1c115),
U64_C(0x179bf3f8edb27e1d), U64_C(0x01fe0db07dd394da),
U64_C(0xda8a0b76ecc37b87), U64_C(0x44ae53e1df9584cb),
U64_C(0xb310b4b77347a205), U64_C(0xdfab323c787b8512),
U64_C(0x3b511268d070b78e), U64_C(0x65e6e3d2b9396753),
U64_C(0x6864b271e2574d58), U64_C(0x259784c98fc789d7),
U64_C(0x02e11a7dfabb35a9), U64_C(0x8841a6dfa337158b),
U64_C(0x7ade78c39b5dcdd0), U64_C(0xb7cf804d9a2cc84a),
U64_C(0x20b6bd831b7f7742), U64_C(0x75bd331d3a88d272),
U64_C(0x418f6aab4b2d7a5e), U64_C(0xd9951cbb6babdaf4),
U64_C(0xb6318dfde7ff5c90), U64_C(0x1f389b112264aa83),
U64_C(0x492c024284fbaec0), U64_C(0xe33a0363c608f9a0),
U64_C(0x2688930408af28a4), U64_C(0xc7538a1a341ce4ad),
U64_C(0x5da8e677ee2171ae), U64_C(0x8c9e92254a5c7fc4),
U64_C(0x63d8cd55aae938b5), U64_C(0x29ebd8daa97a3706),
U64_C(0x959827b37be88aa1), U64_C(0x1484e4356adadf6e),
U64_C(0xa7945082199d7d6b), U64_C(0xbf6ce8a455fa1cd4),
U64_C(0x9cc542eac9edcae5), U64_C(0x79c16f0e1c356ca3),
U64_C(0x89bfab6fdee48151), U64_C(0xd4174d1830c5f0ff),
U64_C(0x9258048415eb419d), U64_C(0x6139d72850520d1c),
U64_C(0x6a85a80c18ec78f1), U64_C(0xcd11f88e0171059a),
U64_C(0xcceff53e7ca29140), U64_C(0xd229639f2315af19),
U64_C(0x90b91ef9ef507434), U64_C(0x5977d28d074a1be1),
U64_C(0x311360fce51d56b9), U64_C(0xc093a92d5a1f2f91),
U64_C(0x1a19a25bb6dc5416), U64_C(0xeb996b8a09de2d3e),
U64_C(0xfee3820f1ed7668a), U64_C(0xd7085ad5b7ad518c),
U64_C(0x7fff41890fe53345), U64_C(0xec5948bd67dde602),
U64_C(0x2fd5f65dbaaa68e0), U64_C(0xa5754affe32648c2),
U64_C(0xf8ddac880d07396c), U64_C(0x6fa491468c548664),
U64_C(0x0c7c5c1326bdbed1), U64_C(0x4a33158f03930fb3),
U64_C(0x699abfc19f84d982), U64_C(0xe4fa2054a80b329c),
U64_C(0x6707f9af438252fa), U64_C(0x08a368e9cfd6d49e),
U64_C(0x47b1442c58fd25b8), U64_C(0xbbb3dc5ebc91769b),
U64_C(0x1665fe489061eac7), U64_C(0x33f27a811fa66310),
U64_C(0x93a609346838d547), U64_C(0x30ed6d4c98cec263),
U64_C(0x1dd9816cd8df9f2a), U64_C(0x94662a03063b1e7b),
U64_C(0x83fdd9fbeb896066), U64_C(0x7b207573e68e590a),
U64_C(0x5f49fc0a149a4407), U64_C(0x343259b671a5a82c),
U64_C(0xfbc2bb458a6f981f), U64_C(0xc272b350a0a41a38),
U64_C(0x3aaf1fd8ada32354), U64_C(0x6cbb868b0b3c2717),
U64_C(0xa2b569c88d2583fe), U64_C(0xf180c9d1bf027928),
U64_C(0xaf37386bd64ba9f5), U64_C(0x12bacab2790a8088),
U64_C(0x4c0d3b0810435055), U64_C(0xb2eeb9070e9436df),
U64_C(0xc5b29067cea7d104), U64_C(0xdcb425f1ff132461),
U64_C(0x4f122cc5972bf126), U64_C(0xac282fa651230886),
U64_C(0xe7e537992f6393ef), U64_C(0xe61b3a2952b00735),
U64_C(0x709c0a57ae302ce7), U64_C(0xe02514ae416058d3),
U64_C(0xc44c9dd7b37445de), U64_C(0x5a68c5408022ba92),
U64_C(0x1c278cdca50c0bf0), U64_C(0x6e5a9cf6f18712be),
U64_C(0x86dce0b17f319ef3), U64_C(0x2d34ec2040115d49),
U64_C(0x4bcd183f7e409b69), U64_C(0x2815d56ad4a9a3dc),
U64_C(0x24698979f2141d0d), U64_C(0x0000000000000000),
U64_C(0x1ec696a15fb73e59), U64_C(0xd86b110b16784e2e),
U64_C(0x8e7f8858b0e74a6d), U64_C(0x063e2e8713d05fe6),
U64_C(0xe2c40ed3bbdb6d7a), U64_C(0xb1f1aeca89fc97ac),
U64_C(0xe1db191e3cb3cc09), U64_C(0x6418ee62c4eaf389),
U64_C(0xc6ad87aa49cf7077), U64_C(0xd6f65765ca7ec556),
U64_C(0x9afb6c6dda3d9503), U64_C(0x7ce05644888d9236),
U64_C(0x8d609f95378feb1e), U64_C(0x23a9aa4e9c17d631),
U64_C(0x6226c0e5d73aac6f), U64_C(0x56149953a69f0443),
U64_C(0xeeb852c09d66d3ab), U64_C(0x2b0ac2a753c102af),
U64_C(0x07c023376e03cb3c), U64_C(0x2ccae1903dc2c993),
U64_C(0xd3d76e2f5ec63bc3), U64_C(0x9e2458973356ff4c),
U64_C(0xa66a5d32644ee9b1), U64_C(0x0a427294356de137),
U64_C(0x783f62be61e6f879), U64_C(0x1344c70204d91452),
U64_C(0x5b96c8f0fdf12e48), U64_C(0xa90916ecc59bf613),
U64_C(0xbe92e5142829880e), U64_C(0x727d102a548b194e),
U64_C(0x1be7afebcb0fc0cc), U64_C(0x3e702b2244c8491b),
U64_C(0xd5e940a84d166425), U64_C(0x66f9f41f3e51c620),
U64_C(0xabe80c913f20c3ba), U64_C(0xf07ec461c2d1edf2),
U64_C(0xf361d3ac45b94c81), U64_C(0x0521394a94b8fe95),
U64_C(0xadd622162cf09c5c), U64_C(0xe97871f7f3651897),
U64_C(0xf4a1f09b2bba87bd), U64_C(0x095d6559b2054044),
U64_C(0x0bbc7f2448be75ed), U64_C(0x2af4cf172e129675),
U64_C(0x157ae98517094bb4), U64_C(0x9fda55274e856b96),
U64_C(0x914713499283e0ee), U64_C(0xb952c623462a4332),
U64_C(0x74433ead475b46a8), U64_C(0x8b5eb112245fb4f8),
U64_C(0xa34b6478f0f61724), U64_C(0x11a5dd7ffe6221fb),
U64_C(0xc16da49d27ccbb4b), U64_C(0x76a224d0bde07301),
U64_C(0x8aa0bca2598c2022), U64_C(0x4df336b86d90c48f),
U64_C(0xea67663a740db9e4), U64_C(0xef465f70e0b54771),
U64_C(0x39b008152acb8227), U64_C(0x7d1e5bf4f55e06ec),
U64_C(0x105bd0cf83b1b521), U64_C(0x775c2960c033e7db),
U64_C(0x7e014c397236a79f), U64_C(0x811cc386113255cf),
U64_C(0xeda7450d1a0e72d8), U64_C(0x5889df3d7a998f3b),
U64_C(0x2e2bfbedc779fc3a), U64_C(0xce0eef438619a4e9),
U64_C(0x372d4e7bf6cd095f), U64_C(0x04df34fae96b6a4f),
U64_C(0xf923a13870d4adb6), U64_C(0xa1aa7e050a4d228d),
U64_C(0xa8f71b5cb84862c9), U64_C(0xb52e9a306097fde3),
U64_C(0x0d8251a35b6e2a0b), U64_C(0x2257a7fee1c442eb),
U64_C(0x73831d9a29588d94), U64_C(0x51d4ba64c89ccf7f),
U64_C(0x502ab7d4b54f5ba5), U64_C(0x97793dce8153bf08),
U64_C(0xe5042de4d5d8a646), U64_C(0x9687307efc802bd2),
U64_C(0xa05473b5779eb657), U64_C(0xb4d097801d446939),
U64_C(0xcff0e2f3fbca3033), U64_C(0xc38cbee0dd778ee2),
U64_C(0x464f499c252eb162), U64_C(0xcad1dbb96f72cea6),
U64_C(0xba4dd1eec142e241), U64_C(0xb00fa37af42f0376) },
/* 2 */
{ U64_C(0xcce4cd3aa968b245), U64_C(0x089d5484e80b7faf),
U64_C(0x638246c1b3548304), U64_C(0xd2fe0ec8c2355492),
U64_C(0xa7fbdf7ff2374eee), U64_C(0x4df1600c92337a16),
U64_C(0x84e503ea523b12fb), U64_C(0x0790bbfd53ab0c4a),
U64_C(0x198a780f38f6ea9d), U64_C(0x2ab30c8f55ec48cb),
U64_C(0xe0f7fed6b2c49db5), U64_C(0xb6ecf3f422cadbdc),
U64_C(0x409c9a541358df11), U64_C(0xd3ce8a56dfde3fe3),
U64_C(0xc3e9224312c8c1a0), U64_C(0x0d6dfa58816ba507),
U64_C(0xddf3e1b179952777), U64_C(0x04c02a42748bb1d9),
U64_C(0x94c2abff9f2decb8), U64_C(0x4f91752da8f8acf4),
U64_C(0x78682befb169bf7b), U64_C(0xe1c77a48af2ff6c4),
U64_C(0x0c5d7ec69c80ce76), U64_C(0x4cc1e4928fd81167),
U64_C(0xfeed3d24d9997b62), U64_C(0x518bb6dfc3a54a23),
U64_C(0x6dbf2d26151f9b90), U64_C(0xb5bc624b05ea664f),
U64_C(0xe86aaa525acfe21a), U64_C(0x4801ced0fb53a0be),
U64_C(0xc91463e6c00868ed), U64_C(0x1027a815cd16fe43),
U64_C(0xf67069a0319204cd), U64_C(0xb04ccc976c8abce7),
U64_C(0xc0b9b3fc35e87c33), U64_C(0xf380c77c58f2de65),
U64_C(0x50bb3241de4e2152), U64_C(0xdf93f490435ef195),
U64_C(0xf1e0d25d62390887), U64_C(0xaf668bfb1a3c3141),
U64_C(0xbc11b251f00a7291), U64_C(0x73a5eed47e427d47),
U64_C(0x25bee3f6ee4c3b2e), U64_C(0x43cc0beb34786282),
U64_C(0xc824e778dde3039c), U64_C(0xf97d86d98a327728),
U64_C(0xf2b043e24519b514), U64_C(0xe297ebf7880f4b57),
U64_C(0x3a94a49a98fab688), U64_C(0x868516cb68f0c419),
U64_C(0xeffa11af0964ee50), U64_C(0xa4ab4ec0d517f37d),
U64_C(0xa9c6b498547c567a), U64_C(0x8e18424f80fbbbb6),
U64_C(0x0bcdc53bcf2bc23c), U64_C(0x137739aaea3643d0),
U64_C(0x2c1333ec1bac2ff0), U64_C(0x8d48d3f0a7db0625),
U64_C(0x1e1ac3f26b5de6d7), U64_C(0xf520f81f16b2b95e),
U64_C(0x9f0f6ec450062e84), U64_C(0x0130849e1deb6b71),
U64_C(0xd45e31ab8c7533a9), U64_C(0x652279a2fd14e43f),
U64_C(0x3209f01e70f1c927), U64_C(0xbe71a770cac1a473),
U64_C(0x0e3d6be7a64b1894), U64_C(0x7ec8148cff29d840),
U64_C(0xcb7476c7fac3be0f), U64_C(0x72956a4a63a91636),
U64_C(0x37f95ec21991138f), U64_C(0x9e3fea5a4ded45f5),
U64_C(0x7b38ba50964902e8), U64_C(0x222e580bbde73764),
U64_C(0x61e253e0899f55e6), U64_C(0xfc8d2805e352ad80),
U64_C(0x35994be3235ac56d), U64_C(0x09add01af5e014de),
U64_C(0x5e8659a6780539c6), U64_C(0xb17c48097161d796),
U64_C(0x026015213acbd6e2), U64_C(0xd1ae9f77e515e901),
U64_C(0xb7dc776a3f21b0ad), U64_C(0xaba6a1b96eb78098),
U64_C(0x9bcf4486248d9f5d), U64_C(0x582666c536455efd),
U64_C(0xfdbdac9bfeb9c6f1), U64_C(0xc47999be4163cdea),
U64_C(0x765540081722a7ef), U64_C(0x3e548ed8ec710751),
U64_C(0x3d041f67cb51bac2), U64_C(0x7958af71ac82d40a),
U64_C(0x36c9da5c047a78fe), U64_C(0xed9a048e33af38b2),
U64_C(0x26ee7249c96c86bd), U64_C(0x900281bdeba65d61),
U64_C(0x11172c8bd0fd9532), U64_C(0xea0abf73600434f8),
U64_C(0x42fc8f75299309f3), U64_C(0x34a9cf7d3eb1ae1c),
U64_C(0x2b838811480723ba), U64_C(0x5ce64c8742ceef24),
U64_C(0x1adae9b01fd6570e), U64_C(0x3c349bf9d6bad1b3),
U64_C(0x82453c891c7b75c0), U64_C(0x97923a40b80d512b),
U64_C(0x4a61dbf1c198765c), U64_C(0xb48ce6d518010d3e),
U64_C(0xcfb45c858e480fd6), U64_C(0xd933cbf30d1e96ae),
U64_C(0xd70ea014ab558e3a), U64_C(0xc189376228031742),
U64_C(0x9262949cd16d8b83), U64_C(0xeb3a3bed7def5f89),
U64_C(0x49314a4ee6b8cbcf), U64_C(0xdcc3652f647e4c06),
U64_C(0xda635a4c2a3e2b3d), U64_C(0x470c21a940f3d35b),
U64_C(0x315961a157d174b4), U64_C(0x6672e81dda3459ac),
U64_C(0x5b76f77a1165e36e), U64_C(0x445cb01667d36ec8),
U64_C(0xc5491d205c88a69b), U64_C(0x456c34887a3805b9),
U64_C(0xffddb9bac4721013), U64_C(0x99af51a71e4649bf),
U64_C(0xa15be01cbc7729d5), U64_C(0x52db2760e485f7b0),
U64_C(0x8c78576eba306d54), U64_C(0xae560f6507d75a30),
U64_C(0x95f22f6182c687c9), U64_C(0x71c5fbf54489aba5),
U64_C(0xca44f259e728d57e), U64_C(0x88b87d2ccebbdc8d),
U64_C(0xbab18d32be4a15aa), U64_C(0x8be8ec93e99b611e),
U64_C(0x17b713e89ebdf209), U64_C(0xb31c5d284baa0174),
U64_C(0xeeca9531148f8521), U64_C(0xb8d198138481c348),
U64_C(0x8988f9b2d350b7fc), U64_C(0xb9e11c8d996aa839),
U64_C(0x5a4673e40c8e881f), U64_C(0x1687977683569978),
U64_C(0xbf4123eed72acf02), U64_C(0x4ea1f1b3b513c785),
U64_C(0xe767452be16f91ff), U64_C(0x7505d1b730021a7c),
U64_C(0xa59bca5ec8fc980c), U64_C(0xad069eda20f7e7a3),
U64_C(0x38f4b1bba231606a), U64_C(0x60d2d77e94743e97),
U64_C(0x9affc0183966f42c), U64_C(0x248e6768f3a7505f),
U64_C(0xcdd449a4b483d934), U64_C(0x87b59255751baf68),
U64_C(0x1bea6d2e023d3c7f), U64_C(0x6b1f12455b5ffcab),
U64_C(0x743555292de9710d), U64_C(0xd8034f6d10f5fddf),
U64_C(0xc6198c9f7ba81b08), U64_C(0xbb8109aca3a17edb),
U64_C(0xfa2d1766ad12cabb), U64_C(0xc729080166437079),
U64_C(0x9c5fff7b77269317), U64_C(0x0000000000000000),
U64_C(0x15d706c9a47624eb), U64_C(0x6fdf38072fd44d72),
U64_C(0x5fb6dd3865ee52b7), U64_C(0xa33bf53d86bcff37),
U64_C(0xe657c1b5fc84fa8e), U64_C(0xaa962527735cebe9),
U64_C(0x39c43525bfda0b1b), U64_C(0x204e4d2a872ce186),
U64_C(0x7a083ece8ba26999), U64_C(0x554b9c9db72efbfa),
U64_C(0xb22cd9b656416a05), U64_C(0x96a2bedea5e63a5a),
U64_C(0x802529a826b0a322), U64_C(0x8115ad363b5bc853),
U64_C(0x8375b81701901eb1), U64_C(0x3069e53f4a3a1fc5),
U64_C(0xbd2136cfede119e0), U64_C(0x18bafc91251d81ec),
U64_C(0x1d4a524d4c7d5b44), U64_C(0x05f0aedc6960daa8),
U64_C(0x29e39d3072ccf558), U64_C(0x70f57f6b5962c0d4),
U64_C(0x989fd53903ad22ce), U64_C(0xf84d024797d91c59),
U64_C(0x547b1803aac5908b), U64_C(0xf0d056c37fd263f6),
U64_C(0xd56eb535919e58d8), U64_C(0x1c7ad6d351963035),
U64_C(0x2e7326cd2167f912), U64_C(0xac361a443d1c8cd2),
U64_C(0x697f076461942a49), U64_C(0x4b515f6fdc731d2d),
U64_C(0x8ad8680df4700a6f), U64_C(0x41ac1eca0eb3b460),
U64_C(0x7d988533d80965d3), U64_C(0xa8f6300649973d0b),
U64_C(0x7765c4960ac9cc9e), U64_C(0x7ca801adc5e20ea2),
U64_C(0xdea3700e5eb59ae4), U64_C(0xa06b6482a19c42a4),
U64_C(0x6a2f96db46b497da), U64_C(0x27def6d7d487edcc),
U64_C(0x463ca5375d18b82a), U64_C(0xa6cb5be1efdc259f),
U64_C(0x53eba3fef96e9cc1), U64_C(0xce84d81b93a364a7),
U64_C(0xf4107c810b59d22f), U64_C(0x333974806d1aa256),
U64_C(0x0f0def79bba073e5), U64_C(0x231edc95a00c5c15),
U64_C(0xe437d494c64f2c6c), U64_C(0x91320523f64d3610),
U64_C(0x67426c83c7df32dd), U64_C(0x6eefbc99323f2603),
U64_C(0x9d6f7be56acdf866), U64_C(0x5916e25b2bae358c),
U64_C(0x7ff89012e2c2b331), U64_C(0x035091bf2720bd93),
U64_C(0x561b0d22900e4669), U64_C(0x28d319ae6f279e29),
U64_C(0x2f43a2533c8c9263), U64_C(0xd09e1be9f8fe8270),
U64_C(0xf740ed3e2c796fbc), U64_C(0xdb53ded237d5404c),
U64_C(0x62b2c25faebfe875), U64_C(0x0afd41a5d2c0a94d),
U64_C(0x6412fd3ce0ff8f4e), U64_C(0xe3a76f6995e42026),
U64_C(0x6c8fa9b808f4f0e1), U64_C(0xc2d9a6dd0f23aad1),
U64_C(0x8f28c6d19d10d0c7), U64_C(0x85d587744fd0798a),
U64_C(0xa20b71a39b579446), U64_C(0x684f83fa7c7f4138),
U64_C(0xe507500adba4471d), U64_C(0x3f640a46f19a6c20),
U64_C(0x1247bd34f7dd28a1), U64_C(0x2d23b77206474481),
U64_C(0x93521002cc86e0f2), U64_C(0x572b89bc8de52d18),
U64_C(0xfb1d93f8b0f9a1ca), U64_C(0xe95a2ecc4724896b),
U64_C(0x3ba420048511ddf9), U64_C(0xd63e248ab6bee54b),
U64_C(0x5dd6c8195f258455), U64_C(0x06a03f634e40673b),
U64_C(0x1f2a476c76b68da6), U64_C(0x217ec9b49ac78af7),
U64_C(0xecaa80102e4453c3), U64_C(0x14e78257b99d4f9a) },
/* 3 */
{ U64_C(0x20329b2cc87bba05), U64_C(0x4f5eb6f86546a531),
U64_C(0xd4f44775f751b6b1), U64_C(0x8266a47b850dfa8b),
U64_C(0xbb986aa15a6ca985), U64_C(0xc979eb08f9ae0f99),
U64_C(0x2da6f447a2375ea1), U64_C(0x1e74275dcd7d8576),
U64_C(0xbc20180a800bc5f8), U64_C(0xb4a2f701b2dc65be),
U64_C(0xe726946f981b6d66), U64_C(0x48e6c453bf21c94c),
U64_C(0x42cad9930f0a4195), U64_C(0xefa47b64aacccd20),
U64_C(0x71180a8960409a42), U64_C(0x8bb3329bf6a44e0c),
U64_C(0xd34c35de2d36dacc), U64_C(0xa92f5b7cbc23dc96),
U64_C(0xb31a85aa68bb09c3), U64_C(0x13e04836a73161d2),
U64_C(0xb24dfc4129c51d02), U64_C(0x8ae44b70b7da5acd),
U64_C(0xe671ed84d96579a7), U64_C(0xa4bb3417d66f3832),
U64_C(0x4572ab38d56d2de8), U64_C(0xb1b47761ea47215c),
U64_C(0xe81c09cf70aba15d), U64_C(0xffbdb872ce7f90ac),
U64_C(0xa8782297fd5dc857), U64_C(0x0d946f6b6a4ce4a4),
U64_C(0xe4df1f4f5b995138), U64_C(0x9ebc71edca8c5762),
U64_C(0x0a2c1dc0b02b88d9), U64_C(0x3b503c115d9d7b91),
U64_C(0xc64376a8111ec3a2), U64_C(0xcec199a323c963e4),
U64_C(0xdc76a87ec58616f7), U64_C(0x09d596e073a9b487),
U64_C(0x14583a9d7d560daf), U64_C(0xf4c6dc593f2a0cb4),
U64_C(0xdd21d19584f80236), U64_C(0x4a4836983ddde1d3),
U64_C(0xe58866a41ae745f9), U64_C(0xf591a5b27e541875),
U64_C(0x891dc05074586693), U64_C(0x5b068c651810a89e),
U64_C(0xa30346bc0c08544f), U64_C(0x3dbf3751c684032d),
U64_C(0x2a1e86ec785032dc), U64_C(0xf73f5779fca830ea),
U64_C(0xb60c05ca30204d21), U64_C(0x0cc316802b32f065),
U64_C(0x8770241bdd96be69), U64_C(0xb861e18199ee95db),
U64_C(0xf805cad91418fcd1), U64_C(0x29e70dccbbd20e82),
U64_C(0xc7140f435060d763), U64_C(0x0f3a9da0e8b0cc3b),
U64_C(0xa2543f574d76408e), U64_C(0xbd7761e1c175d139),
U64_C(0x4b1f4f737ca3f512), U64_C(0x6dc2df1f2fc137ab),
U64_C(0xf1d05c3967b14856), U64_C(0xa742bf3715ed046c),
U64_C(0x654030141d1697ed), U64_C(0x07b872abda676c7d),
U64_C(0x3ce84eba87fa17ec), U64_C(0xc1fb0403cb79afdf),
U64_C(0x3e46bc7105063f73), U64_C(0x278ae987121cd678),
U64_C(0xa1adb4778ef47cd0), U64_C(0x26dd906c5362c2b9),
U64_C(0x05168060589b44e2), U64_C(0xfbfc41f9d79ac08f),
U64_C(0x0e6de44ba9ced8fa), U64_C(0x9feb08068bf243a3),
U64_C(0x7b341749d06b129b), U64_C(0x229c69e74a87929a),
U64_C(0xe09ee6c4427c011b), U64_C(0x5692e30e725c4c3a),
U64_C(0xda99a33e5e9f6e4b), U64_C(0x353dd85af453a36b),
U64_C(0x25241b4c90e0fee7), U64_C(0x5de987258309d022),
U64_C(0xe230140fc0802984), U64_C(0x93281e86a0c0b3c6),
U64_C(0xf229d719a4337408), U64_C(0x6f6c2dd4ad3d1f34),
U64_C(0x8ea5b2fbae3f0aee), U64_C(0x8331dd90c473ee4a),
U64_C(0x346aa1b1b52db7aa), U64_C(0xdf8f235e06042aa9),
U64_C(0xcc6f6b68a1354b7b), U64_C(0x6c95a6f46ebf236a),
U64_C(0x52d31a856bb91c19), U64_C(0x1a35ded6d498d555),
U64_C(0xf37eaef2e54d60c9), U64_C(0x72e181a9a3c2a61c),
U64_C(0x98537aad51952fde), U64_C(0x16f6c856ffaa2530),
U64_C(0xd960281e9d1d5215), U64_C(0x3a0745fa1ce36f50),
U64_C(0x0b7b642bf1559c18), U64_C(0x59a87eae9aec8001),
U64_C(0x5e100c05408bec7c), U64_C(0x0441f98b19e55023),
U64_C(0xd70dcc5534d38aef), U64_C(0x927f676de1bea707),
U64_C(0x9769e70db925e3e5), U64_C(0x7a636ea29115065a),
U64_C(0x468b201816ef11b6), U64_C(0xab81a9b73edff409),
U64_C(0xc0ac7de88a07bb1e), U64_C(0x1f235eb68c0391b7),
U64_C(0x6056b074458dd30f), U64_C(0xbe8eeac102f7ed67),
U64_C(0xcd381283e04b5fba), U64_C(0x5cbefecec277c4e3),
U64_C(0xd21b4c356c48ce0d), U64_C(0x1019c31664b35d8c),
U64_C(0x247362a7d19eea26), U64_C(0xebe582efb3299d03),
U64_C(0x02aef2cb82fc289f), U64_C(0x86275df09ce8aaa8),
U64_C(0x28b07427faac1a43), U64_C(0x38a9b7319e1f47cf),
U64_C(0xc82e92e3b8d01b58), U64_C(0x06ef0b409b1978bc),
U64_C(0x62f842bfc771fb90), U64_C(0x9904034610eb3b1f),
U64_C(0xded85ab5477a3e68), U64_C(0x90d195a663428f98),
U64_C(0x5384636e2ac708d8), U64_C(0xcbd719c37b522706),
U64_C(0xae9729d76644b0eb), U64_C(0x7c8c65e20a0c7ee6),
U64_C(0x80c856b007f1d214), U64_C(0x8c0b40302cc32271),
U64_C(0xdbcedad51fe17a8a), U64_C(0x740e8ae938dbdea0),
U64_C(0xa615c6dc549310ad), U64_C(0x19cc55f6171ae90b),
U64_C(0x49b1bdb8fe5fdd8d), U64_C(0xed0a89af2830e5bf),
U64_C(0x6a7aadb4f5a65bd6), U64_C(0x7e22972988f05679),
U64_C(0xf952b3325566e810), U64_C(0x39fecedadf61530e),
U64_C(0x6101c99f04f3c7ce), U64_C(0x2e5f7f6761b562ff),
U64_C(0xf08725d226cf5c97), U64_C(0x63af3b54860fef51),
U64_C(0x8ff2cb10ef411e2f), U64_C(0x884ab9bb35267252),
U64_C(0x4df04433e7ba8dae), U64_C(0x9afd8866d3690741),
U64_C(0x66b9bb34de94abb3), U64_C(0x9baaf18d92171380),
U64_C(0x543c11c5f0a064a5), U64_C(0x17a1b1bdbed431f1),
U64_C(0xb5f58eeaf3a2717f), U64_C(0xc355f6c849858740),
U64_C(0xec5df044694ef17e), U64_C(0xd83751f5dc6346d4),
U64_C(0xfc4433520dfdacf2), U64_C(0x0000000000000000),
U64_C(0x5a51f58e596ebc5f), U64_C(0x3285aaf12e34cf16),
U64_C(0x8d5c39db6dbd36b0), U64_C(0x12b731dde64f7513),
U64_C(0x94906c2d7aa7dfbb), U64_C(0x302b583aacc8e789),
U64_C(0x9d45facd090e6b3c), U64_C(0x2165e2c78905aec4),
U64_C(0x68d45f7f775a7349), U64_C(0x189b2c1d5664fdca),
U64_C(0xe1c99f2f030215da), U64_C(0x6983269436246788),
U64_C(0x8489af3b1e148237), U64_C(0xe94b702431d5b59c),
U64_C(0x33d2d31a6f4adbd7), U64_C(0xbfd9932a4389f9a6),
U64_C(0xb0e30e8aab39359d), U64_C(0xd1e2c715afcaf253),
U64_C(0x150f43763c28196e), U64_C(0xc4ed846393e2eb3d),
U64_C(0x03f98b20c3823c5e), U64_C(0xfd134ab94c83b833),
U64_C(0x556b682eb1de7064), U64_C(0x36c4537a37d19f35),
U64_C(0x7559f30279a5ca61), U64_C(0x799ae58252973a04),
U64_C(0x9c12832648707ffd), U64_C(0x78cd9c6913e92ec5),
U64_C(0x1d8dac7d0effb928), U64_C(0x439da0784e745554),
U64_C(0x413352b3cc887dcb), U64_C(0xbacf134a1b12bd44),
U64_C(0x114ebafd25cd494d), U64_C(0x2f08068c20cb763e),
U64_C(0x76a07822ba27f63f), U64_C(0xeab2fb04f25789c2),
U64_C(0xe3676de481fe3d45), U64_C(0x1b62a73d95e6c194),
U64_C(0x641749ff5c68832c), U64_C(0xa5ec4dfc97112cf3),
U64_C(0xf6682e92bdd6242b), U64_C(0x3f11c59a44782bb2),
U64_C(0x317c21d1edb6f348), U64_C(0xd65ab5be75ad9e2e),
U64_C(0x6b2dd45fb4d84f17), U64_C(0xfaab381296e4d44e),
U64_C(0xd0b5befeeeb4e692), U64_C(0x0882ef0b32d7a046),
U64_C(0x512a91a5a83b2047), U64_C(0x963e9ee6f85bf724),
U64_C(0x4e09cf132438b1f0), U64_C(0x77f701c9fb59e2fe),
U64_C(0x7ddb1c094b726a27), U64_C(0x5f4775ee01f5f8bd),
U64_C(0x9186ec4d223c9b59), U64_C(0xfeeac1998f01846d),
U64_C(0xac39db1ce4b89874), U64_C(0xb75b7c21715e59e0),
U64_C(0xafc0503c273aa42a), U64_C(0x6e3b543fec430bf5),
U64_C(0x704f7362213e8e83), U64_C(0x58ff0745db9294c0),
U64_C(0x67eec2df9feabf72), U64_C(0xa0facd9ccf8a6811),
U64_C(0xb936986ad890811a), U64_C(0x95c715c63bd9cb7a),
U64_C(0xca8060283a2c33c7), U64_C(0x507de84ee9453486),
U64_C(0x85ded6d05f6a96f6), U64_C(0x1cdad5964f81ade9),
U64_C(0xd5a33e9eb62fa270), U64_C(0x40642b588df6690a),
U64_C(0x7f75eec2c98e42b8), U64_C(0x2cf18dace3494a60),
U64_C(0x23cb100c0bf9865b), U64_C(0xeef3028febb2d9e1),
U64_C(0x4425d2d394133929), U64_C(0xaad6d05c7fa1e0c8),
U64_C(0xad6ea2f7a5c68cb5), U64_C(0xc2028f2308fb9381),
U64_C(0x819f2f5b468fc6d5), U64_C(0xc5bafd88d29cfffc),
U64_C(0x47dc59f357910577), U64_C(0x2b49ff07392e261d),
U64_C(0x57c59ae5332258fb), U64_C(0x73b6f842e2bcb2dd),
U64_C(0xcf96e04862b77725), U64_C(0x4ca73dd8a6c4996f),
U64_C(0x015779eb417e14c1), U64_C(0x37932a9176af8bf4) },
/* 4 */
{ U64_C(0x190a2c9b249df23e), U64_C(0x2f62f8b62263e1e9),
U64_C(0x7a7f754740993655), U64_C(0x330b7ba4d5564d9f),
U64_C(0x4c17a16a46672582), U64_C(0xb22f08eb7d05f5b8),
U64_C(0x535f47f40bc148cc), U64_C(0x3aec5d27d4883037),
U64_C(0x10ed0a1825438f96), U64_C(0x516101f72c233d17),
U64_C(0x13cc6f949fd04eae), U64_C(0x739853c441474bfd),
U64_C(0x653793d90d3f5b1b), U64_C(0x5240647b96b0fc2f),
U64_C(0x0c84890ad27623e0), U64_C(0xd7189b32703aaea3),
U64_C(0x2685de3523bd9c41), U64_C(0x99317c5b11bffefa),
U64_C(0x0d9baa854f079703), U64_C(0x70b93648fbd48ac5),
U64_C(0xa80441fce30bc6be), U64_C(0x7287704bdc36ff1e),
U64_C(0xb65384ed33dc1f13), U64_C(0xd36417343ee34408),
U64_C(0x39cd38ab6e1bf10f), U64_C(0x5ab861770a1f3564),
U64_C(0x0ebacf09f594563b), U64_C(0xd04572b884708530),
U64_C(0x3cae9722bdb3af47), U64_C(0x4a556b6f2f5cbaf2),
U64_C(0xe1704f1f76c4bd74), U64_C(0x5ec4ed7144c6dfcf),
U64_C(0x16afc01d4c7810e6), U64_C(0x283f113cd629ca7a),
U64_C(0xaf59a8761741ed2d), U64_C(0xeed5a3991e215fac),
U64_C(0x3bf37ea849f984d4), U64_C(0xe413e096a56ce33c),
U64_C(0x2c439d3a98f020d1), U64_C(0x637559dc6404c46b),
U64_C(0x9e6c95d1e5f5d569), U64_C(0x24bb9836045fe99a),
U64_C(0x44efa466dac8ecc9), U64_C(0xc6eab2a5c80895d6),
U64_C(0x803b50c035220cc4), U64_C(0x0321658cba93c138),
U64_C(0x8f9ebc465dc7ee1c), U64_C(0xd15a5137190131d3),
U64_C(0x0fa5ec8668e5e2d8), U64_C(0x91c979578d1037b1),
U64_C(0x0642ca05693b9f70), U64_C(0xefca80168350eb4f),
U64_C(0x38d21b24f36a45ec), U64_C(0xbeab81e1af73d658),
U64_C(0x8cbfd9cae7542f24), U64_C(0xfd19cc0d81f11102),
U64_C(0x0ac6430fbb4dbc90), U64_C(0x1d76a09d6a441895),
U64_C(0x2a01573ff1cbbfa1), U64_C(0xb572e161894fde2b),
U64_C(0x8124734fa853b827), U64_C(0x614b1fdf43e6b1b0),
U64_C(0x68ac395c4238cc18), U64_C(0x21d837bfd7f7b7d2),
U64_C(0x20c714304a860331), U64_C(0x5cfaab726324aa14),
U64_C(0x74c5ba4eb50d606e), U64_C(0xf3a3030474654739),
U64_C(0x23e671bcf015c209), U64_C(0x45f087e947b9582a),
U64_C(0xd8bd77b418df4c7b), U64_C(0xe06f6c90ebb50997),
U64_C(0x0bd96080263c0873), U64_C(0x7e03f9410e40dcfe),
U64_C(0xb8e94be4c6484928), U64_C(0xfb5b0608e8ca8e72),
U64_C(0x1a2b49179e0e3306), U64_C(0x4e29e76961855059),
U64_C(0x4f36c4e6fcf4e4ba), U64_C(0x49740ee395cf7bca),
U64_C(0xc2963ea386d17f7d), U64_C(0x90d65ad810618352),
U64_C(0x12d34c1b02a1fa4d), U64_C(0xfa44258775bb3a91),
U64_C(0x18150f14b9ec46dd), U64_C(0x1491861e6b9a653d),
U64_C(0x9a1019d7ab2c3fc2), U64_C(0x3668d42d06fe13d7),
U64_C(0xdcc1fbb25606a6d0), U64_C(0x969490dd795a1c22),
U64_C(0x3549b1a1bc6dd2ef), U64_C(0xc94f5e23a0ed770e),
U64_C(0xb9f6686b5b39fdcb), U64_C(0xc4d4f4a6efeae00d),
U64_C(0xe732851a1fff2204), U64_C(0x94aad6de5eb869f9),
U64_C(0x3f8ff2ae07206e7f), U64_C(0xfe38a9813b62d03a),
U64_C(0xa7a1ad7a8bee2466), U64_C(0x7b6056c8dde882b6),
U64_C(0x302a1e286fc58ca7), U64_C(0x8da0fa457a259bc7),
U64_C(0xb3302b64e074415b), U64_C(0x5402ae7eff8b635f),
U64_C(0x08f8050c9cafc94b), U64_C(0xae468bf98a3059ce),
U64_C(0x88c355cca98dc58f), U64_C(0xb10e6d67c7963480),
U64_C(0xbad70de7e1aa3cf3), U64_C(0xbfb4a26e320262bb),
U64_C(0xcb711820870f02d5), U64_C(0xce12b7a954a75c9d),
U64_C(0x563ce87dd8691684), U64_C(0x9f73b65e7884618a),
U64_C(0x2b1e74b06cba0b42), U64_C(0x47cec1ea605b2df1),
U64_C(0x1c698312f735ac76), U64_C(0x5fdbcefed9b76b2c),
U64_C(0x831a354c8fb1cdfc), U64_C(0x820516c312c0791f),
U64_C(0xb74ca762aeadabf0), U64_C(0xfc06ef821c80a5e1),
U64_C(0x5723cbf24518a267), U64_C(0x9d4df05d5f661451),
U64_C(0x588627742dfd40bf), U64_C(0xda8331b73f3d39a0),
U64_C(0x17b0e392d109a405), U64_C(0xf965400bcf28fba9),
U64_C(0x7c3dbf4229a2a925), U64_C(0x023e460327e275db),
U64_C(0x6cd0b55a0ce126b3), U64_C(0xe62da695828e96e7),
U64_C(0x42ad6e63b3f373b9), U64_C(0xe50cc319381d57df),
U64_C(0xc5cbd729729b54ee), U64_C(0x46d1e265fd2a9912),
U64_C(0x6428b056904eeff8), U64_C(0x8be23040131e04b7),
U64_C(0x6709d5da2add2ec0), U64_C(0x075de98af44a2b93),
U64_C(0x8447dcc67bfbe66f), U64_C(0x6616f655b7ac9a23),
U64_C(0xd607b8bded4b1a40), U64_C(0x0563af89d3a85e48),
U64_C(0x3db1b4ad20c21ba4), U64_C(0x11f22997b8323b75),
U64_C(0x292032b34b587e99), U64_C(0x7f1cdace9331681d),
U64_C(0x8e819fc9c0b65aff), U64_C(0xa1e3677fe2d5bb16),
U64_C(0xcd33d225ee349da5), U64_C(0xd9a2543b85aef898),
U64_C(0x795e10cbfa0af76d), U64_C(0x25a4bbb9992e5d79),
U64_C(0x78413344677b438e), U64_C(0xf0826688cef68601),
U64_C(0xd27b34bba392f0eb), U64_C(0x551d8df162fad7bc),
U64_C(0x1e57c511d0d7d9ad), U64_C(0xdeffbdb171e4d30b),
U64_C(0xf4feea8e802f6caa), U64_C(0xa480c8f6317de55e),
U64_C(0xa0fc44f07fa40ff5), U64_C(0x95b5f551c3c9dd1a),
U64_C(0x22f952336d6476ea), U64_C(0x0000000000000000),
U64_C(0xa6be8ef5169f9085), U64_C(0xcc2cf1aa73452946),
U64_C(0x2e7ddb39bf12550a), U64_C(0xd526dd3157d8db78),
U64_C(0x486b2d6c08becf29), U64_C(0x9b0f3a58365d8b21),
U64_C(0xac78cdfaadd22c15), U64_C(0xbc95c7e28891a383),
U64_C(0x6a927f5f65dab9c3), U64_C(0xc3891d2c1ba0cb9e),
U64_C(0xeaa92f9f50f8b507), U64_C(0xcf0d9426c9d6e87e),
U64_C(0xca6e3baf1a7eb636), U64_C(0xab25247059980786),
U64_C(0x69b31ad3df4978fb), U64_C(0xe2512a93cc577c4c),
U64_C(0xff278a0ea61364d9), U64_C(0x71a615c766a53e26),
U64_C(0x89dc764334fc716c), U64_C(0xf87a638452594f4a),
U64_C(0xf2bc208be914f3da), U64_C(0x8766b94ac1682757),
U64_C(0xbbc82e687cdb8810), U64_C(0x626a7a53f9757088),
U64_C(0xa2c202f358467a2e), U64_C(0x4d0882e5db169161),
U64_C(0x09e7268301de7da8), U64_C(0xe897699c771ac0dc),
U64_C(0xc8507dac3d9cc3ed), U64_C(0xc0a878a0a1330aa6),
U64_C(0x978bb352e42ba8c1), U64_C(0xe9884a13ea6b743f),
U64_C(0x279afdbabecc28a2), U64_C(0x047c8c064ed9eaab),
U64_C(0x507e2278b15289f4), U64_C(0x599904fbb08cf45c),
U64_C(0xbd8ae46d15e01760), U64_C(0x31353da7f2b43844),
U64_C(0x8558ff49e68a528c), U64_C(0x76fbfc4d92ef15b5),
U64_C(0x3456922e211c660c), U64_C(0x86799ac55c1993b4),
U64_C(0x3e90d1219a51da9c), U64_C(0x2d5cbeb505819432),
U64_C(0x982e5fd48cce4a19), U64_C(0xdb9c1238a24c8d43),
U64_C(0xd439febecaa96f9b), U64_C(0x418c0bef0960b281),
U64_C(0x158ea591f6ebd1de), U64_C(0x1f48e69e4da66d4e),
U64_C(0x8afd13cf8e6fb054), U64_C(0xf5e1c9011d5ed849),
U64_C(0xe34e091c5126c8af), U64_C(0xad67ee7530a398f6),
U64_C(0x43b24dec2e82c75a), U64_C(0x75da99c1287cd48d),
U64_C(0x92e81cdb3783f689), U64_C(0xa3dd217cc537cecd),
U64_C(0x60543c50de970553), U64_C(0x93f73f54aaf2426a),
U64_C(0xa91b62737e7a725d), U64_C(0xf19d4507538732e2),
U64_C(0x77e4dfc20f9ea156), U64_C(0x7d229ccdb4d31dc6),
U64_C(0x1b346a98037f87e5), U64_C(0xedf4c615a4b29e94),
U64_C(0x4093286094110662), U64_C(0xb0114ee85ae78063),
U64_C(0x6ff1d0d6b672e78b), U64_C(0x6dcf96d591909250),
U64_C(0xdfe09e3eec9567e8), U64_C(0x3214582b4827f97c),
U64_C(0xb46dc2ee143e6ac8), U64_C(0xf6c0ac8da7cd1971),
U64_C(0xebb60c10cd8901e4), U64_C(0xf7df8f023abcad92),
U64_C(0x9c52d3d2c217a0b2), U64_C(0x6b8d5cd0f8ab0d20),
U64_C(0x3777f7a29b8fa734), U64_C(0x011f238f9d71b4e3),
U64_C(0xc1b75b2f3c42be45), U64_C(0x5de588fdfe551ef7),
U64_C(0x6eeef3592b035368), U64_C(0xaa3a07ffc4e9b365),
U64_C(0xecebe59a39c32a77), U64_C(0x5ba742f8976e8187),
U64_C(0x4b4a48e0b22d0e11), U64_C(0xddded83dcb771233),
U64_C(0xa59feb79ac0c51bd), U64_C(0xc7f5912a55792135) },
/* 5 */
{ U64_C(0x6d6ae04668a9b08a), U64_C(0x3ab3f04b0be8c743),
U64_C(0xe51e166b54b3c908), U64_C(0xbe90a9eb35c2f139),
U64_C(0xb2c7066637f2bec1), U64_C(0xaa6945613392202c),
U64_C(0x9a28c36f3b5201eb), U64_C(0xddce5a93ab536994),
U64_C(0x0e34133ef6382827), U64_C(0x52a02ba1ec55048b),
U64_C(0xa2f88f97c4b2a177), U64_C(0x8640e513ca2251a5),
U64_C(0xcdf1d36258137622), U64_C(0xfe6cb708dedf8ddb),
U64_C(0x8a174a9ec8121e5d), U64_C(0x679896036b81560e),
U64_C(0x59ed033395795fee), U64_C(0x1dd778ab8b74edaf),
U64_C(0xee533ef92d9f926d), U64_C(0x2a8c79baf8a8d8f5),
U64_C(0x6bcf398e69b119f6), U64_C(0xe20491742fafdd95),
U64_C(0x276488e0809c2aec), U64_C(0xea955b82d88f5cce),
U64_C(0x7102c63a99d9e0c4), U64_C(0xf9763017a5c39946),
U64_C(0x429fa2501f151b3d), U64_C(0x4659c72bea05d59e),
U64_C(0x984b7fdccf5a6634), U64_C(0xf742232953fbb161),
U64_C(0x3041860e08c021c7), U64_C(0x747bfd9616cd9386),
U64_C(0x4bb1367192312787), U64_C(0x1b72a1638a6c44d3),
U64_C(0x4a0e68a6e8359a66), U64_C(0x169a5039f258b6ca),
U64_C(0xb98a2ef44edee5a4), U64_C(0xd9083fe85e43a737),
U64_C(0x967f6ce239624e13), U64_C(0x8874f62d3c1a7982),
U64_C(0x3c1629830af06e3f), U64_C(0x9165ebfd427e5a8e),
U64_C(0xb5dd81794ceeaa5c), U64_C(0x0de8f15a7834f219),
U64_C(0x70bd98ede3dd5d25), U64_C(0xaccc9ca9328a8950),
U64_C(0x56664eda1945ca28), U64_C(0x221db34c0f8859ae),
U64_C(0x26dbd637fa98970d), U64_C(0x1acdffb4f068f932),
U64_C(0x4585254f64090fa0), U64_C(0x72de245e17d53afa),
U64_C(0x1546b25d7c546cf4), U64_C(0x207e0ffffb803e71),
U64_C(0xfaaad2732bcf4378), U64_C(0xb462dfae36ea17bd),
U64_C(0xcf926fd1ac1b11fd), U64_C(0xe0672dc7dba7ba4a),
U64_C(0xd3fa49ad5d6b41b3), U64_C(0x8ba81449b216a3bc),
U64_C(0x14f9ec8a0650d115), U64_C(0x40fc1ee3eb1d7ce2),
U64_C(0x23a2ed9b758ce44f), U64_C(0x782c521b14fddc7e),
U64_C(0x1c68267cf170504e), U64_C(0xbcf31558c1ca96e6),
U64_C(0xa781b43b4ba6d235), U64_C(0xf6fd7dfe29ff0c80),
U64_C(0xb0a4bad5c3fad91e), U64_C(0xd199f51ea963266c),
U64_C(0x414340349119c103), U64_C(0x5405f269ed4dadf7),
U64_C(0xabd61bb649969dcd), U64_C(0x6813dbeae7bdc3c8),
U64_C(0x65fb2ab09f8931d1), U64_C(0xf1e7fae152e3181d),
U64_C(0xc1a67cef5a2339da), U64_C(0x7a4feea8e0f5bba1),
U64_C(0x1e0b9acf05783791), U64_C(0x5b8ebf8061713831),
U64_C(0x80e53cdbcb3af8d9), U64_C(0x7e898bd315e57502),
U64_C(0xc6bcfbf0213f2d47), U64_C(0x95a38e86b76e942d),
U64_C(0x092e94218d243cba), U64_C(0x8339debf453622e7),
U64_C(0xb11be402b9fe64ff), U64_C(0x57d9100d634177c9),
U64_C(0xcc4e8db52217cbc3), U64_C(0x3b0cae9c71ec7aa2),
U64_C(0xfb158ca451cbfe99), U64_C(0x2b33276d82ac6514),
U64_C(0x01bf5ed77a04bde1), U64_C(0xc5601994af33f779),
U64_C(0x75c4a3416cc92e67), U64_C(0xf3844652a6eb7fc2),
U64_C(0x3487e375fdd0ef64), U64_C(0x18ae430704609eed),
U64_C(0x4d14efb993298efb), U64_C(0x815a620cb13e4538),
U64_C(0x125c354207487869), U64_C(0x9eeea614ce42cf48),
U64_C(0xce2d3106d61fac1c), U64_C(0xbbe99247bad6827b),
U64_C(0x071a871f7b1c149d), U64_C(0x2e4a1cc10db81656),
U64_C(0x77a71ff298c149b8), U64_C(0x06a5d9c80118a97c),
U64_C(0xad73c27e488e34b1), U64_C(0x443a7b981e0db241),
U64_C(0xe3bbcfa355ab6074), U64_C(0x0af276450328e684),
U64_C(0x73617a896dd1871b), U64_C(0x58525de4ef7de20f),
U64_C(0xb7be3dcab8e6cd83), U64_C(0x19111dd07e64230c),
U64_C(0x842359a03e2a367a), U64_C(0x103f89f1f3401fb6),
U64_C(0xdc710444d157d475), U64_C(0xb835702334da5845),
U64_C(0x4320fc876511a6dc), U64_C(0xd026abc9d3679b8d),
U64_C(0x17250eee885c0b2b), U64_C(0x90dab52a387ae76f),
U64_C(0x31fed8d972c49c26), U64_C(0x89cba8fa461ec463),
U64_C(0x2ff5421677bcabb7), U64_C(0x396f122f85e41d7d),
U64_C(0xa09b332430bac6a8), U64_C(0xc888e8ced7070560),
U64_C(0xaeaf201ac682ee8f), U64_C(0x1180d7268944a257),
U64_C(0xf058a43628e7a5fc), U64_C(0xbd4c4b8fbbce2b07),
U64_C(0xa1246df34abe7b49), U64_C(0x7d5569b79be9af3c),
U64_C(0xa9b5a705bd9efa12), U64_C(0xdb6b835baa4bc0e8),
U64_C(0x05793bac8f147342), U64_C(0x21c1512881848390),
U64_C(0xfdb0556c50d357e5), U64_C(0x613d4fcb6a99ff72),
U64_C(0x03dce2648e0cda3e), U64_C(0xe949b9e6568386f0),
U64_C(0xfc0f0bbb2ad7ea04), U64_C(0x6a70675913b5a417),
U64_C(0x7f36d5046fe1c8e3), U64_C(0x0c57af8d02304ff8),
U64_C(0x32223abdfcc84618), U64_C(0x0891caf6f720815b),
U64_C(0xa63eeaec31a26fd4), U64_C(0x2507345374944d33),
U64_C(0x49d28ac266394058), U64_C(0xf5219f9aa7f3d6be),
U64_C(0x2d96fea583b4cc68), U64_C(0x5a31e1571b7585d0),
U64_C(0x8ed12fe53d02d0fe), U64_C(0xdfade6205f5b0e4b),
U64_C(0x4cabb16ee92d331a), U64_C(0x04c6657bf510cea3),
U64_C(0xd73c2cd6a87b8f10), U64_C(0xe1d87310a1a307ab),
U64_C(0x6cd5be9112ad0d6b), U64_C(0x97c032354366f3f2),
U64_C(0xd4e0ceb22677552e), U64_C(0x0000000000000000),
U64_C(0x29509bde76a402cb), U64_C(0xc27a9e8bd42fe3e4),
U64_C(0x5ef7842cee654b73), U64_C(0xaf107ecdbc86536e),
U64_C(0x3fcacbe784fcb401), U64_C(0xd55f90655c73e8cf),
U64_C(0xe6c2f40fdabf1336), U64_C(0xe8f6e7312c873b11),
U64_C(0xeb2a0555a28be12f), U64_C(0xe4a148bc2eb774e9),
U64_C(0x9b979db84156bc0a), U64_C(0x6eb60222e6a56ab4),
U64_C(0x87ffbbc4b026ec44), U64_C(0xc703a5275b3b90a6),
U64_C(0x47e699fc9001687f), U64_C(0x9c8d1aa73a4aa897),
U64_C(0x7cea3760e1ed12dd), U64_C(0x4ec80ddd1d2554c5),
U64_C(0x13e36b957d4cc588), U64_C(0x5d2b66486069914d),
U64_C(0x92b90999cc7280b0), U64_C(0x517cc9c56259deb5),
U64_C(0xc937b619ad03b881), U64_C(0xec30824ad997f5b2),
U64_C(0xa45d565fc5aa080b), U64_C(0xd6837201d27f32f1),
U64_C(0x635ef3789e9198ad), U64_C(0x531f75769651b96a),
U64_C(0x4f77530a6721e924), U64_C(0x486dd4151c3dfdb9),
U64_C(0x5f48dafb9461f692), U64_C(0x375b011173dc355a),
U64_C(0x3da9775470f4d3de), U64_C(0x8d0dcd81b30e0ac0),
U64_C(0x36e45fc609d888bb), U64_C(0x55baacbe97491016),
U64_C(0x8cb29356c90ab721), U64_C(0x76184125e2c5f459),
U64_C(0x99f4210bb55edbd5), U64_C(0x6f095cf59ca1d755),
U64_C(0x9f51f8c3b44672a9), U64_C(0x3538bda287d45285),
U64_C(0x50c39712185d6354), U64_C(0xf23b1885dcefc223),
U64_C(0x79930ccc6ef9619f), U64_C(0xed8fdc9da3934853),
U64_C(0xcb540aaa590bdf5e), U64_C(0x5c94389f1a6d2cac),
U64_C(0xe77daad8a0bbaed7), U64_C(0x28efc5090ca0bf2a),
U64_C(0xbf2ff73c4fc64cd8), U64_C(0xb37858b14df60320),
U64_C(0xf8c96ec0dfc724a7), U64_C(0x828680683f329f06),
U64_C(0x941cd051cd6a29cc), U64_C(0xc3c5c05cae2b5e05),
U64_C(0xb601631dc2e27062), U64_C(0xc01922382027843b),
U64_C(0x24b86a840e90f0d2), U64_C(0xd245177a276ffc52),
U64_C(0x0f8b4de98c3c95c6), U64_C(0x3e759530fef809e0),
U64_C(0x0b4d2892792c5b65), U64_C(0xc4df4743d5374a98),
U64_C(0xa5e20888bfaeb5ea), U64_C(0xba56cc90c0d23f9a),
U64_C(0x38d04cf8ffe0a09c), U64_C(0x62e1adafe495254c),
U64_C(0x0263bcb3f40867df), U64_C(0xcaeb547d230f62bf),
U64_C(0x6082111c109d4293), U64_C(0xdad4dd8cd04f7d09),
U64_C(0xefec602e579b2f8c), U64_C(0x1fb4c4187f7c8a70),
U64_C(0xffd3e9dfa4db303a), U64_C(0x7bf0b07f9af10640),
U64_C(0xf49ec14dddf76b5f), U64_C(0x8f6e713247066d1f),
U64_C(0x339d646a86ccfbf9), U64_C(0x64447467e58d8c30),
U64_C(0x2c29a072f9b07189), U64_C(0xd8b7613f24471ad6),
U64_C(0x6627c8d41185ebef), U64_C(0xa347d140beb61c96),
U64_C(0xde12b8f7255fb3aa), U64_C(0x9d324470404e1576),
U64_C(0x9306574eb6763d51), U64_C(0xa80af9d2c79a47f3),
U64_C(0x859c0777442e8b9b), U64_C(0x69ac853d9db97e29) },
/* 6 */
{ U64_C(0xc3407dfc2de6377e), U64_C(0x5b9e93eea4256f77),
U64_C(0xadb58fdd50c845e0), U64_C(0x5219ff11a75bed86),
U64_C(0x356b61cfd90b1de9), U64_C(0xfb8f406e25abe037),
U64_C(0x7a5a0231c0f60796), U64_C(0x9d3cd216e1f5020b),
U64_C(0x0c6550fb6b48d8f3), U64_C(0xf57508c427ff1c62),
U64_C(0x4ad35ffa71cb407d), U64_C(0x6290a2da1666aa6d),
U64_C(0xe284ec2349355f9f), U64_C(0xb3c307c53d7c84ec),
U64_C(0x05e23c0468365a02), U64_C(0x190bac4d6c9ebfa8),
U64_C(0x94bbbee9e28b80fa), U64_C(0xa34fc777529cb9b5),
U64_C(0xcc7b39f095bcd978), U64_C(0x2426addb0ce532e3),
U64_C(0x7e79329312ce4fc7), U64_C(0xab09a72eebec2917),
U64_C(0xf8d15499f6b9d6c2), U64_C(0x1a55b8babf8c895d),
U64_C(0xdb8add17fb769a85), U64_C(0xb57f2f368658e81b),
U64_C(0x8acd36f18f3f41f6), U64_C(0x5ce3b7bba50f11d3),
U64_C(0x114dcc14d5ee2f0a), U64_C(0xb91a7fcded1030e8),
U64_C(0x81d5425fe55de7a1), U64_C(0xb6213bc1554adeee),
U64_C(0x80144ef95f53f5f2), U64_C(0x1e7688186db4c10c),
U64_C(0x3b912965db5fe1bc), U64_C(0xc281715a97e8252d),
U64_C(0x54a5d7e21c7f8171), U64_C(0x4b12535ccbc5522e),
U64_C(0x1d289cefbea6f7f9), U64_C(0x6ef5f2217d2e729e),
U64_C(0xe6a7dc819b0d17ce), U64_C(0x1b94b41c05829b0e),
U64_C(0x33d7493c622f711e), U64_C(0xdcf7f942fa5ce421),
U64_C(0x600fba8b7f7a8ecb), U64_C(0x46b60f011a83988e),
U64_C(0x235b898e0dcf4c47), U64_C(0x957ab24f588592a9),
U64_C(0x4354330572b5c28c), U64_C(0xa5f3ef84e9b8d542),
U64_C(0x8c711e02341b2d01), U64_C(0x0b1874ae6a62a657),
U64_C(0x1213d8e306fc19ff), U64_C(0xfe6d7c6a4d9dba35),
U64_C(0x65ed868f174cd4c9), U64_C(0x88522ea0e6236550),
U64_C(0x899322065c2d7703), U64_C(0xc01e690bfef4018b),
U64_C(0x915982ed8abddaf8), U64_C(0xbe675b98ec3a4e4c),
U64_C(0xa996bf7f82f00db1), U64_C(0xe1daf8d49a27696a),
U64_C(0x2effd5d3dc8986e7), U64_C(0xd153a51f2b1a2e81),
U64_C(0x18caa0ebd690adfb), U64_C(0x390e3134b243c51a),
U64_C(0x2778b92cdff70416), U64_C(0x029f1851691c24a6),
U64_C(0x5e7cafeacc133575), U64_C(0xfa4e4cc89fa5f264),
U64_C(0x5a5f9f481e2b7d24), U64_C(0x484c47ab18d764db),
U64_C(0x400a27f2a1a7f479), U64_C(0xaeeb9b2a83da7315),
U64_C(0x721c626879869734), U64_C(0x042330a2d2384851),
U64_C(0x85f672fd3765aff0), U64_C(0xba446b3a3e02061d),
U64_C(0x73dd6ecec3888567), U64_C(0xffac70ccf793a866),
U64_C(0xdfa9edb5294ed2d4), U64_C(0x6c6aea7014325638),
U64_C(0x834a5a0e8c41c307), U64_C(0xcdba35562fb2cb2b),
U64_C(0x0ad97808d06cb404), U64_C(0x0f3b440cb85aee06),
U64_C(0xe5f9c876481f213b), U64_C(0x98deee1289c35809),
U64_C(0x59018bbfcd394bd1), U64_C(0xe01bf47220297b39),
U64_C(0xde68e1139340c087), U64_C(0x9fa3ca4788e926ad),
U64_C(0xbb85679c840c144e), U64_C(0x53d8f3b71d55ffd5),
U64_C(0x0da45c5dd146caa0), U64_C(0x6f34fe87c72060cd),
U64_C(0x57fbc315cf6db784), U64_C(0xcee421a1fca0fdde),
U64_C(0x3d2d0196607b8d4b), U64_C(0x642c8a29ad42c69a),
U64_C(0x14aff010bdd87508), U64_C(0xac74837beac657b3),
U64_C(0x3216459ad821634d), U64_C(0x3fb219c70967a9ed),
U64_C(0x06bc28f3bb246cf7), U64_C(0xf2082c9126d562c6),
U64_C(0x66b39278c45ee23c), U64_C(0xbd394f6f3f2878b9),
U64_C(0xfd33689d9e8f8cc0), U64_C(0x37f4799eb017394f),
U64_C(0x108cc0b26fe03d59), U64_C(0xda4bd1b1417888d6),
U64_C(0xb09d1332ee6eb219), U64_C(0x2f3ed975668794b4),
U64_C(0x58c0871977375982), U64_C(0x7561463d78ace990),
U64_C(0x09876cff037e82f1), U64_C(0x7fb83e35a8c05d94),
U64_C(0x26b9b58a65f91645), U64_C(0xef20b07e9873953f),
U64_C(0x3148516d0b3355b8), U64_C(0x41cb2b541ba9e62a),
U64_C(0x790416c613e43163), U64_C(0xa011d380818e8f40),
U64_C(0x3a5025c36151f3ef), U64_C(0xd57095bdf92266d0),
U64_C(0x498d4b0da2d97688), U64_C(0x8b0c3a57353153a5),
U64_C(0x21c491df64d368e1), U64_C(0x8f2f0af5e7091bf4),
U64_C(0x2da1c1240f9bb012), U64_C(0xc43d59a92ccc49da),
U64_C(0xbfa6573e56345c1f), U64_C(0x828b56a8364fd154),
U64_C(0x9a41f643e0df7caf), U64_C(0xbcf843c985266aea),
U64_C(0x2b1de9d7b4bfdce5), U64_C(0x20059d79dedd7ab2),
U64_C(0x6dabe6d6ae3c446b), U64_C(0x45e81bf6c991ae7b),
U64_C(0x6351ae7cac68b83e), U64_C(0xa432e32253b6c711),
U64_C(0xd092a9b991143cd2), U64_C(0xcac711032e98b58f),
U64_C(0xd8d4c9e02864ac70), U64_C(0xc5fc550f96c25b89),
U64_C(0xd7ef8dec903e4276), U64_C(0x67729ede7e50f06f),
U64_C(0xeac28c7af045cf3d), U64_C(0xb15c1f945460a04a),
U64_C(0x9cfddeb05bfb1058), U64_C(0x93c69abce3a1fe5e),
U64_C(0xeb0380dc4a4bdd6e), U64_C(0xd20db1e8f8081874),
U64_C(0x229a8528b7c15e14), U64_C(0x44291750739fbc28),
U64_C(0xd3ccbd4e42060a27), U64_C(0xf62b1c33f4ed2a97),
U64_C(0x86a8660ae4779905), U64_C(0xd62e814a2a305025),
U64_C(0x477703a7a08d8add), U64_C(0x7b9b0e977af815c5),
U64_C(0x78c51a60a9ea2330), U64_C(0xa6adfb733aaae3b7),
U64_C(0x97e5aa1e3199b60f), U64_C(0x0000000000000000),
U64_C(0xf4b404629df10e31), U64_C(0x5564db44a6719322),
U64_C(0x9207961a59afec0d), U64_C(0x9624a6b88b97a45c),
U64_C(0x363575380a192b1c), U64_C(0x2c60cd82b595a241),
U64_C(0x7d272664c1dc7932), U64_C(0x7142769faa94a1c1),
U64_C(0xa1d0df263b809d13), U64_C(0x1630e841d4c451ae),
U64_C(0xc1df65ad44fa13d8), U64_C(0x13d2d445bcf20bac),
U64_C(0xd915c546926abe23), U64_C(0x38cf3d92084dd749),
U64_C(0xe766d0272103059d), U64_C(0xc7634d5effde7f2f),
U64_C(0x077d2455012a7ea4), U64_C(0xedbfa82ff16fb199),
U64_C(0xaf2a978c39d46146), U64_C(0x42953fa3c8bbd0df),
U64_C(0xcb061da59496a7dc), U64_C(0x25e7a17db6eb20b0),
U64_C(0x34aa6d6963050fba), U64_C(0xa76cf7d580a4f1e4),
U64_C(0xf7ea10954ee338c4), U64_C(0xfcf2643b24819e93),
U64_C(0xcf252d0746aeef8d), U64_C(0x4ef06f58a3f3082c),
U64_C(0x563acfb37563a5d7), U64_C(0x5086e740ce47c920),
U64_C(0x2982f186dda3f843), U64_C(0x87696aac5e798b56),
U64_C(0x5d22bb1d1f010380), U64_C(0x035e14f7d31236f5),
U64_C(0x3cec0d30da759f18), U64_C(0xf3c920379cdb7095),
U64_C(0xb8db736b571e22bb), U64_C(0xdd36f5e44052f672),
U64_C(0xaac8ab8851e23b44), U64_C(0xa857b3d938fe1fe2),
U64_C(0x17f1e4e76eca43fd), U64_C(0xec7ea4894b61a3ca),
U64_C(0x9e62c6e132e734fe), U64_C(0xd4b1991b432c7483),
U64_C(0x6ad6c283af163acf), U64_C(0x1ce9904904a8e5aa),
U64_C(0x5fbda34c761d2726), U64_C(0xf910583f4cb7c491),
U64_C(0xc6a241f845d06d7c), U64_C(0x4f3163fe19fd1a7f),
U64_C(0xe99c988d2357f9c8), U64_C(0x8eee06535d0709a7),
U64_C(0x0efa48aa0254fc55), U64_C(0xb4be23903c56fa48),
U64_C(0x763f52caabbedf65), U64_C(0xeee1bcd8227d876c),
U64_C(0xe345e085f33b4dcc), U64_C(0x3e731561b369bbbe),
U64_C(0x2843fd2067adea10), U64_C(0x2adce5710eb1ceb6),
U64_C(0xb7e03767ef44ccbd), U64_C(0x8db012a48e153f52),
U64_C(0x61ceb62dc5749c98), U64_C(0xe85d942b9959eb9b),
U64_C(0x4c6f7709caef2c8a), U64_C(0x84377e5b8d6bbda3),
U64_C(0x30895dcbb13d47eb), U64_C(0x74a04a9bc2a2fbc3),
U64_C(0x6b17ce251518289c), U64_C(0xe438c4d0f2113368),
U64_C(0x1fb784bed7bad35f), U64_C(0x9b80fae55ad16efc),
U64_C(0x77fe5e6c11b0cd36), U64_C(0xc858095247849129),
U64_C(0x08466059b97090a2), U64_C(0x01c10ca6ba0e1253),
U64_C(0x6988d6747c040c3a), U64_C(0x6849dad2c60a1e69),
U64_C(0x5147ebe67449db73), U64_C(0xc99905f4fd8a837a),
U64_C(0x991fe2b433cd4a5a), U64_C(0xf09734c04fc94660),
U64_C(0xa28ecbd1e892abe6), U64_C(0xf1563866f5c75433),
U64_C(0x4dae7baf70e13ed9), U64_C(0x7ce62ac27bd26b61),
U64_C(0x70837a39109ab392), U64_C(0x90988e4b30b3c8ab),
U64_C(0xb2020b63877296bf), U64_C(0x156efcb607d6675b) },
/* 7 */
{ U64_C(0xe63f55ce97c331d0), U64_C(0x25b506b0015bba16),
U64_C(0xc8706e29e6ad9ba8), U64_C(0x5b43d3775d521f6a),
U64_C(0x0bfa3d577035106e), U64_C(0xab95fc172afb0e66),
U64_C(0xf64b63979e7a3276), U64_C(0xf58b4562649dad4b),
U64_C(0x48f7c3dbae0c83f1), U64_C(0xff31916642f5c8c5),
U64_C(0xcbb048dc1c4a0495), U64_C(0x66b8f83cdf622989),
U64_C(0x35c130e908e2b9b0), U64_C(0x7c761a61f0b34fa1),
U64_C(0x3601161cf205268d), U64_C(0x9e54ccfe2219b7d6),
U64_C(0x8b7d90a538940837), U64_C(0x9cd403588ea35d0b),
U64_C(0xbc3c6fea9ccc5b5a), U64_C(0xe5ff733b6d24aeed),
U64_C(0xceed22de0f7eb8d2), U64_C(0xec8581cab1ab545e),
U64_C(0xb96105e88ff8e71d), U64_C(0x8ca03501871a5ead),
U64_C(0x76ccce65d6db2a2f), U64_C(0x5883f582a7b58057),
U64_C(0x3f7be4ed2e8adc3e), U64_C(0x0fe7be06355cd9c9),
U64_C(0xee054e6c1d11be83), U64_C(0x1074365909b903a6),
U64_C(0x5dde9f80b4813c10), U64_C(0x4a770c7d02b6692c),
U64_C(0x5379c8d5d7809039), U64_C(0xb4067448161ed409),
U64_C(0x5f5e5026183bd6cd), U64_C(0xe898029bf4c29df9),
U64_C(0x7fb63c940a54d09c), U64_C(0xc5171f897f4ba8bc),
U64_C(0xa6f28db7b31d3d72), U64_C(0x2e4f3be7716eaa78),
U64_C(0x0d6771a099e63314), U64_C(0x82076254e41bf284),
U64_C(0x2f0fd2b42733df98), U64_C(0x5c9e76d3e2dc49f0),
U64_C(0x7aeb569619606cdb), U64_C(0x83478b07b2468764),
U64_C(0xcfadcb8d5923cd32), U64_C(0x85dac7f05b95a41e),
U64_C(0xb5469d1b4043a1e9), U64_C(0xb821ecbbd9a592fd),
U64_C(0x1b8e0b0e798c13c8), U64_C(0x62a57b6d9a0be02e),
U64_C(0xfcf1b793b81257f8), U64_C(0x9d94ea0bd8fe28eb),
U64_C(0x4cea408aeb654a56), U64_C(0x23284a47e888996c),
U64_C(0x2d8f1d128b893545), U64_C(0xf4cbac3132c0d8ab),
U64_C(0xbd7c86b9ca912eba), U64_C(0x3a268eef3dbe6079),
U64_C(0xf0d62f6077a9110c), U64_C(0x2735c916ade150cb),
U64_C(0x89fd5f03942ee2ea), U64_C(0x1acee25d2fd16628),
U64_C(0x90f39bab41181bff), U64_C(0x430dfe8cde39939f),
U64_C(0xf70b8ac4c8274796), U64_C(0x1c53aeaac6024552),
U64_C(0x13b410acf35e9c9b), U64_C(0xa532ab4249faa24f),
U64_C(0x2b1251e5625a163f), U64_C(0xd7e3e676da4841c7),
U64_C(0xa7b264e4e5404892), U64_C(0xda8497d643ae72d3),
U64_C(0x861ae105a1723b23), U64_C(0x38a6414991048aa4),
U64_C(0x6578dec92585b6b4), U64_C(0x0280cfa6acbaeadd),
U64_C(0x88bdb650c273970a), U64_C(0x9333bd5ebbff84c2),
U64_C(0x4e6a8f2c47dfa08b), U64_C(0x321c954db76cef2a),
U64_C(0x418d312a72837942), U64_C(0xb29b38bfffcdf773),
U64_C(0x6c022c38f90a4c07), U64_C(0x5a033a240b0f6a8a),
U64_C(0x1f93885f3ce5da6f), U64_C(0xc38a537e96988bc6),
U64_C(0x39e6a81ac759ff44), U64_C(0x29929e43cee0fce2),
U64_C(0x40cdd87924de0ca2), U64_C(0xe9d8ebc8a29fe819),
U64_C(0x0c2798f3cfbb46f4), U64_C(0x55e484223e53b343),
U64_C(0x4650948ecd0d2fd8), U64_C(0x20e86cb2126f0651),
U64_C(0x6d42c56baf5739e7), U64_C(0xa06fc1405ace1e08),
U64_C(0x7babbfc54f3d193b), U64_C(0x424d17df8864e67f),
U64_C(0xd8045870ef14980e), U64_C(0xc6d7397c85ac3781),
U64_C(0x21a885e1443273b1), U64_C(0x67f8116f893f5c69),
U64_C(0x24f5efe35706cff6), U64_C(0xd56329d076f2ab1a),
U64_C(0x5e1eb9754e66a32d), U64_C(0x28d2771098bd8902),
U64_C(0x8f6013f47dfdc190), U64_C(0x17a993fdb637553c),
U64_C(0xe0a219397e1012aa), U64_C(0x786b9930b5da8606),
U64_C(0x6e82e39e55b0a6da), U64_C(0x875a0856f72f4ec3),
U64_C(0x3741ff4fa458536d), U64_C(0xac4859b3957558fc),
U64_C(0x7ef6d5c75c09a57c), U64_C(0xc04a758b6c7f14fb),
U64_C(0xf9acdd91ab26ebbf), U64_C(0x7391a467c5ef9668),
U64_C(0x335c7c1ee1319aca), U64_C(0xa91533b18641e4bb),
U64_C(0xe4bf9a683b79db0d), U64_C(0x8e20faa72ba0b470),
U64_C(0x51f907737b3a7ae4), U64_C(0x2268a314bed5ec8c),
U64_C(0xd944b123b949edee), U64_C(0x31dcb3b84d8b7017),
U64_C(0xd3fe65279f218860), U64_C(0x097af2f1dc8ffab3),
U64_C(0x9b09a6fc312d0b91), U64_C(0xcc6ded78a3c4520f),
U64_C(0x3481d9ba5ebfcc50), U64_C(0x4f2a667f1182d56b),
U64_C(0xdfd9fdd4509ace94), U64_C(0x26752045fbbc252b),
U64_C(0xbffc491f662bc467), U64_C(0xdd593272fc202449),
U64_C(0x3cbbc218d46d4303), U64_C(0x91b372f817456e1f),
U64_C(0x681faf69bc6385a0), U64_C(0xb686bbeebaa43ed4),
U64_C(0x1469b5084cd0ca01), U64_C(0x98c98009cbca94ac),
U64_C(0x6438379a73d8c354), U64_C(0xc2caba2dc0c5fe26),
U64_C(0x3e3b0dbe78d7a9de), U64_C(0x50b9ee202d670f04),
U64_C(0x4590b27b37eab0e5), U64_C(0x6025b4cb36b10af3),
U64_C(0xfb2c1237079c0162), U64_C(0xa12f28130c936be8),
U64_C(0x4b37e52e54eb1ccc), U64_C(0x083a1ba28ad28f53),
U64_C(0xc10a9cd83a22611b), U64_C(0x9f1425ad7444c236),
U64_C(0x069d4cf7e9d3237a), U64_C(0xedc56899e7f621be),
U64_C(0x778c273680865fcf), U64_C(0x309c5aeb1bd605f7),
U64_C(0x8de0dc52d1472b4d), U64_C(0xf8ec34c2fd7b9e5f),
U64_C(0xea18cd3d58787724), U64_C(0xaad515447ca67b86),
U64_C(0x9989695a9d97e14c), U64_C(0x0000000000000000),
U64_C(0xf196c63321f464ec), U64_C(0x71116bc169557cb5),
U64_C(0xaf887f466f92c7c1), U64_C(0x972e3e0ffe964d65),
U64_C(0x190ec4a8d536f915), U64_C(0x95aef1a9522ca7b8),
U64_C(0xdc19db21aa7d51a9), U64_C(0x94ee18fa0471d258),
U64_C(0x8087adf248a11859), U64_C(0xc457f6da2916dd5c),
U64_C(0xfa6cfb6451c17482), U64_C(0xf256e0c6db13fbd1),
U64_C(0x6a9f60cf10d96f7d), U64_C(0x4daaa9d9bd383fb6),
U64_C(0x03c026f5fae79f3d), U64_C(0xde99148706c7bb74),
U64_C(0x2a52b8b6340763df), U64_C(0x6fc20acd03edd33a),
U64_C(0xd423c08320afdefa), U64_C(0xbbe1ca4e23420dc0),
U64_C(0x966ed75ca8cb3885), U64_C(0xeb58246e0e2502c4),
U64_C(0x055d6a021334bc47), U64_C(0xa47242111fa7d7af),
U64_C(0xe3623fcc84f78d97), U64_C(0x81c744a11efc6db9),
U64_C(0xaec8961539cfb221), U64_C(0xf31609958d4e8e31),
U64_C(0x63e5923ecc5695ce), U64_C(0x47107ddd9b505a38),
U64_C(0xa3afe7b5a0298135), U64_C(0x792b7063e387f3e6),
U64_C(0x0140e953565d75e0), U64_C(0x12f4f9ffa503e97b),
U64_C(0x750ce8902c3cb512), U64_C(0xdbc47e8515f30733),
U64_C(0x1ed3610c6ab8af8f), U64_C(0x5239218681dde5d9),
U64_C(0xe222d69fd2aaf877), U64_C(0xfe71783514a8bd25),
U64_C(0xcaf0a18f4a177175), U64_C(0x61655d9860ec7f13),
U64_C(0xe77fbc9dc19e4430), U64_C(0x2ccff441ddd440a5),
U64_C(0x16e97aaee06a20dc), U64_C(0xa855dae2d01c915b),
U64_C(0x1d1347f9905f30b2), U64_C(0xb7c652bdecf94b34),
U64_C(0xd03e43d265c6175d), U64_C(0xfdb15ec0ee4f2218),
U64_C(0x57644b8492e9599e), U64_C(0x07dda5a4bf8e569a),
U64_C(0x54a46d71680ec6a3), U64_C(0x5624a2d7c4b42c7e),
U64_C(0xbebca04c3076b187), U64_C(0x7d36f332a6ee3a41),
U64_C(0x3b6667bc6be31599), U64_C(0x695f463aea3ef040),
U64_C(0xad08b0e0c3282d1c), U64_C(0xb15b1e4a052a684e),
U64_C(0x44d05b2861b7c505), U64_C(0x15295c5b1a8dbfe1),
U64_C(0x744c01c37a61c0f2), U64_C(0x59c31cd1f1e8f5b7),
U64_C(0xef45a73f4b4ccb63), U64_C(0x6bdf899c46841a9d),
U64_C(0x3dfb2b4b823036e3), U64_C(0xa2ef0ee6f674f4d5),
U64_C(0x184e2dfb836b8cf5), U64_C(0x1134df0a5fe47646),
U64_C(0xbaa1231d751f7820), U64_C(0xd17eaa81339b62bd),
U64_C(0xb01bf71953771dae), U64_C(0x849a2ea30dc8d1fe),
U64_C(0x705182923f080955), U64_C(0x0ea757556301ac29),
U64_C(0x041d83514569c9a7), U64_C(0x0abad4042668658e),
U64_C(0x49b72a88f851f611), U64_C(0x8a3d79f66ec97dd7),
U64_C(0xcd2d042bf59927ef), U64_C(0xc930877ab0f0ee48),
U64_C(0x9273540deda2f122), U64_C(0xc797d02fd3f14261),
U64_C(0xe1e2f06a284d674a), U64_C(0xd2be8c74c97cfd80),
U64_C(0x9a494faf67707e71), U64_C(0xb3dbd1eca9908293),
U64_C(0x72d14d3493b2e388), U64_C(0xd6a30f258c153427) },
};
static const u64 C16[12][8] =
{
{ U64_C(0xdd806559f2a64507), U64_C(0x05767436cc744d23),
U64_C(0xa2422a08a460d315), U64_C(0x4b7ce09192676901),
U64_C(0x714eb88d7585c4fc), U64_C(0x2f6a76432e45d016),
U64_C(0xebcb2f81c0657c1f), U64_C(0xb1085bda1ecadae9) },
{ U64_C(0xe679047021b19bb7), U64_C(0x55dda21bd7cbcd56),
U64_C(0x5cb561c2db0aa7ca), U64_C(0x9ab5176b12d69958),
U64_C(0x61d55e0f16b50131), U64_C(0xf3feea720a232b98),
U64_C(0x4fe39d460f70b5d7), U64_C(0x6fa3b58aa99d2f1a) },
{ U64_C(0x991e96f50aba0ab2), U64_C(0xc2b6f443867adb31),
U64_C(0xc1c93a376062db09), U64_C(0xd3e20fe490359eb1),
U64_C(0xf2ea7514b1297b7b), U64_C(0x06f15e5f529c1f8b),
U64_C(0x0a39fc286a3d8435), U64_C(0xf574dcac2bce2fc7) },
{ U64_C(0x220cbebc84e3d12e), U64_C(0x3453eaa193e837f1),
U64_C(0xd8b71333935203be), U64_C(0xa9d72c82ed03d675),
U64_C(0x9d721cad685e353f), U64_C(0x488e857e335c3c7d),
U64_C(0xf948e1a05d71e4dd), U64_C(0xef1fdfb3e81566d2) },
{ U64_C(0x601758fd7c6cfe57), U64_C(0x7a56a27ea9ea63f5),
U64_C(0xdfff00b723271a16), U64_C(0xbfcd1747253af5a3),
U64_C(0x359e35d7800fffbd), U64_C(0x7f151c1f1686104a),
U64_C(0x9a3f410c6ca92363), U64_C(0x4bea6bacad474799) },
{ U64_C(0xfa68407a46647d6e), U64_C(0xbf71c57236904f35),
U64_C(0x0af21f66c2bec6b6), U64_C(0xcffaa6b71c9ab7b4),
U64_C(0x187f9ab49af08ec6), U64_C(0x2d66c4f95142a46c),
U64_C(0x6fa4c33b7a3039c0), U64_C(0xae4faeae1d3ad3d9) },
{ U64_C(0x8886564d3a14d493), U64_C(0x3517454ca23c4af3),
U64_C(0x06476983284a0504), U64_C(0x0992abc52d822c37),
U64_C(0xd3473e33197a93c9), U64_C(0x399ec6c7e6bf87c9),
U64_C(0x51ac86febf240954), U64_C(0xf4c70e16eeaac5ec) },
{ U64_C(0xa47f0dd4bf02e71e), U64_C(0x36acc2355951a8d9),
U64_C(0x69d18d2bd1a5c42f), U64_C(0xf4892bcb929b0690),
U64_C(0x89b4443b4ddbc49a), U64_C(0x4eb7f8719c36de1e),
U64_C(0x03e7aa020c6e4141), U64_C(0x9b1f5b424d93c9a7) },
{ U64_C(0x7261445183235adb), U64_C(0x0e38dc92cb1f2a60),
U64_C(0x7b2b8a9aa6079c54), U64_C(0x800a440bdbb2ceb1),
U64_C(0x3cd955b7e00d0984), U64_C(0x3a7d3a1b25894224),
U64_C(0x944c9ad8ec165fde), U64_C(0x378f5a541631229b) },
{ U64_C(0x74b4c7fb98459ced), U64_C(0x3698fad1153bb6c3),
U64_C(0x7a1e6c303b7652f4), U64_C(0x9fe76702af69334b),
U64_C(0x1fffe18a1b336103), U64_C(0x8941e71cff8a78db),
U64_C(0x382ae548b2e4f3f3), U64_C(0xabbedea680056f52) },
{ U64_C(0x6bcaa4cd81f32d1b), U64_C(0xdea2594ac06fd85d),
U64_C(0xefbacd1d7d476e98), U64_C(0x8a1d71efea48b9ca),
U64_C(0x2001802114846679), U64_C(0xd8fa6bbbebab0761),
U64_C(0x3002c6cd635afe94), U64_C(0x7bcd9ed0efc889fb) },
{ U64_C(0x48bc924af11bd720), U64_C(0xfaf417d5d9b21b99),
U64_C(0xe71da4aa88e12852), U64_C(0x5d80ef9d1891cc86),
U64_C(0xf82012d430219f9b), U64_C(0xcda43c32bcdf1d77),
U64_C(0xd21380b00449b17a), U64_C(0x378ee767f11631ba) },
};
#define strido(out, temp, i) do { \
u64 t; \
t = stribog_table[0][(temp[0] >> (i * 8)) & 0xff]; \
t ^= stribog_table[1][(temp[1] >> (i * 8)) & 0xff]; \
t ^= stribog_table[2][(temp[2] >> (i * 8)) & 0xff]; \
t ^= stribog_table[3][(temp[3] >> (i * 8)) & 0xff]; \
t ^= stribog_table[4][(temp[4] >> (i * 8)) & 0xff]; \
t ^= stribog_table[5][(temp[5] >> (i * 8)) & 0xff]; \
t ^= stribog_table[6][(temp[6] >> (i * 8)) & 0xff]; \
t ^= stribog_table[7][(temp[7] >> (i * 8)) & 0xff]; \
out[i] = t; } while(0)
static void LPSX (u64 *out, const u64 *a, const u64 *b)
{
u64 temp[8];
temp[0] = a[0] ^ b[0];
temp[1] = a[1] ^ b[1];
temp[2] = a[2] ^ b[2];
temp[3] = a[3] ^ b[3];
temp[4] = a[4] ^ b[4];
temp[5] = a[5] ^ b[5];
temp[6] = a[6] ^ b[6];
temp[7] = a[7] ^ b[7];
strido (out, temp, 0);
strido (out, temp, 1);
strido (out, temp, 2);
strido (out, temp, 3);
strido (out, temp, 4);
strido (out, temp, 5);
strido (out, temp, 6);
strido (out, temp, 7);
}
static inline void g (u64 *h, u64 *m, u64 *N)
{
u64 K[8];
u64 T[8];
int i;
LPSX (K, h, N);
LPSX (T, K, m);
LPSX (K, K, C16[0]);
for (i = 1; i < 12; i++)
{
LPSX (T, K, T);
LPSX (K, K, C16[i]);
}
h[0] ^= T[0] ^ K[0] ^ m[0];
h[1] ^= T[1] ^ K[1] ^ m[1];
h[2] ^= T[2] ^ K[2] ^ m[2];
h[3] ^= T[3] ^ K[3] ^ m[3];
h[4] ^= T[4] ^ K[4] ^ m[4];
h[5] ^= T[5] ^ K[5] ^ m[5];
h[6] ^= T[6] ^ K[6] ^ m[6];
h[7] ^= T[7] ^ K[7] ^ m[7];
}
static unsigned int
transform (void *context, const unsigned char *inbuf_arg, size_t datalen);
static void
stribog_init_512 (void *context, unsigned int flags)
{
STRIBOG_CONTEXT *hd = context;
(void)flags;
memset (hd, 0, sizeof (*hd));
hd->bctx.blocksize = 64;
hd->bctx.bwrite = transform;
}
static void
stribog_init_256 (void *context, unsigned int flags)
{
STRIBOG_CONTEXT *hd = context;
stribog_init_512 (context, flags);
memset (hd->h, 1, 64);
}
static void
transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count)
{
u64 M[8];
u64 l, cf;
int i;
for (i = 0; i < 8; i++)
M[i] = buf_get_le64(data + i * 8);
g (hd->h, M, hd->N);
l = hd->N[0];
hd->N[0] += count;
if (hd->N[0] < l)
{ /* overflow */
for (i = 1; i < 8; i++)
{
hd->N[i]++;
if (hd->N[i] != 0)
break;
}
}
hd->Sigma[0] += M[0];
cf = 0;
for (i = 1; i < 8; 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
transform_blk (void *context, const unsigned char *inbuf_arg)
{
STRIBOG_CONTEXT *hd = context;
transform_bits (hd, inbuf_arg, 64 * 8);
return /* burn_stack */ 768;
}
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;
}
/*
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
stribog_final (void *context)
{
STRIBOG_CONTEXT *hd = context;
u64 Z[8] = {};
int i;
/* 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;
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);
g (hd->h, hd->Sigma, Z);
for (i = 0; i < 8; i++)
hd->h[i] = le_bswap64(hd->h[i]);
_gcry_burn_stack (768);
}
static byte *
stribog_read_512 (void *context)
{
STRIBOG_CONTEXT *hd = context;
return hd->result;
}
static byte *
stribog_read_256 (void *context)
{
STRIBOG_CONTEXT *hd = context;
return hd->result + 32;
}
static gcry_md_oid_spec_t oid_spec_stribog256[] =
{
/* id-tc26-signwithdigest-gost3410-12-256 */
{ "1.2.643.7.1.1.3.2" },
/* id-tc26-gost3411-12-256 */
{ "1.2.643.7.1.1.2.2" },
{ NULL },
};
static gcry_md_oid_spec_t oid_spec_stribog512[] =
{
/* id-tc26-signwithdigest-gost3410-12-512 */
{ "1.2.643.7.1.1.3.3" },
/* id-tc26-gost3411-12-512 */
{ "1.2.643.7.1.1.2.3" },
{ NULL },
};
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 =
{
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/tiger.c b/cipher/tiger.c
index c78e3ac3..a03a00d5 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -1,859 +1,859 @@
/* tiger.c - The TIGER hash function
* Copyright (C) 1998, 2001, 2002, 2003, 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-/* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */
+/* See https://www.cs.technion.ac.il/~biham/Reports/Tiger/ */
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#include "cipher.h"
#include "hash-common.h"
#include "bithelp.h"
#include "bufhelp.h"
typedef struct
{
gcry_md_block_ctx_t bctx;
u64 a, b, c;
int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */
} TIGER_CONTEXT;
/*********************************
* Okay, okay, this is not the fastest code - improvements are welcome.
*
*/
/* Some test vectors:
* "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A
* "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951
* "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF
* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
* 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386
* "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"
* 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"
* 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc"
* "eedings of Fast Software Encryption 3, Cambridge."
* EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc"
* "eedings of Fast Software Encryption 3, Cambridge, 1996."
* 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC
* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF"
* "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
* 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4
*/
static u64 sbox1[256] = {
U64_C(0x02aab17cf7e90c5e) /* 0 */, U64_C(0xac424b03e243a8ec) /* 1 */,
U64_C(0x72cd5be30dd5fcd3) /* 2 */, U64_C(0x6d019b93f6f97f3a) /* 3 */,
U64_C(0xcd9978ffd21f9193) /* 4 */, U64_C(0x7573a1c9708029e2) /* 5 */,
U64_C(0xb164326b922a83c3) /* 6 */, U64_C(0x46883eee04915870) /* 7 */,
U64_C(0xeaace3057103ece6) /* 8 */, U64_C(0xc54169b808a3535c) /* 9 */,
U64_C(0x4ce754918ddec47c) /* 10 */, U64_C(0x0aa2f4dfdc0df40c) /* 11 */,
U64_C(0x10b76f18a74dbefa) /* 12 */, U64_C(0xc6ccb6235ad1ab6a) /* 13 */,
U64_C(0x13726121572fe2ff) /* 14 */, U64_C(0x1a488c6f199d921e) /* 15 */,
U64_C(0x4bc9f9f4da0007ca) /* 16 */, U64_C(0x26f5e6f6e85241c7) /* 17 */,
U64_C(0x859079dbea5947b6) /* 18 */, U64_C(0x4f1885c5c99e8c92) /* 19 */,
U64_C(0xd78e761ea96f864b) /* 20 */, U64_C(0x8e36428c52b5c17d) /* 21 */,
U64_C(0x69cf6827373063c1) /* 22 */, U64_C(0xb607c93d9bb4c56e) /* 23 */,
U64_C(0x7d820e760e76b5ea) /* 24 */, U64_C(0x645c9cc6f07fdc42) /* 25 */,
U64_C(0xbf38a078243342e0) /* 26 */, U64_C(0x5f6b343c9d2e7d04) /* 27 */,
U64_C(0xf2c28aeb600b0ec6) /* 28 */, U64_C(0x6c0ed85f7254bcac) /* 29 */,
U64_C(0x71592281a4db4fe5) /* 30 */, U64_C(0x1967fa69ce0fed9f) /* 31 */,
U64_C(0xfd5293f8b96545db) /* 32 */, U64_C(0xc879e9d7f2a7600b) /* 33 */,
U64_C(0x860248920193194e) /* 34 */, U64_C(0xa4f9533b2d9cc0b3) /* 35 */,
U64_C(0x9053836c15957613) /* 36 */, U64_C(0xdb6dcf8afc357bf1) /* 37 */,
U64_C(0x18beea7a7a370f57) /* 38 */, U64_C(0x037117ca50b99066) /* 39 */,
U64_C(0x6ab30a9774424a35) /* 40 */, U64_C(0xf4e92f02e325249b) /* 41 */,
U64_C(0x7739db07061ccae1) /* 42 */, U64_C(0xd8f3b49ceca42a05) /* 43 */,
U64_C(0xbd56be3f51382f73) /* 44 */, U64_C(0x45faed5843b0bb28) /* 45 */,
U64_C(0x1c813d5c11bf1f83) /* 46 */, U64_C(0x8af0e4b6d75fa169) /* 47 */,
U64_C(0x33ee18a487ad9999) /* 48 */, U64_C(0x3c26e8eab1c94410) /* 49 */,
U64_C(0xb510102bc0a822f9) /* 50 */, U64_C(0x141eef310ce6123b) /* 51 */,
U64_C(0xfc65b90059ddb154) /* 52 */, U64_C(0xe0158640c5e0e607) /* 53 */,
U64_C(0x884e079826c3a3cf) /* 54 */, U64_C(0x930d0d9523c535fd) /* 55 */,
U64_C(0x35638d754e9a2b00) /* 56 */, U64_C(0x4085fccf40469dd5) /* 57 */,
U64_C(0xc4b17ad28be23a4c) /* 58 */, U64_C(0xcab2f0fc6a3e6a2e) /* 59 */,
U64_C(0x2860971a6b943fcd) /* 60 */, U64_C(0x3dde6ee212e30446) /* 61 */,
U64_C(0x6222f32ae01765ae) /* 62 */, U64_C(0x5d550bb5478308fe) /* 63 */,
U64_C(0xa9efa98da0eda22a) /* 64 */, U64_C(0xc351a71686c40da7) /* 65 */,
U64_C(0x1105586d9c867c84) /* 66 */, U64_C(0xdcffee85fda22853) /* 67 */,
U64_C(0xccfbd0262c5eef76) /* 68 */, U64_C(0xbaf294cb8990d201) /* 69 */,
U64_C(0xe69464f52afad975) /* 70 */, U64_C(0x94b013afdf133e14) /* 71 */,
U64_C(0x06a7d1a32823c958) /* 72 */, U64_C(0x6f95fe5130f61119) /* 73 */,
U64_C(0xd92ab34e462c06c0) /* 74 */, U64_C(0xed7bde33887c71d2) /* 75 */,
U64_C(0x79746d6e6518393e) /* 76 */, U64_C(0x5ba419385d713329) /* 77 */,
U64_C(0x7c1ba6b948a97564) /* 78 */, U64_C(0x31987c197bfdac67) /* 79 */,
U64_C(0xde6c23c44b053d02) /* 80 */, U64_C(0x581c49fed002d64d) /* 81 */,
U64_C(0xdd474d6338261571) /* 82 */, U64_C(0xaa4546c3e473d062) /* 83 */,
U64_C(0x928fce349455f860) /* 84 */, U64_C(0x48161bbacaab94d9) /* 85 */,
U64_C(0x63912430770e6f68) /* 86 */, U64_C(0x6ec8a5e602c6641c) /* 87 */,
U64_C(0x87282515337ddd2b) /* 88 */, U64_C(0x2cda6b42034b701b) /* 89 */,
U64_C(0xb03d37c181cb096d) /* 90 */, U64_C(0xe108438266c71c6f) /* 91 */,
U64_C(0x2b3180c7eb51b255) /* 92 */, U64_C(0xdf92b82f96c08bbc) /* 93 */,
U64_C(0x5c68c8c0a632f3ba) /* 94 */, U64_C(0x5504cc861c3d0556) /* 95 */,
U64_C(0xabbfa4e55fb26b8f) /* 96 */, U64_C(0x41848b0ab3baceb4) /* 97 */,
U64_C(0xb334a273aa445d32) /* 98 */, U64_C(0xbca696f0a85ad881) /* 99 */,
U64_C(0x24f6ec65b528d56c) /* 100 */, U64_C(0x0ce1512e90f4524a) /* 101 */,
U64_C(0x4e9dd79d5506d35a) /* 102 */, U64_C(0x258905fac6ce9779) /* 103 */,
U64_C(0x2019295b3e109b33) /* 104 */, U64_C(0xf8a9478b73a054cc) /* 105 */,
U64_C(0x2924f2f934417eb0) /* 106 */, U64_C(0x3993357d536d1bc4) /* 107 */,
U64_C(0x38a81ac21db6ff8b) /* 108 */, U64_C(0x47c4fbf17d6016bf) /* 109 */,
U64_C(0x1e0faadd7667e3f5) /* 110 */, U64_C(0x7abcff62938beb96) /* 111 */,
U64_C(0xa78dad948fc179c9) /* 112 */, U64_C(0x8f1f98b72911e50d) /* 113 */,
U64_C(0x61e48eae27121a91) /* 114 */, U64_C(0x4d62f7ad31859808) /* 115 */,
U64_C(0xeceba345ef5ceaeb) /* 116 */, U64_C(0xf5ceb25ebc9684ce) /* 117 */,
U64_C(0xf633e20cb7f76221) /* 118 */, U64_C(0xa32cdf06ab8293e4) /* 119 */,
U64_C(0x985a202ca5ee2ca4) /* 120 */, U64_C(0xcf0b8447cc8a8fb1) /* 121 */,
U64_C(0x9f765244979859a3) /* 122 */, U64_C(0xa8d516b1a1240017) /* 123 */,
U64_C(0x0bd7ba3ebb5dc726) /* 124 */, U64_C(0xe54bca55b86adb39) /* 125 */,
U64_C(0x1d7a3afd6c478063) /* 126 */, U64_C(0x519ec608e7669edd) /* 127 */,
U64_C(0x0e5715a2d149aa23) /* 128 */, U64_C(0x177d4571848ff194) /* 129 */,
U64_C(0xeeb55f3241014c22) /* 130 */, U64_C(0x0f5e5ca13a6e2ec2) /* 131 */,
U64_C(0x8029927b75f5c361) /* 132 */, U64_C(0xad139fabc3d6e436) /* 133 */,
U64_C(0x0d5df1a94ccf402f) /* 134 */, U64_C(0x3e8bd948bea5dfc8) /* 135 */,
U64_C(0xa5a0d357bd3ff77e) /* 136 */, U64_C(0xa2d12e251f74f645) /* 137 */,
U64_C(0x66fd9e525e81a082) /* 138 */, U64_C(0x2e0c90ce7f687a49) /* 139 */,
U64_C(0xc2e8bcbeba973bc5) /* 140 */, U64_C(0x000001bce509745f) /* 141 */,
U64_C(0x423777bbe6dab3d6) /* 142 */, U64_C(0xd1661c7eaef06eb5) /* 143 */,
U64_C(0xa1781f354daacfd8) /* 144 */, U64_C(0x2d11284a2b16affc) /* 145 */,
U64_C(0xf1fc4f67fa891d1f) /* 146 */, U64_C(0x73ecc25dcb920ada) /* 147 */,
U64_C(0xae610c22c2a12651) /* 148 */, U64_C(0x96e0a810d356b78a) /* 149 */,
U64_C(0x5a9a381f2fe7870f) /* 150 */, U64_C(0xd5ad62ede94e5530) /* 151 */,
U64_C(0xd225e5e8368d1427) /* 152 */, U64_C(0x65977b70c7af4631) /* 153 */,
U64_C(0x99f889b2de39d74f) /* 154 */, U64_C(0x233f30bf54e1d143) /* 155 */,
U64_C(0x9a9675d3d9a63c97) /* 156 */, U64_C(0x5470554ff334f9a8) /* 157 */,
U64_C(0x166acb744a4f5688) /* 158 */, U64_C(0x70c74caab2e4aead) /* 159 */,
U64_C(0xf0d091646f294d12) /* 160 */, U64_C(0x57b82a89684031d1) /* 161 */,
U64_C(0xefd95a5a61be0b6b) /* 162 */, U64_C(0x2fbd12e969f2f29a) /* 163 */,
U64_C(0x9bd37013feff9fe8) /* 164 */, U64_C(0x3f9b0404d6085a06) /* 165 */,
U64_C(0x4940c1f3166cfe15) /* 166 */, U64_C(0x09542c4dcdf3defb) /* 167 */,
U64_C(0xb4c5218385cd5ce3) /* 168 */, U64_C(0xc935b7dc4462a641) /* 169 */,
U64_C(0x3417f8a68ed3b63f) /* 170 */, U64_C(0xb80959295b215b40) /* 171 */,
U64_C(0xf99cdaef3b8c8572) /* 172 */, U64_C(0x018c0614f8fcb95d) /* 173 */,
U64_C(0x1b14accd1a3acdf3) /* 174 */, U64_C(0x84d471f200bb732d) /* 175 */,
U64_C(0xc1a3110e95e8da16) /* 176 */, U64_C(0x430a7220bf1a82b8) /* 177 */,
U64_C(0xb77e090d39df210e) /* 178 */, U64_C(0x5ef4bd9f3cd05e9d) /* 179 */,
U64_C(0x9d4ff6da7e57a444) /* 180 */, U64_C(0xda1d60e183d4a5f8) /* 181 */,
U64_C(0xb287c38417998e47) /* 182 */, U64_C(0xfe3edc121bb31886) /* 183 */,
U64_C(0xc7fe3ccc980ccbef) /* 184 */, U64_C(0xe46fb590189bfd03) /* 185 */,
U64_C(0x3732fd469a4c57dc) /* 186 */, U64_C(0x7ef700a07cf1ad65) /* 187 */,
U64_C(0x59c64468a31d8859) /* 188 */, U64_C(0x762fb0b4d45b61f6) /* 189 */,
U64_C(0x155baed099047718) /* 190 */, U64_C(0x68755e4c3d50baa6) /* 191 */,
U64_C(0xe9214e7f22d8b4df) /* 192 */, U64_C(0x2addbf532eac95f4) /* 193 */,
U64_C(0x32ae3909b4bd0109) /* 194 */, U64_C(0x834df537b08e3450) /* 195 */,
U64_C(0xfa209da84220728d) /* 196 */, U64_C(0x9e691d9b9efe23f7) /* 197 */,
U64_C(0x0446d288c4ae8d7f) /* 198 */, U64_C(0x7b4cc524e169785b) /* 199 */,
U64_C(0x21d87f0135ca1385) /* 200 */, U64_C(0xcebb400f137b8aa5) /* 201 */,
U64_C(0x272e2b66580796be) /* 202 */, U64_C(0x3612264125c2b0de) /* 203 */,
U64_C(0x057702bdad1efbb2) /* 204 */, U64_C(0xd4babb8eacf84be9) /* 205 */,
U64_C(0x91583139641bc67b) /* 206 */, U64_C(0x8bdc2de08036e024) /* 207 */,
U64_C(0x603c8156f49f68ed) /* 208 */, U64_C(0xf7d236f7dbef5111) /* 209 */,
U64_C(0x9727c4598ad21e80) /* 210 */, U64_C(0xa08a0896670a5fd7) /* 211 */,
U64_C(0xcb4a8f4309eba9cb) /* 212 */, U64_C(0x81af564b0f7036a1) /* 213 */,
U64_C(0xc0b99aa778199abd) /* 214 */, U64_C(0x959f1ec83fc8e952) /* 215 */,
U64_C(0x8c505077794a81b9) /* 216 */, U64_C(0x3acaaf8f056338f0) /* 217 */,
U64_C(0x07b43f50627a6778) /* 218 */, U64_C(0x4a44ab49f5eccc77) /* 219 */,
U64_C(0x3bc3d6e4b679ee98) /* 220 */, U64_C(0x9cc0d4d1cf14108c) /* 221 */,
U64_C(0x4406c00b206bc8a0) /* 222 */, U64_C(0x82a18854c8d72d89) /* 223 */,
U64_C(0x67e366b35c3c432c) /* 224 */, U64_C(0xb923dd61102b37f2) /* 225 */,
U64_C(0x56ab2779d884271d) /* 226 */, U64_C(0xbe83e1b0ff1525af) /* 227 */,
U64_C(0xfb7c65d4217e49a9) /* 228 */, U64_C(0x6bdbe0e76d48e7d4) /* 229 */,
U64_C(0x08df828745d9179e) /* 230 */, U64_C(0x22ea6a9add53bd34) /* 231 */,
U64_C(0xe36e141c5622200a) /* 232 */, U64_C(0x7f805d1b8cb750ee) /* 233 */,
U64_C(0xafe5c7a59f58e837) /* 234 */, U64_C(0xe27f996a4fb1c23c) /* 235 */,
U64_C(0xd3867dfb0775f0d0) /* 236 */, U64_C(0xd0e673de6e88891a) /* 237 */,
U64_C(0x123aeb9eafb86c25) /* 238 */, U64_C(0x30f1d5d5c145b895) /* 239 */,
U64_C(0xbb434a2dee7269e7) /* 240 */, U64_C(0x78cb67ecf931fa38) /* 241 */,
U64_C(0xf33b0372323bbf9c) /* 242 */, U64_C(0x52d66336fb279c74) /* 243 */,
U64_C(0x505f33ac0afb4eaa) /* 244 */, U64_C(0xe8a5cd99a2cce187) /* 245 */,
U64_C(0x534974801e2d30bb) /* 246 */, U64_C(0x8d2d5711d5876d90) /* 247 */,
U64_C(0x1f1a412891bc038e) /* 248 */, U64_C(0xd6e2e71d82e56648) /* 249 */,
U64_C(0x74036c3a497732b7) /* 250 */, U64_C(0x89b67ed96361f5ab) /* 251 */,
U64_C(0xffed95d8f1ea02a2) /* 252 */, U64_C(0xe72b3bd61464d43d) /* 253 */,
U64_C(0xa6300f170bdc4820) /* 254 */, U64_C(0xebc18760ed78a77a) /* 255 */
};
static u64 sbox2[256] = {
U64_C(0xe6a6be5a05a12138) /* 256 */, U64_C(0xb5a122a5b4f87c98) /* 257 */,
U64_C(0x563c6089140b6990) /* 258 */, U64_C(0x4c46cb2e391f5dd5) /* 259 */,
U64_C(0xd932addbc9b79434) /* 260 */, U64_C(0x08ea70e42015aff5) /* 261 */,
U64_C(0xd765a6673e478cf1) /* 262 */, U64_C(0xc4fb757eab278d99) /* 263 */,
U64_C(0xdf11c6862d6e0692) /* 264 */, U64_C(0xddeb84f10d7f3b16) /* 265 */,
U64_C(0x6f2ef604a665ea04) /* 266 */, U64_C(0x4a8e0f0ff0e0dfb3) /* 267 */,
U64_C(0xa5edeef83dbcba51) /* 268 */, U64_C(0xfc4f0a2a0ea4371e) /* 269 */,
U64_C(0xe83e1da85cb38429) /* 270 */, U64_C(0xdc8ff882ba1b1ce2) /* 271 */,
U64_C(0xcd45505e8353e80d) /* 272 */, U64_C(0x18d19a00d4db0717) /* 273 */,
U64_C(0x34a0cfeda5f38101) /* 274 */, U64_C(0x0be77e518887caf2) /* 275 */,
U64_C(0x1e341438b3c45136) /* 276 */, U64_C(0xe05797f49089ccf9) /* 277 */,
U64_C(0xffd23f9df2591d14) /* 278 */, U64_C(0x543dda228595c5cd) /* 279 */,
U64_C(0x661f81fd99052a33) /* 280 */, U64_C(0x8736e641db0f7b76) /* 281 */,
U64_C(0x15227725418e5307) /* 282 */, U64_C(0xe25f7f46162eb2fa) /* 283 */,
U64_C(0x48a8b2126c13d9fe) /* 284 */, U64_C(0xafdc541792e76eea) /* 285 */,
U64_C(0x03d912bfc6d1898f) /* 286 */, U64_C(0x31b1aafa1b83f51b) /* 287 */,
U64_C(0xf1ac2796e42ab7d9) /* 288 */, U64_C(0x40a3a7d7fcd2ebac) /* 289 */,
U64_C(0x1056136d0afbbcc5) /* 290 */, U64_C(0x7889e1dd9a6d0c85) /* 291 */,
U64_C(0xd33525782a7974aa) /* 292 */, U64_C(0xa7e25d09078ac09b) /* 293 */,
U64_C(0xbd4138b3eac6edd0) /* 294 */, U64_C(0x920abfbe71eb9e70) /* 295 */,
U64_C(0xa2a5d0f54fc2625c) /* 296 */, U64_C(0xc054e36b0b1290a3) /* 297 */,
U64_C(0xf6dd59ff62fe932b) /* 298 */, U64_C(0x3537354511a8ac7d) /* 299 */,
U64_C(0xca845e9172fadcd4) /* 300 */, U64_C(0x84f82b60329d20dc) /* 301 */,
U64_C(0x79c62ce1cd672f18) /* 302 */, U64_C(0x8b09a2add124642c) /* 303 */,
U64_C(0xd0c1e96a19d9e726) /* 304 */, U64_C(0x5a786a9b4ba9500c) /* 305 */,
U64_C(0x0e020336634c43f3) /* 306 */, U64_C(0xc17b474aeb66d822) /* 307 */,
U64_C(0x6a731ae3ec9baac2) /* 308 */, U64_C(0x8226667ae0840258) /* 309 */,
U64_C(0x67d4567691caeca5) /* 310 */, U64_C(0x1d94155c4875adb5) /* 311 */,
U64_C(0x6d00fd985b813fdf) /* 312 */, U64_C(0x51286efcb774cd06) /* 313 */,
U64_C(0x5e8834471fa744af) /* 314 */, U64_C(0xf72ca0aee761ae2e) /* 315 */,
U64_C(0xbe40e4cdaee8e09a) /* 316 */, U64_C(0xe9970bbb5118f665) /* 317 */,
U64_C(0x726e4beb33df1964) /* 318 */, U64_C(0x703b000729199762) /* 319 */,
U64_C(0x4631d816f5ef30a7) /* 320 */, U64_C(0xb880b5b51504a6be) /* 321 */,
U64_C(0x641793c37ed84b6c) /* 322 */, U64_C(0x7b21ed77f6e97d96) /* 323 */,
U64_C(0x776306312ef96b73) /* 324 */, U64_C(0xae528948e86ff3f4) /* 325 */,
U64_C(0x53dbd7f286a3f8f8) /* 326 */, U64_C(0x16cadce74cfc1063) /* 327 */,
U64_C(0x005c19bdfa52c6dd) /* 328 */, U64_C(0x68868f5d64d46ad3) /* 329 */,
U64_C(0x3a9d512ccf1e186a) /* 330 */, U64_C(0x367e62c2385660ae) /* 331 */,
U64_C(0xe359e7ea77dcb1d7) /* 332 */, U64_C(0x526c0773749abe6e) /* 333 */,
U64_C(0x735ae5f9d09f734b) /* 334 */, U64_C(0x493fc7cc8a558ba8) /* 335 */,
U64_C(0xb0b9c1533041ab45) /* 336 */, U64_C(0x321958ba470a59bd) /* 337 */,
U64_C(0x852db00b5f46c393) /* 338 */, U64_C(0x91209b2bd336b0e5) /* 339 */,
U64_C(0x6e604f7d659ef19f) /* 340 */, U64_C(0xb99a8ae2782ccb24) /* 341 */,
U64_C(0xccf52ab6c814c4c7) /* 342 */, U64_C(0x4727d9afbe11727b) /* 343 */,
U64_C(0x7e950d0c0121b34d) /* 344 */, U64_C(0x756f435670ad471f) /* 345 */,
U64_C(0xf5add442615a6849) /* 346 */, U64_C(0x4e87e09980b9957a) /* 347 */,
U64_C(0x2acfa1df50aee355) /* 348 */, U64_C(0xd898263afd2fd556) /* 349 */,
U64_C(0xc8f4924dd80c8fd6) /* 350 */, U64_C(0xcf99ca3d754a173a) /* 351 */,
U64_C(0xfe477bacaf91bf3c) /* 352 */, U64_C(0xed5371f6d690c12d) /* 353 */,
U64_C(0x831a5c285e687094) /* 354 */, U64_C(0xc5d3c90a3708a0a4) /* 355 */,
U64_C(0x0f7f903717d06580) /* 356 */, U64_C(0x19f9bb13b8fdf27f) /* 357 */,
U64_C(0xb1bd6f1b4d502843) /* 358 */, U64_C(0x1c761ba38fff4012) /* 359 */,
U64_C(0x0d1530c4e2e21f3b) /* 360 */, U64_C(0x8943ce69a7372c8a) /* 361 */,
U64_C(0xe5184e11feb5ce66) /* 362 */, U64_C(0x618bdb80bd736621) /* 363 */,
U64_C(0x7d29bad68b574d0b) /* 364 */, U64_C(0x81bb613e25e6fe5b) /* 365 */,
U64_C(0x071c9c10bc07913f) /* 366 */, U64_C(0xc7beeb7909ac2d97) /* 367 */,
U64_C(0xc3e58d353bc5d757) /* 368 */, U64_C(0xeb017892f38f61e8) /* 369 */,
U64_C(0xd4effb9c9b1cc21a) /* 370 */, U64_C(0x99727d26f494f7ab) /* 371 */,
U64_C(0xa3e063a2956b3e03) /* 372 */, U64_C(0x9d4a8b9a4aa09c30) /* 373 */,
U64_C(0x3f6ab7d500090fb4) /* 374 */, U64_C(0x9cc0f2a057268ac0) /* 375 */,
U64_C(0x3dee9d2dedbf42d1) /* 376 */, U64_C(0x330f49c87960a972) /* 377 */,
U64_C(0xc6b2720287421b41) /* 378 */, U64_C(0x0ac59ec07c00369c) /* 379 */,
U64_C(0xef4eac49cb353425) /* 380 */, U64_C(0xf450244eef0129d8) /* 381 */,
U64_C(0x8acc46e5caf4deb6) /* 382 */, U64_C(0x2ffeab63989263f7) /* 383 */,
U64_C(0x8f7cb9fe5d7a4578) /* 384 */, U64_C(0x5bd8f7644e634635) /* 385 */,
U64_C(0x427a7315bf2dc900) /* 386 */, U64_C(0x17d0c4aa2125261c) /* 387 */,
U64_C(0x3992486c93518e50) /* 388 */, U64_C(0xb4cbfee0a2d7d4c3) /* 389 */,
U64_C(0x7c75d6202c5ddd8d) /* 390 */, U64_C(0xdbc295d8e35b6c61) /* 391 */,
U64_C(0x60b369d302032b19) /* 392 */, U64_C(0xce42685fdce44132) /* 393 */,
U64_C(0x06f3ddb9ddf65610) /* 394 */, U64_C(0x8ea4d21db5e148f0) /* 395 */,
U64_C(0x20b0fce62fcd496f) /* 396 */, U64_C(0x2c1b912358b0ee31) /* 397 */,
U64_C(0xb28317b818f5a308) /* 398 */, U64_C(0xa89c1e189ca6d2cf) /* 399 */,
U64_C(0x0c6b18576aaadbc8) /* 400 */, U64_C(0xb65deaa91299fae3) /* 401 */,
U64_C(0xfb2b794b7f1027e7) /* 402 */, U64_C(0x04e4317f443b5beb) /* 403 */,
U64_C(0x4b852d325939d0a6) /* 404 */, U64_C(0xd5ae6beefb207ffc) /* 405 */,
U64_C(0x309682b281c7d374) /* 406 */, U64_C(0xbae309a194c3b475) /* 407 */,
U64_C(0x8cc3f97b13b49f05) /* 408 */, U64_C(0x98a9422ff8293967) /* 409 */,
U64_C(0x244b16b01076ff7c) /* 410 */, U64_C(0xf8bf571c663d67ee) /* 411 */,
U64_C(0x1f0d6758eee30da1) /* 412 */, U64_C(0xc9b611d97adeb9b7) /* 413 */,
U64_C(0xb7afd5887b6c57a2) /* 414 */, U64_C(0x6290ae846b984fe1) /* 415 */,
U64_C(0x94df4cdeacc1a5fd) /* 416 */, U64_C(0x058a5bd1c5483aff) /* 417 */,
U64_C(0x63166cc142ba3c37) /* 418 */, U64_C(0x8db8526eb2f76f40) /* 419 */,
U64_C(0xe10880036f0d6d4e) /* 420 */, U64_C(0x9e0523c9971d311d) /* 421 */,
U64_C(0x45ec2824cc7cd691) /* 422 */, U64_C(0x575b8359e62382c9) /* 423 */,
U64_C(0xfa9e400dc4889995) /* 424 */, U64_C(0xd1823ecb45721568) /* 425 */,
U64_C(0xdafd983b8206082f) /* 426 */, U64_C(0xaa7d29082386a8cb) /* 427 */,
U64_C(0x269fcd4403b87588) /* 428 */, U64_C(0x1b91f5f728bdd1e0) /* 429 */,
U64_C(0xe4669f39040201f6) /* 430 */, U64_C(0x7a1d7c218cf04ade) /* 431 */,
U64_C(0x65623c29d79ce5ce) /* 432 */, U64_C(0x2368449096c00bb1) /* 433 */,
U64_C(0xab9bf1879da503ba) /* 434 */, U64_C(0xbc23ecb1a458058e) /* 435 */,
U64_C(0x9a58df01bb401ecc) /* 436 */, U64_C(0xa070e868a85f143d) /* 437 */,
U64_C(0x4ff188307df2239e) /* 438 */, U64_C(0x14d565b41a641183) /* 439 */,
U64_C(0xee13337452701602) /* 440 */, U64_C(0x950e3dcf3f285e09) /* 441 */,
U64_C(0x59930254b9c80953) /* 442 */, U64_C(0x3bf299408930da6d) /* 443 */,
U64_C(0xa955943f53691387) /* 444 */, U64_C(0xa15edecaa9cb8784) /* 445 */,
U64_C(0x29142127352be9a0) /* 446 */, U64_C(0x76f0371fff4e7afb) /* 447 */,
U64_C(0x0239f450274f2228) /* 448 */, U64_C(0xbb073af01d5e868b) /* 449 */,
U64_C(0xbfc80571c10e96c1) /* 450 */, U64_C(0xd267088568222e23) /* 451 */,
U64_C(0x9671a3d48e80b5b0) /* 452 */, U64_C(0x55b5d38ae193bb81) /* 453 */,
U64_C(0x693ae2d0a18b04b8) /* 454 */, U64_C(0x5c48b4ecadd5335f) /* 455 */,
U64_C(0xfd743b194916a1ca) /* 456 */, U64_C(0x2577018134be98c4) /* 457 */,
U64_C(0xe77987e83c54a4ad) /* 458 */, U64_C(0x28e11014da33e1b9) /* 459 */,
U64_C(0x270cc59e226aa213) /* 460 */, U64_C(0x71495f756d1a5f60) /* 461 */,
U64_C(0x9be853fb60afef77) /* 462 */, U64_C(0xadc786a7f7443dbf) /* 463 */,
U64_C(0x0904456173b29a82) /* 464 */, U64_C(0x58bc7a66c232bd5e) /* 465 */,
U64_C(0xf306558c673ac8b2) /* 466 */, U64_C(0x41f639c6b6c9772a) /* 467 */,
U64_C(0x216defe99fda35da) /* 468 */, U64_C(0x11640cc71c7be615) /* 469 */,
U64_C(0x93c43694565c5527) /* 470 */, U64_C(0xea038e6246777839) /* 471 */,
U64_C(0xf9abf3ce5a3e2469) /* 472 */, U64_C(0x741e768d0fd312d2) /* 473 */,
U64_C(0x0144b883ced652c6) /* 474 */, U64_C(0xc20b5a5ba33f8552) /* 475 */,
U64_C(0x1ae69633c3435a9d) /* 476 */, U64_C(0x97a28ca4088cfdec) /* 477 */,
U64_C(0x8824a43c1e96f420) /* 478 */, U64_C(0x37612fa66eeea746) /* 479 */,
U64_C(0x6b4cb165f9cf0e5a) /* 480 */, U64_C(0x43aa1c06a0abfb4a) /* 481 */,
U64_C(0x7f4dc26ff162796b) /* 482 */, U64_C(0x6cbacc8e54ed9b0f) /* 483 */,
U64_C(0xa6b7ffefd2bb253e) /* 484 */, U64_C(0x2e25bc95b0a29d4f) /* 485 */,
U64_C(0x86d6a58bdef1388c) /* 486 */, U64_C(0xded74ac576b6f054) /* 487 */,
U64_C(0x8030bdbc2b45805d) /* 488 */, U64_C(0x3c81af70e94d9289) /* 489 */,
U64_C(0x3eff6dda9e3100db) /* 490 */, U64_C(0xb38dc39fdfcc8847) /* 491 */,
U64_C(0x123885528d17b87e) /* 492 */, U64_C(0xf2da0ed240b1b642) /* 493 */,
U64_C(0x44cefadcd54bf9a9) /* 494 */, U64_C(0x1312200e433c7ee6) /* 495 */,
U64_C(0x9ffcc84f3a78c748) /* 496 */, U64_C(0xf0cd1f72248576bb) /* 497 */,
U64_C(0xec6974053638cfe4) /* 498 */, U64_C(0x2ba7b67c0cec4e4c) /* 499 */,
U64_C(0xac2f4df3e5ce32ed) /* 500 */, U64_C(0xcb33d14326ea4c11) /* 501 */,
U64_C(0xa4e9044cc77e58bc) /* 502 */, U64_C(0x5f513293d934fcef) /* 503 */,
U64_C(0x5dc9645506e55444) /* 504 */, U64_C(0x50de418f317de40a) /* 505 */,
U64_C(0x388cb31a69dde259) /* 506 */, U64_C(0x2db4a83455820a86) /* 507 */,
U64_C(0x9010a91e84711ae9) /* 508 */, U64_C(0x4df7f0b7b1498371) /* 509 */,
U64_C(0xd62a2eabc0977179) /* 510 */, U64_C(0x22fac097aa8d5c0e) /* 511 */
};
static u64 sbox3[256] = {
U64_C(0xf49fcc2ff1daf39b) /* 512 */, U64_C(0x487fd5c66ff29281) /* 513 */,
U64_C(0xe8a30667fcdca83f) /* 514 */, U64_C(0x2c9b4be3d2fcce63) /* 515 */,
U64_C(0xda3ff74b93fbbbc2) /* 516 */, U64_C(0x2fa165d2fe70ba66) /* 517 */,
U64_C(0xa103e279970e93d4) /* 518 */, U64_C(0xbecdec77b0e45e71) /* 519 */,
U64_C(0xcfb41e723985e497) /* 520 */, U64_C(0xb70aaa025ef75017) /* 521 */,
U64_C(0xd42309f03840b8e0) /* 522 */, U64_C(0x8efc1ad035898579) /* 523 */,
U64_C(0x96c6920be2b2abc5) /* 524 */, U64_C(0x66af4163375a9172) /* 525 */,
U64_C(0x2174abdcca7127fb) /* 526 */, U64_C(0xb33ccea64a72ff41) /* 527 */,
U64_C(0xf04a4933083066a5) /* 528 */, U64_C(0x8d970acdd7289af5) /* 529 */,
U64_C(0x8f96e8e031c8c25e) /* 530 */, U64_C(0xf3fec02276875d47) /* 531 */,
U64_C(0xec7bf310056190dd) /* 532 */, U64_C(0xf5adb0aebb0f1491) /* 533 */,
U64_C(0x9b50f8850fd58892) /* 534 */, U64_C(0x4975488358b74de8) /* 535 */,
U64_C(0xa3354ff691531c61) /* 536 */, U64_C(0x0702bbe481d2c6ee) /* 537 */,
U64_C(0x89fb24057deded98) /* 538 */, U64_C(0xac3075138596e902) /* 539 */,
U64_C(0x1d2d3580172772ed) /* 540 */, U64_C(0xeb738fc28e6bc30d) /* 541 */,
U64_C(0x5854ef8f63044326) /* 542 */, U64_C(0x9e5c52325add3bbe) /* 543 */,
U64_C(0x90aa53cf325c4623) /* 544 */, U64_C(0xc1d24d51349dd067) /* 545 */,
U64_C(0x2051cfeea69ea624) /* 546 */, U64_C(0x13220f0a862e7e4f) /* 547 */,
U64_C(0xce39399404e04864) /* 548 */, U64_C(0xd9c42ca47086fcb7) /* 549 */,
U64_C(0x685ad2238a03e7cc) /* 550 */, U64_C(0x066484b2ab2ff1db) /* 551 */,
U64_C(0xfe9d5d70efbf79ec) /* 552 */, U64_C(0x5b13b9dd9c481854) /* 553 */,
U64_C(0x15f0d475ed1509ad) /* 554 */, U64_C(0x0bebcd060ec79851) /* 555 */,
U64_C(0xd58c6791183ab7f8) /* 556 */, U64_C(0xd1187c5052f3eee4) /* 557 */,
U64_C(0xc95d1192e54e82ff) /* 558 */, U64_C(0x86eea14cb9ac6ca2) /* 559 */,
U64_C(0x3485beb153677d5d) /* 560 */, U64_C(0xdd191d781f8c492a) /* 561 */,
U64_C(0xf60866baa784ebf9) /* 562 */, U64_C(0x518f643ba2d08c74) /* 563 */,
U64_C(0x8852e956e1087c22) /* 564 */, U64_C(0xa768cb8dc410ae8d) /* 565 */,
U64_C(0x38047726bfec8e1a) /* 566 */, U64_C(0xa67738b4cd3b45aa) /* 567 */,
U64_C(0xad16691cec0dde19) /* 568 */, U64_C(0xc6d4319380462e07) /* 569 */,
U64_C(0xc5a5876d0ba61938) /* 570 */, U64_C(0x16b9fa1fa58fd840) /* 571 */,
U64_C(0x188ab1173ca74f18) /* 572 */, U64_C(0xabda2f98c99c021f) /* 573 */,
U64_C(0x3e0580ab134ae816) /* 574 */, U64_C(0x5f3b05b773645abb) /* 575 */,
U64_C(0x2501a2be5575f2f6) /* 576 */, U64_C(0x1b2f74004e7e8ba9) /* 577 */,
U64_C(0x1cd7580371e8d953) /* 578 */, U64_C(0x7f6ed89562764e30) /* 579 */,
U64_C(0xb15926ff596f003d) /* 580 */, U64_C(0x9f65293da8c5d6b9) /* 581 */,
U64_C(0x6ecef04dd690f84c) /* 582 */, U64_C(0x4782275fff33af88) /* 583 */,
U64_C(0xe41433083f820801) /* 584 */, U64_C(0xfd0dfe409a1af9b5) /* 585 */,
U64_C(0x4325a3342cdb396b) /* 586 */, U64_C(0x8ae77e62b301b252) /* 587 */,
U64_C(0xc36f9e9f6655615a) /* 588 */, U64_C(0x85455a2d92d32c09) /* 589 */,
U64_C(0xf2c7dea949477485) /* 590 */, U64_C(0x63cfb4c133a39eba) /* 591 */,
U64_C(0x83b040cc6ebc5462) /* 592 */, U64_C(0x3b9454c8fdb326b0) /* 593 */,
U64_C(0x56f56a9e87ffd78c) /* 594 */, U64_C(0x2dc2940d99f42bc6) /* 595 */,
U64_C(0x98f7df096b096e2d) /* 596 */, U64_C(0x19a6e01e3ad852bf) /* 597 */,
U64_C(0x42a99ccbdbd4b40b) /* 598 */, U64_C(0xa59998af45e9c559) /* 599 */,
U64_C(0x366295e807d93186) /* 600 */, U64_C(0x6b48181bfaa1f773) /* 601 */,
U64_C(0x1fec57e2157a0a1d) /* 602 */, U64_C(0x4667446af6201ad5) /* 603 */,
U64_C(0xe615ebcacfb0f075) /* 604 */, U64_C(0xb8f31f4f68290778) /* 605 */,
U64_C(0x22713ed6ce22d11e) /* 606 */, U64_C(0x3057c1a72ec3c93b) /* 607 */,
U64_C(0xcb46acc37c3f1f2f) /* 608 */, U64_C(0xdbb893fd02aaf50e) /* 609 */,
U64_C(0x331fd92e600b9fcf) /* 610 */, U64_C(0xa498f96148ea3ad6) /* 611 */,
U64_C(0xa8d8426e8b6a83ea) /* 612 */, U64_C(0xa089b274b7735cdc) /* 613 */,
U64_C(0x87f6b3731e524a11) /* 614 */, U64_C(0x118808e5cbc96749) /* 615 */,
U64_C(0x9906e4c7b19bd394) /* 616 */, U64_C(0xafed7f7e9b24a20c) /* 617 */,
U64_C(0x6509eadeeb3644a7) /* 618 */, U64_C(0x6c1ef1d3e8ef0ede) /* 619 */,
U64_C(0xb9c97d43e9798fb4) /* 620 */, U64_C(0xa2f2d784740c28a3) /* 621 */,
U64_C(0x7b8496476197566f) /* 622 */, U64_C(0x7a5be3e6b65f069d) /* 623 */,
U64_C(0xf96330ed78be6f10) /* 624 */, U64_C(0xeee60de77a076a15) /* 625 */,
U64_C(0x2b4bee4aa08b9bd0) /* 626 */, U64_C(0x6a56a63ec7b8894e) /* 627 */,
U64_C(0x02121359ba34fef4) /* 628 */, U64_C(0x4cbf99f8283703fc) /* 629 */,
U64_C(0x398071350caf30c8) /* 630 */, U64_C(0xd0a77a89f017687a) /* 631 */,
U64_C(0xf1c1a9eb9e423569) /* 632 */, U64_C(0x8c7976282dee8199) /* 633 */,
U64_C(0x5d1737a5dd1f7abd) /* 634 */, U64_C(0x4f53433c09a9fa80) /* 635 */,
U64_C(0xfa8b0c53df7ca1d9) /* 636 */, U64_C(0x3fd9dcbc886ccb77) /* 637 */,
U64_C(0xc040917ca91b4720) /* 638 */, U64_C(0x7dd00142f9d1dcdf) /* 639 */,
U64_C(0x8476fc1d4f387b58) /* 640 */, U64_C(0x23f8e7c5f3316503) /* 641 */,
U64_C(0x032a2244e7e37339) /* 642 */, U64_C(0x5c87a5d750f5a74b) /* 643 */,
U64_C(0x082b4cc43698992e) /* 644 */, U64_C(0xdf917becb858f63c) /* 645 */,
U64_C(0x3270b8fc5bf86dda) /* 646 */, U64_C(0x10ae72bb29b5dd76) /* 647 */,
U64_C(0x576ac94e7700362b) /* 648 */, U64_C(0x1ad112dac61efb8f) /* 649 */,
U64_C(0x691bc30ec5faa427) /* 650 */, U64_C(0xff246311cc327143) /* 651 */,
U64_C(0x3142368e30e53206) /* 652 */, U64_C(0x71380e31e02ca396) /* 653 */,
U64_C(0x958d5c960aad76f1) /* 654 */, U64_C(0xf8d6f430c16da536) /* 655 */,
U64_C(0xc8ffd13f1be7e1d2) /* 656 */, U64_C(0x7578ae66004ddbe1) /* 657 */,
U64_C(0x05833f01067be646) /* 658 */, U64_C(0xbb34b5ad3bfe586d) /* 659 */,
U64_C(0x095f34c9a12b97f0) /* 660 */, U64_C(0x247ab64525d60ca8) /* 661 */,
U64_C(0xdcdbc6f3017477d1) /* 662 */, U64_C(0x4a2e14d4decad24d) /* 663 */,
U64_C(0xbdb5e6d9be0a1eeb) /* 664 */, U64_C(0x2a7e70f7794301ab) /* 665 */,
U64_C(0xdef42d8a270540fd) /* 666 */, U64_C(0x01078ec0a34c22c1) /* 667 */,
U64_C(0xe5de511af4c16387) /* 668 */, U64_C(0x7ebb3a52bd9a330a) /* 669 */,
U64_C(0x77697857aa7d6435) /* 670 */, U64_C(0x004e831603ae4c32) /* 671 */,
U64_C(0xe7a21020ad78e312) /* 672 */, U64_C(0x9d41a70c6ab420f2) /* 673 */,
U64_C(0x28e06c18ea1141e6) /* 674 */, U64_C(0xd2b28cbd984f6b28) /* 675 */,
U64_C(0x26b75f6c446e9d83) /* 676 */, U64_C(0xba47568c4d418d7f) /* 677 */,
U64_C(0xd80badbfe6183d8e) /* 678 */, U64_C(0x0e206d7f5f166044) /* 679 */,
U64_C(0xe258a43911cbca3e) /* 680 */, U64_C(0x723a1746b21dc0bc) /* 681 */,
U64_C(0xc7caa854f5d7cdd3) /* 682 */, U64_C(0x7cac32883d261d9c) /* 683 */,
U64_C(0x7690c26423ba942c) /* 684 */, U64_C(0x17e55524478042b8) /* 685 */,
U64_C(0xe0be477656a2389f) /* 686 */, U64_C(0x4d289b5e67ab2da0) /* 687 */,
U64_C(0x44862b9c8fbbfd31) /* 688 */, U64_C(0xb47cc8049d141365) /* 689 */,
U64_C(0x822c1b362b91c793) /* 690 */, U64_C(0x4eb14655fb13dfd8) /* 691 */,
U64_C(0x1ecbba0714e2a97b) /* 692 */, U64_C(0x6143459d5cde5f14) /* 693 */,
U64_C(0x53a8fbf1d5f0ac89) /* 694 */, U64_C(0x97ea04d81c5e5b00) /* 695 */,
U64_C(0x622181a8d4fdb3f3) /* 696 */, U64_C(0xe9bcd341572a1208) /* 697 */,
U64_C(0x1411258643cce58a) /* 698 */, U64_C(0x9144c5fea4c6e0a4) /* 699 */,
U64_C(0x0d33d06565cf620f) /* 700 */, U64_C(0x54a48d489f219ca1) /* 701 */,
U64_C(0xc43e5eac6d63c821) /* 702 */, U64_C(0xa9728b3a72770daf) /* 703 */,
U64_C(0xd7934e7b20df87ef) /* 704 */, U64_C(0xe35503b61a3e86e5) /* 705 */,
U64_C(0xcae321fbc819d504) /* 706 */, U64_C(0x129a50b3ac60bfa6) /* 707 */,
U64_C(0xcd5e68ea7e9fb6c3) /* 708 */, U64_C(0xb01c90199483b1c7) /* 709 */,
U64_C(0x3de93cd5c295376c) /* 710 */, U64_C(0xaed52edf2ab9ad13) /* 711 */,
U64_C(0x2e60f512c0a07884) /* 712 */, U64_C(0xbc3d86a3e36210c9) /* 713 */,
U64_C(0x35269d9b163951ce) /* 714 */, U64_C(0x0c7d6e2ad0cdb5fa) /* 715 */,
U64_C(0x59e86297d87f5733) /* 716 */, U64_C(0x298ef221898db0e7) /* 717 */,
U64_C(0x55000029d1a5aa7e) /* 718 */, U64_C(0x8bc08ae1b5061b45) /* 719 */,
U64_C(0xc2c31c2b6c92703a) /* 720 */, U64_C(0x94cc596baf25ef42) /* 721 */,
U64_C(0x0a1d73db22540456) /* 722 */, U64_C(0x04b6a0f9d9c4179a) /* 723 */,
U64_C(0xeffdafa2ae3d3c60) /* 724 */, U64_C(0xf7c8075bb49496c4) /* 725 */,
U64_C(0x9cc5c7141d1cd4e3) /* 726 */, U64_C(0x78bd1638218e5534) /* 727 */,
U64_C(0xb2f11568f850246a) /* 728 */, U64_C(0xedfabcfa9502bc29) /* 729 */,
U64_C(0x796ce5f2da23051b) /* 730 */, U64_C(0xaae128b0dc93537c) /* 731 */,
U64_C(0x3a493da0ee4b29ae) /* 732 */, U64_C(0xb5df6b2c416895d7) /* 733 */,
U64_C(0xfcabbd25122d7f37) /* 734 */, U64_C(0x70810b58105dc4b1) /* 735 */,
U64_C(0xe10fdd37f7882a90) /* 736 */, U64_C(0x524dcab5518a3f5c) /* 737 */,
U64_C(0x3c9e85878451255b) /* 738 */, U64_C(0x4029828119bd34e2) /* 739 */,
U64_C(0x74a05b6f5d3ceccb) /* 740 */, U64_C(0xb610021542e13eca) /* 741 */,
U64_C(0x0ff979d12f59e2ac) /* 742 */, U64_C(0x6037da27e4f9cc50) /* 743 */,
U64_C(0x5e92975a0df1847d) /* 744 */, U64_C(0xd66de190d3e623fe) /* 745 */,
U64_C(0x5032d6b87b568048) /* 746 */, U64_C(0x9a36b7ce8235216e) /* 747 */,
U64_C(0x80272a7a24f64b4a) /* 748 */, U64_C(0x93efed8b8c6916f7) /* 749 */,
U64_C(0x37ddbff44cce1555) /* 750 */, U64_C(0x4b95db5d4b99bd25) /* 751 */,
U64_C(0x92d3fda169812fc0) /* 752 */, U64_C(0xfb1a4a9a90660bb6) /* 753 */,
U64_C(0x730c196946a4b9b2) /* 754 */, U64_C(0x81e289aa7f49da68) /* 755 */,
U64_C(0x64669a0f83b1a05f) /* 756 */, U64_C(0x27b3ff7d9644f48b) /* 757 */,
U64_C(0xcc6b615c8db675b3) /* 758 */, U64_C(0x674f20b9bcebbe95) /* 759 */,
U64_C(0x6f31238275655982) /* 760 */, U64_C(0x5ae488713e45cf05) /* 761 */,
U64_C(0xbf619f9954c21157) /* 762 */, U64_C(0xeabac46040a8eae9) /* 763 */,
U64_C(0x454c6fe9f2c0c1cd) /* 764 */, U64_C(0x419cf6496412691c) /* 765 */,
U64_C(0xd3dc3bef265b0f70) /* 766 */, U64_C(0x6d0e60f5c3578a9e) /* 767 */
};
static u64 sbox4[256] = {
U64_C(0x5b0e608526323c55) /* 768 */, U64_C(0x1a46c1a9fa1b59f5) /* 769 */,
U64_C(0xa9e245a17c4c8ffa) /* 770 */, U64_C(0x65ca5159db2955d7) /* 771 */,
U64_C(0x05db0a76ce35afc2) /* 772 */, U64_C(0x81eac77ea9113d45) /* 773 */,
U64_C(0x528ef88ab6ac0a0d) /* 774 */, U64_C(0xa09ea253597be3ff) /* 775 */,
U64_C(0x430ddfb3ac48cd56) /* 776 */, U64_C(0xc4b3a67af45ce46f) /* 777 */,
U64_C(0x4ececfd8fbe2d05e) /* 778 */, U64_C(0x3ef56f10b39935f0) /* 779 */,
U64_C(0x0b22d6829cd619c6) /* 780 */, U64_C(0x17fd460a74df2069) /* 781 */,
U64_C(0x6cf8cc8e8510ed40) /* 782 */, U64_C(0xd6c824bf3a6ecaa7) /* 783 */,
U64_C(0x61243d581a817049) /* 784 */, U64_C(0x048bacb6bbc163a2) /* 785 */,
U64_C(0xd9a38ac27d44cc32) /* 786 */, U64_C(0x7fddff5baaf410ab) /* 787 */,
U64_C(0xad6d495aa804824b) /* 788 */, U64_C(0xe1a6a74f2d8c9f94) /* 789 */,
U64_C(0xd4f7851235dee8e3) /* 790 */, U64_C(0xfd4b7f886540d893) /* 791 */,
U64_C(0x247c20042aa4bfda) /* 792 */, U64_C(0x096ea1c517d1327c) /* 793 */,
U64_C(0xd56966b4361a6685) /* 794 */, U64_C(0x277da5c31221057d) /* 795 */,
U64_C(0x94d59893a43acff7) /* 796 */, U64_C(0x64f0c51ccdc02281) /* 797 */,
U64_C(0x3d33bcc4ff6189db) /* 798 */, U64_C(0xe005cb184ce66af1) /* 799 */,
U64_C(0xff5ccd1d1db99bea) /* 800 */, U64_C(0xb0b854a7fe42980f) /* 801 */,
U64_C(0x7bd46a6a718d4b9f) /* 802 */, U64_C(0xd10fa8cc22a5fd8c) /* 803 */,
U64_C(0xd31484952be4bd31) /* 804 */, U64_C(0xc7fa975fcb243847) /* 805 */,
U64_C(0x4886ed1e5846c407) /* 806 */, U64_C(0x28cddb791eb70b04) /* 807 */,
U64_C(0xc2b00be2f573417f) /* 808 */, U64_C(0x5c9590452180f877) /* 809 */,
U64_C(0x7a6bddfff370eb00) /* 810 */, U64_C(0xce509e38d6d9d6a4) /* 811 */,
U64_C(0xebeb0f00647fa702) /* 812 */, U64_C(0x1dcc06cf76606f06) /* 813 */,
U64_C(0xe4d9f28ba286ff0a) /* 814 */, U64_C(0xd85a305dc918c262) /* 815 */,
U64_C(0x475b1d8732225f54) /* 816 */, U64_C(0x2d4fb51668ccb5fe) /* 817 */,
U64_C(0xa679b9d9d72bba20) /* 818 */, U64_C(0x53841c0d912d43a5) /* 819 */,
U64_C(0x3b7eaa48bf12a4e8) /* 820 */, U64_C(0x781e0e47f22f1ddf) /* 821 */,
U64_C(0xeff20ce60ab50973) /* 822 */, U64_C(0x20d261d19dffb742) /* 823 */,
U64_C(0x16a12b03062a2e39) /* 824 */, U64_C(0x1960eb2239650495) /* 825 */,
U64_C(0x251c16fed50eb8b8) /* 826 */, U64_C(0x9ac0c330f826016e) /* 827 */,
U64_C(0xed152665953e7671) /* 828 */, U64_C(0x02d63194a6369570) /* 829 */,
U64_C(0x5074f08394b1c987) /* 830 */, U64_C(0x70ba598c90b25ce1) /* 831 */,
U64_C(0x794a15810b9742f6) /* 832 */, U64_C(0x0d5925e9fcaf8c6c) /* 833 */,
U64_C(0x3067716cd868744e) /* 834 */, U64_C(0x910ab077e8d7731b) /* 835 */,
U64_C(0x6a61bbdb5ac42f61) /* 836 */, U64_C(0x93513efbf0851567) /* 837 */,
U64_C(0xf494724b9e83e9d5) /* 838 */, U64_C(0xe887e1985c09648d) /* 839 */,
U64_C(0x34b1d3c675370cfd) /* 840 */, U64_C(0xdc35e433bc0d255d) /* 841 */,
U64_C(0xd0aab84234131be0) /* 842 */, U64_C(0x08042a50b48b7eaf) /* 843 */,
U64_C(0x9997c4ee44a3ab35) /* 844 */, U64_C(0x829a7b49201799d0) /* 845 */,
U64_C(0x263b8307b7c54441) /* 846 */, U64_C(0x752f95f4fd6a6ca6) /* 847 */,
U64_C(0x927217402c08c6e5) /* 848 */, U64_C(0x2a8ab754a795d9ee) /* 849 */,
U64_C(0xa442f7552f72943d) /* 850 */, U64_C(0x2c31334e19781208) /* 851 */,
U64_C(0x4fa98d7ceaee6291) /* 852 */, U64_C(0x55c3862f665db309) /* 853 */,
U64_C(0xbd0610175d53b1f3) /* 854 */, U64_C(0x46fe6cb840413f27) /* 855 */,
U64_C(0x3fe03792df0cfa59) /* 856 */, U64_C(0xcfe700372eb85e8f) /* 857 */,
U64_C(0xa7be29e7adbce118) /* 858 */, U64_C(0xe544ee5cde8431dd) /* 859 */,
U64_C(0x8a781b1b41f1873e) /* 860 */, U64_C(0xa5c94c78a0d2f0e7) /* 861 */,
U64_C(0x39412e2877b60728) /* 862 */, U64_C(0xa1265ef3afc9a62c) /* 863 */,
U64_C(0xbcc2770c6a2506c5) /* 864 */, U64_C(0x3ab66dd5dce1ce12) /* 865 */,
U64_C(0xe65499d04a675b37) /* 866 */, U64_C(0x7d8f523481bfd216) /* 867 */,
U64_C(0x0f6f64fcec15f389) /* 868 */, U64_C(0x74efbe618b5b13c8) /* 869 */,
U64_C(0xacdc82b714273e1d) /* 870 */, U64_C(0xdd40bfe003199d17) /* 871 */,
U64_C(0x37e99257e7e061f8) /* 872 */, U64_C(0xfa52626904775aaa) /* 873 */,
U64_C(0x8bbbf63a463d56f9) /* 874 */, U64_C(0xf0013f1543a26e64) /* 875 */,
U64_C(0xa8307e9f879ec898) /* 876 */, U64_C(0xcc4c27a4150177cc) /* 877 */,
U64_C(0x1b432f2cca1d3348) /* 878 */, U64_C(0xde1d1f8f9f6fa013) /* 879 */,
U64_C(0x606602a047a7ddd6) /* 880 */, U64_C(0xd237ab64cc1cb2c7) /* 881 */,
U64_C(0x9b938e7225fcd1d3) /* 882 */, U64_C(0xec4e03708e0ff476) /* 883 */,
U64_C(0xfeb2fbda3d03c12d) /* 884 */, U64_C(0xae0bced2ee43889a) /* 885 */,
U64_C(0x22cb8923ebfb4f43) /* 886 */, U64_C(0x69360d013cf7396d) /* 887 */,
U64_C(0x855e3602d2d4e022) /* 888 */, U64_C(0x073805bad01f784c) /* 889 */,
U64_C(0x33e17a133852f546) /* 890 */, U64_C(0xdf4874058ac7b638) /* 891 */,
U64_C(0xba92b29c678aa14a) /* 892 */, U64_C(0x0ce89fc76cfaadcd) /* 893 */,
U64_C(0x5f9d4e0908339e34) /* 894 */, U64_C(0xf1afe9291f5923b9) /* 895 */,
U64_C(0x6e3480f60f4a265f) /* 896 */, U64_C(0xeebf3a2ab29b841c) /* 897 */,
U64_C(0xe21938a88f91b4ad) /* 898 */, U64_C(0x57dfeff845c6d3c3) /* 899 */,
U64_C(0x2f006b0bf62caaf2) /* 900 */, U64_C(0x62f479ef6f75ee78) /* 901 */,
U64_C(0x11a55ad41c8916a9) /* 902 */, U64_C(0xf229d29084fed453) /* 903 */,
U64_C(0x42f1c27b16b000e6) /* 904 */, U64_C(0x2b1f76749823c074) /* 905 */,
U64_C(0x4b76eca3c2745360) /* 906 */, U64_C(0x8c98f463b91691bd) /* 907 */,
U64_C(0x14bcc93cf1ade66a) /* 908 */, U64_C(0x8885213e6d458397) /* 909 */,
U64_C(0x8e177df0274d4711) /* 910 */, U64_C(0xb49b73b5503f2951) /* 911 */,
U64_C(0x10168168c3f96b6b) /* 912 */, U64_C(0x0e3d963b63cab0ae) /* 913 */,
U64_C(0x8dfc4b5655a1db14) /* 914 */, U64_C(0xf789f1356e14de5c) /* 915 */,
U64_C(0x683e68af4e51dac1) /* 916 */, U64_C(0xc9a84f9d8d4b0fd9) /* 917 */,
U64_C(0x3691e03f52a0f9d1) /* 918 */, U64_C(0x5ed86e46e1878e80) /* 919 */,
U64_C(0x3c711a0e99d07150) /* 920 */, U64_C(0x5a0865b20c4e9310) /* 921 */,
U64_C(0x56fbfc1fe4f0682e) /* 922 */, U64_C(0xea8d5de3105edf9b) /* 923 */,
U64_C(0x71abfdb12379187a) /* 924 */, U64_C(0x2eb99de1bee77b9c) /* 925 */,
U64_C(0x21ecc0ea33cf4523) /* 926 */, U64_C(0x59a4d7521805c7a1) /* 927 */,
U64_C(0x3896f5eb56ae7c72) /* 928 */, U64_C(0xaa638f3db18f75dc) /* 929 */,
U64_C(0x9f39358dabe9808e) /* 930 */, U64_C(0xb7defa91c00b72ac) /* 931 */,
U64_C(0x6b5541fd62492d92) /* 932 */, U64_C(0x6dc6dee8f92e4d5b) /* 933 */,
U64_C(0x353f57abc4beea7e) /* 934 */, U64_C(0x735769d6da5690ce) /* 935 */,
U64_C(0x0a234aa642391484) /* 936 */, U64_C(0xf6f9508028f80d9d) /* 937 */,
U64_C(0xb8e319a27ab3f215) /* 938 */, U64_C(0x31ad9c1151341a4d) /* 939 */,
U64_C(0x773c22a57bef5805) /* 940 */, U64_C(0x45c7561a07968633) /* 941 */,
U64_C(0xf913da9e249dbe36) /* 942 */, U64_C(0xda652d9b78a64c68) /* 943 */,
U64_C(0x4c27a97f3bc334ef) /* 944 */, U64_C(0x76621220e66b17f4) /* 945 */,
U64_C(0x967743899acd7d0b) /* 946 */, U64_C(0xf3ee5bcae0ed6782) /* 947 */,
U64_C(0x409f753600c879fc) /* 948 */, U64_C(0x06d09a39b5926db6) /* 949 */,
U64_C(0x6f83aeb0317ac588) /* 950 */, U64_C(0x01e6ca4a86381f21) /* 951 */,
U64_C(0x66ff3462d19f3025) /* 952 */, U64_C(0x72207c24ddfd3bfb) /* 953 */,
U64_C(0x4af6b6d3e2ece2eb) /* 954 */, U64_C(0x9c994dbec7ea08de) /* 955 */,
U64_C(0x49ace597b09a8bc4) /* 956 */, U64_C(0xb38c4766cf0797ba) /* 957 */,
U64_C(0x131b9373c57c2a75) /* 958 */, U64_C(0xb1822cce61931e58) /* 959 */,
U64_C(0x9d7555b909ba1c0c) /* 960 */, U64_C(0x127fafdd937d11d2) /* 961 */,
U64_C(0x29da3badc66d92e4) /* 962 */, U64_C(0xa2c1d57154c2ecbc) /* 963 */,
U64_C(0x58c5134d82f6fe24) /* 964 */, U64_C(0x1c3ae3515b62274f) /* 965 */,
U64_C(0xe907c82e01cb8126) /* 966 */, U64_C(0xf8ed091913e37fcb) /* 967 */,
U64_C(0x3249d8f9c80046c9) /* 968 */, U64_C(0x80cf9bede388fb63) /* 969 */,
U64_C(0x1881539a116cf19e) /* 970 */, U64_C(0x5103f3f76bd52457) /* 971 */,
U64_C(0x15b7e6f5ae47f7a8) /* 972 */, U64_C(0xdbd7c6ded47e9ccf) /* 973 */,
U64_C(0x44e55c410228bb1a) /* 974 */, U64_C(0xb647d4255edb4e99) /* 975 */,
U64_C(0x5d11882bb8aafc30) /* 976 */, U64_C(0xf5098bbb29d3212a) /* 977 */,
U64_C(0x8fb5ea14e90296b3) /* 978 */, U64_C(0x677b942157dd025a) /* 979 */,
U64_C(0xfb58e7c0a390acb5) /* 980 */, U64_C(0x89d3674c83bd4a01) /* 981 */,
U64_C(0x9e2da4df4bf3b93b) /* 982 */, U64_C(0xfcc41e328cab4829) /* 983 */,
U64_C(0x03f38c96ba582c52) /* 984 */, U64_C(0xcad1bdbd7fd85db2) /* 985 */,
U64_C(0xbbb442c16082ae83) /* 986 */, U64_C(0xb95fe86ba5da9ab0) /* 987 */,
U64_C(0xb22e04673771a93f) /* 988 */, U64_C(0x845358c9493152d8) /* 989 */,
U64_C(0xbe2a488697b4541e) /* 990 */, U64_C(0x95a2dc2dd38e6966) /* 991 */,
U64_C(0xc02c11ac923c852b) /* 992 */, U64_C(0x2388b1990df2a87b) /* 993 */,
U64_C(0x7c8008fa1b4f37be) /* 994 */, U64_C(0x1f70d0c84d54e503) /* 995 */,
U64_C(0x5490adec7ece57d4) /* 996 */, U64_C(0x002b3c27d9063a3a) /* 997 */,
U64_C(0x7eaea3848030a2bf) /* 998 */, U64_C(0xc602326ded2003c0) /* 999 */,
U64_C(0x83a7287d69a94086) /* 1000 */, U64_C(0xc57a5fcb30f57a8a) /* 1001 */,
U64_C(0xb56844e479ebe779) /* 1002 */, U64_C(0xa373b40f05dcbce9) /* 1003 */,
U64_C(0xd71a786e88570ee2) /* 1004 */, U64_C(0x879cbacdbde8f6a0) /* 1005 */,
U64_C(0x976ad1bcc164a32f) /* 1006 */, U64_C(0xab21e25e9666d78b) /* 1007 */,
U64_C(0x901063aae5e5c33c) /* 1008 */, U64_C(0x9818b34448698d90) /* 1009 */,
U64_C(0xe36487ae3e1e8abb) /* 1010 */, U64_C(0xafbdf931893bdcb4) /* 1011 */,
U64_C(0x6345a0dc5fbbd519) /* 1012 */, U64_C(0x8628fe269b9465ca) /* 1013 */,
U64_C(0x1e5d01603f9c51ec) /* 1014 */, U64_C(0x4de44006a15049b7) /* 1015 */,
U64_C(0xbf6c70e5f776cbb1) /* 1016 */, U64_C(0x411218f2ef552bed) /* 1017 */,
U64_C(0xcb0c0708705a36a3) /* 1018 */, U64_C(0xe74d14754f986044) /* 1019 */,
U64_C(0xcd56d9430ea8280e) /* 1020 */, U64_C(0xc12591d7535f5065) /* 1021 */,
U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */
};
static unsigned int
transform ( void *ctx, const unsigned char *data, size_t nblks );
static void
do_init (void *context, int variant)
{
TIGER_CONTEXT *hd = context;
hd->a = 0x0123456789abcdefLL;
hd->b = 0xfedcba9876543210LL;
hd->c = 0xf096a5b4c3b2e187LL;
hd->bctx.nblocks = 0;
hd->bctx.nblocks_high = 0;
hd->bctx.count = 0;
hd->bctx.blocksize = 64;
hd->bctx.bwrite = transform;
hd->variant = variant;
}
static void
tiger_init (void *context, unsigned int flags)
{
(void)flags;
do_init (context, 0);
}
static void
tiger1_init (void *context, unsigned int flags)
{
(void)flags;
do_init (context, 1);
}
static void
tiger2_init (void *context, unsigned int flags)
{
(void)flags;
do_init (context, 2);
}
#define tiger_round(xa, xb, xc, xx, xmul) { \
xc ^= xx; \
xa -= ( sbox1[ (xc) & 0xff ] ^ sbox2[ ((xc) >> 16) & 0xff ] \
^ sbox3[ ((xc) >> 32) & 0xff ] ^ sbox4[ ((xc) >> 48) & 0xff ]); \
xb += ( sbox4[ ((xc) >> 8) & 0xff ] ^ sbox3[ ((xc) >> 24) & 0xff ] \
^ sbox2[ ((xc) >> 40) & 0xff ] ^ sbox1[ ((xc) >> 56) & 0xff ]); \
xb *= xmul; }
#define pass(ya, yb, yc, yx, ymul) { \
tiger_round( ya, yb, yc, yx[0], ymul ); \
tiger_round( yb, yc, ya, yx[1], ymul ); \
tiger_round( yc, ya, yb, yx[2], ymul ); \
tiger_round( ya, yb, yc, yx[3], ymul ); \
tiger_round( yb, yc, ya, yx[4], ymul ); \
tiger_round( yc, ya, yb, yx[5], ymul ); \
tiger_round( ya, yb, yc, yx[6], ymul ); \
tiger_round( yb, yc, ya, yx[7], ymul ); }
#define key_schedule(x) { \
x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; \
x[1] ^= x[0]; \
x[2] += x[1]; \
x[3] -= x[2] ^ ((~x[1]) << 19 ); \
x[4] ^= x[3]; \
x[5] += x[4]; \
x[6] -= x[5] ^ ((~x[4]) >> 23 ); \
x[7] ^= x[6]; \
x[0] += x[7]; \
x[1] -= x[0] ^ ((~x[7]) << 19 ); \
x[2] ^= x[1]; \
x[3] += x[2]; \
x[4] -= x[3] ^ ((~x[2]) >> 23 ); \
x[5] ^= x[4]; \
x[6] += x[5]; \
x[7] -= x[6] ^ 0x0123456789abcdefLL; }
/****************
* Transform the message DATA which consists of 512 bytes (8 words)
*/
static unsigned int
transform_blk ( void *ctx, const unsigned char *data )
{
TIGER_CONTEXT *hd = ctx;
u64 a,b,c,aa,bb,cc;
u64 x[8];
int i;
for ( i = 0; i < 8; i++ )
x[i] = buf_get_le64(data + i * 8);
/* save */
a = aa = hd->a;
b = bb = hd->b;
c = cc = hd->c;
pass( a, b, c, x, 5);
key_schedule( x );
pass( c, a, b, x, 7);
key_schedule( x );
pass( b, c, a, x, 9);
/* feedforward */
a ^= aa;
b -= bb;
c += cc;
/* store */
hd->a = a;
hd->b = b;
hd->c = c;
return /*burn_stack*/ 21*8+11*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;
}
/* The routine terminates the computation
*/
static void
tiger_final( void *context )
{
TIGER_CONTEXT *hd = context;
u32 t, th, msb, lsb;
byte *p;
unsigned int burn;
byte pad = hd->variant == 2? 0x80 : 0x01;
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++] = pad;
if (hd->bctx.count < 56)
memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
hd->bctx.count = 56;
/* 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 */
/* fill pad and next block with zeroes */
memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
hd->bctx.count = 64 + 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 );
}
p = hd->bctx.buf;
#define X(a) do { buf_put_be64(p, hd->a); p += 8; } while(0)
#define Y(a) do { buf_put_le64(p, hd->a); p += 8; } while(0)
if (hd->variant == 0)
{
X(a);
X(b);
X(c);
}
else
{
Y(a);
Y(b);
Y(c);
}
#undef X
#undef Y
_gcry_burn_stack (burn);
}
static byte *
tiger_read( void *context )
{
TIGER_CONTEXT *hd = context;
return hd->bctx.buf;
}
/* 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 =
{
GCRY_MD_TIGER, {0, 0},
"TIGER192", NULL, 0, NULL, 24,
tiger_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
NULL, NULL,
sizeof (TIGER_CONTEXT)
};
/* This is the fixed TIGER implementation. */
static 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[] =
{
/* GNU.digestAlgorithm TIGER */
{ "1.3.6.1.4.1.11591.12.2" },
{ NULL }
};
gcry_md_spec_t _gcry_digest_spec_tiger1 =
{
GCRY_MD_TIGER1, {0, 0},
"TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24,
tiger1_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
NULL, NULL,
sizeof (TIGER_CONTEXT)
};
/* This is TIGER2 which usues a changed padding algorithm. */
gcry_md_spec_t _gcry_digest_spec_tiger2 =
{
GCRY_MD_TIGER2, {0, 0},
"TIGER2", NULL, 0, NULL, 24,
tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
NULL, NULL,
sizeof (TIGER_CONTEXT)
};
diff --git a/cipher/twofish-aarch64.S b/cipher/twofish-aarch64.S
index 9f35b5cd..585151f0 100644
--- a/cipher/twofish-aarch64.S
+++ b/cipher/twofish-aarch64.S
@@ -1,321 +1,321 @@
/* twofish-aarch64.S - ARMv8/AArch64 assembly implementation of Twofish cipher
*
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include "asm-common-aarch64.h"
#if defined(__AARCH64EL__)
#ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
.text
/* structure of TWOFISH_context: */
#define s0 0
#define s1 ((s0) + 4 * 256)
#define s2 ((s1) + 4 * 256)
#define s3 ((s2) + 4 * 256)
#define w ((s3) + 4 * 256)
#define k ((w) + 4 * 8)
/* register macros */
#define CTX x0
#define RDST x1
#define RSRC x2
#define CTXs0 CTX
#define CTXs1 x3
#define CTXs2 x4
#define CTXs3 x5
#define CTXw x17
#define RA w6
#define RB w7
#define RC w8
#define RD w9
#define RX w10
#define RY w11
#define xRX x10
#define xRY x11
#define RMASK w12
#define RT0 w13
#define RT1 w14
#define RT2 w15
#define RT3 w16
#define xRT0 x13
#define xRT1 x14
#define xRT2 x15
#define xRT3 x16
/* helper macros */
#ifndef __AARCH64EL__
/* bswap on big-endian */
#define host_to_le(reg) \
rev reg, reg;
#define le_to_host(reg) \
rev reg, reg;
#else
/* nop on little-endian */
#define host_to_le(reg) /*_*/
#define le_to_host(reg) /*_*/
#endif
#define ldr_input_aligned_le(rin, a, b, c, d) \
ldr a, [rin, #0]; \
ldr b, [rin, #4]; \
le_to_host(a); \
ldr c, [rin, #8]; \
le_to_host(b); \
ldr d, [rin, #12]; \
le_to_host(c); \
le_to_host(d);
#define str_output_aligned_le(rout, a, b, c, d) \
le_to_host(a); \
le_to_host(b); \
str a, [rout, #0]; \
le_to_host(c); \
str b, [rout, #4]; \
le_to_host(d); \
str c, [rout, #8]; \
str d, [rout, #12];
/* unaligned word reads/writes allowed */
#define ldr_input_le(rin, ra, rb, rc, rd, rtmp) \
ldr_input_aligned_le(rin, ra, rb, rc, rd)
#define str_output_le(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
str_output_aligned_le(rout, ra, rb, rc, rd)
/**********************************************************************
1-way twofish
**********************************************************************/
#define encrypt_round(a, b, rc, rd, n, ror_a, adj_a) \
and RT0, RMASK, b, lsr#(8 - 2); \
and RY, RMASK, b, lsr#(16 - 2); \
and RT1, RMASK, b, lsr#(24 - 2); \
ldr RY, [CTXs3, xRY]; \
and RT2, RMASK, b, lsl#(2); \
ldr RT0, [CTXs2, xRT0]; \
and RT3, RMASK, a, lsr#(16 - 2 + (adj_a)); \
ldr RT1, [CTXs0, xRT1]; \
and RX, RMASK, a, lsr#(8 - 2 + (adj_a)); \
ldr RT2, [CTXs1, xRT2]; \
ldr RX, [CTXs1, xRX]; \
ror_a(a); \
\
eor RY, RY, RT0; \
ldr RT3, [CTXs2, xRT3]; \
and RT0, RMASK, a, lsl#(2); \
eor RY, RY, RT1; \
and RT1, RMASK, a, lsr#(24 - 2); \
eor RY, RY, RT2; \
ldr RT0, [CTXs0, xRT0]; \
eor RX, RX, RT3; \
ldr RT1, [CTXs3, xRT1]; \
eor RX, RX, RT0; \
\
ldr RT3, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
eor RX, RX, RT1; \
ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
\
add RT0, RX, RY, lsl #1; \
add RX, RX, RY; \
add RT0, RT0, RT3; \
add RX, RX, RT2; \
eor rd, RT0, rd, ror #31; \
eor rc, rc, RX;
#define dummy(x) /*_*/
#define ror1(r) \
ror r, r, #1;
#define decrypt_round(a, b, rc, rd, n, ror_b, adj_b) \
and RT3, RMASK, b, lsl#(2 - (adj_b)); \
and RT1, RMASK, b, lsr#(8 - 2 + (adj_b)); \
ror_b(b); \
and RT2, RMASK, a, lsl#(2); \
and RT0, RMASK, a, lsr#(8 - 2); \
\
ldr RY, [CTXs1, xRT3]; \
ldr RX, [CTXs0, xRT2]; \
and RT3, RMASK, b, lsr#(16 - 2); \
ldr RT1, [CTXs2, xRT1]; \
and RT2, RMASK, a, lsr#(16 - 2); \
ldr RT0, [CTXs1, xRT0]; \
\
ldr RT3, [CTXs3, xRT3]; \
eor RY, RY, RT1; \
\
and RT1, RMASK, b, lsr#(24 - 2); \
eor RX, RX, RT0; \
ldr RT2, [CTXs2, xRT2]; \
and RT0, RMASK, a, lsr#(24 - 2); \
\
ldr RT1, [CTXs0, xRT1]; \
\
eor RY, RY, RT3; \
ldr RT0, [CTXs3, xRT0]; \
eor RX, RX, RT2; \
eor RY, RY, RT1; \
\
ldr RT1, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
eor RX, RX, RT0; \
ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
\
add RT0, RX, RY, lsl #1; \
add RX, RX, RY; \
add RT0, RT0, RT1; \
add RX, RX, RT2; \
eor rd, rd, RT0; \
eor rc, RX, rc, ror #31;
#define first_encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, dummy, 0); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
#define encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
#define last_encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
ror1(RA);
#define first_decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, dummy, 0); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
#define decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
#define last_decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
ror1(RD);
.globl _gcry_twofish_arm_encrypt_block
ELF(.type _gcry_twofish_arm_encrypt_block,%function;)
_gcry_twofish_arm_encrypt_block:
/* input:
* x0: ctx
* x1: dst
* x2: src
*/
CFI_STARTPROC();
add CTXw, CTX, #(w);
ldr_input_le(RSRC, RA, RB, RC, RD, RT0);
/* Input whitening */
ldp RT0, RT1, [CTXw, #(0*8)];
ldp RT2, RT3, [CTXw, #(1*8)];
add CTXs3, CTX, #(s3);
add CTXs2, CTX, #(s2);
add CTXs1, CTX, #(s1);
mov RMASK, #(0xff << 2);
eor RA, RA, RT0;
eor RB, RB, RT1;
eor RC, RC, RT2;
eor RD, RD, RT3;
first_encrypt_cycle(0);
encrypt_cycle(1);
encrypt_cycle(2);
encrypt_cycle(3);
encrypt_cycle(4);
encrypt_cycle(5);
encrypt_cycle(6);
last_encrypt_cycle(7);
/* Output whitening */
ldp RT0, RT1, [CTXw, #(2*8)];
ldp RT2, RT3, [CTXw, #(3*8)];
eor RC, RC, RT0;
eor RD, RD, RT1;
eor RA, RA, RT2;
eor RB, RB, RT3;
str_output_le(RDST, RC, RD, RA, RB, RT0, RT1);
ret;
CFI_ENDPROC();
.ltorg
ELF(.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block;)
.globl _gcry_twofish_arm_decrypt_block
ELF(.type _gcry_twofish_arm_decrypt_block,%function;)
_gcry_twofish_arm_decrypt_block:
/* input:
* %r0: ctx
* %r1: dst
* %r2: src
*/
CFI_STARTPROC();
add CTXw, CTX, #(w);
ldr_input_le(RSRC, RC, RD, RA, RB, RT0);
/* Input whitening */
ldp RT0, RT1, [CTXw, #(2*8)];
ldp RT2, RT3, [CTXw, #(3*8)];
add CTXs3, CTX, #(s3);
add CTXs2, CTX, #(s2);
add CTXs1, CTX, #(s1);
mov RMASK, #(0xff << 2);
eor RC, RC, RT0;
eor RD, RD, RT1;
eor RA, RA, RT2;
eor RB, RB, RT3;
first_decrypt_cycle(7);
decrypt_cycle(6);
decrypt_cycle(5);
decrypt_cycle(4);
decrypt_cycle(3);
decrypt_cycle(2);
decrypt_cycle(1);
last_decrypt_cycle(0);
/* Output whitening */
ldp RT0, RT1, [CTXw, #(0*8)];
ldp RT2, RT3, [CTXw, #(1*8)];
eor RA, RA, RT0;
eor RB, RB, RT1;
eor RC, RC, RT2;
eor RD, RD, RT3;
str_output_le(RDST, RA, RB, RC, RD, RT0, RT1);
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block;)
#endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
#endif /*__AARCH64EL__*/
diff --git a/cipher/twofish-amd64.S b/cipher/twofish-amd64.S
index 3cb73431..f61e79c9 100644
--- a/cipher/twofish-amd64.S
+++ b/cipher/twofish-amd64.S
@@ -1,1184 +1,1184 @@
/* twofish-amd64.S - AMD64 assembly implementation of Twofish cipher
*
* Copyright (C) 2013-2015 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/>.
+ * License along with this program; if not, see <https://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(USE_TWOFISH)
#include "asm-common-amd64.h"
.text
/* structure of TWOFISH_context: */
#define s0 0
#define s1 ((s0) + 4 * 256)
#define s2 ((s1) + 4 * 256)
#define s3 ((s2) + 4 * 256)
#define w ((s3) + 4 * 256)
#define k ((w) + 4 * 8)
/* register macros */
#define CTX %rdi
#define RA %rax
#define RB %rbx
#define RC %rcx
#define RD %rdx
#define RAd %eax
#define RBd %ebx
#define RCd %ecx
#define RDd %edx
#define RAbl %al
#define RBbl %bl
#define RCbl %cl
#define RDbl %dl
#define RAbh %ah
#define RBbh %bh
#define RCbh %ch
#define RDbh %dh
#define RX %r8
#define RY %r9
#define RXd %r8d
#define RYd %r9d
#define RT0 %rsi
#define RT1 %rbp
#define RT2 %r10
#define RT3 %r11
#define RT0d %esi
#define RT1d %ebp
#define RT2d %r10d
#define RT3d %r11d
/***********************************************************************
* AMD64 assembly implementation of the Twofish cipher
***********************************************************************/
#define enc_g1_2(a, b, x, y) \
movzbl b ## bl, RT3d; \
movzbl b ## bh, RT1d; \
movzbl a ## bl, RT2d; \
movzbl a ## bh, RT0d; \
rorl $16, b ## d; \
rorl $16, a ## d; \
movl s1(CTX, RT3, 4), RYd; \
movzbl b ## bl, RT3d; \
movl s0(CTX, RT2, 4), RXd; \
movzbl a ## bl, RT2d; \
xorl s2(CTX, RT1, 4), RYd; \
movzbl b ## bh, RT1d; \
xorl s1(CTX, RT0, 4), RXd; \
movzbl a ## bh, RT0d; \
rorl $16, b ## d; \
rorl $16, a ## d; \
xorl s3(CTX, RT3, 4), RYd; \
xorl s2(CTX, RT2, 4), RXd; \
xorl s0(CTX, RT1, 4), RYd; \
xorl s3(CTX, RT0, 4), RXd;
#define dec_g1_2(a, b, x, y) \
movzbl a ## bl, RT2d; \
movzbl a ## bh, RT0d; \
movzbl b ## bl, RT3d; \
movzbl b ## bh, RT1d; \
rorl $16, a ## d; \
rorl $16, b ## d; \
movl s0(CTX, RT2, 4), RXd; \
movzbl a ## bl, RT2d; \
movl s1(CTX, RT3, 4), RYd; \
movzbl b ## bl, RT3d; \
xorl s1(CTX, RT0, 4), RXd; \
movzbl a ## bh, RT0d; \
xorl s2(CTX, RT1, 4), RYd; \
movzbl b ## bh, RT1d; \
rorl $16, a ## d; \
rorl $16, b ## d; \
xorl s2(CTX, RT2, 4), RXd; \
xorl s3(CTX, RT3, 4), RYd; \
xorl s3(CTX, RT0, 4), RXd; \
xorl s0(CTX, RT1, 4), RYd;
#define encrypt_round(ra, rb, rc, rd, n) \
enc_g1_2(##ra, ##rb, RX, RY); \
\
leal (RXd, RYd, 2), RT0d; \
addl RYd, RXd; \
addl (k + 8 * (n) + 4)(CTX), RT0d; \
roll $1, rd ## d; \
addl (k + 8 * (n))(CTX), RXd; \
xorl RT0d, rd ## d; \
xorl RXd, rc ## d; \
rorl $1, rc ## d;
#define decrypt_round(ra, rb, rc, rd, n) \
dec_g1_2(##ra, ##rb, RX, RY); \
\
leal (RXd, RYd, 2), RT0d; \
addl RYd, RXd; \
addl (k + 8 * (n) + 4)(CTX), RT0d; \
roll $1, rc ## d; \
addl (k + 8 * (n))(CTX), RXd; \
xorl RXd, rc ## d; \
xorl RT0d, rd ## d; \
rorl $1, rd ## d;
#define encrypt_cycle(a, b, c, d, nc) \
encrypt_round(##a, ##b, ##c, ##d, (nc) * 2); \
encrypt_round(##c, ##d, ##a, ##b, (nc) * 2 + 1);
#define decrypt_cycle(a, b, c, d, nc) \
decrypt_round(##c, ##d, ##a, ##b, (nc) * 2 + 1); \
decrypt_round(##a, ##b, ##c, ##d, (nc) * 2);
#define inpack(in, n, x, m) \
movl (4 * (n))(in), x; \
xorl (w + 4 * (m))(CTX), x;
#define outunpack(out, n, x, m) \
xorl (w + 4 * (m))(CTX), x; \
movl x, (4 * (n))(out);
.align 8
.globl _gcry_twofish_amd64_encrypt_block
ELF(.type _gcry_twofish_amd64_encrypt_block,@function;)
_gcry_twofish_amd64_encrypt_block:
/* input:
* %rdi: context, CTX
* %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);
inpack(RX, 1, RBd, 1);
inpack(RX, 2, RCd, 2);
inpack(RX, 3, RDd, 3);
encrypt_cycle(RA, RB, RC, RD, 0);
encrypt_cycle(RA, RB, RC, RD, 1);
encrypt_cycle(RA, RB, RC, RD, 2);
encrypt_cycle(RA, RB, RC, RD, 3);
encrypt_cycle(RA, RB, RC, RD, 4);
encrypt_cycle(RA, RB, RC, RD, 5);
encrypt_cycle(RA, RB, RC, RD, 6);
encrypt_cycle(RA, RB, RC, RD, 7);
movq (0 * 8)(%rsp), RX; /*dst*/
outunpack(RX, 0, RCd, 4);
outunpack(RX, 1, RDd, 5);
outunpack(RX, 2, RAd, 6);
outunpack(RX, 3, RBd, 7);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
.align 8
.globl _gcry_twofish_amd64_decrypt_block
ELF(.type _gcry_twofish_amd64_decrypt_block,@function;)
_gcry_twofish_amd64_decrypt_block:
/* input:
* %rdi: context, CTX
* %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);
inpack(RX, 1, RDd, 5);
inpack(RX, 2, RAd, 6);
inpack(RX, 3, RBd, 7);
decrypt_cycle(RA, RB, RC, RD, 7);
decrypt_cycle(RA, RB, RC, RD, 6);
decrypt_cycle(RA, RB, RC, RD, 5);
decrypt_cycle(RA, RB, RC, RD, 4);
decrypt_cycle(RA, RB, RC, RD, 3);
decrypt_cycle(RA, RB, RC, RD, 2);
decrypt_cycle(RA, RB, RC, RD, 1);
decrypt_cycle(RA, RB, RC, RD, 0);
movq (0 * 8)(%rsp), RX; /*dst*/
outunpack(RX, 0, RAd, 0);
outunpack(RX, 1, RBd, 1);
outunpack(RX, 2, RCd, 2);
outunpack(RX, 3, RDd, 3);
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
#undef CTX
#undef RA
#undef RB
#undef RC
#undef RD
#undef RAd
#undef RBd
#undef RCd
#undef RDd
#undef RAbl
#undef RBbl
#undef RCbl
#undef RDbl
#undef RAbh
#undef RBbh
#undef RCbh
#undef RDbh
#undef RX
#undef RY
#undef RXd
#undef RYd
#undef RT0
#undef RT1
#undef RT2
#undef RT3
#undef RT0d
#undef RT1d
#undef RT2d
#undef RT3d
/***********************************************************************
* AMD64 assembly implementation of the Twofish cipher, 3-way parallel
***********************************************************************/
#define CTX %rdi
#define RIO %rdx
#define RAB0 %rax
#define RAB1 %rbx
#define RAB2 %rcx
#define RAB0d %eax
#define RAB1d %ebx
#define RAB2d %ecx
#define RAB0bh %ah
#define RAB1bh %bh
#define RAB2bh %ch
#define RAB0bl %al
#define RAB1bl %bl
#define RAB2bl %cl
#define RCD0 %r8
#define RCD1 %r9
#define RCD2 %r10
#define RCD0d %r8d
#define RCD1d %r9d
#define RCD2d %r10d
#define RX0 %rbp
#define RX1 %r11
#define RX2 %r12
#define RX0d %ebp
#define RX1d %r11d
#define RX2d %r12d
#define RY0 %r13
#define RY1 %r14
#define RY2 %r15
#define RY0d %r13d
#define RY1d %r14d
#define RY2d %r15d
#define RT0 %rdx
#define RT1 %rsi
#define RT0d %edx
#define RT1d %esi
#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
movzbl ab ## bl, tmp2 ## d; \
movzbl ab ## bh, tmp1 ## d; \
rorq $(rot), ab; \
op1##l T0(CTX, tmp2, 4), dst ## d; \
op2##l T1(CTX, tmp1, 4), dst ## d;
/*
* Combined G1 & G2 function. Reordered with help of rotates to have moves
* at beginning.
*/
#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
/* G1,1 && G2,1 */ \
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
\
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
\
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
\
/* 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); \
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); \
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); \
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; \
addl x ## d, y ## d; \
addl k+4*(2*(n))(CTX), x ## d; \
xorl ab ## d, x ## d; \
addl k+4*(2*(n)+1)(CTX), y ## d; \
shrq $32, ab; \
roll $1, ab ## d; \
xorl y ## d, ab ## d; \
shlq $32, ab; \
rorl $1, x ## d; \
orq x, ab;
#define dec_round_end(ba, x, y, n) \
addl y ## d, x ## d; \
addl x ## d, y ## d; \
addl k+4*(2*(n))(CTX), x ## d; \
addl k+4*(2*(n)+1)(CTX), y ## d; \
xorl ba ## d, y ## d; \
shrq $32, ba; \
roll $1, ba ## d; \
xorl x ## d, ba ## d; \
shlq $32, ba; \
rorl $1, y ## d; \
orq y, ba;
#define encrypt_round3(ab, cd, n) \
g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
\
enc_round_end(ab ## 0, RX0, RY0, n); \
enc_round_end(ab ## 1, RX1, RY1, n); \
enc_round_end(ab ## 2, RX2, RY2, n);
#define decrypt_round3(ba, dc, n) \
g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
\
dec_round_end(ba ## 0, RX0, RY0, n); \
dec_round_end(ba ## 1, RX1, RY1, n); \
dec_round_end(ba ## 2, RX2, RY2, n);
#define encrypt_cycle3(ab, cd, n) \
encrypt_round3(ab, cd, n*2); \
encrypt_round3(ab, cd, (n*2)+1);
#define decrypt_cycle3(ba, dc, n) \
decrypt_round3(ba, dc, (n*2)+1); \
decrypt_round3(ba, dc, (n*2));
#define inpack3(xy, m) \
xorq w+4*m(CTX), xy ## 0; \
xorq w+4*m(CTX), xy ## 1; \
xorq w+4*m(CTX), xy ## 2;
#define outunpack3(xy, m) \
xorq w+4*m(CTX), xy ## 0; \
xorq w+4*m(CTX), xy ## 1; \
xorq w+4*m(CTX), xy ## 2;
#define inpack_enc3() \
inpack3(RAB, 0); \
inpack3(RCD, 2);
#define outunpack_enc3() \
outunpack3(RAB, 6); \
outunpack3(RCD, 4);
#define inpack_dec3() \
inpack3(RAB, 4); \
rorq $32, RAB0; \
rorq $32, RAB1; \
rorq $32, RAB2; \
inpack3(RCD, 6); \
rorq $32, RCD0; \
rorq $32, RCD1; \
rorq $32, RCD2;
#define outunpack_dec3() \
rorq $32, RCD0; \
rorq $32, RCD1; \
rorq $32, RCD2; \
outunpack3(RCD, 0); \
rorq $32, RAB0; \
rorq $32, RAB1; \
rorq $32, RAB2; \
outunpack3(RAB, 2);
.align 8
ELF(.type __twofish_enc_blk3,@function;)
__twofish_enc_blk3:
/* input:
* %rdi: ctx, CTX
* RAB0,RCD0,RAB1,RCD1,RAB2,RCD2: three plaintext blocks
* output:
* RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three ciphertext blocks
*/
CFI_STARTPROC();
inpack_enc3();
encrypt_cycle3(RAB, RCD, 0);
encrypt_cycle3(RAB, RCD, 1);
encrypt_cycle3(RAB, RCD, 2);
encrypt_cycle3(RAB, RCD, 3);
encrypt_cycle3(RAB, RCD, 4);
encrypt_cycle3(RAB, RCD, 5);
encrypt_cycle3(RAB, RCD, 6);
encrypt_cycle3(RAB, RCD, 7);
outunpack_enc3();
ret;
CFI_ENDPROC();
ELF(.size __twofish_enc_blk3,.-__twofish_enc_blk3;)
.align 8
ELF(.type __twofish_dec_blk3,@function;)
__twofish_dec_blk3:
/* input:
* %rdi: ctx, CTX
* RAB0,RCD0,RAB1,RCD1,RAB2,RCD2: three ciphertext blocks
* output:
* RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three plaintext blocks
*/
CFI_STARTPROC();
inpack_dec3();
decrypt_cycle3(RAB, RCD, 7);
decrypt_cycle3(RAB, RCD, 6);
decrypt_cycle3(RAB, RCD, 5);
decrypt_cycle3(RAB, RCD, 4);
decrypt_cycle3(RAB, RCD, 3);
decrypt_cycle3(RAB, RCD, 2);
decrypt_cycle3(RAB, RCD, 1);
decrypt_cycle3(RAB, RCD, 0);
outunpack_dec3();
ret;
CFI_ENDPROC();
ELF(.size __twofish_dec_blk3,.-__twofish_dec_blk3;)
.align 8
.globl _gcry_twofish_amd64_ctr_enc
ELF(.type _gcry_twofish_amd64_ctr_enc,@function;)
_gcry_twofish_amd64_ctr_enc:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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);
movq %rcx, RX0;
/* load IV and byteswap */
movq 8(RX0), RT0;
movq 0(RX0), RT1;
movq RT0, RCD0;
movq RT1, RAB0;
bswapq RT0;
bswapq RT1;
/* construct IVs */
movq RT0, RCD1;
movq RT1, RAB1;
movq RT0, RCD2;
movq RT1, RAB2;
addq $1, RCD1;
adcq $0, RAB1;
bswapq RCD1;
bswapq RAB1;
addq $2, RCD2;
adcq $0, RAB2;
bswapq RCD2;
bswapq RAB2;
addq $3, RT0;
adcq $0, RT1;
bswapq RT0;
bswapq RT1;
/* store new IV */
movq RT0, 8(RX0);
movq RT1, 0(RX0);
call __twofish_enc_blk3;
movq (7 * 8)(%rsp), RX0; /*src*/
movq (6 * 8)(%rsp), RX1; /*dst*/
/* XOR key-stream with plaintext */
xorq (0 * 8)(RX0), RCD0;
xorq (1 * 8)(RX0), RAB0;
xorq (2 * 8)(RX0), RCD1;
xorq (3 * 8)(RX0), RAB1;
xorq (4 * 8)(RX0), RCD2;
xorq (5 * 8)(RX0), RAB2;
movq RCD0, (0 * 8)(RX1);
movq RAB0, (1 * 8)(RX1);
movq RCD1, (2 * 8)(RX1);
movq RAB1, (3 * 8)(RX1);
movq RCD2, (4 * 8)(RX1);
movq RAB2, (5 * 8)(RX1);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_ctr_enc,.-_gcry_twofish_amd64_ctr_enc;)
.align 8
.globl _gcry_twofish_amd64_cbc_dec
ELF(.type _gcry_twofish_amd64_cbc_dec,@function;)
_gcry_twofish_amd64_cbc_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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);
movq %rcx, (8 * 8)(%rsp);
movq %rdx, RX0;
/* load input */
movq (0 * 8)(RX0), RAB0;
movq (1 * 8)(RX0), RCD0;
movq (2 * 8)(RX0), RAB1;
movq (3 * 8)(RX0), RCD1;
movq (4 * 8)(RX0), RAB2;
movq (5 * 8)(RX0), RCD2;
call __twofish_dec_blk3;
movq (8 * 8)(%rsp), RT0; /*iv*/
movq (7 * 8)(%rsp), RX0; /*src*/
movq (6 * 8)(%rsp), RX1; /*dst*/
movq (4 * 8)(RX0), RY0;
movq (5 * 8)(RX0), RY1;
xorq (0 * 8)(RT0), RCD0;
xorq (1 * 8)(RT0), RAB0;
xorq (0 * 8)(RX0), RCD1;
xorq (1 * 8)(RX0), RAB1;
xorq (2 * 8)(RX0), RCD2;
xorq (3 * 8)(RX0), RAB2;
movq RY0, (0 * 8)(RT0);
movq RY1, (1 * 8)(RT0);
movq RCD0, (0 * 8)(RX1);
movq RAB0, (1 * 8)(RX1);
movq RCD1, (2 * 8)(RX1);
movq RAB1, (3 * 8)(RX1);
movq RCD2, (4 * 8)(RX1);
movq RAB2, (5 * 8)(RX1);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_cbc_dec,.-_gcry_twofish_amd64_cbc_dec;)
.align 8
.globl _gcry_twofish_amd64_cfb_dec
ELF(.type _gcry_twofish_amd64_cfb_dec,@function;)
_gcry_twofish_amd64_cfb_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %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);
movq %rdx, RX0;
movq %rcx, RX1;
/* load input */
movq (0 * 8)(RX1), RAB0;
movq (1 * 8)(RX1), RCD0;
movq (0 * 8)(RX0), RAB1;
movq (1 * 8)(RX0), RCD1;
movq (2 * 8)(RX0), RAB2;
movq (3 * 8)(RX0), RCD2;
/* Update IV */
movq (4 * 8)(RX0), RY0;
movq (5 * 8)(RX0), RY1;
movq RY0, (0 * 8)(RX1);
movq RY1, (1 * 8)(RX1);
call __twofish_enc_blk3;
movq (7 * 8)(%rsp), RX0; /*src*/
movq (6 * 8)(%rsp), RX1; /*dst*/
xorq (0 * 8)(RX0), RCD0;
xorq (1 * 8)(RX0), RAB0;
xorq (2 * 8)(RX0), RCD1;
xorq (3 * 8)(RX0), RAB1;
xorq (4 * 8)(RX0), RCD2;
xorq (5 * 8)(RX0), RAB2;
movq RCD0, (0 * 8)(RX1);
movq RAB0, (1 * 8)(RX1);
movq RCD1, (2 * 8)(RX1);
movq RAB1, (3 * 8)(RX1);
movq RCD2, (4 * 8)(RX1);
movq RAB2, (5 * 8)(RX1);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_cfb_dec,.-_gcry_twofish_amd64_cfb_dec;)
.align 8
.globl _gcry_twofish_amd64_ocb_enc
ELF(.type _gcry_twofish_amd64_ocb_enc,@function;)
_gcry_twofish_amd64_ocb_enc:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %rdx: src (3 blocks)
* %rcx: offset
* %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;
movq %rcx, RX1;
movq %r8, RX2;
movq %r9, RY0;
movq %rsi, RY1;
/* Load offset */
movq (0 * 8)(RX1), RT0;
movq (1 * 8)(RX1), RT1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq (RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (0 * 8)(RX0), RAB0;
movq (1 * 8)(RX0), RCD0;
/* Store Offset_i */
movq RT0, (0 * 8)(RY1);
movq RT1, (1 * 8)(RY1);
/* Checksum_i = Checksum_{i-1} xor P_i */
xor RAB0, (0 * 8)(RX2);
xor RCD0, (1 * 8)(RX2);
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB0;
xorq RT1, RCD0;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 8(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (2 * 8)(RX0), RAB1;
movq (3 * 8)(RX0), RCD1;
/* Store Offset_i */
movq RT0, (2 * 8)(RY1);
movq RT1, (3 * 8)(RY1);
/* Checksum_i = Checksum_{i-1} xor P_i */
xor RAB1, (0 * 8)(RX2);
xor RCD1, (1 * 8)(RX2);
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB1;
xorq RT1, RCD1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 16(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (4 * 8)(RX0), RAB2;
movq (5 * 8)(RX0), RCD2;
/* Store Offset_i */
movq RT0, (4 * 8)(RY1);
movq RT1, (5 * 8)(RY1);
/* Checksum_i = Checksum_{i-1} xor P_i */
xor RAB2, (0 * 8)(RX2);
xor RCD2, (1 * 8)(RX2);
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB2;
xorq RT1, RCD2;
/* Store offset */
movq RT0, (0 * 8)(RX1);
movq RT1, (1 * 8)(RX1);
/* CX_i = ENCIPHER(K, PX_i) */
call __twofish_enc_blk3;
movq (6 * 8)(%rsp), RX1; /*dst*/
/* C_i = CX_i xor Offset_i */
xorq RCD0, (0 * 8)(RX1);
xorq RAB0, (1 * 8)(RX1);
xorq RCD1, (2 * 8)(RX1);
xorq RAB1, (3 * 8)(RX1);
xorq RCD2, (4 * 8)(RX1);
xorq RAB2, (5 * 8)(RX1);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_ocb_enc,.-_gcry_twofish_amd64_ocb_enc;)
.align 8
.globl _gcry_twofish_amd64_ocb_dec
ELF(.type _gcry_twofish_amd64_ocb_dec,@function;)
_gcry_twofish_amd64_ocb_dec:
/* input:
* %rdi: ctx, CTX
* %rsi: dst (3 blocks)
* %rdx: src (3 blocks)
* %rcx: offset
* %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);
movq %rdx, RX0;
movq %rcx, RX1;
movq %r9, RY0;
movq %rsi, RY1;
/* Load offset */
movq (0 * 8)(RX1), RT0;
movq (1 * 8)(RX1), RT1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq (RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (0 * 8)(RX0), RAB0;
movq (1 * 8)(RX0), RCD0;
/* Store Offset_i */
movq RT0, (0 * 8)(RY1);
movq RT1, (1 * 8)(RY1);
/* CX_i = C_i xor Offset_i */
xorq RT0, RAB0;
xorq RT1, RCD0;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 8(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (2 * 8)(RX0), RAB1;
movq (3 * 8)(RX0), RCD1;
/* Store Offset_i */
movq RT0, (2 * 8)(RY1);
movq RT1, (3 * 8)(RY1);
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB1;
xorq RT1, RCD1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 16(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (4 * 8)(RX0), RAB2;
movq (5 * 8)(RX0), RCD2;
/* Store Offset_i */
movq RT0, (4 * 8)(RY1);
movq RT1, (5 * 8)(RY1);
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB2;
xorq RT1, RCD2;
/* Store offset */
movq RT0, (0 * 8)(RX1);
movq RT1, (1 * 8)(RX1);
/* PX_i = DECIPHER(K, CX_i) */
call __twofish_dec_blk3;
movq (7 * 8)(%rsp), RX2; /*checksum*/
movq (6 * 8)(%rsp), RX1; /*dst*/
/* Load checksum */
movq (0 * 8)(RX2), RT0;
movq (1 * 8)(RX2), RT1;
/* P_i = PX_i xor Offset_i */
xorq RCD0, (0 * 8)(RX1);
xorq RAB0, (1 * 8)(RX1);
xorq RCD1, (2 * 8)(RX1);
xorq RAB1, (3 * 8)(RX1);
xorq RCD2, (4 * 8)(RX1);
xorq RAB2, (5 * 8)(RX1);
/* Checksum_i = Checksum_{i-1} xor P_i */
xorq (0 * 8)(RX1), RT0;
xorq (1 * 8)(RX1), RT1;
xorq (2 * 8)(RX1), RT0;
xorq (3 * 8)(RX1), RT1;
xorq (4 * 8)(RX1), RT0;
xorq (5 * 8)(RX1), RT1;
/* Store checksum */
movq RT0, (0 * 8)(RX2);
movq RT1, (1 * 8)(RX2);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_ocb_dec,.-_gcry_twofish_amd64_ocb_dec;)
.align 8
.globl _gcry_twofish_amd64_ocb_auth
ELF(.type _gcry_twofish_amd64_ocb_auth,@function;)
_gcry_twofish_amd64_ocb_auth:
/* input:
* %rdi: ctx, CTX
* %rsi: abuf (3 blocks)
* %rdx: offset
* %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;
movq %rdx, RX1;
movq %r8, RY0;
/* Load offset */
movq (0 * 8)(RX1), RT0;
movq (1 * 8)(RX1), RT1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq (RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (0 * 8)(RX0), RAB0;
movq (1 * 8)(RX0), RCD0;
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB0;
xorq RT1, RCD0;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 8(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (2 * 8)(RX0), RAB1;
movq (3 * 8)(RX0), RCD1;
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB1;
xorq RT1, RCD1;
/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
movq 16(RY0), RY2;
xorq (0 * 8)(RY2), RT0;
xorq (1 * 8)(RY2), RT1;
movq (4 * 8)(RX0), RAB2;
movq (5 * 8)(RX0), RCD2;
/* PX_i = P_i xor Offset_i */
xorq RT0, RAB2;
xorq RT1, RCD2;
/* Store offset */
movq RT0, (0 * 8)(RX1);
movq RT1, (1 * 8)(RX1);
/* C_i = ENCIPHER(K, PX_i) */
call __twofish_enc_blk3;
movq (6 * 8)(%rsp), RX1; /*checksum*/
/* Checksum_i = C_i xor Checksum_i */
xorq RCD0, RCD1;
xorq RAB0, RAB1;
xorq RCD1, RCD2;
xorq RAB1, RAB2;
xorq RCD2, (0 * 8)(RX1);
xorq RAB2, (1 * 8)(RX1);
movq (0 * 8)(%rsp), %rbp;
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;
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);
EXIT_SYSV_FUNC
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_amd64_ocb_auth,.-_gcry_twofish_amd64_ocb_auth;)
#endif /*USE_TWOFISH*/
#endif /*__x86_64*/
diff --git a/cipher/twofish-arm.S b/cipher/twofish-arm.S
index 2e1da6cd..4f54f59a 100644
--- a/cipher/twofish-arm.S
+++ b/cipher/twofish-arm.S
@@ -1,363 +1,363 @@
/* twofish-arm.S - ARM assembly implementation of Twofish cipher
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined(__ARMEL__)
#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
.text
.syntax unified
.arm
/* structure of TWOFISH_context: */
#define s0 0
#define s1 ((s0) + 4 * 256)
#define s2 ((s1) + 4 * 256)
#define s3 ((s2) + 4 * 256)
#define w ((s3) + 4 * 256)
#define k ((w) + 4 * 8)
/* register macros */
#define CTX %r0
#define CTXs0 %r0
#define CTXs1 %r1
#define CTXs3 %r7
#define RA %r3
#define RB %r4
#define RC %r5
#define RD %r6
#define RX %r2
#define RY %ip
#define RMASK %lr
#define RT0 %r8
#define RT1 %r9
#define RT2 %r10
#define RT3 %r11
/* helper macros */
#define ldr_unaligned_le(rout, rsrc, offs, rtmp) \
ldrb rout, [rsrc, #((offs) + 0)]; \
ldrb rtmp, [rsrc, #((offs) + 1)]; \
orr rout, rout, rtmp, lsl #8; \
ldrb rtmp, [rsrc, #((offs) + 2)]; \
orr rout, rout, rtmp, lsl #16; \
ldrb rtmp, [rsrc, #((offs) + 3)]; \
orr rout, rout, rtmp, lsl #24;
#define str_unaligned_le(rin, rdst, offs, rtmp0, rtmp1) \
mov rtmp0, rin, lsr #8; \
strb rin, [rdst, #((offs) + 0)]; \
mov rtmp1, rin, lsr #16; \
strb rtmp0, [rdst, #((offs) + 1)]; \
mov rtmp0, rin, lsr #24; \
strb rtmp1, [rdst, #((offs) + 2)]; \
strb rtmp0, [rdst, #((offs) + 3)];
#ifndef __ARMEL__
/* bswap on big-endian */
#define host_to_le(reg) \
rev reg, reg;
#define le_to_host(reg) \
rev reg, reg;
#else
/* nop on little-endian */
#define host_to_le(reg) /*_*/
#define le_to_host(reg) /*_*/
#endif
#define ldr_input_aligned_le(rin, a, b, c, d) \
ldr a, [rin, #0]; \
ldr b, [rin, #4]; \
le_to_host(a); \
ldr c, [rin, #8]; \
le_to_host(b); \
ldr d, [rin, #12]; \
le_to_host(c); \
le_to_host(d);
#define str_output_aligned_le(rout, a, b, c, d) \
le_to_host(a); \
le_to_host(b); \
str a, [rout, #0]; \
le_to_host(c); \
str b, [rout, #4]; \
le_to_host(d); \
str c, [rout, #8]; \
str d, [rout, #12];
#ifdef __ARM_FEATURE_UNALIGNED
/* unaligned word reads/writes allowed */
#define ldr_input_le(rin, ra, rb, rc, rd, rtmp) \
ldr_input_aligned_le(rin, ra, rb, rc, rd)
#define str_output_le(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
str_output_aligned_le(rout, ra, rb, rc, rd)
#else
/* need to handle unaligned reads/writes by byte reads */
#define ldr_input_le(rin, ra, rb, rc, rd, rtmp0) \
tst rin, #3; \
beq 1f; \
ldr_unaligned_le(ra, rin, 0, rtmp0); \
ldr_unaligned_le(rb, rin, 4, rtmp0); \
ldr_unaligned_le(rc, rin, 8, rtmp0); \
ldr_unaligned_le(rd, rin, 12, rtmp0); \
b 2f; \
1:;\
ldr_input_aligned_le(rin, ra, rb, rc, rd); \
2:;
#define str_output_le(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
tst rout, #3; \
beq 1f; \
str_unaligned_le(ra, rout, 0, rtmp0, rtmp1); \
str_unaligned_le(rb, rout, 4, rtmp0, rtmp1); \
str_unaligned_le(rc, rout, 8, rtmp0, rtmp1); \
str_unaligned_le(rd, rout, 12, rtmp0, rtmp1); \
b 2f; \
1:;\
str_output_aligned_le(rout, ra, rb, rc, rd); \
2:;
#endif
/**********************************************************************
1-way twofish
**********************************************************************/
#define encrypt_round(a, b, rc, rd, n, ror_a, adj_a) \
and RT0, RMASK, b, lsr#(8 - 2); \
and RY, RMASK, b, lsr#(16 - 2); \
add RT0, RT0, #(s2 - s1); \
and RT1, RMASK, b, lsr#(24 - 2); \
ldr RY, [CTXs3, RY]; \
and RT2, RMASK, b, lsl#(2); \
ldr RT0, [CTXs1, RT0]; \
and RT3, RMASK, a, lsr#(16 - 2 + (adj_a)); \
ldr RT1, [CTXs0, RT1]; \
and RX, RMASK, a, lsr#(8 - 2 + (adj_a)); \
ldr RT2, [CTXs1, RT2]; \
add RT3, RT3, #(s2 - s1); \
ldr RX, [CTXs1, RX]; \
ror_a(a); \
\
eor RY, RY, RT0; \
ldr RT3, [CTXs1, RT3]; \
and RT0, RMASK, a, lsl#(2); \
eor RY, RY, RT1; \
and RT1, RMASK, a, lsr#(24 - 2); \
eor RY, RY, RT2; \
ldr RT0, [CTXs0, RT0]; \
eor RX, RX, RT3; \
ldr RT1, [CTXs3, RT1]; \
eor RX, RX, RT0; \
\
ldr RT3, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
eor RX, RX, RT1; \
ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
\
add RT0, RX, RY, lsl #1; \
add RX, RX, RY; \
add RT0, RT0, RT3; \
add RX, RX, RT2; \
eor rd, RT0, rd, ror #31; \
eor rc, rc, RX;
#define dummy(x) /*_*/
#define ror1(r) \
ror r, r, #1;
#define decrypt_round(a, b, rc, rd, n, ror_b, adj_b) \
and RT3, RMASK, b, lsl#(2 - (adj_b)); \
and RT1, RMASK, b, lsr#(8 - 2 + (adj_b)); \
ror_b(b); \
and RT2, RMASK, a, lsl#(2); \
and RT0, RMASK, a, lsr#(8 - 2); \
\
ldr RY, [CTXs1, RT3]; \
add RT1, RT1, #(s2 - s1); \
ldr RX, [CTXs0, RT2]; \
and RT3, RMASK, b, lsr#(16 - 2); \
ldr RT1, [CTXs1, RT1]; \
and RT2, RMASK, a, lsr#(16 - 2); \
ldr RT0, [CTXs1, RT0]; \
\
add RT2, RT2, #(s2 - s1); \
ldr RT3, [CTXs3, RT3]; \
eor RY, RY, RT1; \
\
and RT1, RMASK, b, lsr#(24 - 2); \
eor RX, RX, RT0; \
ldr RT2, [CTXs1, RT2]; \
and RT0, RMASK, a, lsr#(24 - 2); \
\
ldr RT1, [CTXs0, RT1]; \
\
eor RY, RY, RT3; \
ldr RT0, [CTXs3, RT0]; \
eor RX, RX, RT2; \
eor RY, RY, RT1; \
\
ldr RT1, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
eor RX, RX, RT0; \
ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
\
add RT0, RX, RY, lsl #1; \
add RX, RX, RY; \
add RT0, RT0, RT1; \
add RX, RX, RT2; \
eor rd, rd, RT0; \
eor rc, RX, rc, ror #31;
#define first_encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, dummy, 0); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
#define encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
#define last_encrypt_cycle(nc) \
encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
ror1(RA);
#define first_decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, dummy, 0); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
#define decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
#define last_decrypt_cycle(nc) \
decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
ror1(RD);
.align 3
.globl _gcry_twofish_arm_encrypt_block
.type _gcry_twofish_arm_encrypt_block,%function;
_gcry_twofish_arm_encrypt_block:
/* input:
* %r0: ctx
* %r1: dst
* %r2: src
*/
push {%r1, %r4-%r11, %ip, %lr};
add RY, CTXs0, #w;
ldr_input_le(%r2, RA, RB, RC, RD, RT0);
/* Input whitening */
ldm RY, {RT0, RT1, RT2, RT3};
add CTXs3, CTXs0, #(s3 - s0);
add CTXs1, CTXs0, #(s1 - s0);
mov RMASK, #(0xff << 2);
eor RA, RA, RT0;
eor RB, RB, RT1;
eor RC, RC, RT2;
eor RD, RD, RT3;
first_encrypt_cycle(0);
encrypt_cycle(1);
encrypt_cycle(2);
encrypt_cycle(3);
encrypt_cycle(4);
encrypt_cycle(5);
encrypt_cycle(6);
last_encrypt_cycle(7);
add RY, CTXs3, #(w + 4*4 - s3);
pop {%r1}; /* dst */
/* Output whitening */
ldm RY, {RT0, RT1, RT2, RT3};
eor RC, RC, RT0;
eor RD, RD, RT1;
eor RA, RA, RT2;
eor RB, RB, RT3;
str_output_le(%r1, RC, RD, RA, RB, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.ltorg
.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block;
.align 3
.globl _gcry_twofish_arm_decrypt_block
.type _gcry_twofish_arm_decrypt_block,%function;
_gcry_twofish_arm_decrypt_block:
/* input:
* %r0: ctx
* %r1: dst
* %r2: src
*/
push {%r1, %r4-%r11, %ip, %lr};
add CTXs3, CTXs0, #(s3 - s0);
ldr_input_le(%r2, RC, RD, RA, RB, RT0);
add RY, CTXs3, #(w + 4*4 - s3);
add CTXs3, CTXs0, #(s3 - s0);
/* Input whitening */
ldm RY, {RT0, RT1, RT2, RT3};
add CTXs1, CTXs0, #(s1 - s0);
mov RMASK, #(0xff << 2);
eor RC, RC, RT0;
eor RD, RD, RT1;
eor RA, RA, RT2;
eor RB, RB, RT3;
first_decrypt_cycle(7);
decrypt_cycle(6);
decrypt_cycle(5);
decrypt_cycle(4);
decrypt_cycle(3);
decrypt_cycle(2);
decrypt_cycle(1);
last_decrypt_cycle(0);
add RY, CTXs0, #w;
pop {%r1}; /* dst */
/* Output whitening */
ldm RY, {RT0, RT1, RT2, RT3};
eor RA, RA, RT0;
eor RB, RB, RT1;
eor RC, RC, RT2;
eor RD, RD, RT3;
str_output_le(%r1, RA, RB, RC, RD, RT0, RT1);
pop {%r4-%r11, %ip, %pc};
.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block;
#endif /*HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS*/
#endif /*__ARMEL__*/
diff --git a/cipher/twofish-avx2-amd64.S b/cipher/twofish-avx2-amd64.S
index 74cad355..8f0c0ef9 100644
--- a/cipher/twofish-avx2-amd64.S
+++ b/cipher/twofish-avx2-amd64.S
@@ -1,1048 +1,1048 @@
/* twofish-avx2-amd64.S - AMD64/AVX2 assembly implementation of Twofish cipher
*
* Copyright (C) 2013-2017 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/>.
+ * License along with this program; if not, see <https://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(USE_TWOFISH) && \
defined(ENABLE_AVX2_SUPPORT)
#include "asm-common-amd64.h"
.text
/* structure of TWOFISH_context: */
#define s0 0
#define s1 ((s0) + 4 * 256)
#define s2 ((s1) + 4 * 256)
#define s3 ((s2) + 4 * 256)
#define w ((s3) + 4 * 256)
#define k ((w) + 4 * 8)
/* register macros */
#define CTX %rdi
#define RROUND %rbp
#define RROUNDd %ebp
#define RS0 CTX
#define RS1 %r8
#define RS2 %r9
#define RS3 %r10
#define RK %r11
#define RW %rax
#define RA0 %ymm8
#define RB0 %ymm9
#define RC0 %ymm10
#define RD0 %ymm11
#define RA1 %ymm12
#define RB1 %ymm13
#define RC1 %ymm14
#define RD1 %ymm15
/* temp regs */
#define RX0 %ymm0
#define RY0 %ymm1
#define RX1 %ymm2
#define RY1 %ymm3
#define RT0 %ymm4
#define RIDX %ymm5
#define RX0x %xmm0
#define RY0x %xmm1
#define RX1x %xmm2
#define RY1x %xmm3
#define RT0x %xmm4
#define RIDXx %xmm5
#define RTMP0 RX0
#define RTMP0x RX0x
#define RTMP1 RX1
#define RTMP1x RX1x
#define RTMP2 RY0
#define RTMP2x RY0x
#define RTMP3 RY1
#define RTMP3x RY1x
#define RTMP4 RIDX
#define RTMP4x RIDXx
/* vpgatherdd mask and '-1' */
#define RNOT %ymm6
#define RNOTx %xmm6
/* byte mask, (-1 >> 24) */
#define RBYTE %ymm7
/**********************************************************************
16-way AVX2 twofish
**********************************************************************/
#define init_round_constants() \
vpcmpeqd RNOT, RNOT, RNOT; \
leaq k(CTX), RK; \
leaq w(CTX), RW; \
vpsrld $24, RNOT, RBYTE; \
leaq s1(CTX), RS1; \
leaq s2(CTX), RS2; \
leaq s3(CTX), RS3; \
#define g16(ab, rs0, rs1, rs2, rs3, xy) \
vpand RBYTE, ab ## 0, RIDX; \
vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 0; \
vpcmpeqd RNOT, RNOT, RNOT; \
\
vpand RBYTE, ab ## 1, RIDX; \
vpgatherdd RNOT, (rs0, RIDX, 4), xy ## 1; \
vpcmpeqd RNOT, RNOT, RNOT; \
\
vpsrld $8, ab ## 0, RIDX; \
vpand RBYTE, RIDX, RIDX; \
vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 0, xy ## 0; \
\
vpsrld $8, ab ## 1, RIDX; \
vpand RBYTE, RIDX, RIDX; \
vpgatherdd RNOT, (rs1, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 1, xy ## 1; \
\
vpsrld $16, ab ## 0, RIDX; \
vpand RBYTE, RIDX, RIDX; \
vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 0, xy ## 0; \
\
vpsrld $16, ab ## 1, RIDX; \
vpand RBYTE, RIDX, RIDX; \
vpgatherdd RNOT, (rs2, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 1, xy ## 1; \
\
vpsrld $24, ab ## 0, RIDX; \
vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 0, xy ## 0; \
\
vpsrld $24, ab ## 1, RIDX; \
vpgatherdd RNOT, (rs3, RIDX, 4), RT0; \
vpcmpeqd RNOT, RNOT, RNOT; \
vpxor RT0, xy ## 1, xy ## 1;
#define g1_16(a, x) \
g16(a, RS0, RS1, RS2, RS3, x);
#define g2_16(b, y) \
g16(b, RS1, RS2, RS3, RS0, y);
#define encrypt_round_end16(a, b, c, d, nk, r) \
vpaddd RY0, RX0, RX0; \
vpaddd RX0, RY0, RY0; \
vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RX0, RX0; \
vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RY0, RY0; \
\
vpxor RY0, d ## 0, d ## 0; \
\
vpxor RX0, c ## 0, c ## 0; \
vpsrld $1, c ## 0, RT0; \
vpslld $31, c ## 0, c ## 0; \
vpor RT0, c ## 0, c ## 0; \
\
vpaddd RY1, RX1, RX1; \
vpaddd RX1, RY1, RY1; \
vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RX1, RX1; \
vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RY1, RY1; \
\
vpxor RY1, d ## 1, d ## 1; \
\
vpxor RX1, c ## 1, c ## 1; \
vpsrld $1, c ## 1, RT0; \
vpslld $31, c ## 1, c ## 1; \
vpor RT0, c ## 1, c ## 1; \
#define encrypt_round16(a, b, c, d, nk, r) \
g2_16(b, RY); \
\
vpslld $1, b ## 0, RT0; \
vpsrld $31, b ## 0, b ## 0; \
vpor RT0, b ## 0, b ## 0; \
\
vpslld $1, b ## 1, RT0; \
vpsrld $31, b ## 1, b ## 1; \
vpor RT0, b ## 1, b ## 1; \
\
g1_16(a, RX); \
\
encrypt_round_end16(a, b, c, d, nk, r);
#define encrypt_round_first16(a, b, c, d, nk, r) \
vpslld $1, d ## 0, RT0; \
vpsrld $31, d ## 0, d ## 0; \
vpor RT0, d ## 0, d ## 0; \
\
vpslld $1, d ## 1, RT0; \
vpsrld $31, d ## 1, d ## 1; \
vpor RT0, d ## 1, d ## 1; \
\
encrypt_round16(a, b, c, d, nk, r);
#define encrypt_round_last16(a, b, c, d, nk, r) \
g2_16(b, RY); \
\
g1_16(a, RX); \
\
encrypt_round_end16(a, b, c, d, nk, r);
#define decrypt_round_end16(a, b, c, d, nk, r) \
vpaddd RY0, RX0, RX0; \
vpaddd RX0, RY0, RY0; \
vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RX0, RX0; \
vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RY0, RY0; \
\
vpxor RX0, c ## 0, c ## 0; \
\
vpxor RY0, d ## 0, d ## 0; \
vpsrld $1, d ## 0, RT0; \
vpslld $31, d ## 0, d ## 0; \
vpor RT0, d ## 0, d ## 0; \
\
vpaddd RY1, RX1, RX1; \
vpaddd RX1, RY1, RY1; \
vpbroadcastd ((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RX1, RX1; \
vpbroadcastd 4+((nk)+((r)*8))(RK), RT0; \
vpaddd RT0, RY1, RY1; \
\
vpxor RX1, c ## 1, c ## 1; \
\
vpxor RY1, d ## 1, d ## 1; \
vpsrld $1, d ## 1, RT0; \
vpslld $31, d ## 1, d ## 1; \
vpor RT0, d ## 1, d ## 1;
#define decrypt_round16(a, b, c, d, nk, r) \
g1_16(a, RX); \
\
vpslld $1, a ## 0, RT0; \
vpsrld $31, a ## 0, a ## 0; \
vpor RT0, a ## 0, a ## 0; \
\
vpslld $1, a ## 1, RT0; \
vpsrld $31, a ## 1, a ## 1; \
vpor RT0, a ## 1, a ## 1; \
\
g2_16(b, RY); \
\
decrypt_round_end16(a, b, c, d, nk, r);
#define decrypt_round_first16(a, b, c, d, nk, r) \
vpslld $1, c ## 0, RT0; \
vpsrld $31, c ## 0, c ## 0; \
vpor RT0, c ## 0, c ## 0; \
\
vpslld $1, c ## 1, RT0; \
vpsrld $31, c ## 1, c ## 1; \
vpor RT0, c ## 1, c ## 1; \
\
decrypt_round16(a, b, c, d, nk, r)
#define decrypt_round_last16(a, b, c, d, nk, r) \
g1_16(a, RX); \
\
g2_16(b, RY); \
\
decrypt_round_end16(a, b, c, d, nk, r);
#define encrypt_cycle16(r) \
encrypt_round16(RA, RB, RC, RD, 0, r); \
encrypt_round16(RC, RD, RA, RB, 8, r);
#define encrypt_cycle_first16(r) \
encrypt_round_first16(RA, RB, RC, RD, 0, r); \
encrypt_round16(RC, RD, RA, RB, 8, r);
#define encrypt_cycle_last16(r) \
encrypt_round16(RA, RB, RC, RD, 0, r); \
encrypt_round_last16(RC, RD, RA, RB, 8, r);
#define decrypt_cycle16(r) \
decrypt_round16(RC, RD, RA, RB, 8, r); \
decrypt_round16(RA, RB, RC, RD, 0, r);
#define decrypt_cycle_first16(r) \
decrypt_round_first16(RC, RD, RA, RB, 8, r); \
decrypt_round16(RA, RB, RC, RD, 0, r);
#define decrypt_cycle_last16(r) \
decrypt_round16(RC, RD, RA, RB, 8, r); \
decrypt_round_last16(RA, RB, RC, RD, 0, r);
#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 read_blocks8(offs,a,b,c,d) \
vmovdqu 16*offs(RIO), a; \
vmovdqu 16*offs+32(RIO), b; \
vmovdqu 16*offs+64(RIO), c; \
vmovdqu 16*offs+96(RIO), d; \
\
transpose_4x4(a, b, c, d, RX0, RY0);
#define write_blocks8(offs,a,b,c,d) \
transpose_4x4(a, b, c, d, RX0, RY0); \
\
vmovdqu a, 16*offs(RIO); \
vmovdqu b, 16*offs+32(RIO); \
vmovdqu c, 16*offs+64(RIO); \
vmovdqu d, 16*offs+96(RIO);
#define inpack_enc8(a,b,c,d) \
vpbroadcastd 4*0(RW), RT0; \
vpxor RT0, a, a; \
\
vpbroadcastd 4*1(RW), RT0; \
vpxor RT0, b, b; \
\
vpbroadcastd 4*2(RW), RT0; \
vpxor RT0, c, c; \
\
vpbroadcastd 4*3(RW), RT0; \
vpxor RT0, d, d;
#define outunpack_enc8(a,b,c,d) \
vpbroadcastd 4*4(RW), RX0; \
vpbroadcastd 4*5(RW), RY0; \
vpxor RX0, c, RX0; \
vpxor RY0, d, RY0; \
\
vpbroadcastd 4*6(RW), RT0; \
vpxor RT0, a, c; \
vpbroadcastd 4*7(RW), RT0; \
vpxor RT0, b, d; \
\
vmovdqa RX0, a; \
vmovdqa RY0, b;
#define inpack_dec8(a,b,c,d) \
vpbroadcastd 4*4(RW), RX0; \
vpbroadcastd 4*5(RW), RY0; \
vpxor RX0, a, RX0; \
vpxor RY0, b, RY0; \
\
vpbroadcastd 4*6(RW), RT0; \
vpxor RT0, c, a; \
vpbroadcastd 4*7(RW), RT0; \
vpxor RT0, d, b; \
\
vmovdqa RX0, c; \
vmovdqa RY0, d;
#define outunpack_dec8(a,b,c,d) \
vpbroadcastd 4*0(RW), RT0; \
vpxor RT0, a, a; \
\
vpbroadcastd 4*1(RW), RT0; \
vpxor RT0, b, b; \
\
vpbroadcastd 4*2(RW), RT0; \
vpxor RT0, c, c; \
\
vpbroadcastd 4*3(RW), RT0; \
vpxor RT0, d, d;
#define transpose4x4_16(a,b,c,d) \
transpose_4x4(a ## 0, b ## 0, c ## 0, d ## 0, RX0, RY0); \
transpose_4x4(a ## 1, b ## 1, c ## 1, d ## 1, RX0, RY0);
#define inpack_enc16(a,b,c,d) \
inpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \
inpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1);
#define outunpack_enc16(a,b,c,d) \
outunpack_enc8(a ## 0, b ## 0, c ## 0, d ## 0); \
outunpack_enc8(a ## 1, b ## 1, c ## 1, d ## 1);
#define inpack_dec16(a,b,c,d) \
inpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \
inpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1);
#define outunpack_dec16(a,b,c,d) \
outunpack_dec8(a ## 0, b ## 0, c ## 0, d ## 0); \
outunpack_dec8(a ## 1, b ## 1, c ## 1, d ## 1);
.align 8
ELF(.type __twofish_enc_blk16,@function;)
__twofish_enc_blk16:
/* input:
* %rdi: ctx, CTX
* RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
* plaintext blocks
* output:
* RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
* ciphertext blocks
*/
CFI_STARTPROC();
init_round_constants();
transpose4x4_16(RA, RB, RC, RD);
inpack_enc16(RA, RB, RC, RD);
encrypt_cycle_first16(0);
encrypt_cycle16(2);
encrypt_cycle16(4);
encrypt_cycle16(6);
encrypt_cycle16(8);
encrypt_cycle16(10);
encrypt_cycle16(12);
encrypt_cycle_last16(14);
outunpack_enc16(RA, RB, RC, RD);
transpose4x4_16(RA, RB, RC, RD);
ret;
CFI_ENDPROC();
ELF(.size __twofish_enc_blk16,.-__twofish_enc_blk16;)
.align 8
ELF(.type __twofish_dec_blk16,@function;)
__twofish_dec_blk16:
/* input:
* %rdi: ctx, CTX
* RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
* plaintext blocks
* output:
* RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
* ciphertext blocks
*/
CFI_STARTPROC();
init_round_constants();
transpose4x4_16(RA, RB, RC, RD);
inpack_dec16(RA, RB, RC, RD);
decrypt_cycle_first16(14);
decrypt_cycle16(12);
decrypt_cycle16(10);
decrypt_cycle16(8);
decrypt_cycle16(6);
decrypt_cycle16(4);
decrypt_cycle16(2);
decrypt_cycle_last16(0);
outunpack_dec16(RA, RB, RC, RD);
transpose4x4_16(RA, RB, RC, RD);
ret;
CFI_ENDPROC();
ELF(.size __twofish_dec_blk16,.-__twofish_dec_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_twofish_avx2_ctr_enc
ELF(.type _gcry_twofish_avx2_ctr_enc,@function;)
_gcry_twofish_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, RB0;
vpsubq RTMP2, RTMP0, RTMP0; /* +5 ; +4 */
vpshufb RTMP3, RTMP0, RC0;
vpsubq RTMP2, RTMP0, RTMP0; /* +7 ; +6 */
vpshufb RTMP3, RTMP0, RD0;
vpsubq RTMP2, RTMP0, RTMP0; /* +9 ; +8 */
vpshufb RTMP3, RTMP0, RA1;
vpsubq RTMP2, RTMP0, RTMP0; /* +11 ; +10 */
vpshufb RTMP3, RTMP0, RB1;
vpsubq RTMP2, RTMP0, RTMP0; /* +13 ; +12 */
vpshufb RTMP3, RTMP0, RC1;
vpsubq RTMP2, RTMP0, RTMP0; /* +15 ; +14 */
vpshufb RTMP3, RTMP0, RD1;
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, RB0; /* +3 ; +2 */
inc_le128(RTMP0, RNOT, RTMP1);
inc_le128(RTMP0, RNOT, RTMP1);
vpshufb RTMP3, RTMP0, RC0; /* +5 ; +4 */
inc_le128(RTMP0, RNOT, RTMP1);
inc_le128(RTMP0, RNOT, RTMP1);
vpshufb RTMP3, RTMP0, RD0; /* +7 ; +6 */
inc_le128(RTMP0, RNOT, RTMP1);
inc_le128(RTMP0, RNOT, RTMP1);
vpshufb RTMP3, RTMP0, RA1; /* +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, RC1; /* +13 ; +12 */
inc_le128(RTMP0, RNOT, RTMP1);
inc_le128(RTMP0, RNOT, RTMP1);
vpshufb RTMP3, RTMP0, RD1; /* +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 __twofish_enc_blk16;
vpxor (0 * 32)(%rdx), RA0, RA0;
vpxor (1 * 32)(%rdx), RB0, RB0;
vpxor (2 * 32)(%rdx), RC0, RC0;
vpxor (3 * 32)(%rdx), RD0, RD0;
vpxor (4 * 32)(%rdx), RA1, RA1;
vpxor (5 * 32)(%rdx), RB1, RB1;
vpxor (6 * 32)(%rdx), RC1, RC1;
vpxor (7 * 32)(%rdx), RD1, RD1;
vmovdqu RA0, (0 * 32)(%rsi);
vmovdqu RB0, (1 * 32)(%rsi);
vmovdqu RC0, (2 * 32)(%rsi);
vmovdqu RD0, (3 * 32)(%rsi);
vmovdqu RA1, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RC1, (6 * 32)(%rsi);
vmovdqu RD1, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_ctr_enc,.-_gcry_twofish_avx2_ctr_enc;)
.align 8
.globl _gcry_twofish_avx2_cbc_dec
ELF(.type _gcry_twofish_avx2_cbc_dec,@function;)
_gcry_twofish_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), RB0;
vmovdqu (2 * 32)(%rdx), RC0;
vmovdqu (3 * 32)(%rdx), RD0;
vmovdqu (4 * 32)(%rdx), RA1;
vmovdqu (5 * 32)(%rdx), RB1;
vmovdqu (6 * 32)(%rdx), RC1;
vmovdqu (7 * 32)(%rdx), RD1;
call __twofish_dec_blk16;
vmovdqu (%rcx), RNOTx;
vinserti128 $1, (%rdx), RNOT, RNOT;
vpxor RNOT, RA0, RA0;
vpxor (0 * 32 + 16)(%rdx), RB0, RB0;
vpxor (1 * 32 + 16)(%rdx), RC0, RC0;
vpxor (2 * 32 + 16)(%rdx), RD0, RD0;
vpxor (3 * 32 + 16)(%rdx), RA1, RA1;
vpxor (4 * 32 + 16)(%rdx), RB1, RB1;
vpxor (5 * 32 + 16)(%rdx), RC1, RC1;
vpxor (6 * 32 + 16)(%rdx), RD1, RD1;
vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
vmovdqu RNOTx, (%rcx); /* store new IV */
vmovdqu RA0, (0 * 32)(%rsi);
vmovdqu RB0, (1 * 32)(%rsi);
vmovdqu RC0, (2 * 32)(%rsi);
vmovdqu RD0, (3 * 32)(%rsi);
vmovdqu RA1, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RC1, (6 * 32)(%rsi);
vmovdqu RD1, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_cbc_dec,.-_gcry_twofish_avx2_cbc_dec;)
.align 8
.globl _gcry_twofish_avx2_cfb_dec
ELF(.type _gcry_twofish_avx2_cfb_dec,@function;)
_gcry_twofish_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), RB0;
vmovdqu (1 * 32 + 16)(%rdx), RC0;
vmovdqu (2 * 32 + 16)(%rdx), RD0;
vmovdqu (3 * 32 + 16)(%rdx), RA1;
vmovdqu (4 * 32 + 16)(%rdx), RB1;
vmovdqu (5 * 32 + 16)(%rdx), RC1;
vmovdqu (6 * 32 + 16)(%rdx), RD1;
/* Update IV */
vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
vmovdqu RNOTx, (%rcx);
call __twofish_enc_blk16;
vpxor (0 * 32)(%rdx), RA0, RA0;
vpxor (1 * 32)(%rdx), RB0, RB0;
vpxor (2 * 32)(%rdx), RC0, RC0;
vpxor (3 * 32)(%rdx), RD0, RD0;
vpxor (4 * 32)(%rdx), RA1, RA1;
vpxor (5 * 32)(%rdx), RB1, RB1;
vpxor (6 * 32)(%rdx), RC1, RC1;
vpxor (7 * 32)(%rdx), RD1, RD1;
vmovdqu RA0, (0 * 32)(%rsi);
vmovdqu RB0, (1 * 32)(%rsi);
vmovdqu RC0, (2 * 32)(%rsi);
vmovdqu RD0, (3 * 32)(%rsi);
vmovdqu RA1, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RC1, (6 * 32)(%rsi);
vmovdqu RD1, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_cfb_dec,.-_gcry_twofish_avx2_cfb_dec;)
.align 8
.globl _gcry_twofish_avx2_ocb_enc
ELF(.type _gcry_twofish_avx2_ocb_enc,@function;)
_gcry_twofish_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, RB0);
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, RC0);
OCB_INPUT(3, %r12, %r13, RD0);
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, RA1);
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, RC1);
OCB_INPUT(7, %r12, %r13, RD1);
#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 __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;
vpxor (2 * 32)(%rsi), RC0, RC0;
vpxor (3 * 32)(%rsi), RD0, RD0;
vpxor (4 * 32)(%rsi), RA1, RA1;
vpxor (5 * 32)(%rsi), RB1, RB1;
vpxor (6 * 32)(%rsi), RC1, RC1;
vpxor (7 * 32)(%rsi), RD1, RD1;
vmovdqu RA0, (0 * 32)(%rsi);
vmovdqu RB0, (1 * 32)(%rsi);
vmovdqu RC0, (2 * 32)(%rsi);
vmovdqu RD0, (3 * 32)(%rsi);
vmovdqu RA1, (4 * 32)(%rsi);
vmovdqu RB1, (5 * 32)(%rsi);
vmovdqu RC1, (6 * 32)(%rsi);
vmovdqu RD1, (7 * 32)(%rsi);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_ocb_enc,.-_gcry_twofish_avx2_ocb_enc;)
.align 8
.globl _gcry_twofish_avx2_ocb_dec
ELF(.type _gcry_twofish_avx2_ocb_dec,@function;)
_gcry_twofish_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, RB0);
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, RC0);
OCB_INPUT(3, %r12, %r13, RD0);
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, RA1);
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, RC1);
OCB_INPUT(7, %r12, %r13, RD1);
#undef OCB_INPUT
vmovdqu RTMP0x, (%rcx);
mov %r8, %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 __twofish_dec_blk16;
vmovdqu (%rcx), RTMP1x;
vpxor (0 * 32)(%rsi), RA0, RA0;
vpxor (1 * 32)(%rsi), RB0, RB0;
vpxor (2 * 32)(%rsi), RC0, RC0;
vpxor (3 * 32)(%rsi), RD0, RD0;
vpxor (4 * 32)(%rsi), RA1, RA1;
vpxor (5 * 32)(%rsi), RB1, RB1;
vpxor (6 * 32)(%rsi), RC1, RC1;
vpxor (7 * 32)(%rsi), RD1, RD1;
addq $(4 * 8), %rsp;
CFI_ADJUST_CFA_OFFSET(-4 * 8);
/* Checksum_i = Checksum_{i-1} xor P_i */
vmovdqu RA0, (0 * 32)(%rsi);
vpxor RA0, RTMP1, RTMP1;
vmovdqu RB0, (1 * 32)(%rsi);
vpxor RB0, RTMP1, RTMP1;
vmovdqu RC0, (2 * 32)(%rsi);
vpxor RC0, RTMP1, RTMP1;
vmovdqu RD0, (3 * 32)(%rsi);
vpxor RD0, RTMP1, RTMP1;
vmovdqu RA1, (4 * 32)(%rsi);
vpxor RA1, RTMP1, RTMP1;
vmovdqu RB1, (5 * 32)(%rsi);
vpxor RB1, RTMP1, RTMP1;
vmovdqu RC1, (6 * 32)(%rsi);
vpxor RC1, RTMP1, RTMP1;
vmovdqu RD1, (7 * 32)(%rsi);
vpxor RD1, RTMP1, RTMP1;
vextracti128 $1, RTMP1, RNOTx;
vpxor RNOTx, RTMP1x, RTMP1x;
vmovdqu RTMP1x, (%rcx);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_ocb_dec,.-_gcry_twofish_avx2_ocb_dec;)
.align 8
.globl _gcry_twofish_avx2_ocb_auth
ELF(.type _gcry_twofish_avx2_ocb_auth,@function;)
_gcry_twofish_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, RB0);
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, RC0);
OCB_INPUT(3, %r12, %r13, RD0);
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, RA1);
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, RC1);
OCB_INPUT(7, %r12, %r13, RD1);
#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 __twofish_enc_blk16;
vpxor RA0, RB0, RA0;
vpxor RC0, RD0, RC0;
vpxor RA1, RB1, RA1;
vpxor RC1, RD1, RC1;
vpxor RA0, RC0, RA0;
vpxor RA1, RC1, RA1;
addq $(4 * 8), %rsp;
CFI_ADJUST_CFA_OFFSET(-4 * 8);
vpxor RA1, RA0, RTMP1;
vextracti128 $1, RTMP1, RNOTx;
vpxor (%rcx), RTMP1x, RTMP1x;
vpxor RNOTx, RTMP1x, RTMP1x;
vmovdqu RTMP1x, (%rcx);
vzeroall;
ret;
CFI_ENDPROC();
ELF(.size _gcry_twofish_avx2_ocb_auth,.-_gcry_twofish_avx2_ocb_auth;)
.align 16
/* For CTR-mode IV byteswap */
_gcry_twofish_bswap128_mask:
.Lbswap128_mask:
.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
ELF(.size _gcry_twofish_bswap128_mask,.-_gcry_twofish_bswap128_mask;)
#endif /*defined(USE_TWOFISH) && defined(ENABLE_AVX2_SUPPORT)*/
#endif /*__x86_64*/
diff --git a/cipher/whirlpool-sse2-amd64.S b/cipher/whirlpool-sse2-amd64.S
index 5631dc56..ea10cfde 100644
--- a/cipher/whirlpool-sse2-amd64.S
+++ b/cipher/whirlpool-sse2-amd64.S
@@ -1,348 +1,348 @@
/* whirlpool-sse2-amd64.S - AMD64 assembly implementation of Whirlpool
*
* 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/>.
+ * License along with this program; if not, see <https://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(USE_WHIRLPOOL)
#include "asm-common-amd64.h"
.text
/* look-up table offsets on RTAB */
#define RC (0)
#define C0 (RC + (8 * 10))
#define C1 (C0 + (8 * 256))
#define C2 (C1 + (8 * 256))
#define C3 (C2 + (8 * 256))
#define C4 (C3 + (8 * 256))
#define C5 (C4 + (8 * 256))
#define C6 (C5 + (8 * 256))
#define C7 (C6 + (8 * 256))
/* stack variables */
#define STACK_DATAP (0)
#define STACK_STATEP (STACK_DATAP + 8)
#define STACK_ROUNDS (STACK_STATEP + 8)
#define STACK_NBLKS (STACK_ROUNDS + 8)
#define STACK_RBP (STACK_NBLKS + 8)
#define STACK_RBX (STACK_RBP + 8)
#define STACK_R12 (STACK_RBX + 8)
#define STACK_R13 (STACK_R12 + 8)
#define STACK_R14 (STACK_R13 + 8)
#define STACK_R15 (STACK_R14 + 8)
#define STACK_MAX (STACK_R15 + 8)
/* register macros */
#define RTAB %rbp
#define RI1 %rax
#define RI2 %rbx
#define RI3 %rcx
#define RI4 %rdx
#define RI1d %eax
#define RI2d %ebx
#define RI3d %ecx
#define RI4d %edx
#define RI1bl %al
#define RI2bl %bl
#define RI3bl %cl
#define RI4bl %dl
#define RI1bh %ah
#define RI2bh %bh
#define RI3bh %ch
#define RI4bh %dh
#define RB0 %r8
#define RB1 %r9
#define RB2 %r10
#define RB3 %r11
#define RB4 %r12
#define RB5 %r13
#define RB6 %r14
#define RB7 %r15
#define RT0 %rsi
#define RT1 %rdi
#define RT0d %esi
#define RT1d %edi
#define XKEY0 %xmm0
#define XKEY1 %xmm1
#define XKEY2 %xmm2
#define XKEY3 %xmm3
#define XKEY4 %xmm4
#define XKEY5 %xmm5
#define XKEY6 %xmm6
#define XKEY7 %xmm7
#define XSTATE0 %xmm8
#define XSTATE1 %xmm9
#define XSTATE2 %xmm10
#define XSTATE3 %xmm11
#define XSTATE4 %xmm12
#define XSTATE5 %xmm13
#define XSTATE6 %xmm14
#define XSTATE7 %xmm15
/***********************************************************************
* AMD64 assembly implementation of Whirlpool.
* - Using table-lookups
* - Store state in XMM registers
***********************************************************************/
#define __do_whirl(op, ri, \
b0, b1, b2, b3, b4, b5, b6, b7, \
load_ri, load_arg) \
movzbl ri ## bl, RT0d; \
movzbl ri ## bh, RT1d; \
shrq $16, ri; \
op ## q C7(RTAB,RT0,8), b7; \
op ## q C6(RTAB,RT1,8), b6; \
movzbl ri ## bl, RT0d; \
movzbl ri ## bh, RT1d; \
shrq $16, ri; \
op ## q C5(RTAB,RT0,8), b5; \
op ## q C4(RTAB,RT1,8), b4; \
movzbl ri ## bl, RT0d; \
movzbl ri ## bh, RT1d; \
shrl $16, ri ## d; \
op ## q C3(RTAB,RT0,8), b3; \
op ## q C2(RTAB,RT1,8), b2; \
movzbl ri ## bl, RT0d; \
movzbl ri ## bh, RT1d; \
load_ri( load_arg, ri); \
op ## q C1(RTAB,RT0,8), b1; \
op ## q C0(RTAB,RT1,8), b0;
#define do_whirl(op, ri, rb_add, load_ri, load_arg) \
__do_whirl(op, ##ri, rb_add, load_ri, load_arg)
#define dummy(...) /*_*/
#define do_movq(src, dst) movq src, dst;
#define RB_ADD0 RB0, RB1, RB2, RB3, RB4, RB5, RB6, RB7
#define RB_ADD1 RB1, RB2, RB3, RB4, RB5, RB6, RB7, RB0
#define RB_ADD2 RB2, RB3, RB4, RB5, RB6, RB7, RB0, RB1
#define RB_ADD3 RB3, RB4, RB5, RB6, RB7, RB0, RB1, RB2
#define RB_ADD4 RB4, RB5, RB6, RB7, RB0, RB1, RB2, RB3
#define RB_ADD5 RB5, RB6, RB7, RB0, RB1, RB2, RB3, RB4
#define RB_ADD6 RB6, RB7, RB0, RB1, RB2, RB3, RB4, RB5
#define RB_ADD7 RB7, RB0, RB1, RB2, RB3, RB4, RB5, RB6
.align 8
.globl _gcry_whirlpool_transform_amd64
ELF(.type _gcry_whirlpool_transform_amd64,@function;)
_gcry_whirlpool_transform_amd64:
/* input:
* %rdi: state
* %rsi: inblk
* %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);
movq %rsi, STACK_DATAP(%rsp);
movq %rcx, RTAB;
jmp .Lfirst_block;
.align 8
.Lblock_loop:
movq STACK_DATAP(%rsp), %rsi;
movq RI1, %rdi;
.Lfirst_block:
/* load data_block */
movq 0*8(%rsi), RB0;
movq 1*8(%rsi), RB1;
bswapq RB0;
movq 2*8(%rsi), RB2;
bswapq RB1;
movq 3*8(%rsi), RB3;
bswapq RB2;
movq 4*8(%rsi), RB4;
bswapq RB3;
movq 5*8(%rsi), RB5;
bswapq RB4;
movq RB0, XSTATE0;
movq 6*8(%rsi), RB6;
bswapq RB5;
movq RB1, XSTATE1;
movq 7*8(%rsi), RB7;
bswapq RB6;
movq RB2, XSTATE2;
bswapq RB7;
movq RB3, XSTATE3;
movq RB4, XSTATE4;
movq RB5, XSTATE5;
movq RB6, XSTATE6;
movq RB7, XSTATE7;
/* load key */
movq 0*8(%rdi), XKEY0;
movq 1*8(%rdi), XKEY1;
movq 2*8(%rdi), XKEY2;
movq 3*8(%rdi), XKEY3;
movq 4*8(%rdi), XKEY4;
movq 5*8(%rdi), XKEY5;
movq 6*8(%rdi), XKEY6;
movq 7*8(%rdi), XKEY7;
movq XKEY0, RI1;
movq XKEY1, RI2;
movq XKEY2, RI3;
movq XKEY3, RI4;
/* prepare and store state */
pxor XKEY0, XSTATE0;
pxor XKEY1, XSTATE1;
pxor XKEY2, XSTATE2;
pxor XKEY3, XSTATE3;
pxor XKEY4, XSTATE4;
pxor XKEY5, XSTATE5;
pxor XKEY6, XSTATE6;
pxor XKEY7, XSTATE7;
movq XSTATE0, 0*8(%rdi);
movq XSTATE1, 1*8(%rdi);
movq XSTATE2, 2*8(%rdi);
movq XSTATE3, 3*8(%rdi);
movq XSTATE4, 4*8(%rdi);
movq XSTATE5, 5*8(%rdi);
movq XSTATE6, 6*8(%rdi);
movq XSTATE7, 7*8(%rdi);
addq $64, STACK_DATAP(%rsp);
movl $(0), STACK_ROUNDS(%rsp);
.align 8
.Lround_loop:
do_whirl(mov, RI1 /*XKEY0*/, RB_ADD0, do_movq, XKEY4);
do_whirl(xor, RI2 /*XKEY1*/, RB_ADD1, do_movq, XKEY5);
do_whirl(xor, RI3 /*XKEY2*/, RB_ADD2, do_movq, XKEY6);
do_whirl(xor, RI4 /*XKEY3*/, RB_ADD3, do_movq, XKEY7);
do_whirl(xor, RI1 /*XKEY0*/, RB_ADD4, do_movq, XSTATE0);
do_whirl(xor, RI2 /*XKEY1*/, RB_ADD5, do_movq, XSTATE1);
do_whirl(xor, RI3 /*XKEY2*/, RB_ADD6, do_movq, XSTATE2);
do_whirl(xor, RI4 /*XKEY3*/, RB_ADD7, do_movq, XSTATE3);
movl STACK_ROUNDS(%rsp), RT0d;
movq RB1, XKEY1;
addl $1, STACK_ROUNDS(%rsp);
movq RB2, XKEY2;
movq RB3, XKEY3;
xorq RC(RTAB,RT0,8), RB0; /* Add round constant */
movq RB4, XKEY4;
movq RB5, XKEY5;
movq RB0, XKEY0;
movq RB6, XKEY6;
movq RB7, XKEY7;
do_whirl(xor, RI1 /*XSTATE0*/, RB_ADD0, do_movq, XSTATE4);
do_whirl(xor, RI2 /*XSTATE1*/, RB_ADD1, do_movq, XSTATE5);
do_whirl(xor, RI3 /*XSTATE2*/, RB_ADD2, do_movq, XSTATE6);
do_whirl(xor, RI4 /*XSTATE3*/, RB_ADD3, do_movq, XSTATE7);
cmpl $10, STACK_ROUNDS(%rsp);
je .Lis_last_round;
do_whirl(xor, RI1 /*XSTATE4*/, RB_ADD4, do_movq, XKEY0);
do_whirl(xor, RI2 /*XSTATE5*/, RB_ADD5, do_movq, XKEY1);
do_whirl(xor, RI3 /*XSTATE6*/, RB_ADD6, do_movq, XKEY2);
do_whirl(xor, RI4 /*XSTATE7*/, RB_ADD7, do_movq, XKEY3);
movq RB0, XSTATE0;
movq RB1, XSTATE1;
movq RB2, XSTATE2;
movq RB3, XSTATE3;
movq RB4, XSTATE4;
movq RB5, XSTATE5;
movq RB6, XSTATE6;
movq RB7, XSTATE7;
jmp .Lround_loop;
.align 8
.Lis_last_round:
do_whirl(xor, RI1 /*XSTATE4*/, RB_ADD4, dummy, _);
movq STACK_STATEP(%rsp), RI1;
do_whirl(xor, RI2 /*XSTATE5*/, RB_ADD5, dummy, _);
do_whirl(xor, RI3 /*XSTATE6*/, RB_ADD6, dummy, _);
do_whirl(xor, RI4 /*XSTATE7*/, RB_ADD7, dummy, _);
/* store state */
xorq RB0, 0*8(RI1);
xorq RB1, 1*8(RI1);
xorq RB2, 2*8(RI1);
xorq RB3, 3*8(RI1);
xorq RB4, 4*8(RI1);
xorq RB5, 5*8(RI1);
xorq RB6, 6*8(RI1);
xorq RB7, 7*8(RI1);
subq $1, STACK_NBLKS(%rsp);
jnz .Lblock_loop;
movq STACK_RBP(%rsp), %rbp;
movq STACK_RBX(%rsp), %rbx;
movq STACK_R12(%rsp), %r12;
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;
CFI_ENDPROC();
ELF(.size _gcry_whirlpool_transform_amd64,.-_gcry_whirlpool_transform_amd64;)
#endif
#endif
diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c
index d9b79cf1..0c472252 100644
--- a/cipher/whirlpool.c
+++ b/cipher/whirlpool.c
@@ -1,1535 +1,1535 @@
/* whirlpool.c - Whirlpool hashing algorithm
* Copyright (C) 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, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* This is an implementation of the Whirlpool hashing algorithm, which
has been developed by Vincent Rijmen and Paulo S. L. M. Barreto;
it's homepage is located at:
- http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html
+ https://www.larc.usp.br/~pbarreto/WhirlpoolPage.html
The S-Boxes and the structure of the main transformation function,
which implements an optimized version of the algorithm, is taken
from the reference implementation available from
- http://www.larc.usp.br/~pbarreto/whirlpool.zip
+ https://www.larc.usp.br/~pbarreto/whirlpool.zip
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#include "hash-common.h"
/* 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))
# define USE_AMD64_ASM 1
#endif
/* Size of a whirlpool block (in bytes). */
#define BLOCK_SIZE 64
/* Number of rounds. */
#define R 10
/* Types. */
typedef u64 whirlpool_block_t[BLOCK_SIZE / 8];
typedef struct {
gcry_md_block_ctx_t bctx;
whirlpool_block_t hash_state;
int use_bugemu;
struct {
size_t count;
unsigned char length[32];
} bugemu;
} whirlpool_context_t;
/* Macros. */
/* Convert the the buffer BUFFER into a block BLOCK, using I as
counter. */
#define buffer_to_block(buffer, block, i) \
for (i = 0; i < 8; i++) \
(block)[i] = buf_get_be64((buffer) + i * 8);
/* Convert the block BLOCK into a buffer BUFFER, using I as
counter. */
#define block_to_buffer(buffer, block, i) \
for (i = 0; i < 8; i++) \
buf_put_be64((buffer) + i * 8, (block)[i]);
/* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */
#define block_copy(block_dst, block_src, i) \
for (i = 0; i < 8; i++) \
block_dst[i] = block_src[i];
/* XOR the block BLOCK_SRC into BLOCK_DST, using I as counter. */
#define block_xor(block_dst, block_src, i) \
for (i = 0; i < 8; i++) \
block_dst[i] ^= block_src[i];
struct whirlpool_tables_s {
u64 RC[R];
u64 C[8][256];
};
static const struct whirlpool_tables_s tab =
{
/* Round constants. */
{
U64_C (0x1823c6e887b8014f),
U64_C (0x36a6d2f5796f9152),
U64_C (0x60bc9b8ea30c7b35),
U64_C (0x1de0d7c22e4bfe57),
U64_C (0x157737e59ff04ada),
U64_C (0x58c9290ab1a06b85),
U64_C (0xbd5d10f4cb3e0567),
U64_C (0xe427418ba77d95d8),
U64_C (0xfbee7c66dd17479e),
U64_C (0xca2dbf07ad5a8333),
},
/* Main lookup boxes. */
{ {
U64_C (0x18186018c07830d8), U64_C (0x23238c2305af4626),
U64_C (0xc6c63fc67ef991b8), U64_C (0xe8e887e8136fcdfb),
U64_C (0x878726874ca113cb), U64_C (0xb8b8dab8a9626d11),
U64_C (0x0101040108050209), U64_C (0x4f4f214f426e9e0d),
U64_C (0x3636d836adee6c9b), U64_C (0xa6a6a2a6590451ff),
U64_C (0xd2d26fd2debdb90c), U64_C (0xf5f5f3f5fb06f70e),
U64_C (0x7979f979ef80f296), U64_C (0x6f6fa16f5fcede30),
U64_C (0x91917e91fcef3f6d), U64_C (0x52525552aa07a4f8),
U64_C (0x60609d6027fdc047), U64_C (0xbcbccabc89766535),
U64_C (0x9b9b569baccd2b37), U64_C (0x8e8e028e048c018a),
U64_C (0xa3a3b6a371155bd2), U64_C (0x0c0c300c603c186c),
U64_C (0x7b7bf17bff8af684), U64_C (0x3535d435b5e16a80),
U64_C (0x1d1d741de8693af5), U64_C (0xe0e0a7e05347ddb3),
U64_C (0xd7d77bd7f6acb321), U64_C (0xc2c22fc25eed999c),
U64_C (0x2e2eb82e6d965c43), U64_C (0x4b4b314b627a9629),
U64_C (0xfefedffea321e15d), U64_C (0x575741578216aed5),
U64_C (0x15155415a8412abd), U64_C (0x7777c1779fb6eee8),
U64_C (0x3737dc37a5eb6e92), U64_C (0xe5e5b3e57b56d79e),
U64_C (0x9f9f469f8cd92313), U64_C (0xf0f0e7f0d317fd23),
U64_C (0x4a4a354a6a7f9420), U64_C (0xdada4fda9e95a944),
U64_C (0x58587d58fa25b0a2), U64_C (0xc9c903c906ca8fcf),
U64_C (0x2929a429558d527c), U64_C (0x0a0a280a5022145a),
U64_C (0xb1b1feb1e14f7f50), U64_C (0xa0a0baa0691a5dc9),
U64_C (0x6b6bb16b7fdad614), U64_C (0x85852e855cab17d9),
U64_C (0xbdbdcebd8173673c), U64_C (0x5d5d695dd234ba8f),
U64_C (0x1010401080502090), U64_C (0xf4f4f7f4f303f507),
U64_C (0xcbcb0bcb16c08bdd), U64_C (0x3e3ef83eedc67cd3),
U64_C (0x0505140528110a2d), U64_C (0x676781671fe6ce78),
U64_C (0xe4e4b7e47353d597), U64_C (0x27279c2725bb4e02),
U64_C (0x4141194132588273), U64_C (0x8b8b168b2c9d0ba7),
U64_C (0xa7a7a6a7510153f6), U64_C (0x7d7de97dcf94fab2),
U64_C (0x95956e95dcfb3749), U64_C (0xd8d847d88e9fad56),
U64_C (0xfbfbcbfb8b30eb70), U64_C (0xeeee9fee2371c1cd),
U64_C (0x7c7ced7cc791f8bb), U64_C (0x6666856617e3cc71),
U64_C (0xdddd53dda68ea77b), U64_C (0x17175c17b84b2eaf),
U64_C (0x4747014702468e45), U64_C (0x9e9e429e84dc211a),
U64_C (0xcaca0fca1ec589d4), U64_C (0x2d2db42d75995a58),
U64_C (0xbfbfc6bf9179632e), U64_C (0x07071c07381b0e3f),
U64_C (0xadad8ead012347ac), U64_C (0x5a5a755aea2fb4b0),
U64_C (0x838336836cb51bef), U64_C (0x3333cc3385ff66b6),
U64_C (0x636391633ff2c65c), U64_C (0x02020802100a0412),
U64_C (0xaaaa92aa39384993), U64_C (0x7171d971afa8e2de),
U64_C (0xc8c807c80ecf8dc6), U64_C (0x19196419c87d32d1),
U64_C (0x494939497270923b), U64_C (0xd9d943d9869aaf5f),
U64_C (0xf2f2eff2c31df931), U64_C (0xe3e3abe34b48dba8),
U64_C (0x5b5b715be22ab6b9), U64_C (0x88881a8834920dbc),
U64_C (0x9a9a529aa4c8293e), U64_C (0x262698262dbe4c0b),
U64_C (0x3232c8328dfa64bf), U64_C (0xb0b0fab0e94a7d59),
U64_C (0xe9e983e91b6acff2), U64_C (0x0f0f3c0f78331e77),
U64_C (0xd5d573d5e6a6b733), U64_C (0x80803a8074ba1df4),
U64_C (0xbebec2be997c6127), U64_C (0xcdcd13cd26de87eb),
U64_C (0x3434d034bde46889), U64_C (0x48483d487a759032),
U64_C (0xffffdbffab24e354), U64_C (0x7a7af57af78ff48d),
U64_C (0x90907a90f4ea3d64), U64_C (0x5f5f615fc23ebe9d),
U64_C (0x202080201da0403d), U64_C (0x6868bd6867d5d00f),
U64_C (0x1a1a681ad07234ca), U64_C (0xaeae82ae192c41b7),
U64_C (0xb4b4eab4c95e757d), U64_C (0x54544d549a19a8ce),
U64_C (0x93937693ece53b7f), U64_C (0x222288220daa442f),
U64_C (0x64648d6407e9c863), U64_C (0xf1f1e3f1db12ff2a),
U64_C (0x7373d173bfa2e6cc), U64_C (0x12124812905a2482),
U64_C (0x40401d403a5d807a), U64_C (0x0808200840281048),
U64_C (0xc3c32bc356e89b95), U64_C (0xecec97ec337bc5df),
U64_C (0xdbdb4bdb9690ab4d), U64_C (0xa1a1bea1611f5fc0),
U64_C (0x8d8d0e8d1c830791), U64_C (0x3d3df43df5c97ac8),
U64_C (0x97976697ccf1335b), U64_C (0x0000000000000000),
U64_C (0xcfcf1bcf36d483f9), U64_C (0x2b2bac2b4587566e),
U64_C (0x7676c57697b3ece1), U64_C (0x8282328264b019e6),
U64_C (0xd6d67fd6fea9b128), U64_C (0x1b1b6c1bd87736c3),
U64_C (0xb5b5eeb5c15b7774), U64_C (0xafaf86af112943be),
U64_C (0x6a6ab56a77dfd41d), U64_C (0x50505d50ba0da0ea),
U64_C (0x45450945124c8a57), U64_C (0xf3f3ebf3cb18fb38),
U64_C (0x3030c0309df060ad), U64_C (0xefef9bef2b74c3c4),
U64_C (0x3f3ffc3fe5c37eda), U64_C (0x55554955921caac7),
U64_C (0xa2a2b2a2791059db), U64_C (0xeaea8fea0365c9e9),
U64_C (0x656589650fecca6a), U64_C (0xbabad2bab9686903),
U64_C (0x2f2fbc2f65935e4a), U64_C (0xc0c027c04ee79d8e),
U64_C (0xdede5fdebe81a160), U64_C (0x1c1c701ce06c38fc),
U64_C (0xfdfdd3fdbb2ee746), U64_C (0x4d4d294d52649a1f),
U64_C (0x92927292e4e03976), U64_C (0x7575c9758fbceafa),
U64_C (0x06061806301e0c36), U64_C (0x8a8a128a249809ae),
U64_C (0xb2b2f2b2f940794b), U64_C (0xe6e6bfe66359d185),
U64_C (0x0e0e380e70361c7e), U64_C (0x1f1f7c1ff8633ee7),
U64_C (0x6262956237f7c455), U64_C (0xd4d477d4eea3b53a),
U64_C (0xa8a89aa829324d81), U64_C (0x96966296c4f43152),
U64_C (0xf9f9c3f99b3aef62), U64_C (0xc5c533c566f697a3),
U64_C (0x2525942535b14a10), U64_C (0x59597959f220b2ab),
U64_C (0x84842a8454ae15d0), U64_C (0x7272d572b7a7e4c5),
U64_C (0x3939e439d5dd72ec), U64_C (0x4c4c2d4c5a619816),
U64_C (0x5e5e655eca3bbc94), U64_C (0x7878fd78e785f09f),
U64_C (0x3838e038ddd870e5), U64_C (0x8c8c0a8c14860598),
U64_C (0xd1d163d1c6b2bf17), U64_C (0xa5a5aea5410b57e4),
U64_C (0xe2e2afe2434dd9a1), U64_C (0x616199612ff8c24e),
U64_C (0xb3b3f6b3f1457b42), U64_C (0x2121842115a54234),
U64_C (0x9c9c4a9c94d62508), U64_C (0x1e1e781ef0663cee),
U64_C (0x4343114322528661), U64_C (0xc7c73bc776fc93b1),
U64_C (0xfcfcd7fcb32be54f), U64_C (0x0404100420140824),
U64_C (0x51515951b208a2e3), U64_C (0x99995e99bcc72f25),
U64_C (0x6d6da96d4fc4da22), U64_C (0x0d0d340d68391a65),
U64_C (0xfafacffa8335e979), U64_C (0xdfdf5bdfb684a369),
U64_C (0x7e7ee57ed79bfca9), U64_C (0x242490243db44819),
U64_C (0x3b3bec3bc5d776fe), U64_C (0xabab96ab313d4b9a),
U64_C (0xcece1fce3ed181f0), U64_C (0x1111441188552299),
U64_C (0x8f8f068f0c890383), U64_C (0x4e4e254e4a6b9c04),
U64_C (0xb7b7e6b7d1517366), U64_C (0xebeb8beb0b60cbe0),
U64_C (0x3c3cf03cfdcc78c1), U64_C (0x81813e817cbf1ffd),
U64_C (0x94946a94d4fe3540), U64_C (0xf7f7fbf7eb0cf31c),
U64_C (0xb9b9deb9a1676f18), U64_C (0x13134c13985f268b),
U64_C (0x2c2cb02c7d9c5851), U64_C (0xd3d36bd3d6b8bb05),
U64_C (0xe7e7bbe76b5cd38c), U64_C (0x6e6ea56e57cbdc39),
U64_C (0xc4c437c46ef395aa), U64_C (0x03030c03180f061b),
U64_C (0x565645568a13acdc), U64_C (0x44440d441a49885e),
U64_C (0x7f7fe17fdf9efea0), U64_C (0xa9a99ea921374f88),
U64_C (0x2a2aa82a4d825467), U64_C (0xbbbbd6bbb16d6b0a),
U64_C (0xc1c123c146e29f87), U64_C (0x53535153a202a6f1),
U64_C (0xdcdc57dcae8ba572), U64_C (0x0b0b2c0b58271653),
U64_C (0x9d9d4e9d9cd32701), U64_C (0x6c6cad6c47c1d82b),
U64_C (0x3131c43195f562a4), U64_C (0x7474cd7487b9e8f3),
U64_C (0xf6f6fff6e309f115), U64_C (0x464605460a438c4c),
U64_C (0xacac8aac092645a5), U64_C (0x89891e893c970fb5),
U64_C (0x14145014a04428b4), U64_C (0xe1e1a3e15b42dfba),
U64_C (0x16165816b04e2ca6), U64_C (0x3a3ae83acdd274f7),
U64_C (0x6969b9696fd0d206), U64_C (0x09092409482d1241),
U64_C (0x7070dd70a7ade0d7), U64_C (0xb6b6e2b6d954716f),
U64_C (0xd0d067d0ceb7bd1e), U64_C (0xeded93ed3b7ec7d6),
U64_C (0xcccc17cc2edb85e2), U64_C (0x424215422a578468),
U64_C (0x98985a98b4c22d2c), U64_C (0xa4a4aaa4490e55ed),
U64_C (0x2828a0285d885075), U64_C (0x5c5c6d5cda31b886),
U64_C (0xf8f8c7f8933fed6b), U64_C (0x8686228644a411c2),
}, {
U64_C (0xd818186018c07830), U64_C (0x2623238c2305af46),
U64_C (0xb8c6c63fc67ef991), U64_C (0xfbe8e887e8136fcd),
U64_C (0xcb878726874ca113), U64_C (0x11b8b8dab8a9626d),
U64_C (0x0901010401080502), U64_C (0x0d4f4f214f426e9e),
U64_C (0x9b3636d836adee6c), U64_C (0xffa6a6a2a6590451),
U64_C (0x0cd2d26fd2debdb9), U64_C (0x0ef5f5f3f5fb06f7),
U64_C (0x967979f979ef80f2), U64_C (0x306f6fa16f5fcede),
U64_C (0x6d91917e91fcef3f), U64_C (0xf852525552aa07a4),
U64_C (0x4760609d6027fdc0), U64_C (0x35bcbccabc897665),
U64_C (0x379b9b569baccd2b), U64_C (0x8a8e8e028e048c01),
U64_C (0xd2a3a3b6a371155b), U64_C (0x6c0c0c300c603c18),
U64_C (0x847b7bf17bff8af6), U64_C (0x803535d435b5e16a),
U64_C (0xf51d1d741de8693a), U64_C (0xb3e0e0a7e05347dd),
U64_C (0x21d7d77bd7f6acb3), U64_C (0x9cc2c22fc25eed99),
U64_C (0x432e2eb82e6d965c), U64_C (0x294b4b314b627a96),
U64_C (0x5dfefedffea321e1), U64_C (0xd5575741578216ae),
U64_C (0xbd15155415a8412a), U64_C (0xe87777c1779fb6ee),
U64_C (0x923737dc37a5eb6e), U64_C (0x9ee5e5b3e57b56d7),
U64_C (0x139f9f469f8cd923), U64_C (0x23f0f0e7f0d317fd),
U64_C (0x204a4a354a6a7f94), U64_C (0x44dada4fda9e95a9),
U64_C (0xa258587d58fa25b0), U64_C (0xcfc9c903c906ca8f),
U64_C (0x7c2929a429558d52), U64_C (0x5a0a0a280a502214),
U64_C (0x50b1b1feb1e14f7f), U64_C (0xc9a0a0baa0691a5d),
U64_C (0x146b6bb16b7fdad6), U64_C (0xd985852e855cab17),
U64_C (0x3cbdbdcebd817367), U64_C (0x8f5d5d695dd234ba),
U64_C (0x9010104010805020), U64_C (0x07f4f4f7f4f303f5),
U64_C (0xddcbcb0bcb16c08b), U64_C (0xd33e3ef83eedc67c),
U64_C (0x2d0505140528110a), U64_C (0x78676781671fe6ce),
U64_C (0x97e4e4b7e47353d5), U64_C (0x0227279c2725bb4e),
U64_C (0x7341411941325882), U64_C (0xa78b8b168b2c9d0b),
U64_C (0xf6a7a7a6a7510153), U64_C (0xb27d7de97dcf94fa),
U64_C (0x4995956e95dcfb37), U64_C (0x56d8d847d88e9fad),
U64_C (0x70fbfbcbfb8b30eb), U64_C (0xcdeeee9fee2371c1),
U64_C (0xbb7c7ced7cc791f8), U64_C (0x716666856617e3cc),
U64_C (0x7bdddd53dda68ea7), U64_C (0xaf17175c17b84b2e),
U64_C (0x454747014702468e), U64_C (0x1a9e9e429e84dc21),
U64_C (0xd4caca0fca1ec589), U64_C (0x582d2db42d75995a),
U64_C (0x2ebfbfc6bf917963), U64_C (0x3f07071c07381b0e),
U64_C (0xacadad8ead012347), U64_C (0xb05a5a755aea2fb4),
U64_C (0xef838336836cb51b), U64_C (0xb63333cc3385ff66),
U64_C (0x5c636391633ff2c6), U64_C (0x1202020802100a04),
U64_C (0x93aaaa92aa393849), U64_C (0xde7171d971afa8e2),
U64_C (0xc6c8c807c80ecf8d), U64_C (0xd119196419c87d32),
U64_C (0x3b49493949727092), U64_C (0x5fd9d943d9869aaf),
U64_C (0x31f2f2eff2c31df9), U64_C (0xa8e3e3abe34b48db),
U64_C (0xb95b5b715be22ab6), U64_C (0xbc88881a8834920d),
U64_C (0x3e9a9a529aa4c829), U64_C (0x0b262698262dbe4c),
U64_C (0xbf3232c8328dfa64), U64_C (0x59b0b0fab0e94a7d),
U64_C (0xf2e9e983e91b6acf), U64_C (0x770f0f3c0f78331e),
U64_C (0x33d5d573d5e6a6b7), U64_C (0xf480803a8074ba1d),
U64_C (0x27bebec2be997c61), U64_C (0xebcdcd13cd26de87),
U64_C (0x893434d034bde468), U64_C (0x3248483d487a7590),
U64_C (0x54ffffdbffab24e3), U64_C (0x8d7a7af57af78ff4),
U64_C (0x6490907a90f4ea3d), U64_C (0x9d5f5f615fc23ebe),
U64_C (0x3d202080201da040), U64_C (0x0f6868bd6867d5d0),
U64_C (0xca1a1a681ad07234), U64_C (0xb7aeae82ae192c41),
U64_C (0x7db4b4eab4c95e75), U64_C (0xce54544d549a19a8),
U64_C (0x7f93937693ece53b), U64_C (0x2f222288220daa44),
U64_C (0x6364648d6407e9c8), U64_C (0x2af1f1e3f1db12ff),
U64_C (0xcc7373d173bfa2e6), U64_C (0x8212124812905a24),
U64_C (0x7a40401d403a5d80), U64_C (0x4808082008402810),
U64_C (0x95c3c32bc356e89b), U64_C (0xdfecec97ec337bc5),
U64_C (0x4ddbdb4bdb9690ab), U64_C (0xc0a1a1bea1611f5f),
U64_C (0x918d8d0e8d1c8307), U64_C (0xc83d3df43df5c97a),
U64_C (0x5b97976697ccf133), U64_C (0x0000000000000000),
U64_C (0xf9cfcf1bcf36d483), U64_C (0x6e2b2bac2b458756),
U64_C (0xe17676c57697b3ec), U64_C (0xe68282328264b019),
U64_C (0x28d6d67fd6fea9b1), U64_C (0xc31b1b6c1bd87736),
U64_C (0x74b5b5eeb5c15b77), U64_C (0xbeafaf86af112943),
U64_C (0x1d6a6ab56a77dfd4), U64_C (0xea50505d50ba0da0),
U64_C (0x5745450945124c8a), U64_C (0x38f3f3ebf3cb18fb),
U64_C (0xad3030c0309df060), U64_C (0xc4efef9bef2b74c3),
U64_C (0xda3f3ffc3fe5c37e), U64_C (0xc755554955921caa),
U64_C (0xdba2a2b2a2791059), U64_C (0xe9eaea8fea0365c9),
U64_C (0x6a656589650fecca), U64_C (0x03babad2bab96869),
U64_C (0x4a2f2fbc2f65935e), U64_C (0x8ec0c027c04ee79d),
U64_C (0x60dede5fdebe81a1), U64_C (0xfc1c1c701ce06c38),
U64_C (0x46fdfdd3fdbb2ee7), U64_C (0x1f4d4d294d52649a),
U64_C (0x7692927292e4e039), U64_C (0xfa7575c9758fbcea),
U64_C (0x3606061806301e0c), U64_C (0xae8a8a128a249809),
U64_C (0x4bb2b2f2b2f94079), U64_C (0x85e6e6bfe66359d1),
U64_C (0x7e0e0e380e70361c), U64_C (0xe71f1f7c1ff8633e),
U64_C (0x556262956237f7c4), U64_C (0x3ad4d477d4eea3b5),
U64_C (0x81a8a89aa829324d), U64_C (0x5296966296c4f431),
U64_C (0x62f9f9c3f99b3aef), U64_C (0xa3c5c533c566f697),
U64_C (0x102525942535b14a), U64_C (0xab59597959f220b2),
U64_C (0xd084842a8454ae15), U64_C (0xc57272d572b7a7e4),
U64_C (0xec3939e439d5dd72), U64_C (0x164c4c2d4c5a6198),
U64_C (0x945e5e655eca3bbc), U64_C (0x9f7878fd78e785f0),
U64_C (0xe53838e038ddd870), U64_C (0x988c8c0a8c148605),
U64_C (0x17d1d163d1c6b2bf), U64_C (0xe4a5a5aea5410b57),
U64_C (0xa1e2e2afe2434dd9), U64_C (0x4e616199612ff8c2),
U64_C (0x42b3b3f6b3f1457b), U64_C (0x342121842115a542),
U64_C (0x089c9c4a9c94d625), U64_C (0xee1e1e781ef0663c),
U64_C (0x6143431143225286), U64_C (0xb1c7c73bc776fc93),
U64_C (0x4ffcfcd7fcb32be5), U64_C (0x2404041004201408),
U64_C (0xe351515951b208a2), U64_C (0x2599995e99bcc72f),
U64_C (0x226d6da96d4fc4da), U64_C (0x650d0d340d68391a),
U64_C (0x79fafacffa8335e9), U64_C (0x69dfdf5bdfb684a3),
U64_C (0xa97e7ee57ed79bfc), U64_C (0x19242490243db448),
U64_C (0xfe3b3bec3bc5d776), U64_C (0x9aabab96ab313d4b),
U64_C (0xf0cece1fce3ed181), U64_C (0x9911114411885522),
U64_C (0x838f8f068f0c8903), U64_C (0x044e4e254e4a6b9c),
U64_C (0x66b7b7e6b7d15173), U64_C (0xe0ebeb8beb0b60cb),
U64_C (0xc13c3cf03cfdcc78), U64_C (0xfd81813e817cbf1f),
U64_C (0x4094946a94d4fe35), U64_C (0x1cf7f7fbf7eb0cf3),
U64_C (0x18b9b9deb9a1676f), U64_C (0x8b13134c13985f26),
U64_C (0x512c2cb02c7d9c58), U64_C (0x05d3d36bd3d6b8bb),
U64_C (0x8ce7e7bbe76b5cd3), U64_C (0x396e6ea56e57cbdc),
U64_C (0xaac4c437c46ef395), U64_C (0x1b03030c03180f06),
U64_C (0xdc565645568a13ac), U64_C (0x5e44440d441a4988),
U64_C (0xa07f7fe17fdf9efe), U64_C (0x88a9a99ea921374f),
U64_C (0x672a2aa82a4d8254), U64_C (0x0abbbbd6bbb16d6b),
U64_C (0x87c1c123c146e29f), U64_C (0xf153535153a202a6),
U64_C (0x72dcdc57dcae8ba5), U64_C (0x530b0b2c0b582716),
U64_C (0x019d9d4e9d9cd327), U64_C (0x2b6c6cad6c47c1d8),
U64_C (0xa43131c43195f562), U64_C (0xf37474cd7487b9e8),
U64_C (0x15f6f6fff6e309f1), U64_C (0x4c464605460a438c),
U64_C (0xa5acac8aac092645), U64_C (0xb589891e893c970f),
U64_C (0xb414145014a04428), U64_C (0xbae1e1a3e15b42df),
U64_C (0xa616165816b04e2c), U64_C (0xf73a3ae83acdd274),
U64_C (0x066969b9696fd0d2), U64_C (0x4109092409482d12),
U64_C (0xd77070dd70a7ade0), U64_C (0x6fb6b6e2b6d95471),
U64_C (0x1ed0d067d0ceb7bd), U64_C (0xd6eded93ed3b7ec7),
U64_C (0xe2cccc17cc2edb85), U64_C (0x68424215422a5784),
U64_C (0x2c98985a98b4c22d), U64_C (0xeda4a4aaa4490e55),
U64_C (0x752828a0285d8850), U64_C (0x865c5c6d5cda31b8),
U64_C (0x6bf8f8c7f8933fed), U64_C (0xc28686228644a411),
}, {
U64_C (0x30d818186018c078), U64_C (0x462623238c2305af),
U64_C (0x91b8c6c63fc67ef9), U64_C (0xcdfbe8e887e8136f),
U64_C (0x13cb878726874ca1), U64_C (0x6d11b8b8dab8a962),
U64_C (0x0209010104010805), U64_C (0x9e0d4f4f214f426e),
U64_C (0x6c9b3636d836adee), U64_C (0x51ffa6a6a2a65904),
U64_C (0xb90cd2d26fd2debd), U64_C (0xf70ef5f5f3f5fb06),
U64_C (0xf2967979f979ef80), U64_C (0xde306f6fa16f5fce),
U64_C (0x3f6d91917e91fcef), U64_C (0xa4f852525552aa07),
U64_C (0xc04760609d6027fd), U64_C (0x6535bcbccabc8976),
U64_C (0x2b379b9b569baccd), U64_C (0x018a8e8e028e048c),
U64_C (0x5bd2a3a3b6a37115), U64_C (0x186c0c0c300c603c),
U64_C (0xf6847b7bf17bff8a), U64_C (0x6a803535d435b5e1),
U64_C (0x3af51d1d741de869), U64_C (0xddb3e0e0a7e05347),
U64_C (0xb321d7d77bd7f6ac), U64_C (0x999cc2c22fc25eed),
U64_C (0x5c432e2eb82e6d96), U64_C (0x96294b4b314b627a),
U64_C (0xe15dfefedffea321), U64_C (0xaed5575741578216),
U64_C (0x2abd15155415a841), U64_C (0xeee87777c1779fb6),
U64_C (0x6e923737dc37a5eb), U64_C (0xd79ee5e5b3e57b56),
U64_C (0x23139f9f469f8cd9), U64_C (0xfd23f0f0e7f0d317),
U64_C (0x94204a4a354a6a7f), U64_C (0xa944dada4fda9e95),
U64_C (0xb0a258587d58fa25), U64_C (0x8fcfc9c903c906ca),
U64_C (0x527c2929a429558d), U64_C (0x145a0a0a280a5022),
U64_C (0x7f50b1b1feb1e14f), U64_C (0x5dc9a0a0baa0691a),
U64_C (0xd6146b6bb16b7fda), U64_C (0x17d985852e855cab),
U64_C (0x673cbdbdcebd8173), U64_C (0xba8f5d5d695dd234),
U64_C (0x2090101040108050), U64_C (0xf507f4f4f7f4f303),
U64_C (0x8bddcbcb0bcb16c0), U64_C (0x7cd33e3ef83eedc6),
U64_C (0x0a2d050514052811), U64_C (0xce78676781671fe6),
U64_C (0xd597e4e4b7e47353), U64_C (0x4e0227279c2725bb),
U64_C (0x8273414119413258), U64_C (0x0ba78b8b168b2c9d),
U64_C (0x53f6a7a7a6a75101), U64_C (0xfab27d7de97dcf94),
U64_C (0x374995956e95dcfb), U64_C (0xad56d8d847d88e9f),
U64_C (0xeb70fbfbcbfb8b30), U64_C (0xc1cdeeee9fee2371),
U64_C (0xf8bb7c7ced7cc791), U64_C (0xcc716666856617e3),
U64_C (0xa77bdddd53dda68e), U64_C (0x2eaf17175c17b84b),
U64_C (0x8e45474701470246), U64_C (0x211a9e9e429e84dc),
U64_C (0x89d4caca0fca1ec5), U64_C (0x5a582d2db42d7599),
U64_C (0x632ebfbfc6bf9179), U64_C (0x0e3f07071c07381b),
U64_C (0x47acadad8ead0123), U64_C (0xb4b05a5a755aea2f),
U64_C (0x1bef838336836cb5), U64_C (0x66b63333cc3385ff),
U64_C (0xc65c636391633ff2), U64_C (0x041202020802100a),
U64_C (0x4993aaaa92aa3938), U64_C (0xe2de7171d971afa8),
U64_C (0x8dc6c8c807c80ecf), U64_C (0x32d119196419c87d),
U64_C (0x923b494939497270), U64_C (0xaf5fd9d943d9869a),
U64_C (0xf931f2f2eff2c31d), U64_C (0xdba8e3e3abe34b48),
U64_C (0xb6b95b5b715be22a), U64_C (0x0dbc88881a883492),
U64_C (0x293e9a9a529aa4c8), U64_C (0x4c0b262698262dbe),
U64_C (0x64bf3232c8328dfa), U64_C (0x7d59b0b0fab0e94a),
U64_C (0xcff2e9e983e91b6a), U64_C (0x1e770f0f3c0f7833),
U64_C (0xb733d5d573d5e6a6), U64_C (0x1df480803a8074ba),
U64_C (0x6127bebec2be997c), U64_C (0x87ebcdcd13cd26de),
U64_C (0x68893434d034bde4), U64_C (0x903248483d487a75),
U64_C (0xe354ffffdbffab24), U64_C (0xf48d7a7af57af78f),
U64_C (0x3d6490907a90f4ea), U64_C (0xbe9d5f5f615fc23e),
U64_C (0x403d202080201da0), U64_C (0xd00f6868bd6867d5),
U64_C (0x34ca1a1a681ad072), U64_C (0x41b7aeae82ae192c),
U64_C (0x757db4b4eab4c95e), U64_C (0xa8ce54544d549a19),
U64_C (0x3b7f93937693ece5), U64_C (0x442f222288220daa),
U64_C (0xc86364648d6407e9), U64_C (0xff2af1f1e3f1db12),
U64_C (0xe6cc7373d173bfa2), U64_C (0x248212124812905a),
U64_C (0x807a40401d403a5d), U64_C (0x1048080820084028),
U64_C (0x9b95c3c32bc356e8), U64_C (0xc5dfecec97ec337b),
U64_C (0xab4ddbdb4bdb9690), U64_C (0x5fc0a1a1bea1611f),
U64_C (0x07918d8d0e8d1c83), U64_C (0x7ac83d3df43df5c9),
U64_C (0x335b97976697ccf1), U64_C (0x0000000000000000),
U64_C (0x83f9cfcf1bcf36d4), U64_C (0x566e2b2bac2b4587),
U64_C (0xece17676c57697b3), U64_C (0x19e68282328264b0),
U64_C (0xb128d6d67fd6fea9), U64_C (0x36c31b1b6c1bd877),
U64_C (0x7774b5b5eeb5c15b), U64_C (0x43beafaf86af1129),
U64_C (0xd41d6a6ab56a77df), U64_C (0xa0ea50505d50ba0d),
U64_C (0x8a5745450945124c), U64_C (0xfb38f3f3ebf3cb18),
U64_C (0x60ad3030c0309df0), U64_C (0xc3c4efef9bef2b74),
U64_C (0x7eda3f3ffc3fe5c3), U64_C (0xaac755554955921c),
U64_C (0x59dba2a2b2a27910), U64_C (0xc9e9eaea8fea0365),
U64_C (0xca6a656589650fec), U64_C (0x6903babad2bab968),
U64_C (0x5e4a2f2fbc2f6593), U64_C (0x9d8ec0c027c04ee7),
U64_C (0xa160dede5fdebe81), U64_C (0x38fc1c1c701ce06c),
U64_C (0xe746fdfdd3fdbb2e), U64_C (0x9a1f4d4d294d5264),
U64_C (0x397692927292e4e0), U64_C (0xeafa7575c9758fbc),
U64_C (0x0c3606061806301e), U64_C (0x09ae8a8a128a2498),
U64_C (0x794bb2b2f2b2f940), U64_C (0xd185e6e6bfe66359),
U64_C (0x1c7e0e0e380e7036), U64_C (0x3ee71f1f7c1ff863),
U64_C (0xc4556262956237f7), U64_C (0xb53ad4d477d4eea3),
U64_C (0x4d81a8a89aa82932), U64_C (0x315296966296c4f4),
U64_C (0xef62f9f9c3f99b3a), U64_C (0x97a3c5c533c566f6),
U64_C (0x4a102525942535b1), U64_C (0xb2ab59597959f220),
U64_C (0x15d084842a8454ae), U64_C (0xe4c57272d572b7a7),
U64_C (0x72ec3939e439d5dd), U64_C (0x98164c4c2d4c5a61),
U64_C (0xbc945e5e655eca3b), U64_C (0xf09f7878fd78e785),
U64_C (0x70e53838e038ddd8), U64_C (0x05988c8c0a8c1486),
U64_C (0xbf17d1d163d1c6b2), U64_C (0x57e4a5a5aea5410b),
U64_C (0xd9a1e2e2afe2434d), U64_C (0xc24e616199612ff8),
U64_C (0x7b42b3b3f6b3f145), U64_C (0x42342121842115a5),
U64_C (0x25089c9c4a9c94d6), U64_C (0x3cee1e1e781ef066),
U64_C (0x8661434311432252), U64_C (0x93b1c7c73bc776fc),
U64_C (0xe54ffcfcd7fcb32b), U64_C (0x0824040410042014),
U64_C (0xa2e351515951b208), U64_C (0x2f2599995e99bcc7),
U64_C (0xda226d6da96d4fc4), U64_C (0x1a650d0d340d6839),
U64_C (0xe979fafacffa8335), U64_C (0xa369dfdf5bdfb684),
U64_C (0xfca97e7ee57ed79b), U64_C (0x4819242490243db4),
U64_C (0x76fe3b3bec3bc5d7), U64_C (0x4b9aabab96ab313d),
U64_C (0x81f0cece1fce3ed1), U64_C (0x2299111144118855),
U64_C (0x03838f8f068f0c89), U64_C (0x9c044e4e254e4a6b),
U64_C (0x7366b7b7e6b7d151), U64_C (0xcbe0ebeb8beb0b60),
U64_C (0x78c13c3cf03cfdcc), U64_C (0x1ffd81813e817cbf),
U64_C (0x354094946a94d4fe), U64_C (0xf31cf7f7fbf7eb0c),
U64_C (0x6f18b9b9deb9a167), U64_C (0x268b13134c13985f),
U64_C (0x58512c2cb02c7d9c), U64_C (0xbb05d3d36bd3d6b8),
U64_C (0xd38ce7e7bbe76b5c), U64_C (0xdc396e6ea56e57cb),
U64_C (0x95aac4c437c46ef3), U64_C (0x061b03030c03180f),
U64_C (0xacdc565645568a13), U64_C (0x885e44440d441a49),
U64_C (0xfea07f7fe17fdf9e), U64_C (0x4f88a9a99ea92137),
U64_C (0x54672a2aa82a4d82), U64_C (0x6b0abbbbd6bbb16d),
U64_C (0x9f87c1c123c146e2), U64_C (0xa6f153535153a202),
U64_C (0xa572dcdc57dcae8b), U64_C (0x16530b0b2c0b5827),
U64_C (0x27019d9d4e9d9cd3), U64_C (0xd82b6c6cad6c47c1),
U64_C (0x62a43131c43195f5), U64_C (0xe8f37474cd7487b9),
U64_C (0xf115f6f6fff6e309), U64_C (0x8c4c464605460a43),
U64_C (0x45a5acac8aac0926), U64_C (0x0fb589891e893c97),
U64_C (0x28b414145014a044), U64_C (0xdfbae1e1a3e15b42),
U64_C (0x2ca616165816b04e), U64_C (0x74f73a3ae83acdd2),
U64_C (0xd2066969b9696fd0), U64_C (0x124109092409482d),
U64_C (0xe0d77070dd70a7ad), U64_C (0x716fb6b6e2b6d954),
U64_C (0xbd1ed0d067d0ceb7), U64_C (0xc7d6eded93ed3b7e),
U64_C (0x85e2cccc17cc2edb), U64_C (0x8468424215422a57),
U64_C (0x2d2c98985a98b4c2), U64_C (0x55eda4a4aaa4490e),
U64_C (0x50752828a0285d88), U64_C (0xb8865c5c6d5cda31),
U64_C (0xed6bf8f8c7f8933f), U64_C (0x11c28686228644a4),
}, {
U64_C (0x7830d818186018c0), U64_C (0xaf462623238c2305),
U64_C (0xf991b8c6c63fc67e), U64_C (0x6fcdfbe8e887e813),
U64_C (0xa113cb878726874c), U64_C (0x626d11b8b8dab8a9),
U64_C (0x0502090101040108), U64_C (0x6e9e0d4f4f214f42),
U64_C (0xee6c9b3636d836ad), U64_C (0x0451ffa6a6a2a659),
U64_C (0xbdb90cd2d26fd2de), U64_C (0x06f70ef5f5f3f5fb),
U64_C (0x80f2967979f979ef), U64_C (0xcede306f6fa16f5f),
U64_C (0xef3f6d91917e91fc), U64_C (0x07a4f852525552aa),
U64_C (0xfdc04760609d6027), U64_C (0x766535bcbccabc89),
U64_C (0xcd2b379b9b569bac), U64_C (0x8c018a8e8e028e04),
U64_C (0x155bd2a3a3b6a371), U64_C (0x3c186c0c0c300c60),
U64_C (0x8af6847b7bf17bff), U64_C (0xe16a803535d435b5),
U64_C (0x693af51d1d741de8), U64_C (0x47ddb3e0e0a7e053),
U64_C (0xacb321d7d77bd7f6), U64_C (0xed999cc2c22fc25e),
U64_C (0x965c432e2eb82e6d), U64_C (0x7a96294b4b314b62),
U64_C (0x21e15dfefedffea3), U64_C (0x16aed55757415782),
U64_C (0x412abd15155415a8), U64_C (0xb6eee87777c1779f),
U64_C (0xeb6e923737dc37a5), U64_C (0x56d79ee5e5b3e57b),
U64_C (0xd923139f9f469f8c), U64_C (0x17fd23f0f0e7f0d3),
U64_C (0x7f94204a4a354a6a), U64_C (0x95a944dada4fda9e),
U64_C (0x25b0a258587d58fa), U64_C (0xca8fcfc9c903c906),
U64_C (0x8d527c2929a42955), U64_C (0x22145a0a0a280a50),
U64_C (0x4f7f50b1b1feb1e1), U64_C (0x1a5dc9a0a0baa069),
U64_C (0xdad6146b6bb16b7f), U64_C (0xab17d985852e855c),
U64_C (0x73673cbdbdcebd81), U64_C (0x34ba8f5d5d695dd2),
U64_C (0x5020901010401080), U64_C (0x03f507f4f4f7f4f3),
U64_C (0xc08bddcbcb0bcb16), U64_C (0xc67cd33e3ef83eed),
U64_C (0x110a2d0505140528), U64_C (0xe6ce78676781671f),
U64_C (0x53d597e4e4b7e473), U64_C (0xbb4e0227279c2725),
U64_C (0x5882734141194132), U64_C (0x9d0ba78b8b168b2c),
U64_C (0x0153f6a7a7a6a751), U64_C (0x94fab27d7de97dcf),
U64_C (0xfb374995956e95dc), U64_C (0x9fad56d8d847d88e),
U64_C (0x30eb70fbfbcbfb8b), U64_C (0x71c1cdeeee9fee23),
U64_C (0x91f8bb7c7ced7cc7), U64_C (0xe3cc716666856617),
U64_C (0x8ea77bdddd53dda6), U64_C (0x4b2eaf17175c17b8),
U64_C (0x468e454747014702), U64_C (0xdc211a9e9e429e84),
U64_C (0xc589d4caca0fca1e), U64_C (0x995a582d2db42d75),
U64_C (0x79632ebfbfc6bf91), U64_C (0x1b0e3f07071c0738),
U64_C (0x2347acadad8ead01), U64_C (0x2fb4b05a5a755aea),
U64_C (0xb51bef838336836c), U64_C (0xff66b63333cc3385),
U64_C (0xf2c65c636391633f), U64_C (0x0a04120202080210),
U64_C (0x384993aaaa92aa39), U64_C (0xa8e2de7171d971af),
U64_C (0xcf8dc6c8c807c80e), U64_C (0x7d32d119196419c8),
U64_C (0x70923b4949394972), U64_C (0x9aaf5fd9d943d986),
U64_C (0x1df931f2f2eff2c3), U64_C (0x48dba8e3e3abe34b),
U64_C (0x2ab6b95b5b715be2), U64_C (0x920dbc88881a8834),
U64_C (0xc8293e9a9a529aa4), U64_C (0xbe4c0b262698262d),
U64_C (0xfa64bf3232c8328d), U64_C (0x4a7d59b0b0fab0e9),
U64_C (0x6acff2e9e983e91b), U64_C (0x331e770f0f3c0f78),
U64_C (0xa6b733d5d573d5e6), U64_C (0xba1df480803a8074),
U64_C (0x7c6127bebec2be99), U64_C (0xde87ebcdcd13cd26),
U64_C (0xe468893434d034bd), U64_C (0x75903248483d487a),
U64_C (0x24e354ffffdbffab), U64_C (0x8ff48d7a7af57af7),
U64_C (0xea3d6490907a90f4), U64_C (0x3ebe9d5f5f615fc2),
U64_C (0xa0403d202080201d), U64_C (0xd5d00f6868bd6867),
U64_C (0x7234ca1a1a681ad0), U64_C (0x2c41b7aeae82ae19),
U64_C (0x5e757db4b4eab4c9), U64_C (0x19a8ce54544d549a),
U64_C (0xe53b7f93937693ec), U64_C (0xaa442f222288220d),
U64_C (0xe9c86364648d6407), U64_C (0x12ff2af1f1e3f1db),
U64_C (0xa2e6cc7373d173bf), U64_C (0x5a24821212481290),
U64_C (0x5d807a40401d403a), U64_C (0x2810480808200840),
U64_C (0xe89b95c3c32bc356), U64_C (0x7bc5dfecec97ec33),
U64_C (0x90ab4ddbdb4bdb96), U64_C (0x1f5fc0a1a1bea161),
U64_C (0x8307918d8d0e8d1c), U64_C (0xc97ac83d3df43df5),
U64_C (0xf1335b97976697cc), U64_C (0x0000000000000000),
U64_C (0xd483f9cfcf1bcf36), U64_C (0x87566e2b2bac2b45),
U64_C (0xb3ece17676c57697), U64_C (0xb019e68282328264),
U64_C (0xa9b128d6d67fd6fe), U64_C (0x7736c31b1b6c1bd8),
U64_C (0x5b7774b5b5eeb5c1), U64_C (0x2943beafaf86af11),
U64_C (0xdfd41d6a6ab56a77), U64_C (0x0da0ea50505d50ba),
U64_C (0x4c8a574545094512), U64_C (0x18fb38f3f3ebf3cb),
U64_C (0xf060ad3030c0309d), U64_C (0x74c3c4efef9bef2b),
U64_C (0xc37eda3f3ffc3fe5), U64_C (0x1caac75555495592),
U64_C (0x1059dba2a2b2a279), U64_C (0x65c9e9eaea8fea03),
U64_C (0xecca6a656589650f), U64_C (0x686903babad2bab9),
U64_C (0x935e4a2f2fbc2f65), U64_C (0xe79d8ec0c027c04e),
U64_C (0x81a160dede5fdebe), U64_C (0x6c38fc1c1c701ce0),
U64_C (0x2ee746fdfdd3fdbb), U64_C (0x649a1f4d4d294d52),
U64_C (0xe0397692927292e4), U64_C (0xbceafa7575c9758f),
U64_C (0x1e0c360606180630), U64_C (0x9809ae8a8a128a24),
U64_C (0x40794bb2b2f2b2f9), U64_C (0x59d185e6e6bfe663),
U64_C (0x361c7e0e0e380e70), U64_C (0x633ee71f1f7c1ff8),
U64_C (0xf7c4556262956237), U64_C (0xa3b53ad4d477d4ee),
U64_C (0x324d81a8a89aa829), U64_C (0xf4315296966296c4),
U64_C (0x3aef62f9f9c3f99b), U64_C (0xf697a3c5c533c566),
U64_C (0xb14a102525942535), U64_C (0x20b2ab59597959f2),
U64_C (0xae15d084842a8454), U64_C (0xa7e4c57272d572b7),
U64_C (0xdd72ec3939e439d5), U64_C (0x6198164c4c2d4c5a),
U64_C (0x3bbc945e5e655eca), U64_C (0x85f09f7878fd78e7),
U64_C (0xd870e53838e038dd), U64_C (0x8605988c8c0a8c14),
U64_C (0xb2bf17d1d163d1c6), U64_C (0x0b57e4a5a5aea541),
U64_C (0x4dd9a1e2e2afe243), U64_C (0xf8c24e616199612f),
U64_C (0x457b42b3b3f6b3f1), U64_C (0xa542342121842115),
U64_C (0xd625089c9c4a9c94), U64_C (0x663cee1e1e781ef0),
U64_C (0x5286614343114322), U64_C (0xfc93b1c7c73bc776),
U64_C (0x2be54ffcfcd7fcb3), U64_C (0x1408240404100420),
U64_C (0x08a2e351515951b2), U64_C (0xc72f2599995e99bc),
U64_C (0xc4da226d6da96d4f), U64_C (0x391a650d0d340d68),
U64_C (0x35e979fafacffa83), U64_C (0x84a369dfdf5bdfb6),
U64_C (0x9bfca97e7ee57ed7), U64_C (0xb44819242490243d),
U64_C (0xd776fe3b3bec3bc5), U64_C (0x3d4b9aabab96ab31),
U64_C (0xd181f0cece1fce3e), U64_C (0x5522991111441188),
U64_C (0x8903838f8f068f0c), U64_C (0x6b9c044e4e254e4a),
U64_C (0x517366b7b7e6b7d1), U64_C (0x60cbe0ebeb8beb0b),
U64_C (0xcc78c13c3cf03cfd), U64_C (0xbf1ffd81813e817c),
U64_C (0xfe354094946a94d4), U64_C (0x0cf31cf7f7fbf7eb),
U64_C (0x676f18b9b9deb9a1), U64_C (0x5f268b13134c1398),
U64_C (0x9c58512c2cb02c7d), U64_C (0xb8bb05d3d36bd3d6),
U64_C (0x5cd38ce7e7bbe76b), U64_C (0xcbdc396e6ea56e57),
U64_C (0xf395aac4c437c46e), U64_C (0x0f061b03030c0318),
U64_C (0x13acdc565645568a), U64_C (0x49885e44440d441a),
U64_C (0x9efea07f7fe17fdf), U64_C (0x374f88a9a99ea921),
U64_C (0x8254672a2aa82a4d), U64_C (0x6d6b0abbbbd6bbb1),
U64_C (0xe29f87c1c123c146), U64_C (0x02a6f153535153a2),
U64_C (0x8ba572dcdc57dcae), U64_C (0x2716530b0b2c0b58),
U64_C (0xd327019d9d4e9d9c), U64_C (0xc1d82b6c6cad6c47),
U64_C (0xf562a43131c43195), U64_C (0xb9e8f37474cd7487),
U64_C (0x09f115f6f6fff6e3), U64_C (0x438c4c464605460a),
U64_C (0x2645a5acac8aac09), U64_C (0x970fb589891e893c),
U64_C (0x4428b414145014a0), U64_C (0x42dfbae1e1a3e15b),
U64_C (0x4e2ca616165816b0), U64_C (0xd274f73a3ae83acd),
U64_C (0xd0d2066969b9696f), U64_C (0x2d12410909240948),
U64_C (0xade0d77070dd70a7), U64_C (0x54716fb6b6e2b6d9),
U64_C (0xb7bd1ed0d067d0ce), U64_C (0x7ec7d6eded93ed3b),
U64_C (0xdb85e2cccc17cc2e), U64_C (0x578468424215422a),
U64_C (0xc22d2c98985a98b4), U64_C (0x0e55eda4a4aaa449),
U64_C (0x8850752828a0285d), U64_C (0x31b8865c5c6d5cda),
U64_C (0x3fed6bf8f8c7f893), U64_C (0xa411c28686228644),
}, {
U64_C (0xc07830d818186018), U64_C (0x05af462623238c23),
U64_C (0x7ef991b8c6c63fc6), U64_C (0x136fcdfbe8e887e8),
U64_C (0x4ca113cb87872687), U64_C (0xa9626d11b8b8dab8),
U64_C (0x0805020901010401), U64_C (0x426e9e0d4f4f214f),
U64_C (0xadee6c9b3636d836), U64_C (0x590451ffa6a6a2a6),
U64_C (0xdebdb90cd2d26fd2), U64_C (0xfb06f70ef5f5f3f5),
U64_C (0xef80f2967979f979), U64_C (0x5fcede306f6fa16f),
U64_C (0xfcef3f6d91917e91), U64_C (0xaa07a4f852525552),
U64_C (0x27fdc04760609d60), U64_C (0x89766535bcbccabc),
U64_C (0xaccd2b379b9b569b), U64_C (0x048c018a8e8e028e),
U64_C (0x71155bd2a3a3b6a3), U64_C (0x603c186c0c0c300c),
U64_C (0xff8af6847b7bf17b), U64_C (0xb5e16a803535d435),
U64_C (0xe8693af51d1d741d), U64_C (0x5347ddb3e0e0a7e0),
U64_C (0xf6acb321d7d77bd7), U64_C (0x5eed999cc2c22fc2),
U64_C (0x6d965c432e2eb82e), U64_C (0x627a96294b4b314b),
U64_C (0xa321e15dfefedffe), U64_C (0x8216aed557574157),
U64_C (0xa8412abd15155415), U64_C (0x9fb6eee87777c177),
U64_C (0xa5eb6e923737dc37), U64_C (0x7b56d79ee5e5b3e5),
U64_C (0x8cd923139f9f469f), U64_C (0xd317fd23f0f0e7f0),
U64_C (0x6a7f94204a4a354a), U64_C (0x9e95a944dada4fda),
U64_C (0xfa25b0a258587d58), U64_C (0x06ca8fcfc9c903c9),
U64_C (0x558d527c2929a429), U64_C (0x5022145a0a0a280a),
U64_C (0xe14f7f50b1b1feb1), U64_C (0x691a5dc9a0a0baa0),
U64_C (0x7fdad6146b6bb16b), U64_C (0x5cab17d985852e85),
U64_C (0x8173673cbdbdcebd), U64_C (0xd234ba8f5d5d695d),
U64_C (0x8050209010104010), U64_C (0xf303f507f4f4f7f4),
U64_C (0x16c08bddcbcb0bcb), U64_C (0xedc67cd33e3ef83e),
U64_C (0x28110a2d05051405), U64_C (0x1fe6ce7867678167),
U64_C (0x7353d597e4e4b7e4), U64_C (0x25bb4e0227279c27),
U64_C (0x3258827341411941), U64_C (0x2c9d0ba78b8b168b),
U64_C (0x510153f6a7a7a6a7), U64_C (0xcf94fab27d7de97d),
U64_C (0xdcfb374995956e95), U64_C (0x8e9fad56d8d847d8),
U64_C (0x8b30eb70fbfbcbfb), U64_C (0x2371c1cdeeee9fee),
U64_C (0xc791f8bb7c7ced7c), U64_C (0x17e3cc7166668566),
U64_C (0xa68ea77bdddd53dd), U64_C (0xb84b2eaf17175c17),
U64_C (0x02468e4547470147), U64_C (0x84dc211a9e9e429e),
U64_C (0x1ec589d4caca0fca), U64_C (0x75995a582d2db42d),
U64_C (0x9179632ebfbfc6bf), U64_C (0x381b0e3f07071c07),
U64_C (0x012347acadad8ead), U64_C (0xea2fb4b05a5a755a),
U64_C (0x6cb51bef83833683), U64_C (0x85ff66b63333cc33),
U64_C (0x3ff2c65c63639163), U64_C (0x100a041202020802),
U64_C (0x39384993aaaa92aa), U64_C (0xafa8e2de7171d971),
U64_C (0x0ecf8dc6c8c807c8), U64_C (0xc87d32d119196419),
U64_C (0x7270923b49493949), U64_C (0x869aaf5fd9d943d9),
U64_C (0xc31df931f2f2eff2), U64_C (0x4b48dba8e3e3abe3),
U64_C (0xe22ab6b95b5b715b), U64_C (0x34920dbc88881a88),
U64_C (0xa4c8293e9a9a529a), U64_C (0x2dbe4c0b26269826),
U64_C (0x8dfa64bf3232c832), U64_C (0xe94a7d59b0b0fab0),
U64_C (0x1b6acff2e9e983e9), U64_C (0x78331e770f0f3c0f),
U64_C (0xe6a6b733d5d573d5), U64_C (0x74ba1df480803a80),
U64_C (0x997c6127bebec2be), U64_C (0x26de87ebcdcd13cd),
U64_C (0xbde468893434d034), U64_C (0x7a75903248483d48),
U64_C (0xab24e354ffffdbff), U64_C (0xf78ff48d7a7af57a),
U64_C (0xf4ea3d6490907a90), U64_C (0xc23ebe9d5f5f615f),
U64_C (0x1da0403d20208020), U64_C (0x67d5d00f6868bd68),
U64_C (0xd07234ca1a1a681a), U64_C (0x192c41b7aeae82ae),
U64_C (0xc95e757db4b4eab4), U64_C (0x9a19a8ce54544d54),
U64_C (0xece53b7f93937693), U64_C (0x0daa442f22228822),
U64_C (0x07e9c86364648d64), U64_C (0xdb12ff2af1f1e3f1),
U64_C (0xbfa2e6cc7373d173), U64_C (0x905a248212124812),
U64_C (0x3a5d807a40401d40), U64_C (0x4028104808082008),
U64_C (0x56e89b95c3c32bc3), U64_C (0x337bc5dfecec97ec),
U64_C (0x9690ab4ddbdb4bdb), U64_C (0x611f5fc0a1a1bea1),
U64_C (0x1c8307918d8d0e8d), U64_C (0xf5c97ac83d3df43d),
U64_C (0xccf1335b97976697), U64_C (0x0000000000000000),
U64_C (0x36d483f9cfcf1bcf), U64_C (0x4587566e2b2bac2b),
U64_C (0x97b3ece17676c576), U64_C (0x64b019e682823282),
U64_C (0xfea9b128d6d67fd6), U64_C (0xd87736c31b1b6c1b),
U64_C (0xc15b7774b5b5eeb5), U64_C (0x112943beafaf86af),
U64_C (0x77dfd41d6a6ab56a), U64_C (0xba0da0ea50505d50),
U64_C (0x124c8a5745450945), U64_C (0xcb18fb38f3f3ebf3),
U64_C (0x9df060ad3030c030), U64_C (0x2b74c3c4efef9bef),
U64_C (0xe5c37eda3f3ffc3f), U64_C (0x921caac755554955),
U64_C (0x791059dba2a2b2a2), U64_C (0x0365c9e9eaea8fea),
U64_C (0x0fecca6a65658965), U64_C (0xb9686903babad2ba),
U64_C (0x65935e4a2f2fbc2f), U64_C (0x4ee79d8ec0c027c0),
U64_C (0xbe81a160dede5fde), U64_C (0xe06c38fc1c1c701c),
U64_C (0xbb2ee746fdfdd3fd), U64_C (0x52649a1f4d4d294d),
U64_C (0xe4e0397692927292), U64_C (0x8fbceafa7575c975),
U64_C (0x301e0c3606061806), U64_C (0x249809ae8a8a128a),
U64_C (0xf940794bb2b2f2b2), U64_C (0x6359d185e6e6bfe6),
U64_C (0x70361c7e0e0e380e), U64_C (0xf8633ee71f1f7c1f),
U64_C (0x37f7c45562629562), U64_C (0xeea3b53ad4d477d4),
U64_C (0x29324d81a8a89aa8), U64_C (0xc4f4315296966296),
U64_C (0x9b3aef62f9f9c3f9), U64_C (0x66f697a3c5c533c5),
U64_C (0x35b14a1025259425), U64_C (0xf220b2ab59597959),
U64_C (0x54ae15d084842a84), U64_C (0xb7a7e4c57272d572),
U64_C (0xd5dd72ec3939e439), U64_C (0x5a6198164c4c2d4c),
U64_C (0xca3bbc945e5e655e), U64_C (0xe785f09f7878fd78),
U64_C (0xddd870e53838e038), U64_C (0x148605988c8c0a8c),
U64_C (0xc6b2bf17d1d163d1), U64_C (0x410b57e4a5a5aea5),
U64_C (0x434dd9a1e2e2afe2), U64_C (0x2ff8c24e61619961),
U64_C (0xf1457b42b3b3f6b3), U64_C (0x15a5423421218421),
U64_C (0x94d625089c9c4a9c), U64_C (0xf0663cee1e1e781e),
U64_C (0x2252866143431143), U64_C (0x76fc93b1c7c73bc7),
U64_C (0xb32be54ffcfcd7fc), U64_C (0x2014082404041004),
U64_C (0xb208a2e351515951), U64_C (0xbcc72f2599995e99),
U64_C (0x4fc4da226d6da96d), U64_C (0x68391a650d0d340d),
U64_C (0x8335e979fafacffa), U64_C (0xb684a369dfdf5bdf),
U64_C (0xd79bfca97e7ee57e), U64_C (0x3db4481924249024),
U64_C (0xc5d776fe3b3bec3b), U64_C (0x313d4b9aabab96ab),
U64_C (0x3ed181f0cece1fce), U64_C (0x8855229911114411),
U64_C (0x0c8903838f8f068f), U64_C (0x4a6b9c044e4e254e),
U64_C (0xd1517366b7b7e6b7), U64_C (0x0b60cbe0ebeb8beb),
U64_C (0xfdcc78c13c3cf03c), U64_C (0x7cbf1ffd81813e81),
U64_C (0xd4fe354094946a94), U64_C (0xeb0cf31cf7f7fbf7),
U64_C (0xa1676f18b9b9deb9), U64_C (0x985f268b13134c13),
U64_C (0x7d9c58512c2cb02c), U64_C (0xd6b8bb05d3d36bd3),
U64_C (0x6b5cd38ce7e7bbe7), U64_C (0x57cbdc396e6ea56e),
U64_C (0x6ef395aac4c437c4), U64_C (0x180f061b03030c03),
U64_C (0x8a13acdc56564556), U64_C (0x1a49885e44440d44),
U64_C (0xdf9efea07f7fe17f), U64_C (0x21374f88a9a99ea9),
U64_C (0x4d8254672a2aa82a), U64_C (0xb16d6b0abbbbd6bb),
U64_C (0x46e29f87c1c123c1), U64_C (0xa202a6f153535153),
U64_C (0xae8ba572dcdc57dc), U64_C (0x582716530b0b2c0b),
U64_C (0x9cd327019d9d4e9d), U64_C (0x47c1d82b6c6cad6c),
U64_C (0x95f562a43131c431), U64_C (0x87b9e8f37474cd74),
U64_C (0xe309f115f6f6fff6), U64_C (0x0a438c4c46460546),
U64_C (0x092645a5acac8aac), U64_C (0x3c970fb589891e89),
U64_C (0xa04428b414145014), U64_C (0x5b42dfbae1e1a3e1),
U64_C (0xb04e2ca616165816), U64_C (0xcdd274f73a3ae83a),
U64_C (0x6fd0d2066969b969), U64_C (0x482d124109092409),
U64_C (0xa7ade0d77070dd70), U64_C (0xd954716fb6b6e2b6),
U64_C (0xceb7bd1ed0d067d0), U64_C (0x3b7ec7d6eded93ed),
U64_C (0x2edb85e2cccc17cc), U64_C (0x2a57846842421542),
U64_C (0xb4c22d2c98985a98), U64_C (0x490e55eda4a4aaa4),
U64_C (0x5d8850752828a028), U64_C (0xda31b8865c5c6d5c),
U64_C (0x933fed6bf8f8c7f8), U64_C (0x44a411c286862286),
}, {
U64_C (0x18c07830d8181860), U64_C (0x2305af462623238c),
U64_C (0xc67ef991b8c6c63f), U64_C (0xe8136fcdfbe8e887),
U64_C (0x874ca113cb878726), U64_C (0xb8a9626d11b8b8da),
U64_C (0x0108050209010104), U64_C (0x4f426e9e0d4f4f21),
U64_C (0x36adee6c9b3636d8), U64_C (0xa6590451ffa6a6a2),
U64_C (0xd2debdb90cd2d26f), U64_C (0xf5fb06f70ef5f5f3),
U64_C (0x79ef80f2967979f9), U64_C (0x6f5fcede306f6fa1),
U64_C (0x91fcef3f6d91917e), U64_C (0x52aa07a4f8525255),
U64_C (0x6027fdc04760609d), U64_C (0xbc89766535bcbcca),
U64_C (0x9baccd2b379b9b56), U64_C (0x8e048c018a8e8e02),
U64_C (0xa371155bd2a3a3b6), U64_C (0x0c603c186c0c0c30),
U64_C (0x7bff8af6847b7bf1), U64_C (0x35b5e16a803535d4),
U64_C (0x1de8693af51d1d74), U64_C (0xe05347ddb3e0e0a7),
U64_C (0xd7f6acb321d7d77b), U64_C (0xc25eed999cc2c22f),
U64_C (0x2e6d965c432e2eb8), U64_C (0x4b627a96294b4b31),
U64_C (0xfea321e15dfefedf), U64_C (0x578216aed5575741),
U64_C (0x15a8412abd151554), U64_C (0x779fb6eee87777c1),
U64_C (0x37a5eb6e923737dc), U64_C (0xe57b56d79ee5e5b3),
U64_C (0x9f8cd923139f9f46), U64_C (0xf0d317fd23f0f0e7),
U64_C (0x4a6a7f94204a4a35), U64_C (0xda9e95a944dada4f),
U64_C (0x58fa25b0a258587d), U64_C (0xc906ca8fcfc9c903),
U64_C (0x29558d527c2929a4), U64_C (0x0a5022145a0a0a28),
U64_C (0xb1e14f7f50b1b1fe), U64_C (0xa0691a5dc9a0a0ba),
U64_C (0x6b7fdad6146b6bb1), U64_C (0x855cab17d985852e),
U64_C (0xbd8173673cbdbdce), U64_C (0x5dd234ba8f5d5d69),
U64_C (0x1080502090101040), U64_C (0xf4f303f507f4f4f7),
U64_C (0xcb16c08bddcbcb0b), U64_C (0x3eedc67cd33e3ef8),
U64_C (0x0528110a2d050514), U64_C (0x671fe6ce78676781),
U64_C (0xe47353d597e4e4b7), U64_C (0x2725bb4e0227279c),
U64_C (0x4132588273414119), U64_C (0x8b2c9d0ba78b8b16),
U64_C (0xa7510153f6a7a7a6), U64_C (0x7dcf94fab27d7de9),
U64_C (0x95dcfb374995956e), U64_C (0xd88e9fad56d8d847),
U64_C (0xfb8b30eb70fbfbcb), U64_C (0xee2371c1cdeeee9f),
U64_C (0x7cc791f8bb7c7ced), U64_C (0x6617e3cc71666685),
U64_C (0xdda68ea77bdddd53), U64_C (0x17b84b2eaf17175c),
U64_C (0x4702468e45474701), U64_C (0x9e84dc211a9e9e42),
U64_C (0xca1ec589d4caca0f), U64_C (0x2d75995a582d2db4),
U64_C (0xbf9179632ebfbfc6), U64_C (0x07381b0e3f07071c),
U64_C (0xad012347acadad8e), U64_C (0x5aea2fb4b05a5a75),
U64_C (0x836cb51bef838336), U64_C (0x3385ff66b63333cc),
U64_C (0x633ff2c65c636391), U64_C (0x02100a0412020208),
U64_C (0xaa39384993aaaa92), U64_C (0x71afa8e2de7171d9),
U64_C (0xc80ecf8dc6c8c807), U64_C (0x19c87d32d1191964),
U64_C (0x497270923b494939), U64_C (0xd9869aaf5fd9d943),
U64_C (0xf2c31df931f2f2ef), U64_C (0xe34b48dba8e3e3ab),
U64_C (0x5be22ab6b95b5b71), U64_C (0x8834920dbc88881a),
U64_C (0x9aa4c8293e9a9a52), U64_C (0x262dbe4c0b262698),
U64_C (0x328dfa64bf3232c8), U64_C (0xb0e94a7d59b0b0fa),
U64_C (0xe91b6acff2e9e983), U64_C (0x0f78331e770f0f3c),
U64_C (0xd5e6a6b733d5d573), U64_C (0x8074ba1df480803a),
U64_C (0xbe997c6127bebec2), U64_C (0xcd26de87ebcdcd13),
U64_C (0x34bde468893434d0), U64_C (0x487a75903248483d),
U64_C (0xffab24e354ffffdb), U64_C (0x7af78ff48d7a7af5),
U64_C (0x90f4ea3d6490907a), U64_C (0x5fc23ebe9d5f5f61),
U64_C (0x201da0403d202080), U64_C (0x6867d5d00f6868bd),
U64_C (0x1ad07234ca1a1a68), U64_C (0xae192c41b7aeae82),
U64_C (0xb4c95e757db4b4ea), U64_C (0x549a19a8ce54544d),
U64_C (0x93ece53b7f939376), U64_C (0x220daa442f222288),
U64_C (0x6407e9c86364648d), U64_C (0xf1db12ff2af1f1e3),
U64_C (0x73bfa2e6cc7373d1), U64_C (0x12905a2482121248),
U64_C (0x403a5d807a40401d), U64_C (0x0840281048080820),
U64_C (0xc356e89b95c3c32b), U64_C (0xec337bc5dfecec97),
U64_C (0xdb9690ab4ddbdb4b), U64_C (0xa1611f5fc0a1a1be),
U64_C (0x8d1c8307918d8d0e), U64_C (0x3df5c97ac83d3df4),
U64_C (0x97ccf1335b979766), U64_C (0x0000000000000000),
U64_C (0xcf36d483f9cfcf1b), U64_C (0x2b4587566e2b2bac),
U64_C (0x7697b3ece17676c5), U64_C (0x8264b019e6828232),
U64_C (0xd6fea9b128d6d67f), U64_C (0x1bd87736c31b1b6c),
U64_C (0xb5c15b7774b5b5ee), U64_C (0xaf112943beafaf86),
U64_C (0x6a77dfd41d6a6ab5), U64_C (0x50ba0da0ea50505d),
U64_C (0x45124c8a57454509), U64_C (0xf3cb18fb38f3f3eb),
U64_C (0x309df060ad3030c0), U64_C (0xef2b74c3c4efef9b),
U64_C (0x3fe5c37eda3f3ffc), U64_C (0x55921caac7555549),
U64_C (0xa2791059dba2a2b2), U64_C (0xea0365c9e9eaea8f),
U64_C (0x650fecca6a656589), U64_C (0xbab9686903babad2),
U64_C (0x2f65935e4a2f2fbc), U64_C (0xc04ee79d8ec0c027),
U64_C (0xdebe81a160dede5f), U64_C (0x1ce06c38fc1c1c70),
U64_C (0xfdbb2ee746fdfdd3), U64_C (0x4d52649a1f4d4d29),
U64_C (0x92e4e03976929272), U64_C (0x758fbceafa7575c9),
U64_C (0x06301e0c36060618), U64_C (0x8a249809ae8a8a12),
U64_C (0xb2f940794bb2b2f2), U64_C (0xe66359d185e6e6bf),
U64_C (0x0e70361c7e0e0e38), U64_C (0x1ff8633ee71f1f7c),
U64_C (0x6237f7c455626295), U64_C (0xd4eea3b53ad4d477),
U64_C (0xa829324d81a8a89a), U64_C (0x96c4f43152969662),
U64_C (0xf99b3aef62f9f9c3), U64_C (0xc566f697a3c5c533),
U64_C (0x2535b14a10252594), U64_C (0x59f220b2ab595979),
U64_C (0x8454ae15d084842a), U64_C (0x72b7a7e4c57272d5),
U64_C (0x39d5dd72ec3939e4), U64_C (0x4c5a6198164c4c2d),
U64_C (0x5eca3bbc945e5e65), U64_C (0x78e785f09f7878fd),
U64_C (0x38ddd870e53838e0), U64_C (0x8c148605988c8c0a),
U64_C (0xd1c6b2bf17d1d163), U64_C (0xa5410b57e4a5a5ae),
U64_C (0xe2434dd9a1e2e2af), U64_C (0x612ff8c24e616199),
U64_C (0xb3f1457b42b3b3f6), U64_C (0x2115a54234212184),
U64_C (0x9c94d625089c9c4a), U64_C (0x1ef0663cee1e1e78),
U64_C (0x4322528661434311), U64_C (0xc776fc93b1c7c73b),
U64_C (0xfcb32be54ffcfcd7), U64_C (0x0420140824040410),
U64_C (0x51b208a2e3515159), U64_C (0x99bcc72f2599995e),
U64_C (0x6d4fc4da226d6da9), U64_C (0x0d68391a650d0d34),
U64_C (0xfa8335e979fafacf), U64_C (0xdfb684a369dfdf5b),
U64_C (0x7ed79bfca97e7ee5), U64_C (0x243db44819242490),
U64_C (0x3bc5d776fe3b3bec), U64_C (0xab313d4b9aabab96),
U64_C (0xce3ed181f0cece1f), U64_C (0x1188552299111144),
U64_C (0x8f0c8903838f8f06), U64_C (0x4e4a6b9c044e4e25),
U64_C (0xb7d1517366b7b7e6), U64_C (0xeb0b60cbe0ebeb8b),
U64_C (0x3cfdcc78c13c3cf0), U64_C (0x817cbf1ffd81813e),
U64_C (0x94d4fe354094946a), U64_C (0xf7eb0cf31cf7f7fb),
U64_C (0xb9a1676f18b9b9de), U64_C (0x13985f268b13134c),
U64_C (0x2c7d9c58512c2cb0), U64_C (0xd3d6b8bb05d3d36b),
U64_C (0xe76b5cd38ce7e7bb), U64_C (0x6e57cbdc396e6ea5),
U64_C (0xc46ef395aac4c437), U64_C (0x03180f061b03030c),
U64_C (0x568a13acdc565645), U64_C (0x441a49885e44440d),
U64_C (0x7fdf9efea07f7fe1), U64_C (0xa921374f88a9a99e),
U64_C (0x2a4d8254672a2aa8), U64_C (0xbbb16d6b0abbbbd6),
U64_C (0xc146e29f87c1c123), U64_C (0x53a202a6f1535351),
U64_C (0xdcae8ba572dcdc57), U64_C (0x0b582716530b0b2c),
U64_C (0x9d9cd327019d9d4e), U64_C (0x6c47c1d82b6c6cad),
U64_C (0x3195f562a43131c4), U64_C (0x7487b9e8f37474cd),
U64_C (0xf6e309f115f6f6ff), U64_C (0x460a438c4c464605),
U64_C (0xac092645a5acac8a), U64_C (0x893c970fb589891e),
U64_C (0x14a04428b4141450), U64_C (0xe15b42dfbae1e1a3),
U64_C (0x16b04e2ca6161658), U64_C (0x3acdd274f73a3ae8),
U64_C (0x696fd0d2066969b9), U64_C (0x09482d1241090924),
U64_C (0x70a7ade0d77070dd), U64_C (0xb6d954716fb6b6e2),
U64_C (0xd0ceb7bd1ed0d067), U64_C (0xed3b7ec7d6eded93),
U64_C (0xcc2edb85e2cccc17), U64_C (0x422a578468424215),
U64_C (0x98b4c22d2c98985a), U64_C (0xa4490e55eda4a4aa),
U64_C (0x285d8850752828a0), U64_C (0x5cda31b8865c5c6d),
U64_C (0xf8933fed6bf8f8c7), U64_C (0x8644a411c2868622),
}, {
U64_C (0x6018c07830d81818), U64_C (0x8c2305af46262323),
U64_C (0x3fc67ef991b8c6c6), U64_C (0x87e8136fcdfbe8e8),
U64_C (0x26874ca113cb8787), U64_C (0xdab8a9626d11b8b8),
U64_C (0x0401080502090101), U64_C (0x214f426e9e0d4f4f),
U64_C (0xd836adee6c9b3636), U64_C (0xa2a6590451ffa6a6),
U64_C (0x6fd2debdb90cd2d2), U64_C (0xf3f5fb06f70ef5f5),
U64_C (0xf979ef80f2967979), U64_C (0xa16f5fcede306f6f),
U64_C (0x7e91fcef3f6d9191), U64_C (0x5552aa07a4f85252),
U64_C (0x9d6027fdc0476060), U64_C (0xcabc89766535bcbc),
U64_C (0x569baccd2b379b9b), U64_C (0x028e048c018a8e8e),
U64_C (0xb6a371155bd2a3a3), U64_C (0x300c603c186c0c0c),
U64_C (0xf17bff8af6847b7b), U64_C (0xd435b5e16a803535),
U64_C (0x741de8693af51d1d), U64_C (0xa7e05347ddb3e0e0),
U64_C (0x7bd7f6acb321d7d7), U64_C (0x2fc25eed999cc2c2),
U64_C (0xb82e6d965c432e2e), U64_C (0x314b627a96294b4b),
U64_C (0xdffea321e15dfefe), U64_C (0x41578216aed55757),
U64_C (0x5415a8412abd1515), U64_C (0xc1779fb6eee87777),
U64_C (0xdc37a5eb6e923737), U64_C (0xb3e57b56d79ee5e5),
U64_C (0x469f8cd923139f9f), U64_C (0xe7f0d317fd23f0f0),
U64_C (0x354a6a7f94204a4a), U64_C (0x4fda9e95a944dada),
U64_C (0x7d58fa25b0a25858), U64_C (0x03c906ca8fcfc9c9),
U64_C (0xa429558d527c2929), U64_C (0x280a5022145a0a0a),
U64_C (0xfeb1e14f7f50b1b1), U64_C (0xbaa0691a5dc9a0a0),
U64_C (0xb16b7fdad6146b6b), U64_C (0x2e855cab17d98585),
U64_C (0xcebd8173673cbdbd), U64_C (0x695dd234ba8f5d5d),
U64_C (0x4010805020901010), U64_C (0xf7f4f303f507f4f4),
U64_C (0x0bcb16c08bddcbcb), U64_C (0xf83eedc67cd33e3e),
U64_C (0x140528110a2d0505), U64_C (0x81671fe6ce786767),
U64_C (0xb7e47353d597e4e4), U64_C (0x9c2725bb4e022727),
U64_C (0x1941325882734141), U64_C (0x168b2c9d0ba78b8b),
U64_C (0xa6a7510153f6a7a7), U64_C (0xe97dcf94fab27d7d),
U64_C (0x6e95dcfb37499595), U64_C (0x47d88e9fad56d8d8),
U64_C (0xcbfb8b30eb70fbfb), U64_C (0x9fee2371c1cdeeee),
U64_C (0xed7cc791f8bb7c7c), U64_C (0x856617e3cc716666),
U64_C (0x53dda68ea77bdddd), U64_C (0x5c17b84b2eaf1717),
U64_C (0x014702468e454747), U64_C (0x429e84dc211a9e9e),
U64_C (0x0fca1ec589d4caca), U64_C (0xb42d75995a582d2d),
U64_C (0xc6bf9179632ebfbf), U64_C (0x1c07381b0e3f0707),
U64_C (0x8ead012347acadad), U64_C (0x755aea2fb4b05a5a),
U64_C (0x36836cb51bef8383), U64_C (0xcc3385ff66b63333),
U64_C (0x91633ff2c65c6363), U64_C (0x0802100a04120202),
U64_C (0x92aa39384993aaaa), U64_C (0xd971afa8e2de7171),
U64_C (0x07c80ecf8dc6c8c8), U64_C (0x6419c87d32d11919),
U64_C (0x39497270923b4949), U64_C (0x43d9869aaf5fd9d9),
U64_C (0xeff2c31df931f2f2), U64_C (0xabe34b48dba8e3e3),
U64_C (0x715be22ab6b95b5b), U64_C (0x1a8834920dbc8888),
U64_C (0x529aa4c8293e9a9a), U64_C (0x98262dbe4c0b2626),
U64_C (0xc8328dfa64bf3232), U64_C (0xfab0e94a7d59b0b0),
U64_C (0x83e91b6acff2e9e9), U64_C (0x3c0f78331e770f0f),
U64_C (0x73d5e6a6b733d5d5), U64_C (0x3a8074ba1df48080),
U64_C (0xc2be997c6127bebe), U64_C (0x13cd26de87ebcdcd),
U64_C (0xd034bde468893434), U64_C (0x3d487a7590324848),
U64_C (0xdbffab24e354ffff), U64_C (0xf57af78ff48d7a7a),
U64_C (0x7a90f4ea3d649090), U64_C (0x615fc23ebe9d5f5f),
U64_C (0x80201da0403d2020), U64_C (0xbd6867d5d00f6868),
U64_C (0x681ad07234ca1a1a), U64_C (0x82ae192c41b7aeae),
U64_C (0xeab4c95e757db4b4), U64_C (0x4d549a19a8ce5454),
U64_C (0x7693ece53b7f9393), U64_C (0x88220daa442f2222),
U64_C (0x8d6407e9c8636464), U64_C (0xe3f1db12ff2af1f1),
U64_C (0xd173bfa2e6cc7373), U64_C (0x4812905a24821212),
U64_C (0x1d403a5d807a4040), U64_C (0x2008402810480808),
U64_C (0x2bc356e89b95c3c3), U64_C (0x97ec337bc5dfecec),
U64_C (0x4bdb9690ab4ddbdb), U64_C (0xbea1611f5fc0a1a1),
U64_C (0x0e8d1c8307918d8d), U64_C (0xf43df5c97ac83d3d),
U64_C (0x6697ccf1335b9797), U64_C (0x0000000000000000),
U64_C (0x1bcf36d483f9cfcf), U64_C (0xac2b4587566e2b2b),
U64_C (0xc57697b3ece17676), U64_C (0x328264b019e68282),
U64_C (0x7fd6fea9b128d6d6), U64_C (0x6c1bd87736c31b1b),
U64_C (0xeeb5c15b7774b5b5), U64_C (0x86af112943beafaf),
U64_C (0xb56a77dfd41d6a6a), U64_C (0x5d50ba0da0ea5050),
U64_C (0x0945124c8a574545), U64_C (0xebf3cb18fb38f3f3),
U64_C (0xc0309df060ad3030), U64_C (0x9bef2b74c3c4efef),
U64_C (0xfc3fe5c37eda3f3f), U64_C (0x4955921caac75555),
U64_C (0xb2a2791059dba2a2), U64_C (0x8fea0365c9e9eaea),
U64_C (0x89650fecca6a6565), U64_C (0xd2bab9686903baba),
U64_C (0xbc2f65935e4a2f2f), U64_C (0x27c04ee79d8ec0c0),
U64_C (0x5fdebe81a160dede), U64_C (0x701ce06c38fc1c1c),
U64_C (0xd3fdbb2ee746fdfd), U64_C (0x294d52649a1f4d4d),
U64_C (0x7292e4e039769292), U64_C (0xc9758fbceafa7575),
U64_C (0x1806301e0c360606), U64_C (0x128a249809ae8a8a),
U64_C (0xf2b2f940794bb2b2), U64_C (0xbfe66359d185e6e6),
U64_C (0x380e70361c7e0e0e), U64_C (0x7c1ff8633ee71f1f),
U64_C (0x956237f7c4556262), U64_C (0x77d4eea3b53ad4d4),
U64_C (0x9aa829324d81a8a8), U64_C (0x6296c4f431529696),
U64_C (0xc3f99b3aef62f9f9), U64_C (0x33c566f697a3c5c5),
U64_C (0x942535b14a102525), U64_C (0x7959f220b2ab5959),
U64_C (0x2a8454ae15d08484), U64_C (0xd572b7a7e4c57272),
U64_C (0xe439d5dd72ec3939), U64_C (0x2d4c5a6198164c4c),
U64_C (0x655eca3bbc945e5e), U64_C (0xfd78e785f09f7878),
U64_C (0xe038ddd870e53838), U64_C (0x0a8c148605988c8c),
U64_C (0x63d1c6b2bf17d1d1), U64_C (0xaea5410b57e4a5a5),
U64_C (0xafe2434dd9a1e2e2), U64_C (0x99612ff8c24e6161),
U64_C (0xf6b3f1457b42b3b3), U64_C (0x842115a542342121),
U64_C (0x4a9c94d625089c9c), U64_C (0x781ef0663cee1e1e),
U64_C (0x1143225286614343), U64_C (0x3bc776fc93b1c7c7),
U64_C (0xd7fcb32be54ffcfc), U64_C (0x1004201408240404),
U64_C (0x5951b208a2e35151), U64_C (0x5e99bcc72f259999),
U64_C (0xa96d4fc4da226d6d), U64_C (0x340d68391a650d0d),
U64_C (0xcffa8335e979fafa), U64_C (0x5bdfb684a369dfdf),
U64_C (0xe57ed79bfca97e7e), U64_C (0x90243db448192424),
U64_C (0xec3bc5d776fe3b3b), U64_C (0x96ab313d4b9aabab),
U64_C (0x1fce3ed181f0cece), U64_C (0x4411885522991111),
U64_C (0x068f0c8903838f8f), U64_C (0x254e4a6b9c044e4e),
U64_C (0xe6b7d1517366b7b7), U64_C (0x8beb0b60cbe0ebeb),
U64_C (0xf03cfdcc78c13c3c), U64_C (0x3e817cbf1ffd8181),
U64_C (0x6a94d4fe35409494), U64_C (0xfbf7eb0cf31cf7f7),
U64_C (0xdeb9a1676f18b9b9), U64_C (0x4c13985f268b1313),
U64_C (0xb02c7d9c58512c2c), U64_C (0x6bd3d6b8bb05d3d3),
U64_C (0xbbe76b5cd38ce7e7), U64_C (0xa56e57cbdc396e6e),
U64_C (0x37c46ef395aac4c4), U64_C (0x0c03180f061b0303),
U64_C (0x45568a13acdc5656), U64_C (0x0d441a49885e4444),
U64_C (0xe17fdf9efea07f7f), U64_C (0x9ea921374f88a9a9),
U64_C (0xa82a4d8254672a2a), U64_C (0xd6bbb16d6b0abbbb),
U64_C (0x23c146e29f87c1c1), U64_C (0x5153a202a6f15353),
U64_C (0x57dcae8ba572dcdc), U64_C (0x2c0b582716530b0b),
U64_C (0x4e9d9cd327019d9d), U64_C (0xad6c47c1d82b6c6c),
U64_C (0xc43195f562a43131), U64_C (0xcd7487b9e8f37474),
U64_C (0xfff6e309f115f6f6), U64_C (0x05460a438c4c4646),
U64_C (0x8aac092645a5acac), U64_C (0x1e893c970fb58989),
U64_C (0x5014a04428b41414), U64_C (0xa3e15b42dfbae1e1),
U64_C (0x5816b04e2ca61616), U64_C (0xe83acdd274f73a3a),
U64_C (0xb9696fd0d2066969), U64_C (0x2409482d12410909),
U64_C (0xdd70a7ade0d77070), U64_C (0xe2b6d954716fb6b6),
U64_C (0x67d0ceb7bd1ed0d0), U64_C (0x93ed3b7ec7d6eded),
U64_C (0x17cc2edb85e2cccc), U64_C (0x15422a5784684242),
U64_C (0x5a98b4c22d2c9898), U64_C (0xaaa4490e55eda4a4),
U64_C (0xa0285d8850752828), U64_C (0x6d5cda31b8865c5c),
U64_C (0xc7f8933fed6bf8f8), U64_C (0x228644a411c28686),
}, {
U64_C (0x186018c07830d818), U64_C (0x238c2305af462623),
U64_C (0xc63fc67ef991b8c6), U64_C (0xe887e8136fcdfbe8),
U64_C (0x8726874ca113cb87), U64_C (0xb8dab8a9626d11b8),
U64_C (0x0104010805020901), U64_C (0x4f214f426e9e0d4f),
U64_C (0x36d836adee6c9b36), U64_C (0xa6a2a6590451ffa6),
U64_C (0xd26fd2debdb90cd2), U64_C (0xf5f3f5fb06f70ef5),
U64_C (0x79f979ef80f29679), U64_C (0x6fa16f5fcede306f),
U64_C (0x917e91fcef3f6d91), U64_C (0x525552aa07a4f852),
U64_C (0x609d6027fdc04760), U64_C (0xbccabc89766535bc),
U64_C (0x9b569baccd2b379b), U64_C (0x8e028e048c018a8e),
U64_C (0xa3b6a371155bd2a3), U64_C (0x0c300c603c186c0c),
U64_C (0x7bf17bff8af6847b), U64_C (0x35d435b5e16a8035),
U64_C (0x1d741de8693af51d), U64_C (0xe0a7e05347ddb3e0),
U64_C (0xd77bd7f6acb321d7), U64_C (0xc22fc25eed999cc2),
U64_C (0x2eb82e6d965c432e), U64_C (0x4b314b627a96294b),
U64_C (0xfedffea321e15dfe), U64_C (0x5741578216aed557),
U64_C (0x155415a8412abd15), U64_C (0x77c1779fb6eee877),
U64_C (0x37dc37a5eb6e9237), U64_C (0xe5b3e57b56d79ee5),
U64_C (0x9f469f8cd923139f), U64_C (0xf0e7f0d317fd23f0),
U64_C (0x4a354a6a7f94204a), U64_C (0xda4fda9e95a944da),
U64_C (0x587d58fa25b0a258), U64_C (0xc903c906ca8fcfc9),
U64_C (0x29a429558d527c29), U64_C (0x0a280a5022145a0a),
U64_C (0xb1feb1e14f7f50b1), U64_C (0xa0baa0691a5dc9a0),
U64_C (0x6bb16b7fdad6146b), U64_C (0x852e855cab17d985),
U64_C (0xbdcebd8173673cbd), U64_C (0x5d695dd234ba8f5d),
U64_C (0x1040108050209010), U64_C (0xf4f7f4f303f507f4),
U64_C (0xcb0bcb16c08bddcb), U64_C (0x3ef83eedc67cd33e),
U64_C (0x05140528110a2d05), U64_C (0x6781671fe6ce7867),
U64_C (0xe4b7e47353d597e4), U64_C (0x279c2725bb4e0227),
U64_C (0x4119413258827341), U64_C (0x8b168b2c9d0ba78b),
U64_C (0xa7a6a7510153f6a7), U64_C (0x7de97dcf94fab27d),
U64_C (0x956e95dcfb374995), U64_C (0xd847d88e9fad56d8),
U64_C (0xfbcbfb8b30eb70fb), U64_C (0xee9fee2371c1cdee),
U64_C (0x7ced7cc791f8bb7c), U64_C (0x66856617e3cc7166),
U64_C (0xdd53dda68ea77bdd), U64_C (0x175c17b84b2eaf17),
U64_C (0x47014702468e4547), U64_C (0x9e429e84dc211a9e),
U64_C (0xca0fca1ec589d4ca), U64_C (0x2db42d75995a582d),
U64_C (0xbfc6bf9179632ebf), U64_C (0x071c07381b0e3f07),
U64_C (0xad8ead012347acad), U64_C (0x5a755aea2fb4b05a),
U64_C (0x8336836cb51bef83), U64_C (0x33cc3385ff66b633),
U64_C (0x6391633ff2c65c63), U64_C (0x020802100a041202),
U64_C (0xaa92aa39384993aa), U64_C (0x71d971afa8e2de71),
U64_C (0xc807c80ecf8dc6c8), U64_C (0x196419c87d32d119),
U64_C (0x4939497270923b49), U64_C (0xd943d9869aaf5fd9),
U64_C (0xf2eff2c31df931f2), U64_C (0xe3abe34b48dba8e3),
U64_C (0x5b715be22ab6b95b), U64_C (0x881a8834920dbc88),
U64_C (0x9a529aa4c8293e9a), U64_C (0x2698262dbe4c0b26),
U64_C (0x32c8328dfa64bf32), U64_C (0xb0fab0e94a7d59b0),
U64_C (0xe983e91b6acff2e9), U64_C (0x0f3c0f78331e770f),
U64_C (0xd573d5e6a6b733d5), U64_C (0x803a8074ba1df480),
U64_C (0xbec2be997c6127be), U64_C (0xcd13cd26de87ebcd),
U64_C (0x34d034bde4688934), U64_C (0x483d487a75903248),
U64_C (0xffdbffab24e354ff), U64_C (0x7af57af78ff48d7a),
U64_C (0x907a90f4ea3d6490), U64_C (0x5f615fc23ebe9d5f),
U64_C (0x2080201da0403d20), U64_C (0x68bd6867d5d00f68),
U64_C (0x1a681ad07234ca1a), U64_C (0xae82ae192c41b7ae),
U64_C (0xb4eab4c95e757db4), U64_C (0x544d549a19a8ce54),
U64_C (0x937693ece53b7f93), U64_C (0x2288220daa442f22),
U64_C (0x648d6407e9c86364), U64_C (0xf1e3f1db12ff2af1),
U64_C (0x73d173bfa2e6cc73), U64_C (0x124812905a248212),
U64_C (0x401d403a5d807a40), U64_C (0x0820084028104808),
U64_C (0xc32bc356e89b95c3), U64_C (0xec97ec337bc5dfec),
U64_C (0xdb4bdb9690ab4ddb), U64_C (0xa1bea1611f5fc0a1),
U64_C (0x8d0e8d1c8307918d), U64_C (0x3df43df5c97ac83d),
U64_C (0x976697ccf1335b97), U64_C (0x0000000000000000),
U64_C (0xcf1bcf36d483f9cf), U64_C (0x2bac2b4587566e2b),
U64_C (0x76c57697b3ece176), U64_C (0x82328264b019e682),
U64_C (0xd67fd6fea9b128d6), U64_C (0x1b6c1bd87736c31b),
U64_C (0xb5eeb5c15b7774b5), U64_C (0xaf86af112943beaf),
U64_C (0x6ab56a77dfd41d6a), U64_C (0x505d50ba0da0ea50),
U64_C (0x450945124c8a5745), U64_C (0xf3ebf3cb18fb38f3),
U64_C (0x30c0309df060ad30), U64_C (0xef9bef2b74c3c4ef),
U64_C (0x3ffc3fe5c37eda3f), U64_C (0x554955921caac755),
U64_C (0xa2b2a2791059dba2), U64_C (0xea8fea0365c9e9ea),
U64_C (0x6589650fecca6a65), U64_C (0xbad2bab9686903ba),
U64_C (0x2fbc2f65935e4a2f), U64_C (0xc027c04ee79d8ec0),
U64_C (0xde5fdebe81a160de), U64_C (0x1c701ce06c38fc1c),
U64_C (0xfdd3fdbb2ee746fd), U64_C (0x4d294d52649a1f4d),
U64_C (0x927292e4e0397692), U64_C (0x75c9758fbceafa75),
U64_C (0x061806301e0c3606), U64_C (0x8a128a249809ae8a),
U64_C (0xb2f2b2f940794bb2), U64_C (0xe6bfe66359d185e6),
U64_C (0x0e380e70361c7e0e), U64_C (0x1f7c1ff8633ee71f),
U64_C (0x62956237f7c45562), U64_C (0xd477d4eea3b53ad4),
U64_C (0xa89aa829324d81a8), U64_C (0x966296c4f4315296),
U64_C (0xf9c3f99b3aef62f9), U64_C (0xc533c566f697a3c5),
U64_C (0x25942535b14a1025), U64_C (0x597959f220b2ab59),
U64_C (0x842a8454ae15d084), U64_C (0x72d572b7a7e4c572),
U64_C (0x39e439d5dd72ec39), U64_C (0x4c2d4c5a6198164c),
U64_C (0x5e655eca3bbc945e), U64_C (0x78fd78e785f09f78),
U64_C (0x38e038ddd870e538), U64_C (0x8c0a8c148605988c),
U64_C (0xd163d1c6b2bf17d1), U64_C (0xa5aea5410b57e4a5),
U64_C (0xe2afe2434dd9a1e2), U64_C (0x6199612ff8c24e61),
U64_C (0xb3f6b3f1457b42b3), U64_C (0x21842115a5423421),
U64_C (0x9c4a9c94d625089c), U64_C (0x1e781ef0663cee1e),
U64_C (0x4311432252866143), U64_C (0xc73bc776fc93b1c7),
U64_C (0xfcd7fcb32be54ffc), U64_C (0x0410042014082404),
U64_C (0x515951b208a2e351), U64_C (0x995e99bcc72f2599),
U64_C (0x6da96d4fc4da226d), U64_C (0x0d340d68391a650d),
U64_C (0xfacffa8335e979fa), U64_C (0xdf5bdfb684a369df),
U64_C (0x7ee57ed79bfca97e), U64_C (0x2490243db4481924),
U64_C (0x3bec3bc5d776fe3b), U64_C (0xab96ab313d4b9aab),
U64_C (0xce1fce3ed181f0ce), U64_C (0x1144118855229911),
U64_C (0x8f068f0c8903838f), U64_C (0x4e254e4a6b9c044e),
U64_C (0xb7e6b7d1517366b7), U64_C (0xeb8beb0b60cbe0eb),
U64_C (0x3cf03cfdcc78c13c), U64_C (0x813e817cbf1ffd81),
U64_C (0x946a94d4fe354094), U64_C (0xf7fbf7eb0cf31cf7),
U64_C (0xb9deb9a1676f18b9), U64_C (0x134c13985f268b13),
U64_C (0x2cb02c7d9c58512c), U64_C (0xd36bd3d6b8bb05d3),
U64_C (0xe7bbe76b5cd38ce7), U64_C (0x6ea56e57cbdc396e),
U64_C (0xc437c46ef395aac4), U64_C (0x030c03180f061b03),
U64_C (0x5645568a13acdc56), U64_C (0x440d441a49885e44),
U64_C (0x7fe17fdf9efea07f), U64_C (0xa99ea921374f88a9),
U64_C (0x2aa82a4d8254672a), U64_C (0xbbd6bbb16d6b0abb),
U64_C (0xc123c146e29f87c1), U64_C (0x535153a202a6f153),
U64_C (0xdc57dcae8ba572dc), U64_C (0x0b2c0b582716530b),
U64_C (0x9d4e9d9cd327019d), U64_C (0x6cad6c47c1d82b6c),
U64_C (0x31c43195f562a431), U64_C (0x74cd7487b9e8f374),
U64_C (0xf6fff6e309f115f6), U64_C (0x4605460a438c4c46),
U64_C (0xac8aac092645a5ac), U64_C (0x891e893c970fb589),
U64_C (0x145014a04428b414), U64_C (0xe1a3e15b42dfbae1),
U64_C (0x165816b04e2ca616), U64_C (0x3ae83acdd274f73a),
U64_C (0x69b9696fd0d20669), U64_C (0x092409482d124109),
U64_C (0x70dd70a7ade0d770), U64_C (0xb6e2b6d954716fb6),
U64_C (0xd067d0ceb7bd1ed0), U64_C (0xed93ed3b7ec7d6ed),
U64_C (0xcc17cc2edb85e2cc), U64_C (0x4215422a57846842),
U64_C (0x985a98b4c22d2c98), U64_C (0xa4aaa4490e55eda4),
U64_C (0x28a0285d88507528), U64_C (0x5c6d5cda31b8865c),
U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286),
} }
};
#define C tab.C
#define C0 C[0]
#define C1 C[1]
#define C2 C[2]
#define C3 C[3]
#define C4 C[4]
#define C5 C[5]
#define C6 C[6]
#define C7 C[7]
#define rc tab.RC
static unsigned int
whirlpool_transform (void *ctx, const unsigned char *data, size_t nblks);
static void
whirlpool_init (void *ctx, unsigned int flags)
{
whirlpool_context_t *context = ctx;
memset (context, 0, sizeof (*context));
context->bctx.blocksize = BLOCK_SIZE;
context->bctx.bwrite = whirlpool_transform;
if ((flags & GCRY_MD_FLAG_BUGEMU1))
{
memset (&context->bugemu, 0, sizeof context->bugemu);
context->use_bugemu = 1;
}
else
context->use_bugemu = 0;
}
#ifdef USE_AMD64_ASM
#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
extern unsigned int
_gcry_whirlpool_transform_amd64(u64 *state, const unsigned char *data,
size_t nblks, const struct whirlpool_tables_s *tables) ASM_FUNC_ABI;
static unsigned int
whirlpool_transform (void *ctx, const unsigned char *data, size_t nblks)
{
whirlpool_context_t *context = ctx;
return _gcry_whirlpool_transform_amd64(
context->hash_state, data, nblks, &tab) + ASM_EXTRA_STACK;
}
#else /* USE_AMD64_ASM */
/*
* Transform block.
*/
static unsigned int
whirlpool_transform_blk (void *ctx, const unsigned char *data)
{
whirlpool_context_t *context = ctx;
whirlpool_block_t data_block;
whirlpool_block_t key;
whirlpool_block_t state;
whirlpool_block_t block;
unsigned int r;
unsigned int i;
buffer_to_block (data, data_block, i);
block_copy (key, context->hash_state, i);
block_copy (state, context->hash_state, i);
block_xor (state, data_block, i);
for (r = 0; r < R; r++)
{
/* Compute round key K^r. */
block[0] = (C0[(key[0] >> 56) & 0xFF] ^ C1[(key[7] >> 48) & 0xFF] ^
C2[(key[6] >> 40) & 0xFF] ^ C3[(key[5] >> 32) & 0xFF] ^
C4[(key[4] >> 24) & 0xFF] ^ C5[(key[3] >> 16) & 0xFF] ^
C6[(key[2] >> 8) & 0xFF] ^ C7[(key[1] >> 0) & 0xFF] ^ rc[r]);
block[1] = (C0[(key[1] >> 56) & 0xFF] ^ C1[(key[0] >> 48) & 0xFF] ^
C2[(key[7] >> 40) & 0xFF] ^ C3[(key[6] >> 32) & 0xFF] ^
C4[(key[5] >> 24) & 0xFF] ^ C5[(key[4] >> 16) & 0xFF] ^
C6[(key[3] >> 8) & 0xFF] ^ C7[(key[2] >> 0) & 0xFF]);
block[2] = (C0[(key[2] >> 56) & 0xFF] ^ C1[(key[1] >> 48) & 0xFF] ^
C2[(key[0] >> 40) & 0xFF] ^ C3[(key[7] >> 32) & 0xFF] ^
C4[(key[6] >> 24) & 0xFF] ^ C5[(key[5] >> 16) & 0xFF] ^
C6[(key[4] >> 8) & 0xFF] ^ C7[(key[3] >> 0) & 0xFF]);
block[3] = (C0[(key[3] >> 56) & 0xFF] ^ C1[(key[2] >> 48) & 0xFF] ^
C2[(key[1] >> 40) & 0xFF] ^ C3[(key[0] >> 32) & 0xFF] ^
C4[(key[7] >> 24) & 0xFF] ^ C5[(key[6] >> 16) & 0xFF] ^
C6[(key[5] >> 8) & 0xFF] ^ C7[(key[4] >> 0) & 0xFF]);
block[4] = (C0[(key[4] >> 56) & 0xFF] ^ C1[(key[3] >> 48) & 0xFF] ^
C2[(key[2] >> 40) & 0xFF] ^ C3[(key[1] >> 32) & 0xFF] ^
C4[(key[0] >> 24) & 0xFF] ^ C5[(key[7] >> 16) & 0xFF] ^
C6[(key[6] >> 8) & 0xFF] ^ C7[(key[5] >> 0) & 0xFF]);
block[5] = (C0[(key[5] >> 56) & 0xFF] ^ C1[(key[4] >> 48) & 0xFF] ^
C2[(key[3] >> 40) & 0xFF] ^ C3[(key[2] >> 32) & 0xFF] ^
C4[(key[1] >> 24) & 0xFF] ^ C5[(key[0] >> 16) & 0xFF] ^
C6[(key[7] >> 8) & 0xFF] ^ C7[(key[6] >> 0) & 0xFF]);
block[6] = (C0[(key[6] >> 56) & 0xFF] ^ C1[(key[5] >> 48) & 0xFF] ^
C2[(key[4] >> 40) & 0xFF] ^ C3[(key[3] >> 32) & 0xFF] ^
C4[(key[2] >> 24) & 0xFF] ^ C5[(key[1] >> 16) & 0xFF] ^
C6[(key[0] >> 8) & 0xFF] ^ C7[(key[7] >> 0) & 0xFF]);
block[7] = (C0[(key[7] >> 56) & 0xFF] ^ C1[(key[6] >> 48) & 0xFF] ^
C2[(key[5] >> 40) & 0xFF] ^ C3[(key[4] >> 32) & 0xFF] ^
C4[(key[3] >> 24) & 0xFF] ^ C5[(key[2] >> 16) & 0xFF] ^
C6[(key[1] >> 8) & 0xFF] ^ C7[(key[0] >> 0) & 0xFF]);
block_copy (key, block, i);
/* Apply r-th round transformation. */
block[0] = (C0[(state[0] >> 56) & 0xFF] ^ C1[(state[7] >> 48) & 0xFF] ^
C2[(state[6] >> 40) & 0xFF] ^ C3[(state[5] >> 32) & 0xFF] ^
C4[(state[4] >> 24) & 0xFF] ^ C5[(state[3] >> 16) & 0xFF] ^
C6[(state[2] >> 8) & 0xFF] ^ C7[(state[1] >> 0) & 0xFF] ^ key[0]);
block[1] = (C0[(state[1] >> 56) & 0xFF] ^ C1[(state[0] >> 48) & 0xFF] ^
C2[(state[7] >> 40) & 0xFF] ^ C3[(state[6] >> 32) & 0xFF] ^
C4[(state[5] >> 24) & 0xFF] ^ C5[(state[4] >> 16) & 0xFF] ^
C6[(state[3] >> 8) & 0xFF] ^ C7[(state[2] >> 0) & 0xFF] ^ key[1]);
block[2] = (C0[(state[2] >> 56) & 0xFF] ^ C1[(state[1] >> 48) & 0xFF] ^
C2[(state[0] >> 40) & 0xFF] ^ C3[(state[7] >> 32) & 0xFF] ^
C4[(state[6] >> 24) & 0xFF] ^ C5[(state[5] >> 16) & 0xFF] ^
C6[(state[4] >> 8) & 0xFF] ^ C7[(state[3] >> 0) & 0xFF] ^ key[2]);
block[3] = (C0[(state[3] >> 56) & 0xFF] ^ C1[(state[2] >> 48) & 0xFF] ^
C2[(state[1] >> 40) & 0xFF] ^ C3[(state[0] >> 32) & 0xFF] ^
C4[(state[7] >> 24) & 0xFF] ^ C5[(state[6] >> 16) & 0xFF] ^
C6[(state[5] >> 8) & 0xFF] ^ C7[(state[4] >> 0) & 0xFF] ^ key[3]);
block[4] = (C0[(state[4] >> 56) & 0xFF] ^ C1[(state[3] >> 48) & 0xFF] ^
C2[(state[2] >> 40) & 0xFF] ^ C3[(state[1] >> 32) & 0xFF] ^
C4[(state[0] >> 24) & 0xFF] ^ C5[(state[7] >> 16) & 0xFF] ^
C6[(state[6] >> 8) & 0xFF] ^ C7[(state[5] >> 0) & 0xFF] ^ key[4]);
block[5] = (C0[(state[5] >> 56) & 0xFF] ^ C1[(state[4] >> 48) & 0xFF] ^
C2[(state[3] >> 40) & 0xFF] ^ C3[(state[2] >> 32) & 0xFF] ^
C4[(state[1] >> 24) & 0xFF] ^ C5[(state[0] >> 16) & 0xFF] ^
C6[(state[7] >> 8) & 0xFF] ^ C7[(state[6] >> 0) & 0xFF] ^ key[5]);
block[6] = (C0[(state[6] >> 56) & 0xFF] ^ C1[(state[5] >> 48) & 0xFF] ^
C2[(state[4] >> 40) & 0xFF] ^ C3[(state[3] >> 32) & 0xFF] ^
C4[(state[2] >> 24) & 0xFF] ^ C5[(state[1] >> 16) & 0xFF] ^
C6[(state[0] >> 8) & 0xFF] ^ C7[(state[7] >> 0) & 0xFF] ^ key[6]);
block[7] = (C0[(state[7] >> 56) & 0xFF] ^ C1[(state[6] >> 48) & 0xFF] ^
C2[(state[5] >> 40) & 0xFF] ^ C3[(state[4] >> 32) & 0xFF] ^
C4[(state[3] >> 24) & 0xFF] ^ C5[(state[2] >> 16) & 0xFF] ^
C6[(state[1] >> 8) & 0xFF] ^ C7[(state[0] >> 0) & 0xFF] ^ key[7]);
block_copy (state, block, i);
}
/* Compression. */
block_xor (context->hash_state, data_block, i);
block_xor (context->hash_state, state, i);
return /*burn_stack*/ 4 * sizeof(whirlpool_block_t) + 2 * sizeof(int) +
4 * sizeof(void*);
}
static unsigned int
whirlpool_transform ( void *c, const unsigned char *data, size_t nblks )
{
unsigned int burn;
do
{
burn = whirlpool_transform_blk (c, data);
data += BLOCK_SIZE;
}
while (--nblks);
return burn;
}
#endif /* !USE_AMD64_ASM */
/* Bug compatibility Whirlpool version. */
static void
whirlpool_add_bugemu (whirlpool_context_t *context,
const void *buffer_arg, size_t buffer_n)
{
const unsigned char *buffer = buffer_arg;
u64 buffer_size;
unsigned int carry;
unsigned int i;
buffer_size = buffer_n;
if (context->bugemu.count == BLOCK_SIZE)
{
/* Flush the buffer. */
whirlpool_transform (context, context->bctx.buf, 1);
context->bugemu.count = 0;
}
if (! buffer)
return; /* Nothing to add. */
if (context->bugemu.count)
{
while (buffer_n && (context->bugemu.count < BLOCK_SIZE))
{
context->bctx.buf[context->bugemu.count++] = *buffer++;
buffer_n--;
}
whirlpool_add_bugemu (context, NULL, 0);
if (!buffer_n)
return; /* Done. This is the bug we emulate. */
}
while (buffer_n >= BLOCK_SIZE)
{
whirlpool_transform (context, buffer, 1);
context->bugemu.count = 0;
buffer_n -= BLOCK_SIZE;
buffer += BLOCK_SIZE;
}
while (buffer_n && (context->bugemu.count < BLOCK_SIZE))
{
context->bctx.buf[context->bugemu.count++] = *buffer++;
buffer_n--;
}
/* Update bit counter. */
carry = 0;
buffer_size <<= 3;
for (i = 1; i <= 32; i++)
{
if (! (buffer_size || carry))
break;
carry += context->bugemu.length[32 - i] + (buffer_size & 0xFF);
context->bugemu.length[32 - i] = carry;
buffer_size >>= 8;
carry >>= 8;
}
gcry_assert (! (buffer_size || carry));
}
/* Bug compatibility Whirlpool version. */
static void
whirlpool_final_bugemu (void *ctx)
{
whirlpool_context_t *context = ctx;
unsigned int i;
/* Flush. */
whirlpool_add_bugemu (context, NULL, 0);
/* Pad. */
context->bctx.buf[context->bugemu.count++] = 0x80;
if (context->bugemu.count > 32)
{
/* An extra block is necessary. */
while (context->bugemu.count < 64)
context->bctx.buf[context->bugemu.count++] = 0;
whirlpool_add_bugemu (context, NULL, 0);
}
while (context->bugemu.count < 32)
context->bctx.buf[context->bugemu.count++] = 0;
/* Add length of message. */
memcpy (context->bctx.buf + context->bugemu.count,
context->bugemu.length, 32);
context->bugemu.count += 32;
whirlpool_add_bugemu (context, NULL, 0);
block_to_buffer (context->bctx.buf, context->hash_state, i);
}
static void
whirlpool_write (void *ctx, const void *buffer, size_t buffer_n)
{
whirlpool_context_t *context = ctx;
if (context->use_bugemu)
{
whirlpool_add_bugemu (context, buffer, buffer_n);
}
else
{
u64 old_nblocks = context->bctx.nblocks;
_gcry_md_block_write (context, buffer, buffer_n);
gcry_assert (old_nblocks <= context->bctx.nblocks);
}
}
static void
whirlpool_final (void *ctx)
{
whirlpool_context_t *context = ctx;
unsigned int i;
u64 t, th, lsb, msb;
unsigned char *length;
if (context->use_bugemu)
{
whirlpool_final_bugemu (ctx);
return;
}
t = context->bctx.nblocks;
/* if (sizeof t == sizeof context->bctx.nblocks) */
th = context->bctx.nblocks_high;
/* else */
/* th = context->bctx.nblocks >> 64; In case we ever use u128 */
/* multiply by 64 to make a byte count */
lsb = t << 6;
msb = (th << 6) | (t >> 58);
/* add the count */
t = lsb;
if ((lsb += context->bctx.count) < t)
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
lsb <<= 3;
msb <<= 3;
msb |= t >> 61;
/* Flush. */
whirlpool_write (context, NULL, 0);
/* Pad. */
context->bctx.buf[context->bctx.count++] = 0x80;
if (context->bctx.count > 32)
{
/* An extra block is necessary. */
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);
}
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;
buf_put_be64(&length[0 * 8], 0);
buf_put_be64(&length[1 * 8], 0);
buf_put_be64(&length[2 * 8], msb);
buf_put_be64(&length[3 * 8], lsb);
context->bctx.count += 32;
whirlpool_write (context, NULL, 0);
block_to_buffer (context->bctx.buf, context->hash_state, i);
}
static byte *
whirlpool_read (void *ctx)
{
whirlpool_context_t *context = ctx;
return context->bctx.buf;
}
gcry_md_spec_t _gcry_digest_spec_whirlpool =
{
GCRY_MD_WHIRLPOOL, {0, 0},
"WHIRLPOOL", NULL, 0, NULL, 64,
whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, NULL,
NULL, NULL,
sizeof (whirlpool_context_t)
};
diff --git a/compat/Makefile.am b/compat/Makefile.am
index f0ddf34d..5f1f44dc 100644
--- a/compat/Makefile.am
+++ b/compat/Makefile.am
@@ -1,48 +1,48 @@
# 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/>.
+# License along with this program; if not, see <https://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.
# 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@
# AC_LIBOBJ files are:
# getpid.c
# clock.c
#
diff --git a/compat/compat.c b/compat/compat.c
index 8b001de3..d43c06c7 100644
--- a/compat/compat.c
+++ b/compat/compat.c
@@ -1,40 +1,40 @@
/* compat.c - Dummy file to avoid an empty library.
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "../src/g10lib.h"
const char *
_gcry_compat_identification (void)
{
/* For complete list of copyright holders see the file AUTHORS in
the source distribution. */
static const char blurb[] =
"\n\n"
"This is Libgcrypt " PACKAGE_VERSION " - The GNU Crypto Library\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";
return blurb;
}
diff --git a/compat/libcompat.h b/compat/libcompat.h
index b5a76491..fb0ae269 100644
--- a/compat/libcompat.h
+++ b/compat/libcompat.h
@@ -1,37 +1,37 @@
/* libcomapt.h - Prototypes for AC_REPLACE_FUNCtions.
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_LIBCOMPAT_H
#define GCRY_LIBCOMPAT_H
const char *_gcry_compat_identification (void);
#ifndef HAVE_GETPID
pid_t _gcry_getpid (void);
#define getpid() _gcry_getpid ()
#endif
#ifndef HAVE_CLOCK
clock_t _gcry_clock (void);
#define clock() _gcry_clock ()
#endif
#endif /*GCRY_LIBCOMPAT_H*/
diff --git a/configure.ac b/configure.ac
index c9cbdefc..f4384dd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,2818 +1,2818 @@
# 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
#
# 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/>.
+# License along with this program; if not, see <https://www.gnu.org/licenses/>.
# (Process this file with autoconf to produce a configure script.)
AC_REVISION($Revision$)
AC_PREREQ(2.60)
min_automake_version="1.14"
# To build a release you need to create a tag with the version number
# (git tag -s libgcrypt-n.m.k) and run "./autogen.sh --force". Please
# 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_package],[libgcrypt])
m4_define([mym4_major], [1])
m4_define([mym4_minor], [9])
m4_define([mym4_micro], [0])
# 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=23
LIBGCRYPT_LT_AGE=3
LIBGCRYPT_LT_REVISION=0
################################################
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.
#
# 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
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_MACRO_DIR([m4])
AC_CONFIG_LIBOBJ_DIR([compat])
AC_CANONICAL_HOST
AM_MAINTAINER_MODE
AM_SILENT_RULES
AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory])
AH_TOP([
#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
])
AH_BOTTOM([
#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*/
])
AH_VERBATIM([_REENTRANT],
[/* To allow the use of Libgcrypt in multithreaded programs we have to use
special features from the library. */
#ifndef _REENTRANT
# define _REENTRANT 1
#endif
])
######################
## Basic checks. ### (we need some results later on (e.g. $GCC)
######################
AC_PROG_MAKE_SET
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
# AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_PROG_CC
AC_PROG_CPP
AM_PROG_CC_C_O
AM_PROG_AS
AC_ISC_POSIX
AC_PROG_INSTALL
AC_PROG_AWK
AC_GNU_SOURCE
# 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 https://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. 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])
LT_PREREQ([2.2.6])
LT_INIT([win32-dll disable-static])
LT_LANG([Windows Resource])
##########################
## 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"
available_digests="$available_digests sm3"
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
AC_DEFINE(USE_ONLY_8DOT3,1,
[set this to limit filenames to the 8.3 format])
AC_DEFINE(HAVE_DRIVE_LETTERS,1,
[defined if we must run on a stupid file system])
AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
[defined if we run on some of the PCDOS like systems
(DOS, Windoze. OS/2) with special properties like
no file modes])
;;
i?86-emx-os2 | i?86-*-os2*emx)
# OS/2 with the EMX environment
ac_cv_have_dev_random=no
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
;;
i?86-*-msdosdjgpp*)
# DOS with the DJGPP environment
ac_cv_have_dev_random=no
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
;;
*-*-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*)
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
Expose all libc features (__DARWIN_C_FULL).)
;;
*)
;;
esac
if test "$have_w32_system" = yes; then
AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
if test "$have_w32ce_system" = yes; then
AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
fi
fi
AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
# 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"
AC_ARG_ENABLE(endian-check,
AC_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
else
AC_DEFINE(DISABLED_ENDIAN_CHECK,1,[configure did not test for endianness])
fi
AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4)
AC_CHECK_SIZEOF(unsigned long long, 0)
AC_CHECK_SIZEOF(void *, 0)
AC_TYPE_UINTPTR_T
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
|| test "$ac_cv_sizeof_unsigned_long" = "0"; then
AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
fi
# Ensure that we have UINT64_C before we bother to check for uint64_t
AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works],
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <inttypes.h>]],
[[uint64_t foo=UINT64_C(42);]])],
gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no))
if test "$gnupg_cv_uint64_c_works" = "yes" ; then
AC_CHECK_SIZEOF(uint64_t)
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
AC_MSG_ERROR([[
***
*** No 64-bit integer type available.
*** It is not possible to build Libgcrypt on this platform.
***]])
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.
AC_SUBST(emacs_local_vars_begin, ['Local Variables:'])
AC_SUBST(emacs_local_vars_read_only, ['buffer-read-only: t'])
AC_SUBST(emacs_local_vars_end, ['End:'])
############################
## Command line switches. ##
############################
# Implementation of the --enable-ciphers switch.
AC_ARG_ENABLE(ciphers,
AC_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" \
-o "$enabled_ciphers" = "yes" \
-o "$enabled_ciphers" = "no"; then
enabled_ciphers=$default_ciphers
fi
AC_MSG_CHECKING([which symmetric ciphers to include])
for cipher in $enabled_ciphers; do
LIST_MEMBER($cipher, $available_ciphers)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported cipher "$cipher" specified])
fi
done
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]),
[enabled_pubkey_ciphers=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_pubkey_ciphers=""])
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
AC_MSG_CHECKING([which public-key ciphers to include])
for cipher in $enabled_pubkey_ciphers; do
LIST_MEMBER($cipher, $available_pubkey_ciphers)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported public-key cipher specified])
fi
done
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]),
[enabled_digests=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_digests=""])
if test "x$enabled_digests" = "x" \
-o "$enabled_digests" = "yes" \
-o "$enabled_digests" = "no"; then
enabled_digests=$default_digests
fi
AC_MSG_CHECKING([which message digests to include])
for digest in $enabled_digests; do
LIST_MEMBER($digest, $available_digests)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported message digest specified])
fi
done
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]),
[enabled_kdfs=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_kdfs=""])
if test "x$enabled_kdfs" = "x" \
-o "$enabled_kdfs" = "yes" \
-o "$enabled_kdfs" = "no"; then
enabled_kdfs=$default_kdfs
fi
AC_MSG_CHECKING([which key derivation functions to include])
for kdf in $enabled_kdfs; do
LIST_MEMBER($kdf, $available_kdfs)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported key derivation function specified])
fi
done
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]),
[random=`echo $enableval | tr '[A-Z]' '[a-z]'`],
[])
if test "x$random" = "x" -o "$random" = "yes" -o "$random" = "no"; then
random=default
fi
AC_MSG_CHECKING([which random module to use])
if test "$random" != "default" -a "$random" != "auto"; then
LIST_MEMBER($random, $available_random_modules)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported random module specified])
fi
fi
AC_MSG_RESULT($random)
# Implementation of the --disable-dev-random switch.
AC_MSG_CHECKING([whether use of /dev/random is requested])
AC_ARG_ENABLE(dev-random,
[ --disable-dev-random disable the use of dev random],
try_dev_random=$enableval, try_dev_random=yes)
AC_MSG_RESULT($try_dev_random)
# Implementation of the --with-egd-socket switch.
AC_ARG_WITH(egd-socket,
[ --with-egd-socket=NAME Use NAME for the EGD socket)],
egd_socket_name="$withval", egd_socket_name="" )
AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name",
[Define if you don't want the default EGD socket name.
For details see cipher/rndegd.c])
# 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)
# Implementation of --disable-asm.
AC_MSG_CHECKING([whether MPI assembler modules are requested])
AC_ARG_ENABLE([asm],
AC_HELP_STRING([--disable-asm],
[Disable MPI assembler modules]),
[try_asm_modules=$enableval],
[try_asm_modules=yes])
AC_MSG_RESULT($try_asm_modules)
# 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],
[Enable memory guard facility]),
[use_m_guard=$enableval], [use_m_guard=no])
AC_MSG_RESULT($use_m_guard)
if test "$use_m_guard" = yes ; then
AC_DEFINE(M_GUARD,1,[Define to use the (obsolete) malloc guarding feature])
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],
[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 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],
[Use linux capabilities [default=no]]),
[use_capabilities="$withval"],[use_capabilities=no])
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],
[Enable library integrity check]),
[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
AC_DEFINE(ENABLE_HMAC_BINARY_CHECK,1,
[Define to support an HMAC based integrity check])
fi
# 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],
[Disable support for the Jitter entropy collector]),
jentsupport=$enableval,jentsupport=yes)
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]),
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],
[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,
AC_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],
[Disable support for the Intel PCLMUL instructions]),
pclmulsupport=$enableval,pclmulsupport=yes)
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],
[Disable support for the Intel SSE4.1 instructions]),
sse41support=$enableval,sse41support=yes)
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],
[Disable support for the Intel DRNG (RDRAND instruction)]),
drngsupport=$enableval,drngsupport=yes)
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],
[Disable support for the Intel AVX instructions]),
avxsupport=$enableval,avxsupport=yes)
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],
[Disable support for the Intel AVX2 instructions]),
avx2support=$enableval,avx2support=yes)
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],
[Disable support for the ARM NEON instructions]),
neonsupport=$enableval,neonsupport=yes)
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],
[Disable support for the ARMv8 Crypto Extension instructions]),
armcryptosupport=$enableval,armcryptosupport=yes)
AC_MSG_RESULT($armcryptosupport)
# 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],
[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-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],
[Disable the auto-detection of AMD64 as(1) features]),
amd64_as_feature_detection=$enableval,
amd64_as_feature_detection=yes)
AC_MSG_RESULT($amd64_as_feature_detection)
AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME",
[A human readable text with the name of the OS])
# 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
AC_ARG_ENABLE([ld-version-script],
AC_HELP_STRING([--enable-ld-version-script],
[enable/disable use of linker version script.
(default is system dependent)]),
[have_ld_version_script=$enableval],
[ : ] )
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM",
[defined to the name of the strong random device])
AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM",
[defined to the name of the weaker random device])
###############################
#### Checks for libraries. ####
###############################
#
# gpg-error is required.
#
AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION")
if test "x$GPG_ERROR_LIBS" = "x"; then
AC_MSG_ERROR([libgpg-error is needed.
See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ .])
fi
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GCRYPT,
[The default error source for libgcrypt.])
#
# Check whether the GNU Pth library is available. We require this
# to build the optional gcryptrnd program.
#
AC_ARG_WITH(pth-prefix,
AC_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
AC_PATH_PROG(PTH_CONFIG, pth-config, no)
if test "$PTH_CONFIG" = "no"; then
AC_MSG_WARN([[
***
*** 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
***]])
else
GNUPG_PTH_VERSION_CHECK([1.3.7])
if test $have_pth = yes; then
PTH_CFLAGS=`$PTH_CONFIG --cflags`
PTH_LIBS=`$PTH_CONFIG --ldflags`
PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`"
AC_DEFINE(USE_GNU_PTH, 1,
[Defined if the GNU Portable Thread Library should be used])
AC_DEFINE(HAVE_PTH, 1,
[Defined if the GNU Pth is available])
fi
fi
fi
AC_SUBST(PTH_CFLAGS)
AC_SUBST(PTH_LIBS)
#
# Check whether pthreads is available
#
if test "$have_w32_system" != yes; then
AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
if test "$have_pthread" = yes; then
AC_DEFINE(HAVE_PTHREAD, 1 ,[Define if we have pthread.])
fi
fi
# Solaris needs -lsocket and -lnsl. Unisys system includes
# gethostbyname in libsocket but needs libnsl for socket.
AC_SEARCH_LIBS(setsockopt, [socket], ,
[AC_SEARCH_LIBS(setsockopt, [socket], , , [-lnsl])])
AC_SEARCH_LIBS(setsockopt, [nsl])
##################################
#### Checks for header files. ####
##################################
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h sys/select.h sys/msg.h sys/auxv.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)
##########################################
#### Checks for typedefs, structures, ####
#### and compiler characteristics. ####
##########################################
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)
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.
#
AC_CACHE_CHECK(for __builtin_bswap32,
[gcry_cv_have_builtin_bswap32],
[gcry_cv_have_builtin_bswap32=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[int x = 0; int y = __builtin_bswap32(x); return y;])],
[gcry_cv_have_builtin_bswap32=yes])])
if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_BSWAP32,1,
[Defined if compiler has '__builtin_bswap32' intrinsic])
fi
#
# Check for __builtin_bswap64 intrinsic.
#
AC_CACHE_CHECK(for __builtin_bswap64,
[gcry_cv_have_builtin_bswap64],
[gcry_cv_have_builtin_bswap64=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[long long x = 0; long long y = __builtin_bswap64(x); return y;])],
[gcry_cv_have_builtin_bswap64=yes])])
if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_BSWAP64,1,
[Defined if compiler has '__builtin_bswap64' intrinsic])
fi
#
# Check for __builtin_ctz intrinsic.
#
AC_CACHE_CHECK(for __builtin_ctz,
[gcry_cv_have_builtin_ctz],
[gcry_cv_have_builtin_ctz=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[unsigned int x = 0; int y = __builtin_ctz(x); return y;])],
[gcry_cv_have_builtin_ctz=yes])])
if test "$gcry_cv_have_builtin_ctz" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_CTZ, 1,
[Defined if compiler has '__builtin_ctz' 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,
[gcry_cv_have_vla],
[gcry_cv_have_vla=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void f1(char *, int);
char foo(int i) {
char b[(i < 0 ? 0 : i) + 1];
f1(b, sizeof b); return b[0];}]])],
[gcry_cv_have_vla=yes])])
if test "$gcry_cv_have_vla" = "yes" ; then
AC_DEFINE(HAVE_VLA,1, [Defined if variable length arrays are supported])
fi
#
# Check for ELF visibility support.
#
AC_CACHE_CHECK(whether the visibility attribute is supported,
gcry_cv_visibility_attribute,
[gcry_cv_visibility_attribute=no
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo __attribute__ ((visibility ("hidden"))) = 1;
int bar __attribute__ ((visibility ("protected"))) = 1;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; 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
])
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken visibility attribute,
gcry_cv_broken_visibility_attribute,
[gcry_cv_broken_visibility_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo (int x);
int bar (int x) __asm__ ("foo")
__attribute__ ((visibility ("hidden")));
int bar (int x) { return x; }
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep '\.hidden@<:@ _@:>@foo' conftest.s >/dev/null 2>&1;
then
gcry_cv_broken_visibility_attribute=no
fi
fi
])
fi
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken alias attribute,
gcry_cv_broken_alias_attribute,
[gcry_cv_broken_alias_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[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;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; 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
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(if gcc supports -fvisibility=hidden,
gcry_cv_gcc_has_f_visibility,
[gcry_cv_gcc_has_f_visibility=no
_gcc_cflags_save=$CFLAGS
CFLAGS="-fvisibility=hidden"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
gcry_cv_gcc_has_f_visibility=yes)
CFLAGS=$_gcc_cflags_save;
])
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
AC_DEFINE(GCRY_USE_VISIBILITY, 1,
[Define to use the GNU C visibility attribute.])
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
#
AC_CACHE_CHECK([whether the GCC style aligned attribute is supported],
[gcry_cv_gcc_attribute_aligned],
[gcry_cv_gcc_attribute_aligned=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[struct { int a; } foo __attribute__ ((aligned (16)));]])],
[gcry_cv_gcc_attribute_aligned=yes])])
if test "$gcry_cv_gcc_attribute_aligned" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_ALIGNED,1,
[Defined if a GCC style "__attribute__ ((aligned (n))" is supported])
fi
#
# Check whether the compiler supports the GCC style packed attribute
#
AC_CACHE_CHECK([whether the GCC style packed attribute is supported],
[gcry_cv_gcc_attribute_packed],
[gcry_cv_gcc_attribute_packed=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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))),
};]])],
[gcry_cv_gcc_attribute_packed=yes])])
if test "$gcry_cv_gcc_attribute_packed" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_PACKED,1,
[Defined if a GCC style "__attribute__ ((packed))" is supported])
fi
#
# Check whether the compiler supports the GCC style may_alias attribute
#
AC_CACHE_CHECK([whether the GCC style may_alias attribute is supported],
[gcry_cv_gcc_attribute_may_alias],
[gcry_cv_gcc_attribute_may_alias=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[typedef struct foo_s { int a; }
__attribute__ ((may_alias)) foo_t;]])],
[gcry_cv_gcc_attribute_may_alias=yes])])
if test "$gcry_cv_gcc_attribute_may_alias" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_MAY_ALIAS,1,
[Defined if a GCC style "__attribute__ ((may_alias))" is supported])
fi
# Restore flags.
CFLAGS=$_gcc_cflags_save;
#
# Check whether the compiler supports 'asm' or '__asm__' keyword for
# assembler blocks.
#
AC_CACHE_CHECK([whether 'asm' assembler keyword is supported],
[gcry_cv_have_asm],
[gcry_cv_have_asm=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { asm("":::"memory"); }]])],
[gcry_cv_have_asm=yes])])
AC_CACHE_CHECK([whether '__asm__' assembler keyword is supported],
[gcry_cv_have___asm__],
[gcry_cv_have___asm__=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { __asm__("":::"memory"); }]])],
[gcry_cv_have___asm__=yes])])
if test "$gcry_cv_have_asm" = "no" ; then
if test "$gcry_cv_have___asm__" = "yes" ; then
AC_DEFINE(asm,__asm__,
[Define to supported assembler block keyword, if plain 'asm' was not
supported])
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
AC_CACHE_CHECK([whether inline assembly memory barrier is supported],
[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"); }]])],
[gcry_cv_have_asm_volatile_memory=yes])])
fi
else
AC_CACHE_CHECK([whether inline assembly memory barrier is supported],
[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"); }]])],
[gcry_cv_have_asm_volatile_memory=yes])])
fi
if test "$gcry_cv_have_asm_volatile_memory" = "yes" ; then
AC_DEFINE(HAVE_GCC_ASM_VOLATILE_MEMORY,1,
[Define if inline asm memory barrier is supported])
fi
#
# Check whether GCC assembler supports features needed for our ARM
# implementations. This needs to be done before setting up the
# assembler stuff.
#
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__(
/* 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"
);]])],
[gcry_cv_gcc_arm_platform_as_ok=yes])])
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])
fi
#
# Check whether GCC assembler supports features needed for our ARMv8/Aarch64
# implementations. This needs to be done before setting up the
# assembler stuff.
#
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__(
"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"
);]])],
[gcry_cv_gcc_aarch64_platform_as_ok=yes])])
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 underscores in symbols are required. This needs to be
# done before setting up the assembler stuff.
#
GNUPG_SYS_SYMBOL_UNDERSCORE()
#################################
#### ####
#### Setup assembler stuff. ####
#### Define mpi_cpu_arch. ####
#### ####
#################################
AC_ARG_ENABLE(mpi-path,
AC_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
. $srcdir/mpi/config.links
AC_CONFIG_LINKS("$mpi_ln_list")
ac_cv_mpi_sflags="$mpi_sflags"
AC_MSG_RESULT($mpi_cpu_arch)
else
AC_MSG_RESULT(failed)
AC_MSG_ERROR([mpi/config.links missing!])
fi
MPI_SFLAGS="$ac_cv_mpi_sflags"
AC_SUBST(MPI_SFLAGS)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_ADD1, test "$mpi_mod_asm_mpih_add1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_SUB1, test "$mpi_mod_asm_mpih_sub1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL1, test "$mpi_mod_asm_mpih_mul1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL2, test "$mpi_mod_asm_mpih_mul2" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL3, test "$mpi_mod_asm_mpih_mul3" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_LSHIFT, test "$mpi_mod_asm_mpih_lshift" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_RSHIFT, test "$mpi_mod_asm_mpih_rshift" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_UDIV, test "$mpi_mod_asm_udiv" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_UDIV_QRNND, test "$mpi_mod_asm_udiv_qrnnd" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_ADD1, test "$mpi_mod_c_mpih_add1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_SUB1, test "$mpi_mod_c_mpih_sub1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL1, test "$mpi_mod_c_mpih_mul1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL2, test "$mpi_mod_c_mpih_mul2" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL3, test "$mpi_mod_c_mpih_mul3" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_LSHIFT, test "$mpi_mod_c_mpih_lshift" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_RSHIFT, test "$mpi_mod_c_mpih_rshift" = yes)
AM_CONDITIONAL(MPI_MOD_C_UDIV, test "$mpi_mod_c_udiv" = yes)
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
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.
#
AC_CACHE_CHECK([whether compiler supports 'ms_abi' function attribute],
[gcry_cv_gcc_attribute_ms_abi],
[gcry_cv_gcc_attribute_ms_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[int __attribute__ ((ms_abi)) proto(int);]])],
[gcry_cv_gcc_attribute_ms_abi=yes])])
if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_MS_ABI,1,
[Defined if compiler supports "__attribute__ ((ms_abi))" function attribute])
fi
#
# Check whether compiler supports 'sysv_abi' function attribute.
#
AC_CACHE_CHECK([whether compiler supports 'sysv_abi' function attribute],
[gcry_cv_gcc_attribute_sysv_abi],
[gcry_cv_gcc_attribute_sysv_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[int __attribute__ ((sysv_abi)) proto(int);]])],
[gcry_cv_gcc_attribute_sysv_abi=yes])])
if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_SYSV_ABI,1,
[Defined if compiler supports "__attribute__ ((sysv_abi))" function attribute])
fi
#
# Check whether default calling convention is 'ms_abi'.
#
if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
AC_CACHE_CHECK([whether default calling convention is 'ms_abi'],
[gcry_cv_gcc_default_abi_is_ms_abi],
[gcry_cv_gcc_default_abi_is_ms_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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;
}]])],
[gcry_cv_gcc_default_abi_is_ms_abi=yes])])
if test "$gcry_cv_gcc_default_abi_is_ms_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_DEFAULT_ABI_IS_MS_ABI,1,
[Defined if default calling convention is 'ms_abi'])
fi
fi
#
# Check whether default calling convention is 'sysv_abi'.
#
if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
AC_CACHE_CHECK([whether default calling convention is 'sysv_abi'],
[gcry_cv_gcc_default_abi_is_sysv_abi],
[gcry_cv_gcc_default_abi_is_sysv_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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;
}]])],
[gcry_cv_gcc_default_abi_is_sysv_abi=yes])])
if test "$gcry_cv_gcc_default_abi_is_sysv_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_DEFAULT_ABI_IS_SYSV_ABI,1,
[Defined if default calling convention is 'sysv_abi'])
fi
fi
# Restore flags.
CFLAGS=$_gcc_cflags_save;
#
# Check whether GCC inline assembler supports SSSE3 instructions
# This is required for the AES-NI instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports SSSE3 instructions],
[gcry_cv_gcc_inline_asm_ssse3],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_ssse3="n/a"
else
gcry_cv_gcc_inline_asm_ssse3=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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):);
}]])],
[gcry_cv_gcc_inline_asm_ssse3=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_SSSE3,1,
[Defined if inline assembler supports SSSE3 instructions])
fi
#
# Check whether GCC inline assembler supports PCLMUL instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports PCLMUL instructions],
[gcry_cv_gcc_inline_asm_pclmul],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_pclmul="n/a"
else
gcry_cv_gcc_inline_asm_pclmul=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("pclmulqdq \$0, %%xmm1, %%xmm3\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_pclmul=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_PCLMUL,1,
[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" ; then
gcry_cv_gcc_inline_asm_shaext="n/a"
else
gcry_cv_gcc_inline_asm_shaext=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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");
}]])],
[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
gcry_cv_gcc_inline_asm_sse41="n/a"
else
gcry_cv_gcc_inline_asm_sse41=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
int i;
__asm__("pextrd \$2, %%xmm0, %[out]\n\t" : [out] "=m" (i));
}]])],
[gcry_cv_gcc_inline_asm_sse41=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_sse41" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_SSE41,1,
[Defined if inline assembler supports SSE4.1 instructions])
fi
#
# Check whether GCC inline assembler supports AVX instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions],
[gcry_cv_gcc_inline_asm_avx],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_avx="n/a"
else
gcry_cv_gcc_inline_asm_avx=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
}]])],
[gcry_cv_gcc_inline_asm_avx=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX,1,
[Defined if inline assembler supports AVX instructions])
fi
#
# Check whether GCC inline assembler supports AVX2 instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions],
[gcry_cv_gcc_inline_asm_avx2],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_avx2="n/a"
else
gcry_cv_gcc_inline_asm_avx2=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_avx2=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX2,1,
[Defined if inline assembler supports AVX2 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
gcry_cv_gcc_inline_asm_bmi2="n/a"
else
gcry_cv_gcc_inline_asm_bmi2=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[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;
}]])],
[gcry_cv_gcc_inline_asm_bmi2=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_bmi2" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_BMI2,1,
[Defined if inline assembler supports BMI2 instructions])
fi
#
# Check whether GCC assembler needs "-Wa,--divide" to correctly handle
# constant division
#
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");]])],
[gcry_cv_gcc_as_const_division_ok=yes])])
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"
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");]])],
[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.
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
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
gcry_cv_gcc_amd64_platform_as_ok="n/a"
else
gcry_cv_gcc_amd64_platform_as_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__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"
);]])],
[gcry_cv_gcc_amd64_platform_as_ok=yes])
fi])
if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with amd64 assembly implementations])
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
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(
[[__asm__(
".globl asmfunc\n\t"
"asmfunc:\n\t"
"xorq \$(1234), %rbp;\n\t"
);]])],
[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,
[Defined if underlying assembler is compatible with WIN64 assembly implementations])
fi
fi
fi
#
# Check whether GCC assembler supports features needed for assembly
# implementations that use Intel syntax
#
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
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(
[[__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"
);]])],
[gcry_cv_gcc_platform_as_ok_for_intel_syntax=yes])
fi])
if test "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" = "yes" ; then
AC_DEFINE(HAVE_INTEL_SYNTAX_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with Intel syntax assembly implementations])
fi
#
# Check whether compiler is configured for ARMv6 or newer architecture
#
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
gcry_cv_cc_arm_arch_is_v6="n/a"
else
gcry_cv_cc_arm_arch_is_v6=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[
#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
]])],
[gcry_cv_cc_arm_arch_is_v6=yes])
fi])
if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then
AC_DEFINE(HAVE_ARM_ARCH_V6,1,
[Defined if ARM architecture is v6 or newer])
fi
#
# Check whether GCC inline assembler supports NEON instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions],
[gcry_cv_gcc_inline_asm_neon],
[if test "$mpi_cpu_arch" != "arm" ; then
gcry_cv_gcc_inline_asm_neon="n/a"
else
gcry_cv_gcc_inline_asm_neon=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__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"
);
]])],
[gcry_cv_gcc_inline_asm_neon=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_NEON,1,
[Defined if inline assembler supports NEON instructions])
fi
#
# Check whether GCC inline assembler supports AArch32 Crypto Extension instructions
#
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
gcry_cv_gcc_inline_asm_aarch32_crypto="n/a"
else
gcry_cv_gcc_inline_asm_aarch32_crypto=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__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"
);
]])],
[gcry_cv_gcc_inline_asm_aarch32_crypto=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO,1,
[Defined if inline assembler supports AArch32 Crypto Extension instructions])
fi
#
# Check whether GCC inline assembler supports AArch64 NEON instructions
#
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
gcry_cv_gcc_inline_asm_aarch64_neon="n/a"
else
gcry_cv_gcc_inline_asm_aarch64_neon=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__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"
);
]])],
[gcry_cv_gcc_inline_asm_aarch64_neon=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch64_neon" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_NEON,1,
[Defined if inline assembler supports AArch64 NEON instructions])
fi
#
# Check whether GCC inline assembler supports AArch64 Crypto Extension instructions
#
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
gcry_cv_gcc_inline_asm_aarch64_crypto="n/a"
else
gcry_cv_gcc_inline_asm_aarch64_crypto=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__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"
);
]])],
[gcry_cv_gcc_inline_asm_aarch64_crypto=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO,1,
[Defined if inline assembler supports AArch64 Crypto Extension instructions])
fi
#######################################
#### Checks for library functions. ####
#######################################
AC_FUNC_VPRINTF
# We have replacements for these in src/missing-string.c
AC_CHECK_FUNCS(stpcpy strcasecmp)
# We have replacements for these in src/g10lib.h
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 getauxval elf_aux_info)
AC_CHECK_FUNCS(explicit_bzero explicit_memset getentropy)
GNUPG_CHECK_MLOCK
#
# Replacement functions.
#
AC_REPLACE_FUNCS([getpid clock])
#
# Check whether it is necessary to link against libdl.
#
DL_LIBS=""
if test "$use_hmac_binary_check" = yes ; 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)
#
# Check whether we can use Linux capabilities as requested.
#
if test "$use_capabilities" = "yes" ; then
use_capabilities=no
AC_CHECK_HEADERS(sys/capability.h)
if test "$ac_cv_header_sys_capability_h" = "yes" ; then
AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1)
if test "$ac_cv_lib_cap_cap_init" = "yes"; then
AC_DEFINE(USE_CAPABILITIES,1,
[define if capabilities should be used])
LIBS="$LIBS -lcap"
use_capabilities=yes
fi
fi
if test "$use_capabilities" = "no" ; then
AC_MSG_WARN([[
***
*** 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.
***]])
fi
fi
# Check whether a random device is available.
if test "$try_dev_random" = yes ; then
AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
[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])
if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(HAVE_DEV_RANDOM,1,
[defined if the system supports a random device] )
fi
else
AC_MSG_CHECKING(for random device)
ac_cv_have_dev_random=no
AC_MSG_RESULT(has been disabled)
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 mym4_isgit = "yes"; then
AC_DEFINE(IS_DEVELOPMENT_VERSION,1,
[Defined if this is not a regular release])
fi
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]),
[if test $enableval = no ; then
CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'`
fi])
AC_MSG_NOTICE([checking for cc features])
# CFLAGS mangling when using gcc.
if test "$GCC" = yes; then
AC_MSG_CHECKING([if gcc supports -fno-delete-null-pointer-checks])
_gcc_cflags_save=$CFLAGS
CFLAGS="-fno-delete-null-pointer-checks"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
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.
AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wno-missing-field-initializers"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
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
AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wpointer-arith"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
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.
CL_AS_NOEXECSTACK
AC_SUBST(LIBGCRYPT_CONFIG_API_VERSION)
AC_SUBST(LIBGCRYPT_CONFIG_LIBS)
AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS)
AC_SUBST(LIBGCRYPT_CONFIG_HOST)
AC_SUBST(LIBGCRYPT_THREAD_MODULES)
AC_CONFIG_COMMANDS([gcrypt-conf],[[
chmod +x src/libgcrypt-config
]],[[
prefix=$prefix
exec_prefix=$exec_prefix
libdir=$libdir
datadir=$datadir
DATADIRNAME=$DATADIRNAME
]])
#####################
#### 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"$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)"
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
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.])
fi
if test x"$sse41support" = xyes ; then
AC_DEFINE(ENABLE_SSE41_SUPPORT, 1,
[Enable support for Intel SSE4.1 instructions.])
fi
if test x"$avxsupport" = xyes ; then
AC_DEFINE(ENABLE_AVX_SUPPORT,1,
[Enable support for Intel AVX instructions.])
fi
if test x"$avx2support" = xyes ; then
AC_DEFINE(ENABLE_AVX2_SUPPORT,1,
[Enable support for Intel AVX2 instructions.])
fi
if test x"$neonsupport" = xyes ; then
AC_DEFINE(ENABLE_NEON_SUPPORT,1,
[Enable support for ARM NEON instructions.])
fi
if test x"$armcryptosupport" = xyes ; then
AC_DEFINE(ENABLE_ARM_CRYPTO_SUPPORT,1,
[Enable support for ARMv8 Crypto Extension instructions.])
fi
if test x"$jentsupport" = xyes ; then
AC_DEFINE(ENABLE_JENT_SUPPORT, 1,
[Enable support for the jitter entropy collector.])
fi
if test x"$padlocksupport" = xyes ; then
AC_DEFINE(ENABLE_PADLOCK_SUPPORT, 1,
[Enable support for the PadLock engine.])
fi
if test x"$drngsupport" = xyes ; then
AC_DEFINE(ENABLE_DRNG_SUPPORT, 1,
[Enable support for Intel DRNG (RDRAND instruction).])
fi
# Define conditional sources and config.h symbols depending on the
# selected ciphers, pubkey-ciphers, digests, kdfs, and random modules.
LIST_MEMBER(arcfour, $enabled_ciphers)
if test "$found" = "1"; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour.lo"
AC_DEFINE(USE_ARCFOUR, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour-amd64.lo"
;;
esac
fi
LIST_MEMBER(blowfish, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish.lo"
AC_DEFINE(USE_BLOWFISH, 1, [Defined if this module should be included])
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
LIST_MEMBER(cast5, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5.lo"
AC_DEFINE(USE_CAST5, 1, [Defined if this module should be included])
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
LIST_MEMBER(des, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS des.lo"
AC_DEFINE(USE_DES, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS des-amd64.lo"
;;
esac
fi
LIST_MEMBER(aes, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael.lo"
AC_DEFINE(USE_AES, 1, [Defined if this module should be included])
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
LIST_MEMBER(twofish, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish.lo"
AC_DEFINE(USE_TWOFISH, 1, [Defined if this module should be included])
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
LIST_MEMBER(serpent, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent.lo"
AC_DEFINE(USE_SERPENT, 1, [Defined if this module should be included])
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
LIST_MEMBER(rfc2268, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rfc2268.lo"
AC_DEFINE(USE_RFC2268, 1, [Defined if this module should be included])
fi
LIST_MEMBER(seed, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS seed.lo"
AC_DEFINE(USE_SEED, 1, [Defined if this module should be included])
fi
LIST_MEMBER(camellia, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia.lo camellia-glue.lo"
AC_DEFINE(USE_CAMELLIA, 1, [Defined if this module should be included])
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
LIST_MEMBER(idea, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS idea.lo"
AC_DEFINE(USE_IDEA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(salsa20, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20.lo"
AC_DEFINE(USE_SALSA20, 1, [Defined if this module should be included])
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
LIST_MEMBER(gost28147, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS gost28147.lo"
AC_DEFINE(USE_GOST28147, 1, [Defined if this module should be included])
fi
LIST_MEMBER(chacha20, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20.lo"
AC_DEFINE(USE_CHACHA20, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-amd64-ssse3.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-amd64-avx2.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-aarch64.lo"
;;
esac
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-armv7-neon.lo"
fi
fi
LIST_MEMBER(dsa, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo"
AC_DEFINE(USE_DSA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(rsa, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS rsa.lo"
AC_DEFINE(USE_RSA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(elgamal, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS elgamal.lo"
AC_DEFINE(USE_ELGAMAL, 1, [Defined if this module should be included])
fi
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"
AC_DEFINE(USE_ECC, 1, [Defined if this module should be included])
fi
LIST_MEMBER(crc, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo"
AC_DEFINE(USE_CRC, 1, [Defined if this module should be included])
case "${host}" in
i?86-*-* | x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-armv8-ce.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-armv8-aarch64-ce.lo"
;;
esac
fi
LIST_MEMBER(gostr3411-94, $enabled_digests)
if test "$found" = "1" ; then
# GOST R 34.11-94 internally uses GOST 28147-89
LIST_MEMBER(gost28147, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS gostr3411-94.lo"
AC_DEFINE(USE_GOST_R_3411_94, 1, [Defined if this module should be included])
fi
fi
LIST_MEMBER(stribog, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS stribog.lo"
AC_DEFINE(USE_GOST_R_3411_12, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md2, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md2.lo"
AC_DEFINE(USE_MD2, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md4, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md4.lo"
AC_DEFINE(USE_MD4, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md5, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md5.lo"
AC_DEFINE(USE_MD5, 1, [Defined if this module should be included])
fi
LIST_MEMBER(rmd160, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo"
AC_DEFINE(USE_RMD160, 1, [Defined if this module should be included])
fi
LIST_MEMBER(sha256, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256.lo"
AC_DEFINE(USE_SHA256, 1, [Defined if this module should be included])
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
case "$mpi_cpu_arch" in
x86)
# Build with the SHAEXT implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-intel-shaext.lo"
;;
esac
fi
LIST_MEMBER(sha512, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512.lo"
AC_DEFINE(USE_SHA512, 1, [Defined if this module should be included])
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
LIST_MEMBER(sha3, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo"
AC_DEFINE(USE_SHA3, 1, [Defined if this module should be included])
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
LIST_MEMBER(tiger, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS tiger.lo"
AC_DEFINE(USE_TIGER, 1, [Defined if this module should be included])
fi
LIST_MEMBER(whirlpool, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool.lo"
AC_DEFINE(USE_WHIRLPOOL, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool-sse2-amd64.lo"
;;
esac
fi
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_DIGESTS="$GCRYPT_DIGESTS blake2b-amd64-avx2.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2s-amd64-avx.lo"
;;
esac
fi
# SHA-1 needs to be included always for example because it is used by
# random-csprng.c.
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1.lo"
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_DIGESTS="$GCRYPT_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"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch64-ce.lo"
;;
esac
case "$mpi_cpu_arch" in
x86)
# Build with the SHAEXT implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-intel-shaext.lo"
;;
esac
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])
fi
LIST_MEMBER(scrypt, $enabled_kdfs)
if test "$found" = "1" ; then
GCRYPT_KDFS="$GCRYPT_KDFS scrypt.lo"
AC_DEFINE(USE_SCRYPT, 1, [Defined if this module should be included])
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.])
fi
LIST_MEMBER(unix, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo"
AC_DEFINE(USE_RNDUNIX, 1, [Defined if the default Unix RNG should be used.])
fi
LIST_MEMBER(egd, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndegd.lo"
AC_DEFINE(USE_RNDEGD, 1, [Defined if the EGD based RNG should be used.])
fi
LIST_MEMBER(w32, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo"
AC_DEFINE(USE_RNDW32, 1,
[Defined if the Windows specific RNG should be used.])
fi
LIST_MEMBER(w32ce, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo"
AC_DEFINE(USE_RNDW32CE, 1,
[Defined if the WindowsCE specific RNG should be used.])
fi
AC_SUBST([GCRYPT_CIPHERS])
AC_SUBST([GCRYPT_PUBKEY_CIPHERS])
AC_SUBST([GCRYPT_DIGESTS])
AC_SUBST([GCRYPT_KDFS])
AC_SUBST([GCRYPT_RANDOM])
AC_SUBST(LIBGCRYPT_CIPHERS, $enabled_ciphers)
AC_SUBST(LIBGCRYPT_PUBKEY_CIPHERS, $enabled_pubkey_ciphers)
AC_SUBST(LIBGCRYPT_DIGESTS, $enabled_digests)
# For printing the configuration we need a colon separated list of
# algorithm names.
tmp=`echo "$enabled_ciphers" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_CIPHERS, "$tmp",
[List of available cipher algorithms])
tmp=`echo "$enabled_pubkey_ciphers" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_PUBKEY_CIPHERS, "$tmp",
[List of available public key cipher algorithms])
tmp=`echo "$enabled_digests" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp",
[List of available digest algorithms])
tmp=`echo "$enabled_kdfs" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_KDFS, "$tmp",
[List of available KDF algorithms])
#
# 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)
AC_DEFINE(HAVE_CPU_ARCH_X86, 1, [Defined for the x86 platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-x86.lo"
;;
alpha)
AC_DEFINE(HAVE_CPU_ARCH_ALPHA, 1, [Defined for Alpha platforms])
;;
sparc)
AC_DEFINE(HAVE_CPU_ARCH_SPARC, 1, [Defined for SPARC platforms])
;;
mips)
AC_DEFINE(HAVE_CPU_ARCH_MIPS, 1, [Defined for MIPS platforms])
;;
m68k)
AC_DEFINE(HAVE_CPU_ARCH_M68K, 1, [Defined for M68k platforms])
;;
ppc)
AC_DEFINE(HAVE_CPU_ARCH_PPC, 1, [Defined for PPC platforms])
;;
arm)
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
;;
aarch64)
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM AArch64 platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
;;
esac
AC_SUBST([GCRYPT_HWF_MODULES])
#
# Option to disable building of doc file
#
build_doc=yes
AC_ARG_ENABLE([doc], AC_HELP_STRING([--disable-doc],
[do not build the documentation]),
build_doc=$enableval, build_doc=yes)
AM_CONDITIONAL([BUILD_DOC], [test "x$build_doc" != xno])
#
# Provide information about the build.
#
BUILD_REVISION="mym4_revision"
AC_SUBST(BUILD_REVISION)
AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
[GIT commit id revision used to build this package])
changequote(,)dnl
BUILD_VERSION=`echo "$PACKAGE_VERSION" | sed 's/\([0-9.]*\).*/\1./'`
changequote([,])dnl
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],
[set an explicit build timestamp for reproducibility.
(default is the current time in ISO-8601 format)]),
[if test "$enableval" = "yes"; then
BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
else
BUILD_TIMESTAMP="$enableval"
fi],
[BUILD_TIMESTAMP="<none>"])
AC_SUBST(BUILD_TIMESTAMP)
AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
[The time this package was configured for a build])
# And create the 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/libgcrypt.pc
src/versioninfo.rc
tests/Makefile
])
AC_CONFIG_FILES([tests/hashtest-256g], [chmod +x tests/hashtest-256g])
AC_CONFIG_FILES([tests/basic-disable-all-hwf], [chmod +x tests/basic-disable-all-hwf])
AC_OUTPUT
detection_module="${GCRYPT_HWF_MODULES%.lo}"
test -n "$detection_module" || detection_module="none"
# Give some feedback
GCRY_MSG_SHOW([],[])
GCRY_MSG_SHOW([Libgcrypt],[v${VERSION} has been configured as follows:])
GCRY_MSG_SHOW([],[])
GCRY_MSG_SHOW([Platform: ],[$PRINTABLE_OS_NAME ($host)])
GCRY_MSG_SHOW([Hardware detection module:],[$detection_module])
GCRY_MSG_WRAP([Enabled cipher algorithms:],[$enabled_ciphers])
GCRY_MSG_WRAP([Enabled digest algorithms:],[$enabled_digests])
GCRY_MSG_WRAP([Enabled kdf algorithms: ],[$enabled_kdfs])
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([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])
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([],[])
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
diff --git a/doc/announce-1.4.txt b/doc/announce-1.4.txt
index 26e8bb33..63e1beb9 100644
--- a/doc/announce-1.4.txt
+++ b/doc/announce-1.4.txt
@@ -1,155 +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
+listed at https://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 .
+[1] See https://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 .
+[3] See the service directory at https://www.gnupg.org/service.html .
diff --git a/doc/announce.txt b/doc/announce.txt
index 48c41bf4..9fc3a560 100644
--- a/doc/announce.txt
+++ b/doc/announce.txt
@@ -1,91 +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
+listed at https://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 .
+[1] See https://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 .
+[3] For example see https://donate.fsf.org .
+[4] See the service directory at https://www.gnupg.org/service.html .
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index d7bfa4c2..4873c5e7 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -1,6793 +1,6793 @@
\input texinfo @c -*- Texinfo -*-
@c %**start of header
@setfilename gcrypt.info
@include version.texi
@settitle The Libgcrypt Reference Manual
@c Unify some of the indices.
@syncodeindex tp fn
@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.
@noindent
Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc. @*
Copyright @copyright{} 2012, 2013, 2016, 2017 g10 Code GmbH
@quotation
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''.
@end quotation
@end copying
@dircategory GNU Libraries
@direntry
* libgcrypt: (gcrypt). Cryptographic function library.
@end direntry
@c A couple of macros with no effect on texinfo
@c but used by the yat2m processor.
@macro manpage {a}
@end macro
@macro mansect {a}
@end macro
@macro manpause
@end macro
@macro mancont
@end macro
@c
@c Printing stuff taken from gcc.
@c
@macro gnupgtabopt{body}
@code{\body\}
@end macro
@c
@c Titlepage
@c
@setchapternewpage odd
@titlepage
@title The Libgcrypt Reference Manual
@subtitle Version @value{VERSION}
@subtitle @value{UPDATED}
@author Werner Koch (@email{wk@@gnupg.org})
@author Moritz Schulte (@email{mo@@g10code.com})
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@ifnothtml
@summarycontents
@contents
@page
@end ifnothtml
@ifnottex
@node Top
@top The Libgcrypt Library
@insertcopying
@end ifnottex
@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.
@end menu
@ifhtml
@page
@summarycontents
@contents
@end ifhtml
@c **********************************************************
@c ******************* Introduction ***********************
@c **********************************************************
@node Introduction
@chapter 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.
@end menu
@node Getting Started
@section Getting Started
This manual documents the Libgcrypt library application programming
interface (API). All functions and data types provided by the library
are explained.
@noindent
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.
@node Features
@section Features
Libgcrypt might have a couple of advantages over other libraries doing
a similar job.
@table @asis
@item It's Free Software
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.
@item It encapsulates the low level cryptography
Libgcrypt provides a high level interface to cryptographic
building blocks using an extensible and flexible API.
@end table
@node Overview
@section Overview
@noindent
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.
@c **********************************************************
@c ******************* Preparation ************************
@c **********************************************************
@node Preparation
@chapter 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.
@end menu
@node Header
@section Header
All interfaces (data types and functions) of the library are defined
in the header file @file{gcrypt.h}. You must include this in all source
files using the library, either directly or through some other header
file, like this:
@example
#include <gcrypt.h>
@end example
The name space of Libgcrypt is @code{gcry_*} for function
and type names and @code{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 @code{gpg_*} as
name space for function and type names and @code{GPG_*} for other
symbols, including all the error codes.
@noindent
Certain parts of gcrypt.h may be excluded by defining these macros:
@table @code
@item GCRYPT_NO_MPI_MACROS
Do not define the shorthand macros @code{mpi_*} for @code{gcry_mpi_*}.
@item GCRYPT_NO_DEPRECATED
Do not include definitions for deprecated features. This is useful to
make sure that no deprecated features are used.
@end table
@node Building sources
@section 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 @option{-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 @command{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 @option{--cflags} option to @command{libgcrypt-config}. The following
example shows how it can be used at the command line:
@example
gcc -c foo.c `libgcrypt-config --cflags`
@end example
Adding the output of @samp{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 @option{-L} option). For this, the option @option{--libs} to
@command{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 @samp{-lgcrypt}
option). The example shows how to link @file{foo.o} with the Libgcrypt
library to a program @command{foo}.
@example
gcc -o foo foo.o `libgcrypt-config --libs`
@end example
Of course you can also combine both examples to a single command by
specifying both options to @command{libgcrypt-config}:
@example
gcc -o foo foo.c `libgcrypt-config --cflags --libs`
@end example
@node Building sources using Automake
@section 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 @command{libgcrypt-config} script at all.
Libgcrypt provides an extension to Automake that does all
the work for you.
@c A simple macro for optional variables.
@macro ovar{varname}
@r{[}@var{\varname\}@r{]}
@end macro
@defmac AM_PATH_LIBGCRYPT (@ovar{minimum-version}, @ovar{action-if-found}, @ovar{action-if-not-found})
Check whether Libgcrypt (at least version
@var{minimum-version}, if given) exists on the host system. If it is
found, execute @var{action-if-found}, otherwise do
@var{action-if-not-found}, if given.
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
a warning is printed and the string @code{libgcrypt} is appended to the
variable @code{gpg_config_script_warn}.
This macro searches for @command{libgcrypt-config} along the PATH. If
you are cross-compiling, it is useful to set the environment variable
@code{SYSROOT} to the top directory of your target. The macro will
then first look for the helper program in the @file{bin} directory
below that top directory. An absolute directory name must be used for
@code{SYSROOT}. Finally, if the configure command line option
@code{--with-libgcrypt-prefix} is used, only its value is used for the top
directory below which the helper script is expected.
@end defmac
You can use the defined Autoconf variables like this in your
@file{Makefile.am}:
@example
AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS)
LDADD = $(LIBGCRYPT_LIBS)
@end example
@node Initializing the library
@section Initializing the library
Before the library can be used, it must initialize itself. This is
achieved by invoking the function @code{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.
@deftypefun {const char *} gcry_check_version (const char *@var{req_version})
The function @code{gcry_check_version} initializes some subsystems used
by Libgcrypt and must be invoked before any other function in the
library.
@xref{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 @var{req_version}, if this value is not a null
pointer.
@end deftypefun
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:
@example
/* Version check should be the very first call because it
makes sure that important subsystems are initialized.
#define NEED_LIBGCRYPT_VERSION to the minimum required version. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
@{
fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n",
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
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);
@end example
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:
@example
/* Version check should be the very first call because it
makes sure that important subsystems are initialized.
#define NEED_LIBGCRYPT_VERSION to the minimum required version. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
@{
fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n",
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
exit (2);
@}
@anchor{sample-use-suspend-secmem}
/* 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);
@anchor{sample-use-resume-secmem}
/* 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);
@end example
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:
@example
if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
@{
fputs ("libgcrypt has not been initialized\n", stderr);
abort ();
@}
@end example
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.
@node Multi-Threading
@section Multi-Threading
As mentioned earlier, the Libgcrypt library is
thread-safe if you adhere to the following requirements:
@itemize @bullet
@item
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.
@item
The function @code{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
@code{gcry_check_version} before creating the other threads using
Libgcrypt@footnote{At least this is true for POSIX threads,
as @code{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.}.
@item
Just like the function @code{gpg_strerror}, the function
@code{gcry_strerror} is not thread safe. You have to use
@code{gpg_strerror_r} instead.
@end itemize
@node Enabling FIPS mode
@section How to enable the FIPS mode
@cindex FIPS mode
@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
-NIST database at @url{http://csrc.nist.gov/groups/STM/cmvp/} to see what
+NIST database at @url{https://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:
@itemize
@item
If the file @file{/proc/sys/crypto/fips_enabled} exists and contains a
numeric value other than @code{0}, Libgcrypt is put into FIPS mode at
initialization time. Obviously this works only on systems with a
@code{proc} file system (i.e. GNU/Linux).
@item
If the file @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.
@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}).
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
@cindex hardware features
@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
globally using a configuration file. The currently supported features
are
@table @code
@item padlock-rng
@item padlock-aes
@item padlock-sha
@item padlock-mmul
@item intel-cpu
@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 arm-neon
@item arm-aes
@item arm-sha1
@item arm-sha2
@item arm-pmull
@end table
To disable a feature for all processes using Libgcrypt 1.6 or newer,
create the file @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 @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}
@example
gcry_control (GCRYCTL_DISABLE_HWF, "intel-rdrand", NULL);
@end example
@noindent
To print the list of active features you may use this command:
@example
mpicalc --print-config | grep ^hwflist: | tr : '\n' | tail -n +2
@end example
@c **********************************************************
@c ******************* General ****************************
@c **********************************************************
@node Generalities
@chapter Generalities
@menu
* Controlling the library:: Controlling Libgcrypt's behavior.
* Error Handling:: Error codes and such.
@end menu
@node Controlling the library
@section Controlling the library
@deftypefun gcry_error_t gcry_control (enum gcry_ctl_cmds @var{cmd}, ...)
This function can be used to influence the general behavior of
Libgcrypt in several ways. Depending on @var{cmd}, more
arguments can or have to be provided.
@table @code
@item 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
@code{gcry_check_version}. Note that the memory guard is NOT used
when the user of the library has set his own memory management
callbacks.
@item GCRYCTL_ENABLE_QUICK_RANDOM; Arguments: none
This command inhibits the use the very secure random quality level
(@code{GCRY_VERY_STRONG_RANDOM}) and degrades all request down to
@code{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.
@item GCRYCTL_DUMP_RANDOM_STATS; Arguments: none
This command dumps random number generator related statistics to the
library's logging stream.
@item GCRYCTL_DUMP_MEMORY_STATS; Arguments: none
This command dumps memory management related statistics to the library's
logging stream.
@item GCRYCTL_DUMP_SECMEM_STATS; Arguments: none
This command dumps secure memory management related statistics to the
library's logging stream.
@item 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 @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.
Many applications do not require secure memory, so they should disable
it right away. This command should be executed right after
@code{gcry_check_version}.
@item 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
@code{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).
@item 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
@code{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.
@item 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
@var{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.
@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
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.
@item GCRYCTL_DISABLE_SECMEM_WARN; Arguments: none
Disable warning messages about problems with the secure memory
subsystem. This command should be run right after
@code{gcry_check_version}.
@item GCRYCTL_SUSPEND_SECMEM_WARN; Arguments: none
Postpone warning messages from the secure memory subsystem.
@xref{sample-use-suspend-secmem,,the initialization example}, on how to
use it.
@item GCRYCTL_RESUME_SECMEM_WARN; Arguments: none
Resume warning messages from the secure memory subsystem.
@xref{sample-use-resume-secmem,,the initialization example}, on how to
use it.
@item 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 @code{gcry_check_version} and not
later than the command GCRYCTL_INIT_SECMEM. Note that in FIPS mode the
secure memory is always used.
@item 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.
@item 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 @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
way for an attacker without kernel access to control these 16 bytes.
@item 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.
@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.
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
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
@code{gcry_check_version}.
@item 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 @code{gcry_check_version}.
@item GCRYCTL_DISABLE_INTERNAL_LOCKING; Arguments: none
This command does nothing. It exists only for backward compatibility.
@item 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.
@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.
@item GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops
This command is obsolete since version 1.6.
@item GCRYCTL_FAST_POLL; Arguments: none
Run a fast random poll.
@item 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.
@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
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
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}.
@item 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 @code{gcry_check_version}. An application may use this command or
the convenience macro below to check whether FIPS mode is actually
active.
@deftypefun int gcry_fips_mode_active (void)
Returns true if the FIPS mode is active. Note that this is
implemented as a macro.
@end deftypefun
@item 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 @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.
@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.
@item 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
@code{gcry_check_version}. The available generators are:
@table @code
@item GCRY_RNG_TYPE_STANDARD
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
``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.
@item 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.
@end table
The default is @code{GCRY_RNG_TYPE_STANDARD} unless FIPS mode as been
enabled; in which case @code{GCRY_RNG_TYPE_FIPS} is used and locked
against further changes.
@item 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.
@item 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.
@item 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 @code{gcry_check_version}.
@item 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.
@end table
@end deftypefun
@c **********************************************************
@c ******************* Errors ****************************
@c **********************************************************
@node Error Handling
@section 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 @code{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
@code{libgpg-error}. They usually start with @code{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.
@end menu
@node Error Values
@subsection Error Values
@cindex error values
@cindex error codes
@cindex error sources
@deftp {Data type} {gcry_err_code_t}
The @code{gcry_err_code_t} type is an alias for the
@code{libgpg-error} type @code{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.
@end deftp
@deftp {Data type} {gcry_err_source_t}
The @code{gcry_err_source_t} type is an alias for the
@code{libgpg-error} type @code{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.
@end deftp
@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
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
(@code{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.
@end deftp
@deftypefun {gcry_err_code_t} gcry_err_code (@w{gcry_error_t @var{err}})
The static inline function @code{gcry_err_code} returns the
@code{gcry_err_code_t} component of the error value @var{err}. This
function must be used to extract the error code from an error value in
order to compare it with the @code{GPG_ERR_*} error code macros.
@end deftypefun
@deftypefun {gcry_err_source_t} gcry_err_source (@w{gcry_error_t @var{err}})
The static inline function @code{gcry_err_source} returns the
@code{gcry_err_source_t} component of the error value @var{err}. This
function must be used to extract the error source from an error value in
order to compare it with the @code{GPG_ERR_SOURCE_*} error source macros.
@end deftypefun
@deftypefun {gcry_error_t} gcry_err_make (@w{gcry_err_source_t @var{source}}, @w{gcry_err_code_t @var{code}})
The static inline function @code{gcry_err_make} returns the error
value consisting of the error source @var{source} and the error code
@var{code}.
This function can be used in callback functions to construct an error
value to return it to the library.
@end deftypefun
@deftypefun {gcry_error_t} gcry_error (@w{gcry_err_code_t @var{code}})
The static inline function @code{gcry_error} returns the error value
consisting of the default error source and the error code @var{code}.
For @acronym{GCRY} applications, the default error source is
@code{GPG_ERR_SOURCE_USER_1}. You can define
@code{GCRY_ERR_SOURCE_DEFAULT} before including @file{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.
@end deftypefun
The @code{libgpg-error} library provides error codes for all system
error numbers it knows about. If @var{err} is an unknown error
number, the error code @code{GPG_ERR_UNKNOWN_ERRNO} is used. The
following functions can be used to construct error values from system
errno numbers.
@deftypefun {gcry_error_t} gcry_err_make_from_errno (@w{gcry_err_source_t @var{source}}, @w{int @var{err}})
The function @code{gcry_err_make_from_errno} is like
@code{gcry_err_make}, but it takes a system error like @code{errno}
instead of a @code{gcry_err_code_t} error code.
@end deftypefun
@deftypefun {gcry_error_t} gcry_error_from_errno (@w{int @var{err}})
The function @code{gcry_error_from_errno} is like @code{gcry_error},
but it takes a system error like @code{errno} instead of a
@code{gcry_err_code_t} error code.
@end deftypefun
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.
@deftypefun {gcry_err_code_t} gcry_err_code_from_errno (@w{int @var{err}})
The function @code{gcry_err_code_from_errno} returns the error code
for the system error @var{err}. If @var{err} is not a known system
error, the function returns @code{GPG_ERR_UNKNOWN_ERRNO}.
@end deftypefun
@deftypefun {int} gcry_err_code_to_errno (@w{gcry_err_code_t @var{err}})
The function @code{gcry_err_code_to_errno} returns the system error
for the error code @var{err}. If @var{err} is not an error code
representing a system error, or if this system error is not defined on
this system, the function returns @code{0}.
@end deftypefun
@node Error Sources
@subsection Error Sources
@cindex error codes, list of
The library @code{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 @code{0}, the whole error
value will be @code{0}. In this case the error source part is of
course @code{GPG_ERR_SOURCE_UNKNOWN}.
The list of error sources that might occur in applications using
@acronym{Libgcrypt} is:
@table @code
@item GPG_ERR_SOURCE_UNKNOWN
The error source is not known. The value of this error source is
@code{0}.
@item GPG_ERR_SOURCE_GPGME
The error source is @acronym{GPGME} itself.
@item GPG_ERR_SOURCE_GPG
The error source is GnuPG, which is the crypto engine used for the
OpenPGP protocol.
@item GPG_ERR_SOURCE_GPGSM
The error source is GPGSM, which is the crypto engine used for the
OpenPGP protocol.
@item GPG_ERR_SOURCE_GCRYPT
The error source is @code{libgcrypt}, which is used by crypto engines
to perform cryptographic operations.
@item GPG_ERR_SOURCE_GPGAGENT
The error source is @command{gpg-agent}, which is used by crypto
engines to perform operations with the secret key.
@item GPG_ERR_SOURCE_PINENTRY
The error source is @command{pinentry}, which is used by
@command{gpg-agent} to query the passphrase to unlock a secret key.
@item GPG_ERR_SOURCE_SCD
The error source is the SmartCard Daemon, which is used by
@command{gpg-agent} to delegate operations with the secret key to a
SmartCard.
@item GPG_ERR_SOURCE_KEYBOX
The error source is @code{libkbx}, a library used by the crypto
engines to manage local keyrings.
@item GPG_ERR_SOURCE_USER_1
@item GPG_ERR_SOURCE_USER_2
@item GPG_ERR_SOURCE_USER_3
@item 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 @code{GPG_ERR_SOURCE_USER_1} is the default for errors
created with @code{gcry_error} and @code{gcry_error_from_errno},
unless you define @code{GCRY_ERR_SOURCE_DEFAULT} before including
@file{gcrypt.h}.
@end table
@node Error Codes
@subsection Error Codes
@cindex error codes, list of
The library @code{libgpg-error} defines many error values. The
following list includes the most important error codes.
@table @code
@item GPG_ERR_EOF
This value indicates the end of a list, buffer or file.
@item GPG_ERR_NO_ERROR
This value indicates success. The value of this error code is
@code{0}. Also, it is guaranteed that an error value made from the
error code @code{0} will be @code{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.
@item 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.
@item GPG_ERR_ENOMEM
This value means that an out-of-memory condition occurred.
@item GPG_ERR_E...
System errors are mapped to GPG_ERR_EFOO where FOO is the symbol for
the system error.
@item GPG_ERR_INV_VALUE
This value means that some user provided data was out of range.
@item GPG_ERR_UNUSABLE_PUBKEY
This value means that some recipients for a message were invalid.
@item GPG_ERR_UNUSABLE_SECKEY
This value means that some signers were invalid.
@item GPG_ERR_NO_DATA
This value means that data was expected where no data was found.
@item GPG_ERR_CONFLICT
This value means that a conflict of some sort occurred.
@item 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.
@item GPG_ERR_DECRYPT_FAILED
This value indicates that a decryption operation was unsuccessful.
@item GPG_ERR_WRONG_KEY_USAGE
This value indicates that a key is not used appropriately.
@item GPG_ERR_NO_SECKEY
This value indicates that no secret key for the user ID is available.
@item GPG_ERR_UNSUPPORTED_ALGORITHM
This value means a verification failed because the cryptographic
algorithm is not supported by the crypto backend.
@item GPG_ERR_BAD_SIGNATURE
This value means a verification failed because the signature is bad.
@item GPG_ERR_NO_PUBKEY
This value means a verification failed because the public key is not
available.
@item 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
@code{gpg_strerror}. The numeric value of this error code is 176.
@item GPG_ERR_USER_1
@item GPG_ERR_USER_2
@item ...
@item 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.
@end table
@node Error Strings
@subsection Error Strings
@cindex error values, printing of
@cindex error codes, printing of
@cindex error sources, printing of
@cindex error strings
@deftypefun {const char *} gcry_strerror (@w{gcry_error_t @var{err}})
The function @code{gcry_strerror} returns a pointer to a statically
allocated string containing a description of the error code contained
in the error value @var{err}. This string can be used to output a
diagnostic message to the user.
@end deftypefun
@deftypefun {const char *} gcry_strsource (@w{gcry_error_t @var{err}})
The function @code{gcry_strsource} returns a pointer to a statically
allocated string containing a description of the error source
contained in the error value @var{err}. This string can be used to
output a diagnostic message to the user.
@end deftypefun
The following example illustrates the use of the functions described
above:
@example
@{
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));
@}
@}
@end example
@c **********************************************************
@c ******************* General ****************************
@c **********************************************************
@node Handler Functions
@chapter 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.
@end menu
@node Progress handler
@section Progress handler
It is often useful to retrieve some feedback while long running
operations are performed.
@deftp {Data type} gcry_handler_progress_t
Progress handler functions have to be of the type
@code{gcry_handler_progress_t}, which is defined as:
@code{void (*gcry_handler_progress_t) (void *, const char *, int, int, int)}
@end deftp
The following function may be used to register a handler function for
this purpose.
@deftypefun void gcry_set_progress_handler (gcry_handler_progress_t @var{cb}, void *@var{cb_data})
This function installs @var{cb} as the `Progress handler' function.
It may be used only during initialization. @var{cb} must be defined
as follows:
@example
void
my_progress_handler (void *@var{cb_data}, const char *@var{what},
int @var{printchar}, int @var{current}, int @var{total})
@{
/* Do something. */
@}
@end example
A description of the arguments of the progress handler function follows.
@table @var
@item cb_data
The argument provided in the call to @code{gcry_set_progress_handler}.
@item what
A string identifying the type of the progress output. The following
values for @var{what} are defined:
@table @code
@item need_entropy
Not enough entropy is available. @var{total} holds the number of
required bytes.
@item wait_dev_random
Waiting to re-open a random device. @var{total} gives the number of
seconds until the next try.
@item primegen
Values for @var{printchar}:
@table @code
@item \n
Prime generated.
@item !
Need to refresh the pool of prime numbers.
@item <, >
Number of bits adjusted.
@item ^
Searching for a generator.
@item .
Fermat test on 10 candidates failed.
@item :
Restart with a new random value.
@item +
Rabin Miller test passed.
@end table
@end table
@end table
@end deftypefun
@node Allocation handler
@section 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:
@deftp {Data type} gcry_handler_alloc_t
This type is defined as: @code{void *(*gcry_handler_alloc_t) (size_t n)}.
@end deftp
@deftp {Data type} gcry_handler_secure_check_t
This type is defined as: @code{int *(*gcry_handler_secure_check_t) (const void *)}.
@end deftp
@deftp {Data type} gcry_handler_realloc_t
This type is defined as: @code{void *(*gcry_handler_realloc_t) (void *p, size_t n)}.
@end deftp
@deftp {Data type} gcry_handler_free_t
This type is defined as: @code{void *(*gcry_handler_free_t) (void *)}.
@end deftp
Special memory allocation functions can be installed with the
following function:
@deftypefun void gcry_set_allocation_handler (gcry_handler_alloc_t @var{func_alloc}, gcry_handler_alloc_t @var{func_alloc_secure}, gcry_handler_secure_check_t @var{func_secure_check}, gcry_handler_realloc_t @var{func_realloc}, gcry_handler_free_t @var{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.
@end deftypefun
@node Error handler
@section 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 @code{gcry_check_version}.
@deftp {Data type} gcry_handler_no_mem_t
This type is defined as: @code{int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int)}
@end deftp
@deftypefun void gcry_set_outofcore_handler (gcry_handler_no_mem_t @var{func_no_mem}, void *@var{cb_data})
This function registers @var{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 @var{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.
@end deftypefun
@deftp {Data type} gcry_handler_error_t
This type is defined as: @code{void (*gcry_handler_error_t) (void *, int, const char *)}
@end deftp
@deftypefun void gcry_set_fatalerror_handler (gcry_handler_error_t @var{func_error}, void *@var{cb_data})
This function registers @var{func_error} as `error handler',
which means that it will be called in error conditions.
@end deftypefun
@node Logging handler
@section Logging handler
@deftp {Data type} gcry_handler_log_t
This type is defined as: @code{void (*gcry_handler_log_t) (void *, int, const char *, va_list)}
@end deftp
@deftypefun void gcry_set_log_handler (gcry_handler_log_t @var{func_log}, void *@var{cb_data})
This function registers @var{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
@code{gcry_check_version}.
@end deftypefun
@c **********************************************************
@c ******************* Ciphers ****************************
@c **********************************************************
@c @include cipher-ref.texi
@node Symmetric cryptography
@chapter 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.
@end menu
@node Available ciphers
@section Available ciphers
@table @code
@item GCRY_CIPHER_NONE
This is not a real algorithm but used by some functions as error return.
The value always evaluates to false.
@item GCRY_CIPHER_IDEA
@cindex IDEA
This is the IDEA algorithm.
@item GCRY_CIPHER_3DES
@cindex 3DES
@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 bits but
you have to pass 192 bits because the most significant bits of each byte
are ignored.
@item GCRY_CIPHER_CAST5
@cindex CAST5
CAST128-5 block cipher algorithm. The key size is 128 bits.
@item GCRY_CIPHER_BLOWFISH
@cindex Blowfish
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.
@item GCRY_CIPHER_DES_SK
Reserved and not currently implemented.
@item GCRY_CIPHER_AES
@itemx GCRY_CIPHER_AES128
@itemx GCRY_CIPHER_RIJNDAEL
@itemx GCRY_CIPHER_RIJNDAEL128
@cindex Rijndael
@cindex AES
@cindex Advanced Encryption Standard
AES (Rijndael) with a 128 bit key.
@item GCRY_CIPHER_AES192
@itemx GCRY_CIPHER_RIJNDAEL192
AES (Rijndael) with a 192 bit key.
@item GCRY_CIPHER_AES256
@itemx GCRY_CIPHER_RIJNDAEL256
AES (Rijndael) with a 256 bit key.
@item GCRY_CIPHER_TWOFISH
@cindex Twofish
The Twofish algorithm with a 256 bit key.
@item GCRY_CIPHER_TWOFISH128
The Twofish algorithm with a 128 bit key.
@item GCRY_CIPHER_ARCFOUR
@cindex Arcfour
@cindex RC4
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.
@item GCRY_CIPHER_DES
@cindex 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.
@item GCRY_CIPHER_SERPENT128
@itemx GCRY_CIPHER_SERPENT192
@itemx GCRY_CIPHER_SERPENT256
@cindex Serpent
The Serpent cipher from the AES contest.
@item GCRY_CIPHER_RFC2268_40
@itemx GCRY_CIPHER_RFC2268_128
@cindex rfc-2268
@cindex RC2
Ron's Cipher 2 in the 40 and 128 bit variants.
@item GCRY_CIPHER_SEED
@cindex Seed (cipher)
A 128 bit cipher as described by RFC4269.
@item GCRY_CIPHER_CAMELLIA128
@itemx GCRY_CIPHER_CAMELLIA192
@itemx GCRY_CIPHER_CAMELLIA256
@cindex Camellia
The Camellia cipher by NTT. See
-@uref{http://info.isl.ntt.co.jp/@/crypt/@/eng/@/camellia/@/specifications.html}.
+@uref{https://info.isl.ntt.co.jp/@/crypt/@/eng/@/camellia/@/specifications.html}.
@item GCRY_CIPHER_SALSA20
@cindex Salsa20
This is the Salsa20 stream cipher.
@item GCRY_CIPHER_SALSA20R12
@cindex Salsa20/12
This is the Salsa20/12 - reduced round version of Salsa20 stream cipher.
@item GCRY_CIPHER_GOST28147
@cindex GOST 28147-89
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_CHACHA20
@cindex ChaCha20
This is the ChaCha20 stream cipher.
@end table
@node Available cipher modes
@section Available cipher modes
@table @code
@item 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.
@item GCRY_CIPHER_MODE_ECB
@cindex ECB, Electronic Codebook mode
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
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.
@item GCRY_CIPHER_MODE_CBC
@cindex CBC, Cipher Block Chaining mode
Cipher Block Chaining mode.
@item GCRY_CIPHER_MODE_STREAM
Stream mode, only to be used with stream cipher algorithms.
@item GCRY_CIPHER_MODE_OFB
@cindex OFB, Output Feedback mode
Output Feedback mode.
@item GCRY_CIPHER_MODE_CTR
@cindex CTR, Counter mode
Counter mode.
@item GCRY_CIPHER_MODE_AESWRAP
@cindex AES-Wrap 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
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.
@item GCRY_CIPHER_MODE_CCM
@cindex CCM, Counter with CBC-MAC mode
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.
@item GCRY_CIPHER_MODE_GCM
@cindex GCM, Galois/Counter Mode
Galois/Counter Mode (GCM) is an Authenticated Encryption with
Associated Data (AEAD) block cipher mode, which is specified in
'NIST Special Publication 800-38D'.
@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-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
@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
@code{buffer} argument and @code{sizeof(int)} for @code{buflen}.
Note that the use of @code{gcry_cipher_final} is required.
@item GCRY_CIPHER_MODE_XTS
@cindex XTS, XTS mode
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 (@code{GCRY_CIPHER_AES256}). The 128-bit tweak value
is feed to XTS mode as little-endian byte array using
@code{gcry_cipher_setiv} function. When encrypting or decrypting,
full-sized data unit buffers needs to be passed to
@code{gcry_cipher_encrypt} or @code{gcry_cipher_decrypt}. The tweak
value is automatically incremented after each call of
@code{gcry_cipher_encrypt} and @code{gcry_cipher_decrypt}.
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}).
+@uref{https://web.cs.ucdavis.edu/~rogaway/papers/eax.html}).
@end table
@node Working with cipher handles
@section 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:
@deftypefun gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *@var{hd}, int @var{algo}, int @var{mode}, unsigned int @var{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 @var{algo}. See
@ref{Available ciphers}, for a list of supported ciphers and the
according constants.
Besides using the constants directly, the function
@code{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 @var{mode}. See
@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},
@code{GCRY_CIPHER_MODE_CTR} and @code{GCRY_CIPHER_MODE_EAX}) 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.
The third argument @var{flags} can either be passed as @code{0} or as
the bit-wise OR of the following constants.
@table @code
@item GCRY_CIPHER_SECURE
Make sure that all operations are allocated in secure memory. This is
useful when the key material is highly confidential.
@item GCRY_CIPHER_ENABLE_SYNC
@cindex sync mode (OpenPGP)
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 @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
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
GCRY_CIPHER_CBC_CTS.
@end table
@end deftypefun
Use the following function to release an existing handle:
@deftypefun void gcry_cipher_close (gcry_cipher_hd_t @var{h})
This function releases the context created by @code{gcry_cipher_open}.
It also zeroises all sensitive information associated with this cipher
handle.
@end deftypefun
In order to use a handle for performing cryptographic operations, a
`key' has to be set first:
@deftypefun gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l})
Set the key @var{k} used for encryption or decryption in the context
denoted by the handle @var{h}. The length @var{l} (in bytes) of the
key @var{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.
@end deftypefun
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:
@deftypefun gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l})
Set the initialization vector used for encryption or decryption. The
vector is passed as the buffer @var{K} of length @var{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.
@end deftypefun
@deftypefun gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t @var{h}, const void *@var{c}, size_t @var{l})
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
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.
Note that gcry_cipher_reset is implemented as a macro.
@end deftypefun
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:
@deftypefun gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t @var{h}, const void *@var{abuf}, size_t @var{abuflen})
Process the buffer @var{abuf} of length @var{abuflen} as the additional
authenticated data (AAD) for AEAD cipher modes.
@end deftypefun
@deftypefun {gcry_error_t} gcry_cipher_gettag @
(@w{gcry_cipher_hd_t @var{h}}, @
@w{void *@var{tag}}, @w{size_t @var{taglen}})
This function is used to read the authentication tag after encryption.
The function finalizes and outputs the authentication tag to the buffer
@var{tag} of length @var{taglen} bytes.
Depending on the used mode certain restrictions for @var{taglen} are
enforced: For GCM @var{taglen} must be at least 16 or one of the
allowed truncated lengths (4, 8, 12, 13, 14, or 15).
@end deftypefun
@deftypefun {gcry_error_t} gcry_cipher_checktag @
(@w{gcry_cipher_hd_t @var{h}}, @
@w{const void *@var{tag}}, @w{size_t @var{taglen}})
Check the authentication tag after decryption. The authentication
tag is passed as the buffer @var{tag} of length @var{taglen} bytes
and compared to internal authentication tag computed during
decryption. Error code @code{GPG_ERR_CHECKSUM} is returned if
the authentication tag in the buffer @var{tag} does not match
the authentication tag calculated during decryption.
Depending on the used mode certain restrictions for @var{taglen} are
enforced: For GCM @var{taglen} must either be 16 or one of the allowed
truncated lengths (4, 8, 12, 13, 14, or 15).
@end deftypefun
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.
@deftypefun gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t @var{h}, unsigned char *{out}, size_t @var{outsize}, const unsigned char *@var{in}, size_t @var{inlen})
@code{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 @var{h}. There are 2
ways to use the function: If @var{in} is passed as @code{NULL} and
@var{inlen} is @code{0}, in-place encryption of the data in @var{out} of
length @var{outsize} takes place. With @var{in} being not @code{NULL},
@var{inlen} bytes are encrypted to the buffer @var{out} which must have
at least a size of @var{inlen}. @var{outsize} must be set to the
allocated size of @var{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 @code{gcry_cipher_final} is used
before the final data chunk is passed to this function.
The function returns @code{0} on success or an error code.
@end deftypefun
@deftypefun gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t @var{h}, unsigned char *{out}, size_t @var{outsize}, const unsigned char *@var{in}, size_t @var{inlen})
@code{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 @var{h}. There are 2
ways to use the function: If @var{in} is passed as @code{NULL} and
@var{inlen} is @code{0}, in-place decryption of the data in @var{out} or
length @var{outsize} takes place. With @var{in} being not @code{NULL},
@var{inlen} bytes are decrypted to the buffer @var{out} which must have
at least a size of @var{inlen}. @var{outsize} must be set to the
allocated size of @var{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 @code{gcry_cipher_final} is used
before the final data chunk is passed to this function.
The function returns @code{0} on success or an error code.
@end deftypefun
The OCB mode features integrated padding and must thus be told about
the end of the input data. This is done with:
@deftypefun gcry_error_t gcry_cipher_final (gcry_cipher_hd_t @var{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.
@end deftypefun
OpenPGP (as defined in RFC-4880) requires a special sync operation in
some places. The following function is used for this:
@deftypefun gcry_error_t gcry_cipher_sync (gcry_cipher_hd_t @var{h})
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}
@end deftypefun
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:
@deftypefun gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t @var{h}, int @var{cmd}, void *@var{buffer}, size_t @var{buflen})
@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
handle @var{h}. Please see the comments in the source code
(@code{src/global.c}) for details.
@end deftypefun
@deftypefun gcry_error_t gcry_cipher_info (gcry_cipher_hd_t @var{h}, @
int @var{what}, void *@var{buffer}, size_t *@var{nbytes})
@code{gcry_cipher_info} is used to retrieve various
information about a cipher context or the cipher module in general.
@c begin constants for gcry_cipher_info
@table @code
@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
taglen is returned in bytes.
@end table
@c end constants for gcry_cipher_info
@end deftypefun
@node General cipher functions
@section 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.
@deftypefun gcry_error_t gcry_cipher_algo_info (int @var{algo}, int @var{what}, void *@var{buffer}, size_t *@var{nbytes})
This function is used to retrieve information on a specific algorithm.
You pass the cipher algorithm ID as @var{algo} and the type of
information requested as @var{what}. The result is either returned as
the return code of the function or copied to the provided @var{buffer}
whose allocated length must be available in an integer variable with the
address passed in @var{nbytes}. This variable will also receive the
actual used length of the buffer.
Here is a list of supported codes for @var{what}:
@c begin constants for gcry_cipher_algo_info
@table @code
@item 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
@var{nbytes}; @var{buffer} must be zero. Note that it is usually
better to use the convenience function
@code{gcry_cipher_get_algo_keylen}.
@item GCRYCTL_GET_BLKLEN:
Return the block length of the algorithm. The length is returned as a
number of octets in @var{nbytes}; @var{buffer} must be zero. Note
that it is usually better to use the convenience function
@code{gcry_cipher_get_algo_blklen}.
@item GCRYCTL_TEST_ALGO:
Returns @code{0} when the specified algorithm is available for use.
@var{buffer} and @var{nbytes} must be zero.
@end table
@c end constants for gcry_cipher_algo_info
@end deftypefun
@c end gcry_cipher_algo_info
@deftypefun size_t gcry_cipher_get_algo_keylen (@var{algo})
This function returns length of the key for algorithm @var{algo}. If
the algorithm supports multiple key lengths, the maximum supported key
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
checking.
@end deftypefun
@c end gcry_cipher_get_algo_keylen
@deftypefun size_t gcry_cipher_get_algo_blklen (int @var{algo})
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
checking.
@end deftypefun
@c end gcry_cipher_get_algo_blklen
@deftypefun {const char *} gcry_cipher_algo_name (int @var{algo})
@code{gcry_cipher_algo_name} returns a string with the name of the
cipher algorithm @var{algo}. If the algorithm is not known or another
error occurred, the string @code{"?"} is returned. This function should
not be used to test for the availability of an algorithm.
@end deftypefun
@deftypefun int gcry_cipher_map_name (const char *@var{name})
@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.
@end deftypefun
@deftypefun int gcry_cipher_mode_from_oid (const char *@var{string})
Return the cipher mode associated with an @acronym{ASN.1} object
identifier. The object identifier is expected to be in the
@acronym{IETF}-style dotted decimal notation. The function returns
@code{0} for an unknown object identifier or when no mode is associated
with it.
@end deftypefun
@c **********************************************************
@c ******************* Public Key *************************
@c **********************************************************
@node Public Key cryptography
@chapter 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.
@end menu
@node Available algorithms
@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.
@node Used S-expressions
@section Used S-expressions
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
+@uref{https://people.csail.mit.edu/@/rivest/@/sexp.html}) and does not work
with contexts as most of the other building blocks of Libgcrypt do.
@noindent
The following information are stored in S-expressions:
@itemize
@item keys
@item plain text data
@item encrypted data
@item signatures
@end itemize
@noindent
To describe how Libgcrypt expect keys, we use examples. Note that
words in
@ifnottex
uppercase
@end ifnottex
@iftex
italics
@end iftex
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
by using @code{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.
@end menu
@node RSA key parameters
@subsection RSA key parameters
@noindent
An RSA private key is described by this S-expression:
@example
(private-key
(rsa
(n @var{n-mpi})
(e @var{e-mpi})
(d @var{d-mpi})
(p @var{p-mpi})
(q @var{q-mpi})
(u @var{u-mpi})))
@end example
@noindent
An RSA public key is described by this S-expression:
@example
(public-key
(rsa
(n @var{n-mpi})
(e @var{e-mpi})))
@end example
@table @var
@item n-mpi
RSA public modulus @math{n}.
@item e-mpi
RSA public exponent @math{e}.
@item d-mpi
RSA secret exponent @math{d = e^{-1} \bmod (p-1)(q-1)}.
@item p-mpi
RSA secret prime @math{p}.
@item q-mpi
RSA secret prime @math{q} with @math{p < q}.
@item u-mpi
Multiplicative inverse @math{u = p^{-1} \bmod q}.
@end table
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.
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
swap the values and recompute @math{u}. Here is example code to do this:
@example
if (gcry_mpi_cmp (p, q) > 0)
@{
gcry_mpi_swap (p, q);
gcry_mpi_invm (u, p, q);
@}
@end example
@node DSA key parameters
@subsection DSA key parameters
@noindent
A DSA private key is described by this S-expression:
@example
(private-key
(dsa
(p @var{p-mpi})
(q @var{q-mpi})
(g @var{g-mpi})
(y @var{y-mpi})
(x @var{x-mpi})))
@end example
@table @var
@item p-mpi
DSA prime @math{p}.
@item q-mpi
DSA group order @math{q} (which is a prime divisor of @math{p-1}).
@item g-mpi
DSA group generator @math{g}.
@item y-mpi
DSA public key value @math{y = g^x \bmod p}.
@item x-mpi
DSA secret exponent x.
@end table
The public key is similar with "private-key" replaced by "public-key"
and no @var{x-mpi}.
@node ECC key parameters
@subsection ECC key parameters
@anchor{ecc_keyparam}
@noindent
An ECC private key is described by this S-expression:
@example
(private-key
(ecc
(p @var{p-mpi})
(a @var{a-mpi})
(b @var{b-mpi})
(g @var{g-point})
(n @var{n-mpi})
(q @var{q-point})
(d @var{d-mpi})))
@end example
@table @var
@item p-mpi
Prime specifying the field @math{GF(p)}.
@item a-mpi
@itemx b-mpi
The two coefficients of the Weierstrass equation @math{y^2 = x^3 + ax + b}
@item g-point
Base point @math{g}.
@item n-mpi
Order of @math{g}
@item q-point
The point representing the public key @math{Q = dG}.
@item d-mpi
The private key @math{d}
@end table
All point values are encoded in standard format; Libgcrypt does in
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
algorithm’s native compression method.
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
used. For example
@example
(private-key
(ecc
(curve "NIST P-192")
(q @var{q-point})
(d @var{d-mpi})))
@end example
Note that @var{q-point} is optional for a private key. The
@code{curve} parameter may be given in any case and is used to replace
missing parameters.
@noindent
Currently implemented curves are:
@table @code
@item NIST P-192
@itemx 1.2.840.10045.3.1.1
@itemx prime192v1
@itemx secp192r1
The NIST 192 bit curve, its OID, X9.62 and SECP aliases.
@item NIST P-224
@itemx secp224r1
The NIST 224 bit curve and its SECP alias.
@item NIST P-256
@itemx 1.2.840.10045.3.1.7
@itemx prime256v1
@itemx secp256r1
The NIST 256 bit curve, its OID, X9.62 and SECP aliases.
@item NIST P-384
@itemx secp384r1
The NIST 384 bit curve and its SECP alias.
@item NIST P-521
@itemx secp521r1
The NIST 521 bit curve and its SECP alias.
@end table
As usual the OIDs may optionally be prefixed with the string @code{OID.}
or @code{oid.}.
@node Cryptographic Functions
@section Cryptographic Functions
@noindent
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:
@table @code
@item comp
@itemx nocomp
@cindex comp
@cindex nocomp
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.
@item pkcs1
@cindex PKCS1
Use PKCS#1 block type 2 padding for encryption, block type 1 padding
for signing.
@item oaep
@cindex OAEP
Use RSA-OAEP padding for encryption.
@item pss
@cindex PSS
Use RSA-PSS padding for signing.
@item eddsa
@cindex EdDSA
Use the EdDSA scheme signing instead of the default ECDSA algorithm.
Note that the EdDSA uses a special form of the public key.
@item rfc6979
@cindex RFC6979
For DSA and ECDSA use a deterministic scheme for the k parameter.
@item no-blinding
@cindex 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.
@item param
@cindex 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.
@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
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.
@item no-keytest
@cindex 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.
@item use-x931
@cindex X9.31
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 @code{derive-parms} is given or Libgcrypt is
in FIPS mode.
@item use-fips186
@cindex FIPS 186
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
@code{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.
@item use-fips186-2
@cindex FIPS 186-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.
@end table
@noindent
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:
@deftypefun gcry_error_t gcry_pk_encrypt (@w{gcry_sexp_t *@var{r_ciph},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{pkey}})
Obviously a public key must be provided for encryption. It is
expected as an appropriate S-expression (see above) in @var{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.
@noindent
If you don't want to let Libgcrypt handle the padding, you must pass an
appropriate MPI using this expression for @var{data}:
@example
(data
(flags raw)
(value @var{mpi}))
@end example
@noindent
This has the same semantics as the old style MPI only way. @var{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 @var{data}:
@example
(data
(flags pkcs1)
(value @var{block}))
@end example
@noindent
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 @var{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 @var{r_ciph}.
The caller is responsible to release this value using
@code{gcry_sexp_release}. In case of an error, an error code is
returned and @var{r_ciph} will be set to @code{NULL}.
@noindent
The returned S-expression has this format when used with RSA:
@example
(enc-val
(rsa
(a @var{a-mpi})))
@end example
@noindent
Where @var{a-mpi} is an MPI with the result of the RSA operation. When
using the Elgamal algorithm, the return value will have this format:
@example
(enc-val
(elg
(a @var{a-mpi})
(b @var{b-mpi})))
@end example
@noindent
Where @var{a-mpi} and @var{b-mpi} are MPIs with the result of the
Elgamal encryption operation.
@end deftypefun
@c end gcry_pk_encrypt
@deftypefun gcry_error_t gcry_pk_decrypt (@w{gcry_sexp_t *@var{r_plain},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
Obviously a private key must be provided for decryption. It is expected
as an appropriate S-expression (see above) in @var{skey}. The data to
be decrypted must match the format of the result as returned by
@code{gcry_pk_encrypt}, but should be enlarged with a @code{flags}
element:
@example
(enc-val
(flags)
(elg
(a @var{a-mpi})
(b @var{b-mpi})))
@end example
@noindent
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:
@example
(flags @var{padding-method})
@end example
@noindent
Currently @var{padding-method} is either @code{pkcs1} for PKCS#1 block
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
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
@code{flags} is passed in @var{data}, the format is:
@example
(value @var{plaintext})
@end example
@end deftypefun
@c end gcry_pk_decrypt
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:
@deftypefun gcry_error_t gcry_pk_sign (@w{gcry_sexp_t *@var{r_sig},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
This function creates a digital signature for @var{data} using the
private key @var{skey} and place it into the variable at the address of
@var{r_sig}. @var{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:
@example
(data
(flags pkcs1)
(hash @var{hash-algo} @var{block}))
@end example
@noindent
This example requests to sign the data in @var{block} after applying
PKCS#1 block type 1 style padding. @var{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 @var{block} must
match the size of that message digests; the function checks that this
and other constraints are valid.
@noindent
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:
@example
(data
(flags raw)
(value @var{mpi}))
@end example
@noindent
Here, the data to be signed is directly given as an @var{MPI}.
@noindent
For DSA the input data is expected in this format:
@example
(data
(flags raw)
(value @var{mpi}))
@end example
@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
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.
@example
(data
(flags rfc6979)
(hash @var{hash-algo} @var{block}))
@end example
Note that the provided hash-algo is used for the internal HMAC; it
should match the hash-algo used to create @var{block}.
@noindent
The signature is returned as a newly allocated S-expression in
@var{r_sig} using this format for RSA:
@example
(sig-val
(rsa
(s @var{s-mpi})))
@end example
Where @var{s-mpi} is the result of the RSA sign operation. For DSA the
S-expression returned is:
@example
(sig-val
(dsa
(r @var{r-mpi})
(s @var{s-mpi})))
@end example
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 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:
@example
(data
(flags eddsa)
(hash-algo sha512)
(value @var{message}))
@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.
@end deftypefun
@c end gcry_pk_sign
@noindent
The operation most commonly used is definitely the verification of a
signature. Libgcrypt provides this function:
@deftypefun gcry_error_t gcry_pk_verify (@w{gcry_sexp_t @var{sig}}, @w{gcry_sexp_t @var{data}}, @w{gcry_sexp_t @var{pkey}})
This is used to check whether the signature @var{sig} matches the
@var{data}. The public key @var{pkey} must be provided to perform this
verification. This function is similar in its parameters to
@code{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 @code{gcry_pk_sign}, is passed to
the function in @var{sig}.
@noindent
The result is 0 for success (i.e. the data matches the signature), or an
error code where the most relevant code is @code{GCRY_ERR_BAD_SIGNATURE}
to indicate that the signature does not match the provided data.
@end deftypefun
@c end gcry_pk_verify
@node General public-key related Functions
@section General public-key related Functions
@noindent
A couple of utility functions are available to retrieve the length of
the key, map algorithm identifiers and perform sanity checks:
@deftypefun {const char *} gcry_pk_algo_name (int @var{algo})
Map the public key algorithm id @var{algo} to a string representation of
the algorithm name. For unknown algorithms this functions returns the
string @code{"?"}. This function should not be used to test for the
availability of an algorithm.
@end deftypefun
@deftypefun int gcry_pk_map_name (const char *@var{name})
Map the algorithm @var{name} to a public key algorithm Id. Returns 0 if
the algorithm name is not known.
@end deftypefun
@deftypefun int gcry_pk_test_algo (int @var{algo})
Return 0 if the public key algorithm @var{algo} is available for use.
Note that this is implemented as a macro.
@end deftypefun
@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}.
@end deftypefun
@deftypefun {unsigned char *} gcry_pk_get_keygrip (@w{gcry_sexp_t @var{key}}, @w{unsigned char *@var{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. @var{array}
must either provide space for 20 bytes or be @code{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 @var{array} is returned.
@code{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 @var{key}.
@end deftypefun
@deftypefun gcry_error_t gcry_pk_testkey (gcry_sexp_t @var{key})
Return zero if the private key @var{key} is `sane', an error code otherwise.
Note that it is not possible to check the `saneness' of a public key.
@end deftypefun
@deftypefun gcry_error_t gcry_pk_algo_info (@w{int @var{algo}}, @w{int @var{what}}, @w{void *@var{buffer}}, @w{size_t *@var{nbytes}})
Depending on the value of @var{what} return various information about
the public key algorithm with the id @var{algo}. Note that the
function returns @code{-1} on error and the actual error code must be
retrieved using the function @code{gcry_errno}. The currently defined
values for @var{what} are:
@table @code
@item GCRYCTL_TEST_ALGO:
Return 0 if the specified algorithm is available for use.
@var{buffer} must be @code{NULL}, @var{nbytes} may be passed as
@code{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:
@table @code
@item GCRY_PK_USAGE_SIGN
Algorithm is usable for signing.
@item GCRY_PK_USAGE_ENCR
Algorithm is usable for encryption.
@end table
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 0. Disabled algorithms are ignored here because we
want to know whether the algorithm is at all capable of a certain usage.
@item GCRYCTL_GET_ALGO_NPKEY
Return the number of elements the public key for algorithm @var{algo}
consist of. Return 0 for an unknown algorithm.
@item GCRYCTL_GET_ALGO_NSKEY
Return the number of elements the private key for algorithm @var{algo}
consist of. Note that this value is always larger than that of the
public key. Return 0 for an unknown algorithm.
@item GCRYCTL_GET_ALGO_NSIGN
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
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.
@end table
@noindent
Please note that parameters not required should be passed as @code{NULL}.
@end deftypefun
@c end gcry_pk_algo_info
@deftypefun gcry_error_t gcry_pk_ctl (@w{int @var{cmd}}, @w{void *@var{buffer}}, @w{size_t @var{buflen}})
This is a general purpose function to perform certain control
operations. @var{cmd} controls what is to be done. The return value is
0 for success or an error code. Currently supported values for
@var{cmd} are:
@table @code
@item GCRYCTL_DISABLE_ALGO
Disable the algorithm given as an algorithm id in @var{buffer}.
@var{buffer} must point to an @code{int} variable with the algorithm
id and @var{buflen} must have the value @code{sizeof (int)}. This
function is not thread safe and should thus be used before any other
threads are started.
@end table
@end deftypefun
@c end gcry_pk_ctl
@noindent
Libgcrypt also provides a function to generate public key
pairs:
@deftypefun gcry_error_t gcry_pk_genkey (@w{gcry_sexp_t *@var{r_key}}, @w{gcry_sexp_t @var{parms}})
This function create a new public key pair using information given in
the S-expression @var{parms} and stores the private and the public key
in one new S-expression at the address given by @var{r_key}. In case of
an error, @var{r_key} is set to @code{NULL}. The return code is 0 for
success or an error code otherwise.
@noindent
Here is an example for @var{parms} to create an 2048 bit RSA key:
@example
(genkey
(rsa
(nbits 4:2048)))
@end example
@noindent
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:
@table @code
@item 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 @code{4:} in the
above example.
@item curve @var{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 @code{nbits} has been
given. The available names are listed with the description of the ECC
public key parameters.
@item rsa-use-e @var{value}
This is only used with RSA to give a hint for the public exponent. The
@var{value} will be used as a base to test for a usable exponent. Some
values are special:
@table @samp
@item 0
Use a secure and fast value. This is currently the number 41.
@item 1
Use a value as required by some crypto policies. This is currently
the number 65537.
@item 2
Reserved
@item > 2
Use the given value.
@end table
@noindent
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).
@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:
@table @samp
@item 512 <= N <= 1024
Q = 160
@item N = 2048
Q = 224
@item N = 3072
Q = 256
@item N = 7680
Q = 384
@item N = 15360
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
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
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:
@example
(genkey
(dsa
(domain
(p @var{p-mpi})
(q @var{q-mpi})
(g @var{q-mpi}))))
@end example
@code{nbits} and @code{qbits} may not be specified because they are
derived from the domain parameters.
@item derive-parms @var{list}
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
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.
@example
(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#))))
@end example
@example
(genkey
(dsa
(nbits 4:1024)
(derive-parms
(seed @var{seed-mpi}))))
@end example
@item flags @var{flaglist}
This is preferred way to define flags. @var{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.
@example
(genkey
(ecc
(flags transient-key)))
@end example
@item transient-key
@itemx use-x931
@itemx use-fips186
@itemx use-fips186-2
These are deprecated ways to set a flag with that name; see above for
a description of each flag.
@end table
@c end table of parameters
@noindent
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.
@noindent
Here are two examples; the first for Elgamal and the second for
elliptic curve key generation:
@example
(key-data
(public-key
(elg
(p @var{p-mpi})
(g @var{g-mpi})
(y @var{y-mpi})))
(private-key
(elg
(p @var{p-mpi})
(g @var{g-mpi})
(y @var{y-mpi})
(x @var{x-mpi})))
(misc-key-info
(pm1-factors @var{n1 n2 ... nn}))
@end example
@example
(key-data
(public-key
(ecc
(curve Ed25519)
(flags eddsa)
(q @var{q-value})))
(private-key
(ecc
(curve Ed25519)
(flags eddsa)
(q @var{q-value})
(d @var{d-value}))))
@end example
@noindent
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. @var{n1 n2 ... nn} is a list
of prime numbers used to composite @var{p-mpi}; this is in general not
a very useful information and only available if the key generation
algorithm provides them.
@end deftypefun
@c end gcry_pk_genkey
@noindent
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:
@deftypefun gcry_error_t gcry_pubkey_get_sexp (@w{gcry_sexp_t *@var{r_sexp}}, @
@w{int @var{mode}}, @w{gcry_ctx_t @var{ctx}})
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}. @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
public key is returned.
@item GCRY_PK_GET_PUBKEY
Return the public key even if the context has the private key
parameter.
@item GCRY_PK_GET_SECKEY
Return the private key or the error @code{GPG_ERR_NO_SECKEY} if it is
not possible.
@end table
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.
@end deftypefun
@c end gcry_pubkey_get_sexp
@c **********************************************************
@c ******************* Hash Functions *********************
@c **********************************************************
@node Hashing
@chapter 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.
@end menu
@node Available hash algorithms
@section Available hash algorithms
@c begin table of hash algorithms
@cindex SHA-1
@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 Whirlpool
@cindex BLAKE2b-512, BLAKE2b-384, BLAKE2b-256, BLAKE2b-160
@cindex BLAKE2s-256, BLAKE2s-224, BLAKE2s-160, BLAKE2s-128
@cindex CRC32
@table @code
@item 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 @code{0}.
@item 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.
@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
lot of design properties with SHA-1 and thus it is advisable not to use
it for new protocols.
@item 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.
@item 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.
@item 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.
@item 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.
@item GCRY_MD_TIGER1
This is the TIGER variant as used by the NESSIE project. It uses the
most commonly used output print order.
@item GCRY_MD_TIGER2
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
implementation yet available.
@item 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.
@item GCRY_MD_SHA256
This is the SHA-256 algorithm which yields a message digest of 32 bytes.
See FIPS 180-2 for the specification.
@item GCRY_MD_SHA384
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-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.
@item GCRY_MD_SHA3_256
This is the SHA3-256 algorithm which yields a message digest of 32 bytes.
See FIPS 202 for the specification.
@item GCRY_MD_SHA3_384
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.
See FIPS 202 for the specification.
@item GCRY_MD_SHAKE128
This is the SHAKE128 extendable-output function (XOF) algorithm with 128 bit
security strength.
See FIPS 202 for the specification.
@item GCRY_MD_SHAKE256
This is the SHAKE256 extendable-output function (XOF) algorithm with 256 bit
security strength.
See FIPS 202 for the specification.
@item 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.
@item 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.
@item 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.
@item GCRY_MD_WHIRLPOOL
This is the Whirlpool algorithm which yields a message digest of 64
bytes.
@item GCRY_MD_GOSTR3411_94
This is the hash algorithm described in GOST R 34.11-94 which yields a
message digest of 32 bytes.
@item 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.
@item 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.
@item GCRY_MD_BLAKE2B_512
This is the BLAKE2b-512 algorithm which yields a message digest of 64 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2B_384
This is the BLAKE2b-384 algorithm which yields a message digest of 48 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2B_256
This is the BLAKE2b-256 algorithm which yields a message digest of 32 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2B_160
This is the BLAKE2b-160 algorithm which yields a message digest of 20 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2S_256
This is the BLAKE2s-256 algorithm which yields a message digest of 32 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2S_224
This is the BLAKE2s-224 algorithm which yields a message digest of 28 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2S_160
This is the BLAKE2s-160 algorithm which yields a message digest of 20 bytes.
See RFC 7693 for the specification.
@item GCRY_MD_BLAKE2S_128
This is the BLAKE2s-128 algorithm which yields a message digest of 16 bytes.
See RFC 7693 for the specification.
@end table
@c end table of hash algorithms
@node Working with hash algorithms
@section Working with hash algorithms
To use most of these function it is necessary to create a context;
this is done using:
@deftypefun gcry_error_t gcry_md_open (gcry_md_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags})
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.
For a list of supported algorithms, see @ref{Available hash
algorithms}.
The flags allowed for @var{mode} are:
@c begin table of hash flags
@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.
@item GCRY_MD_FLAG_HMAC
@cindex 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
@code{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 @ref{Working with cipher handles}.
@item GCRY_MD_FLAG_BUGEMU1
@cindex bug emulation
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.
@end table
@c begin table of hash flags
You may use the function @code{gcry_md_is_enabled} to later check
whether an algorithm has been enabled.
@end deftypefun
@c end function gcry_md_open
If you want to calculate several hash algorithms at the same time, you
have to use the following function right after the @code{gcry_md_open}:
@deftypefun gcry_error_t gcry_md_enable (gcry_md_hd_t @var{h}, int @var{algo})
Add the message digest algorithm @var{algo} to the digest object
described by handle @var{h}. Duplicated enabling of algorithms is
detected and ignored.
@end deftypefun
If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must
be set using the function:
@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen})
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.
@end deftypefun
After you are done with the hash calculation, you should release the
resources by using:
@deftypefun void gcry_md_close (gcry_md_hd_t @var{h})
Release all resources of hash context @var{h}. @var{h} should not be
used after a call to this function. A @code{NULL} passed as @var{h} is
ignored. The function also zeroises all sensitive information
associated with this handle.
@end deftypefun
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:
@deftypefun void gcry_md_reset (gcry_md_hd_t @var{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.
@end deftypefun
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:
@deftypefun gcry_error_t gcry_md_copy (gcry_md_hd_t *@var{handle_dst}, gcry_md_hd_t @var{handle_src})
Create a new digest object as an exact copy of the object described by
handle @var{handle_src} and store it in @var{handle_dst}. The context
is not reset and you can continue to hash data using this context and
independently using the original context.
@end deftypefun
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.
@deftypefun void gcry_md_write (gcry_md_hd_t @var{h}, const void *@var{buffer}, size_t @var{length})
Pass @var{length} bytes of the data in @var{buffer} to the digest object
with handle @var{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.
@end deftypefun
@deftypefun void gcry_md_putc (gcry_md_hd_t @var{h}, int @var{c})
Pass the byte in @var{c} to the digest object with handle @var{h} to
update the digest value. This is an efficient function, implemented as
a macro to buffer the data before an actual update.
@end deftypefun
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.
@deftypefun void gcry_md_final (gcry_md_hd_t @var{h})
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
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.
@end deftypefun
The way to read out the calculated message digest is by using the
function:
@deftypefun {unsigned char *} gcry_md_read (gcry_md_hd_t @var{h}, int @var{algo})
@code{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 @code{gcry_md_close} or
@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
been enabled.
@end deftypefun
The way to read output of extendable-output function is by using the
function:
@deftypefun gpg_err_code_t gcry_md_extract (gcry_md_hd_t @var{h}, @
int @var{algo}, void *@var{buffer}, size_t @var{length})
@code{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 @var{buffer} of the length @var{length}. Buffer will be fully
populated with new output. @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 non-zero value if the requested algorithm has not
been enabled.
@end deftypefun
Because it is often necessary to get the message digest of blocks of
memory, two fast convenience function are available for this task:
@deftypefun gpg_err_code_t gcry_md_hash_buffers ( @
@w{int @var{algo}}, @w{unsigned int @var{flags}}, @
@w{void *@var{digest}}, @
@w{const gcry_buffer_t *@var{iov}}, @w{int @var{iovcnt}} )
@code{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 @var{iov} and @var{iovcnt}. @var{digest} must be
allocated by the caller, large enough to hold the message digest
yielded by the the specified algorithm @var{algo}. This required size
may be obtained by using the function @code{gcry_md_get_algo_dlen}.
@var{iov} is an array of buffer descriptions with @var{iovcnt} items.
The caller should zero out the structures in this array and for each
array item set the fields @code{.data} to the address of the data to
be hashed, @code{.len} to number of bytes to be hashed. If @var{.off}
is also set, the data is taken starting at @var{.off} bytes from the
begin of the buffer. The field @code{.size} is not used.
The only supported flag value for @var{flags} is
@var{GCRY_MD_FLAG_HMAC} which turns this function into a HMAC
function; the first item in @var{iov} is then used as the key.
On success the function returns 0 and stores the resulting hash or MAC
at @var{digest}.
@end deftypefun
@deftypefun void gcry_md_hash_buffer (int @var{algo}, void *@var{digest}, const void *@var{buffer}, size_t @var{length});
@code{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 @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
@var{algo}. This required size may be obtained by using the function
@code{gcry_md_get_algo_dlen}.
Note that in contrast to @code{gcry_md_hash_buffers} this function
will abort the process if an unavailable algorithm is used.
@end deftypefun
@c ***********************************
@c ***** MD info functions ***********
@c ***********************************
Hash algorithms are identified by internal algorithm numbers (see
@code{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.
@deftypefun {const char *} gcry_md_algo_name (int @var{algo})
Map the digest algorithm id @var{algo} to a string representation of the
algorithm name. For unknown algorithms this function returns the
string @code{"?"}. This function should not be used to test for the
availability of an algorithm.
@end deftypefun
@deftypefun int gcry_md_map_name (const char *@var{name})
Map the algorithm with @var{name} to a digest algorithm identifier.
Returns 0 if the algorithm name is not known. Names representing
@acronym{ASN.1} object identifiers are recognized if the @acronym{IETF}
dotted format is used and the OID is prefixed with either "@code{oid.}"
or "@code{OID.}". For a list of supported OIDs, see the source code at
@file{cipher/md.c}. This function should not be used to test for the
availability of an algorithm.
@end deftypefun
@deftypefun gcry_error_t gcry_md_get_asnoid (int @var{algo}, void *@var{buffer}, size_t *@var{length})
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
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.
@end deftypefun
To test whether an algorithm is actually available for use, the
following macro should be used:
@deftypefun gcry_error_t gcry_md_test_algo (int @var{algo})
The macro returns 0 if the algorithm @var{algo} is available for use.
@end deftypefun
If the length of a message digest is not known, it can be retrieved
using the following function:
@deftypefun {unsigned int} gcry_md_get_algo_dlen (int @var{algo})
Retrieve the length in bytes of the digest yielded by algorithm
@var{algo}. This is often used prior to @code{gcry_md_read} to allocate
sufficient memory for the digest.
@end deftypefun
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:
@deftypefun int gcry_md_get_algo (gcry_md_hd_t @var{h})
Retrieve the algorithm used with the handle @var{h}. Note that this
does not work reliable if more than one algorithm is enabled in @var{h}.
@end deftypefun
The following macro might also be useful:
@deftypefun int gcry_md_is_secure (gcry_md_hd_t @var{h})
This function returns true when the digest object @var{h} is allocated
in "secure memory"; i.e. @var{h} was created with the
@code{GCRY_MD_FLAG_SECURE}.
@end deftypefun
@deftypefun int gcry_md_is_enabled (gcry_md_hd_t @var{h}, int @var{algo})
This function returns true when the algorithm @var{algo} has been
enabled for the digest object @var{h}.
@end deftypefun
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.
@deftypefun void gcry_md_debug (gcry_md_hd_t @var{h}, const char *@var{suffix})
Enable debugging for the digest object with handle @var{h}. This
creates files named @file{dbgmd-<n>.<string>} while doing the
actual hashing. @var{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 @code{gcry_md_write} or
@code{gcry_md_putc}. If @code{NULL} is used for @var{suffix}, the
debugging is stopped and the file closed. This is only rarely required
because @code{gcry_md_close} implicitly stops debugging.
@end deftypefun
@c **********************************************************
@c ******************* MAC Functions **********************
@c **********************************************************
@node Message Authentication Codes
@chapter 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.
@end menu
@node Available MAC algorithms
@section Available MAC algorithms
@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-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
return value. This constant is guaranteed to have the value @code{0}.
@item GCRY_MAC_HMAC_SHA256
This is keyed-hash message authentication code (HMAC) message authentication
algorithm based on the SHA-256 hash algorithm.
@item GCRY_MAC_HMAC_SHA224
This is HMAC message authentication algorithm based on the SHA-224 hash
algorithm.
@item GCRY_MAC_HMAC_SHA512
This is HMAC message authentication algorithm based on the SHA-512 hash
algorithm.
@item GCRY_MAC_HMAC_SHA384
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
algorithm.
@item GCRY_MAC_HMAC_SHA3_224
This is HMAC message authentication algorithm based on the SHA3-224 hash
algorithm.
@item GCRY_MAC_HMAC_SHA3_512
This is HMAC message authentication algorithm based on the SHA3-512 hash
algorithm.
@item GCRY_MAC_HMAC_SHA3_384
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.
@item GCRY_MAC_HMAC_MD5
This is HMAC message authentication algorithm based on the MD5 hash
algorithm.
@item GCRY_MAC_HMAC_MD4
This is HMAC message authentication algorithm based on the MD4 hash
algorithm.
@item GCRY_MAC_HMAC_RMD160
This is HMAC message authentication algorithm based on the RIPE-MD-160 hash
algorithm.
@item GCRY_MAC_HMAC_WHIRLPOOL
This is HMAC message authentication algorithm based on the WHIRLPOOL hash
algorithm.
@item GCRY_MAC_HMAC_GOSTR3411_94
This is HMAC message authentication algorithm based on the GOST R 34.11-94 hash
algorithm.
@item GCRY_MAC_HMAC_STRIBOG256
This is HMAC message authentication algorithm based on the 256-bit hash
algorithm described in GOST R 34.11-2012.
@item GCRY_MAC_HMAC_STRIBOG512
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_CMAC_AES
This is CMAC (Cipher-based MAC) message authentication algorithm based on
the AES block cipher algorithm.
@item GCRY_MAC_CMAC_3DES
This is CMAC message authentication algorithm based on the three-key EDE
Triple-DES block cipher algorithm.
@item GCRY_MAC_CMAC_CAMELLIA
This is CMAC message authentication algorithm based on the Camellia block cipher
algorithm.
@item GCRY_MAC_CMAC_CAST5
This is CMAC message authentication algorithm based on the CAST128-5
block cipher algorithm.
@item GCRY_MAC_CMAC_BLOWFISH
This is CMAC message authentication algorithm based on the Blowfish
block cipher algorithm.
@item GCRY_MAC_CMAC_TWOFISH
This is CMAC message authentication algorithm based on the Twofish
block cipher algorithm.
@item GCRY_MAC_CMAC_SERPENT
This is CMAC message authentication algorithm based on the Serpent
block cipher algorithm.
@item GCRY_MAC_CMAC_SEED
This is CMAC message authentication algorithm based on the SEED
block cipher algorithm.
@item GCRY_MAC_CMAC_RFC2268
This is CMAC message authentication algorithm based on the Ron's Cipher 2
block cipher algorithm.
@item GCRY_MAC_CMAC_IDEA
This is CMAC message authentication algorithm based on the IDEA
block cipher algorithm.
@item GCRY_MAC_CMAC_GOST28147
This is CMAC message authentication algorithm based on the GOST 28147-89
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.
@item GCRY_MAC_GMAC_CAMELLIA
This is GMAC message authentication algorithm based on the Camellia
block cipher algorithm.
@item GCRY_MAC_GMAC_TWOFISH
This is GMAC message authentication algorithm based on the Twofish
block cipher algorithm.
@item GCRY_MAC_GMAC_SERPENT
This is GMAC message authentication algorithm based on the Serpent
block cipher algorithm.
@item GCRY_MAC_GMAC_SEED
This is GMAC message authentication algorithm based on the SEED
block cipher algorithm.
@item GCRY_MAC_POLY1305
This is plain Poly1305 message authentication algorithm, used with
one-time key.
@item GCRY_MAC_POLY1305_AES
This is Poly1305-AES message authentication algorithm, used with
key and one-time nonce.
@item GCRY_MAC_POLY1305_CAMELLIA
This is Poly1305-Camellia message authentication algorithm, used with
key and one-time nonce.
@item GCRY_MAC_POLY1305_TWOFISH
This is Poly1305-Twofish message authentication algorithm, used with
key and one-time nonce.
@item GCRY_MAC_POLY1305_SERPENT
This is Poly1305-Serpent message authentication algorithm, used with
key and one-time nonce.
@item GCRY_MAC_POLY1305_SEED
This is Poly1305-SEED message authentication algorithm, used with
key and one-time nonce.
@end table
@c end table of MAC algorithms
@node Working with MAC algorithms
@section Working with MAC algorithms
To use most of these function it is necessary to create a context;
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
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.
For a list of supported algorithms, see @ref{Available MAC algorithms}.
The flags allowed for @var{mode} are:
@c begin table of MAC flags
@table @code
@item GCRY_MAC_FLAG_SECURE
Allocate all buffers and the resulting MAC in "secure memory". Use this if the
MAC data is highly confidential.
@end table
@c begin table of MAC flags
@end deftypefun
@c end function gcry_mac_open
In order to use a handle for performing MAC algorithm operations, a
`key' has to be set first:
@deftypefun gcry_error_t gcry_mac_setkey (gcry_mac_hd_t @var{h}, const void *@var{key}, size_t @var{keylen})
Set the MAC key to the value of @var{key} of length @var{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.
@end deftypefun
GMAC algorithms and Poly1305-with-cipher algorithms need initialization vector to be set,
which can be performed with function:
@deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen})
Set the IV to the value of @var{iv} of length @var{ivlen} bytes.
@end deftypefun
After you are done with the MAC calculation, you should release the resources
by using:
@deftypefun void gcry_mac_close (gcry_mac_hd_t @var{h})
Release all resources of MAC context @var{h}. @var{h} should not be
used after a call to this function. A @code{NULL} passed as @var{h} is
ignored. The function also clears all sensitive information associated
with this handle.
@end deftypefun
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:
@deftypefun gcry_error_t gcry_mac_reset (gcry_mac_hd_t @var{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.
@end deftypefun
Now that we have prepared everything to calculate MAC, it is time to
see how it is actually done.
@deftypefun gcry_error_t gcry_mac_write (gcry_mac_hd_t @var{h}, const void *@var{buffer}, size_t @var{length})
Pass @var{length} bytes of the data in @var{buffer} to the MAC object
with handle @var{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.
@end deftypefun
The way to read out the calculated MAC is by using the function:
@deftypefun gcry_error_t gcry_mac_read (gcry_mac_hd_t @var{h}, void *@var{buffer}, size_t *@var{length})
@code{gcry_mac_read} returns the MAC after finalizing the calculation.
Function copies the resulting MAC value to @var{buffer} of the length
@var{length}. If @var{length} is larger than length of resulting MAC value,
then length of MAC is returned through @var{length}.
@end deftypefun
To compare existing MAC value with recalculated MAC, one is to use the function:
@deftypefun gcry_error_t gcry_mac_verify (gcry_mac_hd_t @var{h}, void *@var{buffer}, size_t @var{length})
@code{gcry_mac_verify} finalizes MAC calculation and compares result with
@var{length} bytes of data in @var{buffer}. Error code @code{GPG_ERR_CHECKSUM}
is returned if the MAC value in the buffer @var{buffer} does not match
the MAC calculated in object @var{h}.
@end deftypefun
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:
@deftypefun {int} gcry_mac_get_algo (gcry_mac_hd_t @var{h})
Retrieve the algorithm used with the handle @var{h}.
@end deftypefun
@c ***********************************
@c ***** MAC info functions **********
@c ***********************************
MAC algorithms are identified by internal algorithm numbers (see
@code{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.
@deftypefun {const char *} gcry_mac_algo_name (int @var{algo})
Map the MAC algorithm id @var{algo} to a string representation of the
algorithm name. For unknown algorithms this function returns the
string @code{"?"}. This function should not be used to test for the
availability of an algorithm.
@end deftypefun
@deftypefun int gcry_mac_map_name (const char *@var{name})
Map the algorithm with @var{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.
@end deftypefun
To test whether an algorithm is actually available for use, the
following macro should be used:
@deftypefun gcry_error_t gcry_mac_test_algo (int @var{algo})
The macro returns 0 if the MAC algorithm @var{algo} is available for use.
@end deftypefun
If the length of a message digest is not known, it can be retrieved
using the following function:
@deftypefun {unsigned int} gcry_mac_get_algo_maclen (int @var{algo})
Retrieve the length in bytes of the MAC yielded by algorithm @var{algo}.
This is often used prior to @code{gcry_mac_read} to allocate sufficient memory
for the MAC value. On error @code{0} is returned.
@end deftypefun
@deftypefun {unsigned int} gcry_mac_get_algo_keylen (@var{algo})
This function returns length of the key for MAC algorithm @var{algo}. If
the algorithm supports multiple key lengths, the default supported key
length is returned. On error @code{0} is returned. The key length is
returned as number of octets.
@end deftypefun
@c *******************************************************
@c ******************* KDF *****************************
@c *******************************************************
@node Key Derivation
@chapter Key Derivation
@acronym{Libgcypt} provides a general purpose function to derive keys
from strings.
@deftypefun gpg_error_t gcry_kdf_derive ( @
@w{const void *@var{passphrase}}, @w{size_t @var{passphraselen}}, @
@w{int @var{algo}}, @w{int @var{subalgo}}, @
@w{const void *@var{salt}}, @w{size_t @var{saltlen}}, @
@w{unsigned long @var{iterations}}, @
@w{size_t @var{keysize}}, @w{void *@var{keybuffer}} )
Derive a key from a passphrase. @var{keysize} gives the requested
size of the keys 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
use; see below. @var{subalgo} specifies an algorithm used internally
by the KDF algorithms; this is usually a hash algorithm but certain
KDF algorithms may use it differently. @var{salt} is a salt of length
@var{saltlen} octets, as needed by most KDF algorithms.
@var{iterations} is a positive integer parameter to most KDFs.
@noindent
On success 0 is returned; on failure an error code.
@noindent
Currently supported KDFs (parameter @var{algo}):
@table @code
@item GCRY_KDF_SIMPLE_S2K
The OpenPGP simple S2K algorithm (cf. RFC4880). Its use is strongly
deprecated. @var{salt} and @var{iterations} are not needed and may be
passed as @code{NULL}/@code{0}.
@item GCRY_KDF_SALTED_S2K
The OpenPGP salted S2K algorithm (cf. RFC4880). Usually not used.
@var{iterations} is not needed and may be passed as @code{0}. @var{saltlen}
must be given as 8.
@item GCRY_KDF_ITERSALTED_S2K
The OpenPGP iterated+salted S2K algorithm (cf. RFC4880). This is the
default for most OpenPGP applications. @var{saltlen} must be given as
8. Note that OpenPGP defines a special encoding of the
@var{iterations}; however this function takes the plain decoded
iteration count.
@item GCRY_KDF_PBKDF2
The PKCS#5 Passphrase Based Key Derivation Function number 2.
@item 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.
@end table
@end deftypefun
@c **********************************************************
@c ******************* Random *****************************
@c **********************************************************
@node Random Numbers
@chapter Random Numbers
@menu
* Quality of random numbers:: Libgcrypt uses different quality levels.
* Retrieving random numbers:: How to retrieve random numbers.
@end menu
@node Quality of random numbers
@section Quality of random numbers
@acronym{Libgcypt} offers random numbers of different quality levels:
@deftp {Data type} gcry_random_level_t
The constants for the random quality levels are of this enum type.
@end deftp
@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
@code{gcry_create_nonce}.
@item GCRY_STRONG_RANDOM
Use this level for session keys and similar purposes.
@item GCRY_VERY_STRONG_RANDOM
Use this level for long term key material.
@end table
@node Retrieving random numbers
@section Retrieving random numbers
@deftypefun void gcry_randomize (unsigned char *@var{buffer}, size_t @var{length}, enum gcry_random_level @var{level})
Fill @var{buffer} with @var{length} random bytes using a random quality
as defined by @var{level}.
@end deftypefun
@deftypefun {void *} gcry_random_bytes (size_t @var{nbytes}, enum gcry_random_level @var{level})
Convenience function to allocate a memory block consisting of
@var{nbytes} fresh random bytes using a random quality as defined by
@var{level}.
@end deftypefun
@deftypefun {void *} gcry_random_bytes_secure (size_t @var{nbytes}, enum gcry_random_level @var{level})
Convenience function to allocate a memory block consisting of
@var{nbytes} fresh random bytes using a random quality as defined by
@var{level}. This function differs from @code{gcry_random_bytes} in
that the returned buffer is allocated in a ``secure'' area of the
memory.
@end deftypefun
@deftypefun void gcry_create_nonce (unsigned char *@var{buffer}, size_t @var{length})
Fill @var{buffer} with @var{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.
@end deftypefun
@c **********************************************************
@c ******************* S-Expressions ***********************
@c **********************************************************
@node S-expressions
@chapter 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
@cite{Ron Rivest, code and description of S-expressions,
@uref{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.
@end menu
@node Data types for S-expressions
@section Data types for S-expressions
@deftp {Data type} gcry_sexp_t
The @code{gcry_sexp_t} type describes an object with the Libgcrypt internal
representation of an S-expression.
@end deftp
@node Working with S-expressions
@section Working with S-expressions
@noindent
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:
@deftypefun gcry_error_t gcry_sexp_new (@w{gcry_sexp_t *@var{r_sexp}}, @w{const void *@var{buffer}}, @w{size_t @var{length}}, @w{int @var{autodetect}})
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
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
@code{NULL}.
Note that the caller is responsible for releasing the newly allocated
S-expression using @code{gcry_sexp_release}.
@end deftypefun
@deftypefun gcry_error_t gcry_sexp_create (@w{gcry_sexp_t *@var{r_sexp}}, @w{void *@var{buffer}}, @w{size_t @var{length}}, @w{int @var{autodetect}}, @w{void (*@var{freefnc})(void*)})
This function is identical to @code{gcry_sexp_new} but has an extra
argument @var{freefnc}, which, when not set to @code{NULL}, is expected
to be a function to release the @var{buffer}; most likely the standard
@code{free} function is used for this argument. This has the effect of
transferring the ownership of @var{buffer} to the created object in
@var{r_sexp}. The advantage of using this function is that Libgcrypt
might decide to directly use the provided buffer and thus avoid extra
copying.
@end deftypefun
@deftypefun gcry_error_t gcry_sexp_sscan (@w{gcry_sexp_t *@var{r_sexp}}, @w{size_t *@var{erroff}}, @w{const char *@var{buffer}}, @w{size_t @var{length}})
This is another variant of the above functions. It behaves nearly
identical but provides an @var{erroff} argument which will receive the
offset into the buffer where the parsing stopped on error.
@end deftypefun
@deftypefun gcry_error_t gcry_sexp_build (@w{gcry_sexp_t *@var{r_sexp}}, @w{size_t *@var{erroff}}, @w{const char *@var{format}, ...})
This function creates an internal S-expression from the string template
@var{format} and stores it at the address of @var{r_sexp}. If there is a
parsing error, the function returns an appropriate error code and stores
the offset into @var{format} where the parsing stopped in @var{erroff}.
The function supports a couple of printf-like formatting characters and
expects arguments for some of these escape sequences right after
@var{format}. The following format characters are defined:
@table @samp
@item %m
The next argument is expected to be of type @code{gcry_mpi_t} and a copy of
its value is inserted into the resulting S-expression. The MPI is
stored as a signed integer.
@item %M
The next argument is expected to be of type @code{gcry_mpi_t} and a copy of
its value is inserted into the resulting S-expression. The MPI is
stored as an unsigned integer.
@item %s
The next argument is expected to be of type @code{char *} and that
string is inserted into the resulting S-expression.
@item %d
The next argument is expected to be of type @code{int} and its value is
inserted into the resulting S-expression.
@item %u
The next argument is expected to be of type @code{unsigned int} and
its value is inserted into the resulting S-expression.
@item %b
The next argument is expected to be of type @code{int} directly
followed by an argument of type @code{char *}. This represents a
buffer of given length to be inserted into the resulting S-expression.
@item %S
The next argument is expected to be of type @code{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.
@end table
@noindent
No other format characters are defined and would return an error. Note
that the format character @samp{%%} does not exists, because a percent
sign is not a valid character in an S-expression.
@end deftypefun
@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
this is done in addition to the zeroisation always done when freeing
secure memory.
@end deftypefun
@noindent
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.
@deftypefun size_t gcry_sexp_sprint (@w{gcry_sexp_t @var{sexp}}, @w{int @var{mode}}, @w{char *@var{buffer}}, @w{size_t @var{maxlength}})
Copies the S-expression object @var{sexp} into @var{buffer} using the
format specified in @var{mode}. @var{maxlength} must be set to the
allocated length of @var{buffer}. The function returns the actual
length of valid bytes put into @var{buffer} or 0 if the provided buffer
is too short. Passing @code{NULL} for @var{buffer} returns the required
length for @var{buffer}. For convenience reasons an extra byte with
value 0 is appended to the buffer.
@noindent
The following formats are supported:
@table @code
@item GCRYSEXP_FMT_DEFAULT
Returns a convenient external S-expression representation.
@item GCRYSEXP_FMT_CANON
Return the S-expression in canonical format.
@item GCRYSEXP_FMT_BASE64
Not currently supported.
@item GCRYSEXP_FMT_ADVANCED
Returns the S-expression in advanced format.
@end table
@end deftypefun
@deftypefun void gcry_sexp_dump (@w{gcry_sexp_t @var{sexp}})
Dumps @var{sexp} in a format suitable for debugging to Libgcrypt's
logging stream.
@end deftypefun
@noindent
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.
@deftypefun size_t gcry_sexp_canon_len (@w{const unsigned char *@var{buffer}}, @w{size_t @var{length}}, @w{size_t *@var{erroff}}, @w{int *@var{errcode}})
Scan the canonical encoded @var{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 @var{length} is not 0, the maximum
length to scan is given; this can be used for syntax checks of
data passed from outside. @var{errcode} and @var{erroff} may both be
passed as @code{NULL}.
@end deftypefun
@noindent
There are functions to parse S-expressions and retrieve elements:
@deftypefun gcry_sexp_t gcry_sexp_find_token (@w{const gcry_sexp_t @var{list}}, @w{const char *@var{token}}, @w{size_t @var{toklen}})
Scan the S-expression for a sublist with a type (the car of the list)
matching the string @var{token}. If @var{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 @code{NULL}
when not found.
@end deftypefun
@deftypefun int gcry_sexp_length (@w{const gcry_sexp_t @var{list}})
Return the length of the @var{list}. For a valid S-expression this
should be at least 1.
@end deftypefun
@deftypefun gcry_sexp_t gcry_sexp_nth (@w{const gcry_sexp_t @var{list}}, @w{int @var{number}})
Create and return a new S-expression from the element with index @var{number} in
@var{list}. Note that the first element has the index 0. If there is
no such element, @code{NULL} is returned.
@end deftypefun
@deftypefun gcry_sexp_t gcry_sexp_car (@w{const gcry_sexp_t @var{list}})
Create and return a new S-expression from the first element in
@var{list}; this is called the "type" and should always exist per
S-expression specification and in general be a string. @code{NULL} is
returned in case of a problem.
@end deftypefun
@deftypefun gcry_sexp_t gcry_sexp_cdr (@w{const gcry_sexp_t @var{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 @code{NULL} on error.
@end deftypefun
@deftypefun {const char *} gcry_sexp_nth_data (@w{const gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{size_t *@var{datalen}})
This function is used to get data from a @var{list}. A pointer to the
actual data with index @var{number} is returned and the length of this
data will be stored to @var{datalen}. If there is no data at the given
index or the index represents another list, @code{NULL} is returned.
@strong{Caution:} The returned pointer is valid as long as @var{list} is
not modified or released.
@noindent
Here is an example on how to extract and print the surname (Meier) from
the S-expression @samp{(Name Otto Meier (address Burgplatz 3))}:
@example
size_t len;
const char *name;
name = gcry_sexp_nth_data (list, 2, &len);
printf ("my name is %.*s\n", (int)len, name);
@end example
@end deftypefun
@deftypefun {void *} gcry_sexp_nth_buffer (@w{const gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{size_t *@var{rlength}})
This function is used to get data from a @var{list}. A malloced
buffer with the actual data at list index @var{number} is returned and
the length of this buffer will be stored to @var{rlength}. If there
is no data at the given index or the index represents another list,
@code{NULL} is returned. The caller must release the result using
@code{gcry_free}.
@noindent
Here is an example on how to extract and print the CRC value from the
S-expression @samp{(hash crc32 #23ed00d7)}:
@example
size_t len;
char *value;
value = gcry_sexp_nth_buffer (list, 2, &len);
if (value)
fwrite (value, len, 1, stdout);
gcry_free (value);
@end example
@end deftypefun
@deftypefun {char *} gcry_sexp_nth_string (@w{gcry_sexp_t @var{list}}, @w{int @var{number}})
This function is used to get and convert data from a @var{list}. The
data is assumed to be a Nul terminated string. The caller must
release this returned value using @code{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, @code{NULL} is returned.
@end deftypefun
@deftypefun gcry_mpi_t gcry_sexp_nth_mpi (@w{gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{int @var{mpifmt}})
This function is used to get and convert data from a @var{list}. This
data is assumed to be an MPI stored in the format described by
@var{mpifmt} and returned as a standard Libgcrypt MPI. The caller must
release this returned value using @code{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, @code{NULL} is returned. If you use
this function to parse results of a public key function, you most
likely want to use @code{GCRYMPI_FMT_USG}.
@end deftypefun
@deftypefun gpg_error_t gcry_sexp_extract_param ( @
@w{gcry_sexp_t @var{sexp}}, @
@w{const char *@var{path}}, @
@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
space between the parameter names are ignored. Some special characters
may be given to control the conversion:
@table @samp
@item +
Switch to unsigned integer format (GCRYMPI_FMT_USG). This is the
default mode.
@item -
Switch to standard signed format (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 ?
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
parameter name, enclose the name in single quotes.
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
@example
gcry_sexp_extract_param (key, NULL, "n/x+e d-'foo'",
&mpi_n, &mpi_x, &mpi_e, &mpi_d, &mpi_foo, NULL)
@end example
stores the parameter 'n' from @var{key} as an unsigned MPI into
@var{mpi_n}, the parameter 'x' as an opaque MPI into @var{mpi_x}, the
parameters 'e' and 'd' again as an unsigned MPI into @var{mpi_e} and
@var{mpi_d} and finally the parameter 'foo' as a signed MPI into
@var{mpi_foo}.
@var{path} is an optional string used to locate a token. The
exclamation mark separated tokens are used via
@code{gcry_sexp_find_token} to find a start point inside the
S-expression.
In buffer descriptor mode a pointer to a @code{gcry_buffer_t}
descriptor is expected instead of a pointer to an MPI. The caller may
use two different operation modes here: If the @var{data} field of the
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
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
@var{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 @code{NULL}, and all passed buffers
are either truncated if the caller supplied the buffer, or deallocated
if the function allocated the buffer.
@end deftypefun
@c **********************************************************
@c ******************* MPIs ******** ***********************
@c **********************************************************
@node MPI library
@chapter 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.
@end menu
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).
@node Data types
@section Data types
@deftp {Data type} {gcry_mpi_t}
This type represents an object to hold an MPI.
@end deftp
@deftp {Data type} {gcry_mpi_point_t}
This type represents an object to hold a point for elliptic curve math.
@end deftp
@node Basic functions
@section Basic functions
@noindent
To work with MPIs, storage must be allocated and released for the
numbers. This can be done with one of these functions:
@deftypefun gcry_mpi_t gcry_mpi_new (@w{unsigned int @var{nbits}})
Allocate a new MPI object, initialize it to 0 and initially allocate
enough memory for a number of at least @var{nbits}. This pre-allocation is
only a small performance issue and not actually necessary because
Libgcrypt automatically re-allocates the required memory.
@end deftypefun
@deftypefun gcry_mpi_t gcry_mpi_snew (@w{unsigned int @var{nbits}})
This is identical to @code{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.
@end deftypefun
@deftypefun gcry_mpi_t gcry_mpi_copy (@w{const gcry_mpi_t @var{a}})
Create a new MPI as the exact copy of @var{a} but with the constant
and immutable flags cleared.
@end deftypefun
@deftypefun void gcry_mpi_release (@w{gcry_mpi_t @var{a}})
Release the MPI @var{a} and free all associated resources. Passing
@code{NULL} is allowed and ignored. When a MPI stored in the "secure
memory" is released, that memory gets wiped out immediately.
@end deftypefun
@noindent
The simplest operations are used to assign a new value to an MPI:
@deftypefun gcry_mpi_t gcry_mpi_set (@w{gcry_mpi_t @var{w}}, @w{const gcry_mpi_t @var{u}})
Assign the value of @var{u} to @var{w} and return @var{w}. If
@code{NULL} is passed for @var{w}, a new MPI is allocated, set to the
value of @var{u} and returned.
@end deftypefun
@deftypefun gcry_mpi_t gcry_mpi_set_ui (@w{gcry_mpi_t @var{w}}, @w{unsigned long @var{u}})
Assign the value of @var{u} to @var{w} and return @var{w}. If
@code{NULL} is passed for @var{w}, a new MPI is allocated, set to the
value of @var{u} and returned. This function takes an @code{unsigned
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 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}.
@end deftypefun
@deftypefun void gcry_mpi_snatch (@w{gcry_mpi_t @var{w}}, @
@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.
@end deftypefun
@deftypefun void gcry_mpi_neg (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}})
Set the sign of @var{w} to the negative of @var{u}.
@end deftypefun
@deftypefun void gcry_mpi_abs (@w{gcry_mpi_t @var{w}})
Clear the sign of @var{w}.
@end deftypefun
@node MPI formats
@section MPI formats
@noindent
The following functions are used to convert between an external
representation of an MPI and the internal one of Libgcrypt.
@deftypefun gcry_error_t gcry_mpi_scan (@w{gcry_mpi_t *@var{r_mpi}}, @w{enum gcry_mpi_format @var{format}}, @w{const unsigned char *@var{buffer}}, @w{size_t @var{buflen}}, @w{size_t *@var{nscanned}})
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
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
@var{buffer}:
@table @code
@item GCRYMPI_FMT_STD
2-complement stored without a length header. Note that
@code{gcry_mpi_print} stores a @code{0} as a string of zero length.
@item GCRYMPI_FMT_PGP
As used by OpenPGP (only defined as unsigned). This is basically
@code{GCRYMPI_FMT_STD} with a 2 byte big endian length header.
A length header indicating a length of more than 16384 is not allowed.
@item GCRYMPI_FMT_SSH
As used in the Secure Shell protocol. This is @code{GCRYMPI_FMT_STD}
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
high bit is always zero to make clear that an explicit sign ist used.
When using this format, @var{buflen} must be zero.
@item GCRYMPI_FMT_USG
Simple unsigned integer.
@end table
@noindent
Note that all of the above formats store the integer in big-endian
format (MSB first).
@end deftypefun
@deftypefun gcry_error_t gcry_mpi_print (@w{enum gcry_mpi_format @var{format}}, @w{unsigned char *@var{buffer}}, @w{size_t @var{buflen}}, @w{size_t *@var{nwritten}}, @w{const gcry_mpi_t @var{a}})
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
actually stored in @var{buffer} after a successful operation.
@end deftypefun
@deftypefun gcry_error_t gcry_mpi_aprint (@w{enum gcry_mpi_format @var{format}}, @w{unsigned char **@var{buffer}}, @w{size_t *@var{nbytes}}, @w{const gcry_mpi_t @var{a}})
Convert the MPI @var{a} into an external representation described by
@var{format} (see above) and store it in a newly allocated buffer which
address will be stored in the variable @var{buffer} points to. The
number of bytes stored in this buffer will be stored in the variable
@var{nbytes} points to, unless @var{nbytes} is @code{NULL}.
Even if @var{nbytes} is zero, the function allocates at least one byte
and store a zero there. Thus with formats @code{GCRYMPI_FMT_STD} and
@code{GCRYMPI_FMT_USG} the caller may safely set a returned length of
0 to 1 to represent a zero as a 1 byte string.
@end deftypefun
@deftypefun void gcry_mpi_dump (@w{const gcry_mpi_t @var{a}})
Dump the value of @var{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 @code{NULL} for
@var{a}.
@end deftypefun
@node Calculations
@section Calculations
@noindent
Basic arithmetic operations:
@deftypefun void gcry_mpi_add (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}})
@math{@var{w} = @var{u} + @var{v}}.
@end deftypefun
@deftypefun void gcry_mpi_add_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}})
@math{@var{w} = @var{u} + @var{v}}. Note that @var{v} is an unsigned integer.
@end deftypefun
@deftypefun void gcry_mpi_addm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}})
@math{@var{w} = @var{u} + @var{v} \bmod @var{m}}.
@end deftypefun
@deftypefun void gcry_mpi_sub (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}})
@math{@var{w} = @var{u} - @var{v}}.
@end deftypefun
@deftypefun void gcry_mpi_sub_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}})
@math{@var{w} = @var{u} - @var{v}}. @var{v} is an unsigned integer.
@end deftypefun
@deftypefun void gcry_mpi_subm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}})
@math{@var{w} = @var{u} - @var{v} \bmod @var{m}}.
@end deftypefun
@deftypefun void gcry_mpi_mul (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}})
@math{@var{w} = @var{u} * @var{v}}.
@end deftypefun
@deftypefun void gcry_mpi_mul_ui (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{v}})
@math{@var{w} = @var{u} * @var{v}}. @var{v} is an unsigned integer.
@end deftypefun
@deftypefun void gcry_mpi_mulm (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{gcry_mpi_t @var{v}}, @w{gcry_mpi_t @var{m}})
@math{@var{w} = @var{u} * @var{v} \bmod @var{m}}.
@end deftypefun
@deftypefun void gcry_mpi_mul_2exp (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}}, @w{unsigned long @var{e}})
@c FIXME: I am in need for a real TeX{info} guru:
@c I don't know why TeX can grok @var{e} here.
@math{@var{w} = @var{u} * 2^e}.
@end deftypefun
@deftypefun void gcry_mpi_div (@w{gcry_mpi_t @var{q}}, @w{gcry_mpi_t @var{r}}, @w{gcry_mpi_t @var{dividend}}, @w{gcry_mpi_t @var{divisor}}, @w{int @var{round}})
@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} 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}})
@math{@var{r} = @var{dividend} \bmod @var{divisor}}.
@end deftypefun
@deftypefun void gcry_mpi_powm (@w{gcry_mpi_t @var{w}}, @w{const gcry_mpi_t @var{b}}, @w{const gcry_mpi_t @var{e}}, @w{const gcry_mpi_t @var{m}})
@c I don't know why TeX can grok @var{e} here.
@math{@var{w} = @var{b}^e \bmod @var{m}}.
@end deftypefun
@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.
@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}})
Set @var{x} to the multiplicative inverse of @math{@var{a} \bmod @var{m}}.
Return true if the inverse exists.
@end deftypefun
@node Comparisons
@section Comparisons
@noindent
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}
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
sizes using memcmp. If only one number is an opaque value, the opaque
value is less than the other number.
@end deftypefun
@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} >
@var{v} and a negative for @var{u} < @var{v}.
@end deftypefun
@deftypefun int gcry_mpi_is_neg (@w{const gcry_mpi_t @var{a}})
Return 1 if @var{a} is less than zero; return 0 if zero or positive.
@end deftypefun
@node Bit manipulations
@section Bit manipulations
@noindent
There are a couple of functions to get information on arbitrary bits
in an MPI and to set or clear them:
@deftypefun {unsigned int} gcry_mpi_get_nbits (@w{gcry_mpi_t @var{a}})
Return the number of bits required to represent @var{a}.
@end deftypefun
@deftypefun int gcry_mpi_test_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Return true if bit number @var{n} (counting from 0) is set in @var{a}.
@end deftypefun
@deftypefun void gcry_mpi_set_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Set bit number @var{n} in @var{a}.
@end deftypefun
@deftypefun void gcry_mpi_clear_bit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Clear bit number @var{n} in @var{a}.
@end deftypefun
@deftypefun void gcry_mpi_set_highbit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Set bit number @var{n} in @var{a} and clear all bits greater than @var{n}.
@end deftypefun
@deftypefun void gcry_mpi_clear_highbit (@w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Clear bit number @var{n} in @var{a} and all bits greater than @var{n}.
@end deftypefun
@deftypefun void gcry_mpi_rshift (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Shift the value of @var{a} by @var{n} bits to the right and store the
result in @var{x}.
@end deftypefun
@deftypefun void gcry_mpi_lshift (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{unsigned int @var{n}})
Shift the value of @var{a} by @var{n} bits to the left and store the
result in @var{x}.
@end deftypefun
@node EC functions
@section EC functions
@noindent
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.
@deftypefun gcry_mpi_point_t gcry_mpi_point_new (@w{unsigned int @var{nbits}})
Allocate a new point object, initialize it to 0, and allocate enough
memory for a points of at least @var{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 @var{nbits} is usually the right thing to do.
@end deftypefun
@deftypefun void gcry_mpi_point_release (@w{gcry_mpi_point_t @var{point}})
Release @var{point} and free all associated resources. Passing
@code{NULL} is allowed and ignored.
@end deftypefun
@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
@code{gcry_mpi_point_new(0)}.
@end deftypefun
@deftypefun void gcry_mpi_point_get (@w{gcry_mpi_t @var{x}}, @
@w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}}, @
@w{gcry_mpi_point_t @var{point}})
Store the projective coordinates from @var{point} into the MPIs
@var{x}, @var{y}, and @var{z}. If a coordinate is not required,
@code{NULL} may be used for @var{x}, @var{y}, or @var{z}.
@end deftypefun
@deftypefun void gcry_mpi_point_snatch_get (@w{gcry_mpi_t @var{x}}, @
@w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}}, @
@w{gcry_mpi_point_t @var{point}})
Store the projective coordinates from @var{point} into the MPIs
@var{x}, @var{y}, and @var{z}. If a coordinate is not required,
@code{NULL} may be used for @var{x}, @var{y}, or @var{z}. The object
@var{point} is then released. Using this function instead of
@code{gcry_mpi_point_get} and @code{gcry_mpi_point_release} has the
advantage of avoiding some extra memory allocations and copies.
@end deftypefun
@deftypefun gcry_mpi_point_t gcry_mpi_point_set ( @
@w{gcry_mpi_point_t @var{point}}, @
@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}})
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
is allocated and returned. Returns @var{point} or the newly allocated
point object.
@end deftypefun
@deftypefun gcry_mpi_point_t gcry_mpi_point_snatch_set ( @
@w{gcry_mpi_point_t @var{point}}, @
@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @w{gcry_mpi_t @var{z}})
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
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
some extra memory allocations and copies. Returns @var{point} or the
newly allocated point object.
@end deftypefun
@anchor{gcry_mpi_ec_new}
@deftypefun gpg_error_t gcry_mpi_ec_new (@w{gcry_ctx_t *@var{r_ctx}}, @
@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
(@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
parameters. If only @var{curvename} is given, the context is
initialized for this named curve.
If a parameter specifying a point (e.g. @code{g} or @code{q}) is not
found, the parser looks for a non-encoded point by appending
@code{.x}, @code{.y}, and @code{.z} to the parameter name and looking
them all up to create a point. A parameter with the suffix @code{.z}
is optional and defaults to 1.
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
@deftypefun gcry_mpi_t gcry_mpi_ec_get_mpi ( @
@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
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
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
encoded point unless these special names are used:
@table @var
@item q@@eddsa
Return an EdDSA style compressed point. This is only supported for
Twisted Edwards curves.
@end table
@end deftypefun
@deftypefun gcry_mpi_point_t gcry_mpi_ec_get_point ( @
@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
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 point. In any case @code{gcry_mpi_point_release} needs to be
called to release the result. 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.
@end deftypefun
@deftypefun gpg_error_t gcry_mpi_ec_set_mpi ( @
@w{const char *@var{name}}, @w{gcry_mpi_t @var{newvalue}}, @
@w{gcry_ctx_t @var{ctx}})
Store the MPI @var{newvalue} at @var{name} into the context @var{ctx}.
On success @code{0} is returned; on error an error code. Valid names
are the MPI parameters of an elliptic curve (@pxref{ecc_keyparam}).
@end deftypefun
@deftypefun gpg_error_t gcry_mpi_ec_set_point ( @
@w{const char *@var{name}}, @w{gcry_mpi_point_t @var{newvalue}}, @
@w{gcry_ctx_t @var{ctx}})
Store the point @var{newvalue} at @var{name} into the context
@var{ctx}. On success @code{0} is returned; on error an error code.
Valid names are the point parameters of an elliptic curve
(@pxref{ecc_keyparam}).
@end deftypefun
@deftypefun gpg_err_code_t gcry_mpi_ec_decode_point ( @
@w{mpi_point_t @var{result}}, @w{gcry_mpi_t @var{value}}, @
@w{gcry_ctx_t @var{ctx}})
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
prefixed uncompressed encoding. On error an error code is returned
and @var{result} might be changed.
@end deftypefun
@deftypefun int gcry_mpi_ec_get_affine ( @
@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{y}}, @
@w{gcry_mpi_point_t @var{point}}, @w{gcry_ctx_t @var{ctx}})
Compute the affine coordinates from the projective coordinates in
@var{point} and store them into @var{x} and @var{y}. If one
coordinate is not required, @code{NULL} may be passed to @var{x} or
@var{y}. @var{ctx} is the context object which has been created using
@code{gcry_mpi_ec_new}. Returns 0 on success or not 0 if @var{point}
is at infinity.
Note that you can use @code{gcry_mpi_ec_set_point} with the value
@code{GCRYMPI_CONST_ONE} for @var{z} to convert affine coordinates
back into projective coordinates.
@end deftypefun
@deftypefun void gcry_mpi_ec_dup ( @
@w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_point_t @var{u}}, @
@w{gcry_ctx_t @var{ctx}})
Double the point @var{u} of the elliptic curve described by @var{ctx}
and store the result into @var{w}.
@end deftypefun
@deftypefun void gcry_mpi_ec_add ( @
@w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_point_t @var{u}}, @
@w{gcry_mpi_point_t @var{v}}, @w{gcry_ctx_t @var{ctx}})
Add the points @var{u} and @var{v} of the elliptic curve described by
@var{ctx} and store the result into @var{w}.
@end deftypefun
@deftypefun void gcry_mpi_ec_sub ( @
@w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_point_t @var{u}}, @
@w{gcry_mpi_point_t @var{v}}, @w{gcry_ctx_t @var{ctx}})
Subtracts the point @var{v} from the point @var{u} of the elliptic
curve described by @var{ctx} and store the result into @var{w}. Only
Twisted Edwards curves are supported for now.
@end deftypefun
@deftypefun void gcry_mpi_ec_mul ( @
@w{gcry_mpi_point_t @var{w}}, @w{gcry_mpi_t @var{n}}, @
@w{gcry_mpi_point_t @var{u}}, @w{gcry_ctx_t @var{ctx}})
Multiply the point @var{u} of the elliptic curve described by
@var{ctx} by @var{n} and store the result into @var{w}.
@end deftypefun
@deftypefun int gcry_mpi_ec_curve_point ( @
@w{gcry_mpi_point_t @var{point}}, @w{gcry_ctx_t @var{ctx}})
Return true if @var{point} is on the elliptic curve described by
@var{ctx}.
@end deftypefun
@node Miscellaneous
@section Miscellaneous
An MPI data type is allowed to be ``misused'' to store an arbitrary
value. Two functions implement this kludge:
@deftypefun gcry_mpi_t gcry_mpi_set_opaque (@w{gcry_mpi_t @var{a}}, @w{void *@var{p}}, @w{unsigned int @var{nbits}})
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
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.
@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.
@end deftypefun
@deftypefun {void *} gcry_mpi_get_opaque (@w{gcry_mpi_t @var{a}}, @w{unsigned int *@var{nbits}})
Return a pointer to an opaque value stored in @var{a} and return its
size in @var{nbits}. Note that the returned pointer is still owned by
@var{a} and that the function should never be used for an non-opaque
MPI.
@end deftypefun
Each MPI has an associated set of flags for special purposes. The
currently defined flags are:
@table @code
@item GCRYMPI_FLAG_SECURE
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 internal 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.
@item 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.
@item 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 @code{GCRYMPI_CONST_ONE}, @code{GCRYMPI_CONST_TWO},
@code{GCRYMPI_CONST_THREE}, @code{GCRYMPI_CONST_FOUR}, and
@code{GCRYMPI_CONST_EIGHT}.
@item GCRYMPI_FLAG_USER1
@itemx GCRYMPI_FLAG_USER2
@itemx GCRYMPI_FLAG_USER3
@itemx GCRYMPI_FLAG_USER4
These flags are reserved for use by the application.
@end table
@deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @
@w{enum gcry_mpi_flag @var{flag}})
Set the @var{flag} for the MPI @var{a}. The only allowed flags are
@code{GCRYMPI_FLAG_SECURE}, @code{GCRYMPI_FLAG_IMMUTABLE}, and
@code{GCRYMPI_FLAG_CONST}.
@end deftypefun
@deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @
@w{enum gcry_mpi_flag @var{flag}})
Clear @var{flag} for the multi-precision-integers @var{a}. The only
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}})
Return true if @var{flag} is set for @var{a}.
@end deftypefun
To put a random value into an MPI, the following convenience function
may be used:
@deftypefun void gcry_mpi_randomize (@w{gcry_mpi_t @var{w}}, @w{unsigned int @var{nbits}}, @w{enum gcry_random_level @var{level}})
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_create_nonce}.
@end deftypefun
@c **********************************************************
@c ******************** Prime numbers ***********************
@c **********************************************************
@node Prime numbers
@chapter Prime numbers
@menu
* Generation:: Generation of new prime numbers.
* Checking:: Checking if a given number is prime.
@end menu
@node Generation
@section Generation
@deftypefun gcry_error_t gcry_prime_generate (gcry_mpi_t *@var{prime},unsigned int @var{prime_bits}, unsigned int @var{factor_bits}, gcry_mpi_t **@var{factors}, gcry_prime_check_func_t @var{cb_func}, void *@var{cb_arg}, gcry_random_level_t @var{random_level}, unsigned int @var{flags})
Generate a new prime number of @var{prime_bits} bits and store it in
@var{prime}. If @var{factor_bits} is non-zero, one of the prime factors
of (@var{prime} - 1) / 2 must be @var{factor_bits} bits long. If
@var{factors} is non-zero, allocate a new, @code{NULL}-terminated array
holding the prime factors and store it in @var{factors}. @var{flags}
might be used to influence the prime number generation process.
@end deftypefun
@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}.
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.
@end deftypefun
@deftypefun void gcry_prime_release_factors (gcry_mpi_t *@var{factors})
Convenience function to release the @var{factors} array.
@end deftypefun
@node Checking
@section Checking
@deftypefun gcry_error_t gcry_prime_check (gcry_mpi_t @var{p}, unsigned int @var{flags})
Check whether the number @var{p} is prime. Returns zero in case @var{p}
is indeed a prime, returns @code{GPG_ERR_NO_PRIME} in case @var{p} is
not a prime and a different error code in case something went horribly
wrong.
@end deftypefun
@c **********************************************************
@c ******************** Utilities ***************************
@c **********************************************************
@node Utilities
@chapter 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.
@end menu
@node Memory allocation
@section Memory allocation
@deftypefun {void *} gcry_malloc (size_t @var{n})
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.
@end deftypefun
@deftypefun {void *} gcry_malloc_secure (size_t @var{n})
Like @code{gcry_malloc}, but uses secure memory.
@end deftypefun
@deftypefun {void *} gcry_calloc (size_t @var{n}, size_t @var{m})
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.
@end deftypefun
@deftypefun {void *} gcry_calloc_secure (size_t @var{n}, size_t @var{m})
Like @code{gcry_calloc}, but uses secure memory.
@end deftypefun
@deftypefun {void *} gcry_realloc (void *@var{p}, size_t @var{n})
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
whether the memory pointed to by @var{p} is secure memory or not,
gcry_realloc tries to use secure memory as well.
@end deftypefun
@deftypefun void gcry_free (void *@var{p})
Release the memory area pointed to by @var{p}.
@end deftypefun
@node Context management
@section 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.
@deftp {Data type} {gcry_ctx_t}
This type is used to refer to the general purpose context object.
@end deftp
@anchor{gcry_ctx_release}
@deftypefun void gcry_ctx_release (gcry_ctx_t @var{ctx})
Release the context object @var{ctx} and all associated resources. A
@code{NULL} passed as @var{ctx} is ignored.
@end deftypefun
@node Buffer description
@section Buffer description
To help hashing non-contiguous areas of memory a general purpose data
type is defined:
@deftp {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:
@table @code
@item .size
This is either 0 for no information available or indicates the
allocated length of the buffer.
@item .off
This is the offset into the buffer.
@item .len
This is the valid length of the buffer starting at @code{.off}.
@item .data
This is the address of the buffer.
@end table
@end deftp
@node Config reporting
@section How to return Libgcrypt's configuration.
Although @code{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:
@deftypefun {char *} gcry_get_config @
(@w{int @var{mode}}, @
@w{const char *@var{what}})
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
@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.
@end deftypefun
@c **********************************************************
@c ********************* Tools ****************************
@c **********************************************************
@node Tools
@chapter Tools
@menu
* hmac256:: A standalone HMAC-SHA-256 implementation
@end menu
@manpage hmac256.1
@node hmac256
@section A HMAC-SHA-256 tool
@ifset manverb
.B hmac256
\- Compute an HMAC-SHA-256 MAC
@end ifset
@mansect synopsis
@ifset manverb
.B hmac256
.RB [ \-\-binary ]
.I key
.I [FILENAME]
@end ifset
@mansect description
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.
@noindent
@command{hmac256} is commonly invoked as
@example
hmac256 "This is my key" foo.txt
@end example
@noindent
This compute the MAC on the file @file{foo.txt} using the key given on
the command line.
@mansect options
@noindent
@command{hmac256} understands these options:
@table @gnupgtabopt
@item --binary
Print the MAC as a binary string. The default is to print the MAC
encoded has lower case hex digits.
@item --version
Print version of the program and exit.
@end table
@mansect see also
@ifset isman
@command{sha256sum}(1)
@end ifset
@manpause
@c **********************************************************
@c **************** Environment Variables *****************
@c **********************************************************
@node Configuration
@chapter Configuration files and environment variables
This chapter describes which files and environment variables can be
used to change the behaviour of Libgcrypt.
@noindent
The environment variables considered by Libgcrypt are:
@table @code
@item GCRYPT_BARRETT
@cindex GCRYPT_BARRETT
By setting this variable to any value a different algorithm for
modular reduction is used for ECC.
@item GCRYPT_RNDUNIX_DBG
@item GCRYPT_RNDUNIX_DBGALL
@cindex GCRYPT_RNDUNIX_DBG
@cindex 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 @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.
@item GCRYPT_RNDW32_NOPERF
@cindex GCRYPT_RNDW32_NOPERF
Setting this environment variable on Windows to any value disables
the use of performance data (@code{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.
@item GCRYPT_RNDW32_DBG
@cindex 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.
@item HOME
@cindex 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.
@end table
@noindent
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:
@table @file
@item /etc/gcrypt/hwf.deny
@cindex /etc/gcrypt/hwf.deny
This file can be used to disable the use of hardware based
optimizations, @pxref{hardware features}.
@item /etc/gcrypt/random.conf
@cindex /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
@table @file
@item disable-jent
@cindex disable-jent
Disable the use of the jitter based entropy generator.
@item only-urandom
@cindex 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.
@end table
@item /etc/gcrypt/fips_enabled
@itemx /proc/sys/crypto/fips_enabled
@cindex /etc/gcrypt/fips_enabled
@cindex fips_enabled
On Linux these files are used to enable FIPS mode, @pxref{enabling fips mode}.
@item /proc/cpuinfo
@itemx /proc/self/auxv
@cindex /proc/cpuinfo
@cindex /proc/self/auxv
On Linux running on the ARM architecture, these files are used to read
hardware capabilities of the CPU.
@end table
@c **********************************************************
@c ***************** Architecure Overview *****************
@c **********************************************************
@node Architecture
@chapter 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 @code{./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
(@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
@file{INSTALL} and @file{README} in the source distribution on how to do
this.
Libgcrypt is developed using a Subversion@footnote{A version control
system available for many platforms} 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 @indicateurl{ftp://ftp.gnupg.org/gcrypt/libgcrypt/}.
Announcements of new releases are posted to the
@indicateurl{gnupg-announce@@gnupg.org} mailing list@footnote{See
-@url{http://www.gnupg.org/documentation/mailing-lists.en.html} for
+@url{https://www.gnupg.org/documentation/mailing-lists.en.html} for
details.}.
@float Figure,fig:subsystems
@caption{Libgcrypt subsystems}
@center @image{libgcrypt-modules, 150mm,,Libgcrypt subsystems}
@end float
Libgcrypt consists of several subsystems (@pxref{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.
@c * Helper Subsystems Architecture:: About other stuff.
@end menu
@node Public-Key Subsystem Architecture
@section 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.
@c see @ref{S-expression Subsystem Architecture}.
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:
@table @code
@item gcry_pk_encrypt
Encrypt data using a public key.
@item gcry_pk_decrypt
Decrypt data using a private key.
@item gcry_pk_sign
Sign data using a private key.
@item gcry_pk_verify
Verify that a signature matches the data.
@item gcry_pk_testkey
Perform a consistency over a public or private key.
@item gcry_pk_genkey
Create a new public/private key pair.
@end table
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 (@file{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 @math{y = x r^{e} \bmod n}
is decrypted and the unblinded value @math{x' = y' r^{-1} \bmod n}
returned. The blinding value @math{r} is a random value with the size
of the modulus @math{n} and generated with @code{GCRY_WEAK_RANDOM}
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
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.
@node Symmetric Encryption Subsystem Architecture
@section Symmetric Encryption Subsystem Architecture
The interface to work with symmetric encryption algorithms is made up
of functions from the @code{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
(@file{cipher/cipher.c}) implements the modes and calls the core
algorithm functions to process each block.
The most important functions are:
@table @code
@item gcry_cipher_open
Create a new instance to encrypt or decrypt using a specified
algorithm and mode.
@item gcry_cipher_close
Release an instance.
@item gcry_cipher_setkey
Set a key to be used for encryption or decryption.
@item gcry_cipher_setiv
Set an initialization vector to be used for encryption or decryption.
@item gcry_cipher_encrypt
@itemx 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 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,
like block length, key length, map names or to enable features like
padding methods.
@node Hashing and MACing Subsystem Architecture
@section Hashing and MACing Subsystem Architecture
The interface to work with message digests and CRC algorithms is made
up of functions from the @code{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:
@table @code
@item 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.
@item gcry_md_enable
Enable an additional algorithm for the instance.
@item gcry_md_setkey
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.
@item gcry_md_read
Finalize the computation of the message digest or HMAC and return the
result.
@item gcry_md_close
Release an instance
@item gcry_md_hash_buffer
Convenience function to directly compute a message digest over a
memory buffer without the need to create an instance first.
@end table
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.
@node Multi-Precision-Integer Subsystem Architecture
@section 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.
@noindent
Major features of Libgcrypt's multi-precision-integer code compared to
GMP are:
@itemize
@item
Avoidance of stack based allocations to allow protection against
swapping out of sensitive data and for easy zeroing of sensitive
intermediate results.
@item
Optional use of secure memory and tracking of its use so that results
are also put into secure memory.
@item
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.
@item
Removal of unnecessary code to reduce complexity.
@item
Functions specialized for public key cryptography.
@end itemize
@node Prime-Number-Generator Subsystem Architecture
@section 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.@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 /
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
+ 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 @code{save_pool_prime} and
@code{get_pool_prime} in @file{cipher/primegen.c}). The prime
generator optionally supports the finding of an appropriate generator.
@noindent
The primality test works in three steps:
@enumerate
@item
The standard sieve algorithm using the primes up to 4999 is used as a
quick first check.
@item
A Fermat test filters out almost all non-primes.
@item
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.
@end enumerate
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: @code{_gcry_derive_x931_prime} and
@code{_gcry_generate_fips186_2_prime}. These functions are internal
and not available through the public API.
@node Random-Number Subsystem Architecture
@section Random-Number Subsystem Architecture
Libgcrypt provides 3 levels or random quality: The level
@code{GCRY_VERY_STRONG_RANDOM} usually used for key generation, the
level @code{GCRY_STRONG_RANDOM} for all other strong random
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.
@noindent
There are two distinct random generators available:
@itemize
@item
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.
@end itemize
@noindent
Both generators make use of so-called entropy gathering modules:
@table @asis
@item rndlinux
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
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
FIPS mode.
@item 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.
@item rndw32
Targeted for the Microsoft Windows OS. It uses certain properties of
that system and is the only gathering module available for that OS.
@item 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.
@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
@option{disable-jent} can be used to inhibit the use of this module.
@end table
@menu
* CSPRNG Description:: Description of the CSPRNG.
* FIPS PRNG Description:: Description of the FIPS X9.31 PRNG.
@end menu
@node CSPRNG Description
@subsection 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".@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
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.
@c FIXME: The design and implementation needs a more verbose description.
The implementation of the nonce generator (for
@code{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 @code{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.
@node FIPS PRNG Description
@subsection 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 @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
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 @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.
@c @node Helper Subsystems Architecture
@c @section Helper Subsystems Architecture
@c
@c There are a few smaller subsystems which are mainly used internally by
@c Libgcrypt but also available to applications.
@c
@c @menu
@c * S-expression Subsystem Architecture:: Details about the S-expression architecture.
@c * Memory Subsystem Architecture:: Details about the memory allocation architecture.
@c * Miscellaneous Subsystems Architecture:: Details about other subsystems.
@c @end menu
@c
@c @node S-expression Subsystem Architecture
@c @subsection S-expression Subsystem Architecture
@c
@c Libgcrypt provides an interface to S-expression to create and parse
@c them. To use an S-expression with Libgcrypt it needs first be
@c converted into the internal representation used by Libgcrypt (the type
@c @code{gcry_sexp_t}). The conversion functions support a large subset
@c of the S-expression specification and further feature a printf like
@c function to convert a list of big integers or other binary data into
@c an S-expression.
@c
@c Libgcrypt currently implements S-expressions using a tagged linked
@c list. However this is not exposed to an application and may be
@c changed in future releases to reduce overhead when already working
@c with canonically encoded S-expressions. Secure memory is supported by
@c this S-expressions implementation.
@c
@c @node Memory Subsystem Architecture
@c @subsection Memory Subsystem Architecture
@c
@c TBD.
@c
@c
@c @node Miscellaneous Subsystems Architecture
@c @subsection Miscellaneous Subsystems Architecture
@c
@c TBD.
@c
@c
@c **********************************************************
@c ******************* Appendices *************************
@c **********************************************************
@c ********************************************
@node Self-Tests
@appendix 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 @code{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.
@c --------------------------------
@section Power-Up Tests
Power-up tests are only performed if Libgcrypt is in FIPS mode.
@subsection Symmetric Cipher Algorithm Power-Up Tests
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})
@item AES-192
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_192})
@item AES-256
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_256})
@end table
@subsection Hash Algorithm Power-Up Tests
The following hash algorithm tests are run during power-up:
@table @asis
@item SHA-1
A known answer test using the string @code{"abc"} is run.
(@code{cipher/@/sha1.c:@/selftests_sha1})
@item SHA-224
A known answer test using the string @code{"abc"} is run.
(@code{cipher/@/sha256.c:@/selftests_sha224})
@item SHA-256
A known answer test using the string @code{"abc"} is run.
(@code{cipher/@/sha256.c:@/selftests_sha256})
@item SHA-384
A known answer test using the string @code{"abc"} is run.
(@code{cipher/@/sha512.c:@/selftests_sha384})
@item SHA-512
A known answer test using the string @code{"abc"} is run.
(@code{cipher/@/sha512.c:@/selftests_sha512})
@end table
@subsection MAC Algorithm Power-Up Tests
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})
@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})
@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})
@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})
@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})
@end table
@subsection Random Number Power-Up Test
The DRNG is tested during power-up this way:
@enumerate
@item
Requesting one block of random using the public interface to check
general working and the duplicated block detection.
@item
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.
@end enumerate
@subsection Public Key Algorithm Power-Up Tests
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
in turn:
@enumerate
@item
Conversion of S-expression to internal format.
(@code{cipher/@/rsa.c:@/selftests_rsa})
@item
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.
The result is verified using the public key against the original data
and against modified data. (@code{cipher/@/rsa.c:@/selftest_sign_1024})
@item
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.
(@code{cipher/@/rsa.c:@/selftest_encr_1024})
@end enumerate
@item DSA
A pre-defined 1024 bit DSA 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})
@item
Private key consistency check.
(@code{cipher/@/dsa.c:@/selftests_dsa})
@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})
@end enumerate
@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})
@c --------------------------------
@section 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.
@subsection 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.
@table @asis
@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
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.
(@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
@subsection Software Load Tests
No code is loaded at runtime.
@subsection Manual Key Entry Tests
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
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.
@subsection Symmetric Cipher Algorithm Tests
The following symmetric encryption algorithm tests are run in addition
to the power-up tests:
@table @asis
@item 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.
@end table
@subsection Hash Algorithm Tests
The following hash algorithm tests are run in addition to the
power-up tests:
@table @asis
@item SHA-1
@itemx SHA-224
@itemx SHA-256
@enumerate
@item
A known answer test using a 56 byte string is run.
@item
A known answer test using a string of one million letters "a" is run.
@end enumerate
(@code{cipher/@/sha1.c:@/selftests_sha1},
@code{cipher/@/sha256.c:@/selftests_sha224},
@code{cipher/@/sha256.c:@/selftests_sha256})
@item SHA-384
@item SHA-512
@enumerate
@item
A known answer test using a 112 byte string is run.
@item
A known answer test using a string of one million letters "a" is run.
@end enumerate
(@code{cipher/@/sha512.c:@/selftests_sha384},
@code{cipher/@/sha512.c:@/selftests_sha512})
@end table
@subsection MAC Algorithm Tests
The following MAC algorithm tests are run in addition to the power-up
tests:
@table @asis
@item HMAC SHA-1
@enumerate
@item
A known answer test using 9 byte 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.
@item
A known answer test using 9 byte of data and a 49 byte key is run.
@end enumerate
(@code{cipher/hmac-tests.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.
@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.
@item
A known answer test using 54 byte of data and a 131 byte key is run.
@item
A known answer test using 152 byte of data and a 131 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})
@end table
@c ********************************************
@node FIPS Mode
@appendix 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.
@c -------------------------------
@section Restrictions in FIPS Mode
@noindent
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
AES 192 bit symmetric encryption.
@item GCRY_CIPHER_AES256
AES 256 bit symmetric encryption.
@item GCRY_MD_SHA1
SHA-1 message digest.
@item GCRY_MD_SHA224
SHA-224 message digest.
@item GCRY_MD_SHA256
SHA-256 message digest.
@item GCRY_MD_SHA384
SHA-384 message digest.
@item GCRY_MD_SHA512
SHA-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
HMAC using a SHA-224 message digest.
@item GCRY_MD_SHA256,GCRY_MD_FLAG_HMAC
HMAC using a SHA-256 message digest.
@item GCRY_MD_SHA384,GCRY_MD_FLAG_HMAC
HMAC using a SHA-384 message digest.
@item GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC
HMAC using a SHA-512 message digest.
@item GCRY_PK_RSA
RSA encryption and signing.
@item GCRY_PK_DSA
DSA 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.
@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.
@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.
@item
Saving and loading a random seed file is ignored.
@item
An X9.31 style random number generator is used in place of the
large-pool-CSPRNG generator.
@item
The command @code{GCRYCTL_ENABLE_QUICK_RANDOM} is ignored.
@item
Message digest debugging is disabled.
@item
All debug output related to cryptographic data is suppressed.
@item
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.
@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.
@item
In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is
ignored. In standard FIPS mode it disables FIPS mode.
@item
A handler set by @code{gcry_set_outofcore_handler} is ignored.
@item
A handler set by @code{gcry_set_fatalerror_handler} is ignored.
@end itemize
Note that when we speak about disabling FIPS mode, it merely means
that the function @code{gcry_fips_mode_active} returns false; it does
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
8 states (@pxref{tbl:fips-states}) and checks at runtime that only valid
transitions (@pxref{tbl:fips-state-transitions}) may happen.
@float Figure,fig:fips-fsm
@caption{FIPS mode state diagram}
@center @image{fips-fsm,150mm,,FIPS FSM Diagram}
@end float
@float Table,tbl:fips-states
@caption{FIPS mode states}
@noindent
States used by the FIPS FSM:
@table @asis
@item 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.
@item 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
@item Init
The Libgcrypt initialization functions are performed and the library has
not yet run any self-test.
@item Self-Test
Libgcrypt is performing self-tests.
@item Operational
Libgcrypt is in the operational state and all interfaces may be used.
@item Error
Libgrypt is in the error state. When calling any FIPS relevant
interfaces they either return an error (@code{GPG_ERR_NOT_OPERATIONAL})
or put Libgcrypt into the Fatal-Error state and won't return.
@item Fatal-Error
Libgcrypt is in a non-recoverable error state and
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.
@end table
@end float
@float Table,tbl:fips-state-transitions
@caption{FIPS mode state transitions}
@noindent
The valid state transitions (@pxref{fig:fips-fsm}) are:
@table @code
@item 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.
@item 2
Power-On to Init is triggered by the application calling the
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.
@item 4
Self-Test to Operational is triggered after all self-tests passed
successfully.
@item 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.
@item 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.
@item 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.
@item 8
Error to Shutdown is similar to the Operational to Shutdown transition
(5).
@item 9
Error to Fatal-Error is triggered if Libgrypt detects an fatal error
while already being in Error state.
@item 10
Fatal-Error to Shutdown is automatically entered by Libgcrypt
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.
@item 12
Power-On to Fatal-Error will be triggered if certain Libgcrypt functions
are used without having reached the Init state.
@item 13
Self-Test to Fatal-Error is triggered by severe errors in Libgcrypt while
running self-tests.
@item 14
Self-Test to Error is triggered by a failed self-test.
@item 15
Operational to Fatal-Error is triggered if Libcrypt encountered a
non-recoverable error.
@item 16
Operational to Self-Test is triggered if the application requested to run
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.
@item 18
Init to Error is triggered by errors in the initialization code.
@item 19
Init to Fatal-Error is triggered by non-recoverable errors in the
initialization code.
@item 20
Error to Error is triggered by errors while already in the Error
state.
@end table
@end float
@c ********************************************
@section 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
@code{gcry_malloc_secure} and @code{gcry_calloc_secure}. By calling
@code{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 @code{GCRYCTL_TERM_SECMEM}
before process termination. This will zero out the entire secure
memory and thus also the encryption contexts with these keys.
@c **********************************************************
@c ************* Appendices (license etc.) ****************
@c **********************************************************
@include lgpl.texi
@include gpl.texi
@node Figures and Tables
@unnumbered List of Figures and Tables
@listoffloats Figure
@listoffloats Table
@node Concept Index
@unnumbered Concept Index
@printindex cp
@node Function and Data Index
@unnumbered Function and Data Index
@printindex fn
@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/libgcrypt.txt b/libgcrypt.txt
index afce70db..57218078 100644
--- a/libgcrypt.txt
+++ b/libgcrypt.txt
@@ -1,118 +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
+%%web-page: https://www.gnupg.org
-%%support: Paid extension/consulting from http://www.g10code.com
+%%support: Paid extension/consulting from https://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
+%%repository: See https://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
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 1d62b058..0cd84afb 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -1,8027 +1,8027 @@
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
# 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 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.
m4_define([_LT_COPYING], [dnl
# 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
+# 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.
])
# serial 57 LT_INIT
# LT_PREREQ(VERSION)
# ------------------
# Complain and exit if this libtool version is less that VERSION.
m4_defun([LT_PREREQ],
[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
[m4_default([$3],
[m4_fatal([Libtool version $1 or higher is required],
63)])],
[$2])])
# _LT_CHECK_BUILDDIR
# ------------------
# Complain if the absolute build directory name contains unusual characters
m4_defun([_LT_CHECK_BUILDDIR],
[case `pwd` in
*\ * | *\ *)
AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
esac
])
# LT_INIT([OPTIONS])
# ------------------
AC_DEFUN([LT_INIT],
[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
AC_BEFORE([$0], [LT_LANG])dnl
AC_BEFORE([$0], [LT_OUTPUT])dnl
AC_BEFORE([$0], [LTDL_INIT])dnl
m4_require([_LT_CHECK_BUILDDIR])dnl
dnl Autoconf doesn't catch unexpanded LT_ macros by default:
m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
dnl unless we require an AC_DEFUNed macro:
AC_REQUIRE([LTOPTIONS_VERSION])dnl
AC_REQUIRE([LTSUGAR_VERSION])dnl
AC_REQUIRE([LTVERSION_VERSION])dnl
AC_REQUIRE([LTOBSOLETE_VERSION])dnl
m4_require([_LT_PROG_LTMAIN])dnl
_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
dnl Parse OPTIONS
_LT_SET_OPTIONS([$0], [$1])
# This can be used to rebuild libtool when needed
LIBTOOL_DEPS="$ltmain"
# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
AC_SUBST(LIBTOOL)dnl
_LT_SETUP
# Only expand once:
m4_define([LT_INIT])
])# LT_INIT
# Old names:
AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
# _LT_CC_BASENAME(CC)
# -------------------
# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
m4_defun([_LT_CC_BASENAME],
[for cc_temp in $1""; 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_FILEUTILS_DEFAULTS
# ----------------------
# It is okay to use these file commands and assume they have been set
# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
m4_defun([_LT_FILEUTILS_DEFAULTS],
[: ${CP="cp -f"}
: ${MV="mv -f"}
: ${RM="rm -f"}
])# _LT_FILEUTILS_DEFAULTS
# _LT_SETUP
# ---------
m4_defun([_LT_SETUP],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
dnl
_LT_DECL([], [host_alias], [0], [The host system])dnl
_LT_DECL([], [host], [0])dnl
_LT_DECL([], [host_os], [0])dnl
dnl
_LT_DECL([], [build_alias], [0], [The build system])dnl
_LT_DECL([], [build], [0])dnl
_LT_DECL([], [build_os], [0])dnl
dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
test -z "$LN_S" && LN_S="ln -s"
_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
dnl
AC_REQUIRE([LT_CMD_MAX_LEN])dnl
_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_WITH_SYSROOT])dnl
_LT_CONFIG_LIBTOOL_INIT([
# 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
])
if test -n "${ZSH_VERSION+set}" ; then
setopt NO_GLOB_SUBST
fi
_LT_CHECK_OBJDIR
m4_require([_LT_TAG_COMPILER])dnl
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
_LT_CC_BASENAME([$compiler])
# 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
_LT_PATH_MAGIC
fi
;;
esac
# Use C for the default configuration in the libtool script
LT_SUPPORTED_TAG([CC])
_LT_LANG_C_CONFIG
_LT_LANG_DEFAULT_CONFIG
_LT_CONFIG_COMMANDS
])# _LT_SETUP
# _LT_PREPARE_SED_QUOTE_VARS
# --------------------------
# Define a few sed substitution that help us do robust quoting.
m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
[# 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'
])
# _LT_PROG_LTMAIN
# ---------------
# Note that this code is called both from `configure', and `config.status'
# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
# `config.status' has no value for ac_aux_dir unless we are using Automake,
# so we pass a copy along to make sure it has a sensible value anyway.
m4_defun([_LT_PROG_LTMAIN],
[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
ltmain="$ac_aux_dir/ltmain.sh"
])# _LT_PROG_LTMAIN
## ------------------------------------- ##
## Accumulate code for creating libtool. ##
## ------------------------------------- ##
# So that we can recreate a full libtool script including additional
# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
# in macros and then make a single call at the end using the `libtool'
# label.
# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
# ----------------------------------------
# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL_INIT],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_INIT],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_INIT])
# _LT_CONFIG_LIBTOOL([COMMANDS])
# ------------------------------
# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
# -----------------------------------------------------
m4_defun([_LT_CONFIG_SAVE_COMMANDS],
[_LT_CONFIG_LIBTOOL([$1])
_LT_CONFIG_LIBTOOL_INIT([$2])
])
# _LT_FORMAT_COMMENT([COMMENT])
# -----------------------------
# Add leading comment marks to the start of each line, and a trailing
# full-stop to the whole comment if one is not present already.
m4_define([_LT_FORMAT_COMMENT],
[m4_ifval([$1], [
m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
[['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
)])
## ------------------------ ##
## FIXME: Eliminate VARNAME ##
## ------------------------ ##
# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
# -------------------------------------------------------------------
# CONFIGNAME is the name given to the value in the libtool script.
# VARNAME is the (base) name used in the configure script.
# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
# VARNAME. Any other value will be used directly.
m4_define([_LT_DECL],
[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
[lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
[m4_ifval([$1], [$1], [$2])])
lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
m4_ifval([$4],
[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
lt_dict_add_subkey([lt_decl_dict], [$2],
[tagged?], [m4_ifval([$5], [yes], [no])])])
])
# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
# --------------------------------------------------------
m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_tag_varnames],
[_lt_decl_filter([tagged?], [yes], $@)])
# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
# ---------------------------------------------------------
m4_define([_lt_decl_filter],
[m4_case([$#],
[0], [m4_fatal([$0: too few arguments: $#])],
[1], [m4_fatal([$0: too few arguments: $#: $1])],
[2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
[3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
[lt_dict_filter([lt_decl_dict], $@)])[]dnl
])
# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
# --------------------------------------------------
m4_define([lt_decl_quote_varnames],
[_lt_decl_filter([value], [1], $@)])
# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_dquote_varnames],
[_lt_decl_filter([value], [2], $@)])
# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_varnames_tagged],
[m4_assert([$# <= 2])dnl
_$0(m4_quote(m4_default([$1], [[, ]])),
m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
m4_define([_lt_decl_varnames_tagged],
[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_all_varnames],
[_$0(m4_quote(m4_default([$1], [[, ]])),
m4_if([$2], [],
m4_quote(lt_decl_varnames),
m4_quote(m4_shift($@))))[]dnl
])
m4_define([_lt_decl_all_varnames],
[lt_join($@, lt_decl_varnames_tagged([$1],
lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
])
# _LT_CONFIG_STATUS_DECLARE([VARNAME])
# ------------------------------------
# Quote a variable value, and forward it to `config.status' so that its
# declaration there will have the same value as in `configure'. VARNAME
# must have a single quote delimited value for this to work.
m4_define([_LT_CONFIG_STATUS_DECLARE],
[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
# _LT_CONFIG_STATUS_DECLARATIONS
# ------------------------------
# We delimit libtool config variables with single quotes, so when
# we write them to config.status, we have to be sure to quote all
# embedded single quotes properly. In configure, this macro expands
# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
#
# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
[m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAGS
# ----------------
# Output comment and list of tags supported by the script
m4_defun([_LT_LIBTOOL_TAGS],
[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
available_tags="_LT_TAGS"dnl
])
# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
# -----------------------------------
# Extract the dictionary values for VARNAME (optionally with TAG) and
# expand to a commented shell variable setting:
#
# # Some comment about what VAR is for.
# visible_name=$lt_internal_name
m4_define([_LT_LIBTOOL_DECLARE],
[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
[description])))[]dnl
m4_pushdef([_libtool_name],
m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
[0], [_libtool_name=[$]$1],
[1], [_libtool_name=$lt_[]$1],
[2], [_libtool_name=$lt_[]$1],
[_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
])
# _LT_LIBTOOL_CONFIG_VARS
# -----------------------
# Produce commented declarations of non-tagged libtool config variables
# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
# section) are produced by _LT_LIBTOOL_TAG_VARS.
m4_defun([_LT_LIBTOOL_CONFIG_VARS],
[m4_foreach([_lt_var],
m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAG_VARS(TAG)
# -------------------------
m4_define([_LT_LIBTOOL_TAG_VARS],
[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
# _LT_TAGVAR(VARNAME, [TAGNAME])
# ------------------------------
m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
# _LT_CONFIG_COMMANDS
# -------------------
# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
# variables for single and double quote escaping we saved from calls
# to _LT_DECL, we can put quote escaped variables declarations
# into `config.status', and then the shell code to quote escape them in
# for loops in `config.status'. Finally, any additional code accumulated
# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
m4_defun([_LT_CONFIG_COMMANDS],
[AC_PROVIDE_IFELSE([LT_OUTPUT],
dnl If the libtool generation code has been placed in $CONFIG_LT,
dnl instead of duplicating it all over again into config.status,
dnl then we will have config.status run $CONFIG_LT later, so it
dnl needs to know what name is stored there:
[AC_CONFIG_COMMANDS([libtool],
[$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
dnl If the libtool generation code is destined for config.status,
dnl expand the accumulated commands and init code now:
[AC_CONFIG_COMMANDS([libtool],
[_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
])#_LT_CONFIG_COMMANDS
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
[
# 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'
_LT_CONFIG_STATUS_DECLARATIONS
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 lt_decl_all_varnames([[ \
]], lt_decl_quote_varnames); 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 lt_decl_all_varnames([[ \
]], lt_decl_dquote_varnames); 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
_LT_OUTPUT_LIBTOOL_INIT
])
# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
# ------------------------------------
# Generate a child script FILE with all initialization necessary to
# reuse the environment learned by the parent script, and make the
# file executable. If COMMENT is supplied, it is inserted after the
# `#!' sequence but before initialization text begins. After this
# macro, additional text can be appended to FILE to form the body of
# the child script. The macro ends with non-zero status if the
# file could not be fully written (such as if the disk is full).
m4_ifdef([AS_INIT_GENERATED],
[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
[m4_defun([_LT_GENERATED_FILE_INIT],
[m4_require([AS_PREPARE])]dnl
[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
[lt_write_fail=0
cat >$1 <<_ASEOF || lt_write_fail=1
#! $SHELL
# Generated by $as_me.
$2
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$1 <<\_ASEOF || lt_write_fail=1
AS_SHELL_SANITIZE
_AS_PREPARE
exec AS_MESSAGE_FD>&1
_ASEOF
test $lt_write_fail = 0 && chmod +x $1[]dnl
m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
# LT_OUTPUT
# ---------
# This macro allows early generation of the libtool script (before
# AC_OUTPUT is called), incase it is used in configure for compilation
# tests.
AC_DEFUN([LT_OUTPUT],
[: ${CONFIG_LT=./config.lt}
AC_MSG_NOTICE([creating $CONFIG_LT])
_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
[# Run this file to recreate a libtool stub with the current configuration.])
cat >>"$CONFIG_LT" <<\_LTEOF
lt_cl_silent=false
exec AS_MESSAGE_LOG_FD>>config.log
{
echo
AS_BOX([Running $as_me.])
} >&AS_MESSAGE_LOG_FD
lt_cl_help="\
\`$as_me' creates a local libtool stub from the current configuration,
for use in further configure time tests before the real libtool is
generated.
Usage: $[0] [[OPTIONS]]
-h, --help print this help, then exit
-V, --version print version number, then exit
-q, --quiet do not print progress messages
-d, --debug don't remove temporary files
Report bugs to <bug-libtool@gnu.org>."
lt_cl_version="\
m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
configured by $[0], generated by m4_PACKAGE_STRING.
Copyright (C) 2011 Free Software Foundation, Inc.
This config.lt script is free software; the Free Software Foundation
gives unlimited permision to copy, distribute and modify it."
while test $[#] != 0
do
case $[1] in
--version | --v* | -V )
echo "$lt_cl_version"; exit 0 ;;
--help | --h* | -h )
echo "$lt_cl_help"; exit 0 ;;
--debug | --d* | -d )
debug=: ;;
--quiet | --q* | --silent | --s* | -q )
lt_cl_silent=: ;;
-*) AC_MSG_ERROR([unrecognized option: $[1]
Try \`$[0] --help' for more information.]) ;;
*) AC_MSG_ERROR([unrecognized argument: $[1]
Try \`$[0] --help' for more information.]) ;;
esac
shift
done
if $lt_cl_silent; then
exec AS_MESSAGE_FD>/dev/null
fi
_LTEOF
cat >>"$CONFIG_LT" <<_LTEOF
_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
_LTEOF
cat >>"$CONFIG_LT" <<\_LTEOF
AC_MSG_NOTICE([creating $ofile])
_LT_OUTPUT_LIBTOOL_COMMANDS
AS_EXIT(0)
_LTEOF
chmod +x "$CONFIG_LT"
# configure is writing to config.log, but config.lt does its own redirection,
# appending to config.log, which fails on DOS, as config.log is still kept
# open by configure. Here we exec the FD to /dev/null, effectively closing
# config.log, so it can be properly (re)opened and appended to by config.lt.
lt_cl_success=:
test "$silent" = yes &&
lt_config_lt_args="$lt_config_lt_args --quiet"
exec AS_MESSAGE_LOG_FD>/dev/null
$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
exec AS_MESSAGE_LOG_FD>>config.log
$lt_cl_success || AS_EXIT(1)
])# LT_OUTPUT
# _LT_CONFIG(TAG)
# ---------------
# If TAG is the built-in tag, create an initial libtool script with a
# default configuration from the untagged config vars. Otherwise add code
# to config.status for appending the configuration named by TAG from the
# matching tagged config vars.
m4_defun([_LT_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_CONFIG_SAVE_COMMANDS([
m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
m4_if(_LT_TAG, [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.
#
_LT_COPYING
_LT_LIBTOOL_TAGS
# ### BEGIN LIBTOOL CONFIG
_LT_LIBTOOL_CONFIG_VARS
_LT_LIBTOOL_TAG_VARS
# ### 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
_LT_PROG_LTMAIN
# 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)
_LT_PROG_REPLACE_SHELLFNS
mv -f "$cfgfile" "$ofile" ||
(rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
chmod +x "$ofile"
],
[cat <<_LT_EOF >> "$ofile"
dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
dnl in a comment (ie after a #).
# ### BEGIN LIBTOOL TAG CONFIG: $1
_LT_LIBTOOL_TAG_VARS(_LT_TAG)
# ### END LIBTOOL TAG CONFIG: $1
_LT_EOF
])dnl /m4_if
],
[m4_if([$1], [], [
PACKAGE='$PACKAGE'
VERSION='$VERSION'
TIMESTAMP='$TIMESTAMP'
RM='$RM'
ofile='$ofile'], [])
])dnl /_LT_CONFIG_SAVE_COMMANDS
])# _LT_CONFIG
# LT_SUPPORTED_TAG(TAG)
# ---------------------
# Trace this macro to discover what tags are supported by the libtool
# --tag option, using:
# autoconf --trace 'LT_SUPPORTED_TAG:$1'
AC_DEFUN([LT_SUPPORTED_TAG], [])
# C support is built-in for now
m4_define([_LT_LANG_C_enabled], [])
m4_define([_LT_TAGS], [])
# LT_LANG(LANG)
# -------------
# Enable libtool support for the given language if not already enabled.
AC_DEFUN([LT_LANG],
[AC_BEFORE([$0], [LT_OUTPUT])dnl
m4_case([$1],
[C], [_LT_LANG(C)],
[C++], [_LT_LANG(CXX)],
[Go], [_LT_LANG(GO)],
[Java], [_LT_LANG(GCJ)],
[Fortran 77], [_LT_LANG(F77)],
[Fortran], [_LT_LANG(FC)],
[Windows Resource], [_LT_LANG(RC)],
[m4_ifdef([_LT_LANG_]$1[_CONFIG],
[_LT_LANG($1)],
[m4_fatal([$0: unsupported language: "$1"])])])dnl
])# LT_LANG
# _LT_LANG(LANGNAME)
# ------------------
m4_defun([_LT_LANG],
[m4_ifdef([_LT_LANG_]$1[_enabled], [],
[LT_SUPPORTED_TAG([$1])dnl
m4_append([_LT_TAGS], [$1 ])dnl
m4_define([_LT_LANG_]$1[_enabled], [])dnl
_LT_LANG_$1_CONFIG($1)])dnl
])# _LT_LANG
m4_ifndef([AC_PROG_GO], [
############################################################
# NOTE: This macro has been submitted for inclusion into #
# GNU Autoconf as AC_PROG_GO. When it is available in #
# a released version of Autoconf we should remove this #
# macro and use it instead. #
############################################################
m4_defun([AC_PROG_GO],
[AC_LANG_PUSH(Go)dnl
AC_ARG_VAR([GOC], [Go compiler command])dnl
AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
_AC_ARG_VAR_LDFLAGS()dnl
AC_CHECK_TOOL(GOC, gccgo)
if test -z "$GOC"; then
if test -n "$ac_tool_prefix"; then
AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
fi
fi
if test -z "$GOC"; then
AC_CHECK_PROG(GOC, gccgo, gccgo, false)
fi
])#m4_defun
])#m4_ifndef
# _LT_LANG_DEFAULT_CONFIG
# -----------------------
m4_defun([_LT_LANG_DEFAULT_CONFIG],
[AC_PROVIDE_IFELSE([AC_PROG_CXX],
[LT_LANG(CXX)],
[m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
AC_PROVIDE_IFELSE([AC_PROG_F77],
[LT_LANG(F77)],
[m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
AC_PROVIDE_IFELSE([AC_PROG_FC],
[LT_LANG(FC)],
[m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
dnl pulling things in needlessly.
AC_PROVIDE_IFELSE([AC_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([LT_PROG_GCJ],
[LT_LANG(GCJ)],
[m4_ifdef([AC_PROG_GCJ],
[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([A][M_PROG_GCJ],
[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([LT_PROG_GCJ],
[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
AC_PROVIDE_IFELSE([AC_PROG_GO],
[LT_LANG(GO)],
[m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
AC_PROVIDE_IFELSE([LT_PROG_RC],
[LT_LANG(RC)],
[m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
])# _LT_LANG_DEFAULT_CONFIG
# Obsolete macros:
AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
dnl AC_DEFUN([AC_LIBTOOL_F77], [])
dnl AC_DEFUN([AC_LIBTOOL_FC], [])
dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
dnl AC_DEFUN([AC_LIBTOOL_RC], [])
# _LT_TAG_COMPILER
# ----------------
m4_defun([_LT_TAG_COMPILER],
[AC_REQUIRE([AC_PROG_CC])dnl
_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
# 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
])# _LT_TAG_COMPILER
# _LT_COMPILER_BOILERPLATE
# ------------------------
# Check for compiler boilerplate output or warnings with
# the simple compiler test code.
m4_defun([_LT_COMPILER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
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*
])# _LT_COMPILER_BOILERPLATE
# _LT_LINKER_BOILERPLATE
# ----------------------
# Check for linker boilerplate output or warnings with
# the simple link test code.
m4_defun([_LT_LINKER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
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*
])# _LT_LINKER_BOILERPLATE
# _LT_REQUIRED_DARWIN_CHECKS
# -------------------------
m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
case $host_os in
rhapsody* | darwin*)
AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
AC_CHECK_TOOL([LIPO], [lipo], [:])
AC_CHECK_TOOL([OTOOL], [otool], [:])
AC_CHECK_TOOL([OTOOL64], [otool64], [:])
_LT_DECL([], [DSYMUTIL], [1],
[Tool to manipulate archived DWARF debug symbol files on Mac OS X])
_LT_DECL([], [NMEDIT], [1],
[Tool to change global to local symbols on Mac OS X])
_LT_DECL([], [LIPO], [1],
[Tool to manipulate fat objects and archives on Mac OS X])
_LT_DECL([], [OTOOL], [1],
[ldd/readelf like tool for Mach-O binaries on Mac OS X])
_LT_DECL([], [OTOOL64], [1],
[ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
[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" >&AS_MESSAGE_LOG_FD
$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 >&AS_MESSAGE_LOG_FD
# 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 >&AS_MESSAGE_LOG_FD
fi
rm -rf libconftest.dylib*
rm -f conftest.*
fi])
AC_CACHE_CHECK([for -exported_symbols_list linker flag],
[lt_cv_ld_exported_symbols_list],
[lt_cv_ld_exported_symbols_list=no
save_LDFLAGS=$LDFLAGS
echo "_main" > conftest.sym
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[lt_cv_ld_exported_symbols_list=yes],
[lt_cv_ld_exported_symbols_list=no])
LDFLAGS="$save_LDFLAGS"
])
AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
[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" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
int main() { return 0;}
_LT_EOF
echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
$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 >&AS_MESSAGE_LOG_FD
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 >&AS_MESSAGE_LOG_FD
fi
rm -f conftest.err libconftest.a conftest conftest.c
rm -rf conftest.dSYM
])
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
])
# _LT_DARWIN_LINKER_FEATURES([TAG])
# ---------------------------------
# Checks for linker and compiler features on darwin
m4_defun([_LT_DARWIN_LINKER_FEATURES],
[
m4_require([_LT_REQUIRED_DARWIN_CHECKS])
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
if test "$lt_cv_ld_force_load" = "yes"; then
_LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
[FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=''
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)="$_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
_LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
_LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
_LT_TAGVAR(archive_expsym_cmds, $1)="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}"
_LT_TAGVAR(module_expsym_cmds, $1)="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}"
m4_if([$1], [CXX],
[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
fi
],[])
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
])
# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
# ----------------------------------
# Links a minimal program and checks the executable
# for the system default hardcoded library path. In most cases,
# this is /usr/lib:/lib, but when the MPI compilers are used
# the location of the communication and MPI libs are included too.
# If we don't find anything, use the default library path according
# to the aix ld manual.
# Store the results from the different compilers for each TAGNAME.
# Allow to override them for all tags through lt_cv_aix_libpath.
m4_defun([_LT_SYS_MODULE_PATH_AIX],
[m4_require([_LT_DECL_SED])dnl
if test "${lt_cv_aix_libpath+set}" = set; then
aix_libpath=$lt_cv_aix_libpath
else
AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
[AC_LINK_IFELSE([AC_LANG_PROGRAM],[
lt_aix_libpath_sed='[
/Import File Strings/,/^$/ {
/^0/ {
s/^0 *\([^ ]*\) *$/\1/
p
}
}]'
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`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_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi],[])
if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
fi
])
aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
fi
])# _LT_SYS_MODULE_PATH_AIX
# _LT_SHELL_INIT(ARG)
# -------------------
m4_define([_LT_SHELL_INIT],
[m4_divert_text([M4SH-INIT], [$1
])])# _LT_SHELL_INIT
# _LT_PROG_ECHO_BACKSLASH
# -----------------------
# Find how we can fake an echo command that does not interpret backslash.
# In particular, with Autoconf 2.60 or later we add some code to the start
# of the generated configure script which will find a shell with a builtin
# printf (which we can use as an echo command).
m4_defun([_LT_PROG_ECHO_BACKSLASH],
[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
AC_MSG_CHECKING([how to print strings])
# 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*) AC_MSG_RESULT([printf]) ;;
print*) AC_MSG_RESULT([print -r]) ;;
*) AC_MSG_RESULT([cat]) ;;
esac
m4_ifdef([_AS_DETECT_SUGGESTED],
[_AS_DETECT_SUGGESTED([
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" )])])
_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
])# _LT_PROG_ECHO_BACKSLASH
# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[ --with-sysroot[=DIR] Search for dependent libraries within DIR
(or the compiler's sysroot if not specified).],
[], [with_sysroot=no])
dnl lt_sysroot will always be passed unquoted. We quote it here
dnl in case the user passed a directory name.
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|'')
;; #(
*)
AC_MSG_RESULT([${with_sysroot}])
AC_MSG_ERROR([The sysroot must be an absolute path.])
;;
esac
AC_MSG_RESULT([${lt_sysroot:-no}])
_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
[dependent libraries, and in which our libraries should be installed.])])
# _LT_ENABLE_LOCK
# ---------------
m4_defun([_LT_ENABLE_LOCK],
[AC_ARG_ENABLE([libtool-lock],
[AS_HELP_STRING([--disable-libtool-lock],
[avoid locking (might break parallel builds)])])
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 AC_TRY_EVAL(ac_compile); 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 AC_TRY_EVAL(ac_compile); 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 AC_TRY_EVAL(ac_compile); 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"
AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
[AC_LANG_PUSH(C)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
AC_LANG_POP])
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 AC_TRY_EVAL(ac_compile); 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"
])# _LT_ENABLE_LOCK
# _LT_PROG_AR
# -----------
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
[lt_cv_ar_at_file=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[echo conftest.$ac_objext > conftest.lst
lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
AC_TRY_EVAL([lt_ar_try])
if test "$ac_status" -eq 0; then
# Ensure the archiver fails upon bogus file names.
rm -f conftest.$ac_objext libconftest.a
AC_TRY_EVAL([lt_ar_try])
if test "$ac_status" -ne 0; then
lt_cv_ar_at_file=@
fi
fi
rm -f conftest.* libconftest.a
])
])
if test "x$lt_cv_ar_at_file" = xno; then
archiver_list_spec=
else
archiver_list_spec=$lt_cv_ar_at_file
fi
_LT_DECL([], [archiver_list_spec], [1],
[How to feed a file listing to the archiver])
])# _LT_PROG_AR
# _LT_CMD_OLD_ARCHIVE
# -------------------
m4_defun([_LT_CMD_OLD_ARCHIVE],
[_LT_PROG_AR
AC_CHECK_TOOL(STRIP, strip, :)
test -z "$STRIP" && STRIP=:
_LT_DECL([], [STRIP], [1], [A symbol stripping program])
AC_CHECK_TOOL(RANLIB, ranlib, :)
test -z "$RANLIB" && RANLIB=:
_LT_DECL([], [RANLIB], [1],
[Commands used to install an old-style archive])
# 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
_LT_DECL([], [old_postinstall_cmds], [2])
_LT_DECL([], [old_postuninstall_cmds], [2])
_LT_TAGDECL([], [old_archive_cmds], [2],
[Commands used to build an old-style archive])
_LT_DECL([], [lock_old_archive_extraction], [0],
[Whether to use a lock for old archive extraction])
])# _LT_CMD_OLD_ARCHIVE
# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------------------
# Check whether the given compiler option works
AC_DEFUN([_LT_COMPILER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="$3"
# 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\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
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
$2=yes
fi
fi
$RM conftest*
])
if test x"[$]$2" = xyes; then
m4_if([$5], , :, [$5])
else
m4_if([$6], , :, [$6])
fi
])# _LT_COMPILER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------
# Check whether the given linker option works
AC_DEFUN([_LT_LINKER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $3"
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>&AS_MESSAGE_LOG_FD
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.exp conftest.er2 >/dev/null; then
$2=yes
fi
else
$2=yes
fi
fi
$RM -r conftest*
LDFLAGS="$save_LDFLAGS"
])
if test x"[$]$2" = xyes; then
m4_if([$4], , :, [$4])
else
m4_if([$5], , :, [$5])
fi
])# _LT_LINKER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
# LT_CMD_MAX_LEN
#---------------
AC_DEFUN([LT_CMD_MAX_LEN],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
# find the maximum length of command line arguments
AC_MSG_CHECKING([the maximum length of command line arguments])
AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
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
])
if test -n $lt_cv_sys_max_cmd_len ; then
AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
else
AC_MSG_RESULT(none)
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
_LT_DECL([], [max_cmd_len], [0],
[What is the maximum length of a command?])
])# LT_CMD_MAX_LEN
# Old name:
AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
# _LT_HEADER_DLFCN
# ----------------
m4_defun([_LT_HEADER_DLFCN],
[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
])# _LT_HEADER_DLFCN
# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
# ----------------------------------------------------------------
m4_defun([_LT_TRY_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test "$cross_compiling" = yes; then :
[$4]
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 AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
(./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
lt_status=$?
case x$lt_status in
x$lt_dlno_uscore) $1 ;;
x$lt_dlneed_uscore) $2 ;;
x$lt_dlunknown|x*) $3 ;;
esac
else :
# compilation failed
$3
fi
fi
rm -fr conftest*
])# _LT_TRY_DLOPEN_SELF
# LT_SYS_DLOPEN_SELF
# ------------------
AC_DEFUN([LT_SYS_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
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
AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
lt_cv_dlopen="dyld"
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
])
;;
*)
AC_CHECK_FUNC([shl_load],
[lt_cv_dlopen="shl_load"],
[AC_CHECK_LIB([dld], [shl_load],
[lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
[AC_CHECK_FUNC([dlopen],
[lt_cv_dlopen="dlopen"],
[AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
[AC_CHECK_LIB([svld], [dlopen],
[lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
[AC_CHECK_LIB([dld], [dld_link],
[lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
])
])
])
])
])
;;
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"
AC_CACHE_CHECK([whether a program can dlopen itself],
lt_cv_dlopen_self, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
])
if test "x$lt_cv_dlopen_self" = xyes; then
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
lt_cv_dlopen_self_static, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
])
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
_LT_DECL([dlopen_support], [enable_dlopen], [0],
[Whether dlopen is supported])
_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
[Whether dlopen of programs is supported])
_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
[Whether dlopen of statically linked programs is supported])
])# LT_SYS_DLOPEN_SELF
# Old name:
AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
# _LT_COMPILER_C_O([TAGNAME])
# ---------------------------
# Check to see if options -c and -o are simultaneously supported by compiler.
# This macro does not hard code the compiler like AC_PROG_CC_C_O.
m4_defun([_LT_COMPILER_C_O],
[m4_require([_LT_DECL_SED])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=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\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
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_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
fi
fi
chmod u+w . 2>&AS_MESSAGE_LOG_FD
$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*
])
_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
[Does compiler simultaneously support -c and -o options?])
])# _LT_COMPILER_C_O
# _LT_COMPILER_FILE_LOCKS([TAGNAME])
# ----------------------------------
# Check to see if we can do hard links to lock some files if needed
m4_defun([_LT_COMPILER_FILE_LOCKS],
[m4_require([_LT_ENABLE_LOCK])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_COMPILER_C_O([$1])
hard_links="nottested"
if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
# do not overwrite the value of need_locks provided by the user
AC_MSG_CHECKING([if we can lock with hard links])
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
AC_MSG_RESULT([$hard_links])
if test "$hard_links" = no; then
AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
need_locks=warn
fi
else
need_locks=no
fi
_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
])# _LT_COMPILER_FILE_LOCKS
# _LT_CHECK_OBJDIR
# ----------------
m4_defun([_LT_CHECK_OBJDIR],
[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
[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])
objdir=$lt_cv_objdir
_LT_DECL([], [objdir], [0],
[The name of the directory that contains temporary libtool files])dnl
m4_pattern_allow([LT_OBJDIR])dnl
AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
[Define to the sub-directory in which libtool stores uninstalled libraries.])
])# _LT_CHECK_OBJDIR
# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
# --------------------------------------
# Check hardcoding attributes.
m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
[AC_MSG_CHECKING([how to hardcode library paths into programs])
_LT_TAGVAR(hardcode_action, $1)=
if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
test -n "$_LT_TAGVAR(runpath_var, $1)" ||
test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
# We can hardcode non-existent directories.
if test "$_LT_TAGVAR(hardcode_direct, $1)" != 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, $1)" != no &&
test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
# Linking always hardcodes the temporary library directory.
_LT_TAGVAR(hardcode_action, $1)=relink
else
# We can link without hardcoding, and we can hardcode nonexisting dirs.
_LT_TAGVAR(hardcode_action, $1)=immediate
fi
else
# We cannot hardcode anything, or else we can only hardcode existing
# directories.
_LT_TAGVAR(hardcode_action, $1)=unsupported
fi
AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
test "$_LT_TAGVAR(inherit_rpath, $1)" = 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
_LT_TAGDECL([], [hardcode_action], [0],
[How to hardcode a shared library path into an executable])
])# _LT_LINKER_HARDCODE_LIBPATH
# _LT_CMD_STRIPLIB
# ----------------
m4_defun([_LT_CMD_STRIPLIB],
[m4_require([_LT_DECL_EGREP])
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
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"
AC_MSG_RESULT([yes])
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"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
;;
esac
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
])# _LT_CMD_STRIPLIB
# _LT_SYS_DYNAMIC_LINKER([TAG])
# -----------------------------
# PORTME Fill in your ld.so characteristics
m4_defun([_LT_SYS_DYNAMIC_LINKER],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_OBJDUMP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
AC_MSG_CHECKING([dynamic linker characteristics])
m4_if([$1],
[], [
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}'
m4_if([$1], [],[
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`'
m4_if([$1], [],[
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.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-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
AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
[lt_cv_shlibpath_overrides_runpath=no
save_LDFLAGS=$LDFLAGS
save_libdir=$libdir
eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
[lt_cv_shlibpath_overrides_runpath=yes])])
LDFLAGS=$save_LDFLAGS
libdir=$save_libdir
])
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
AC_MSG_RESULT([$dynamic_linker])
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
_LT_DECL([], [variables_saved_for_relink], [1],
[Variables whose values should be saved in libtool wrapper scripts and
restored at link time])
_LT_DECL([], [need_lib_prefix], [0],
[Do we need the "lib" prefix for modules?])
_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
_LT_DECL([], [version_type], [0], [Library versioning type])
_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
_LT_DECL([], [shlibpath_overrides_runpath], [0],
[Is shlibpath searched before the hard-coded library search path?])
_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
_LT_DECL([], [library_names_spec], [1],
[[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]])
_LT_DECL([], [soname_spec], [1],
[[The coded name of the library, if different from the real name]])
_LT_DECL([], [install_override_mode], [1],
[Permission mode override for installation of shared libraries])
_LT_DECL([], [postinstall_cmds], [2],
[Command to use after installation of a shared archive])
_LT_DECL([], [postuninstall_cmds], [2],
[Command to use after uninstallation of a shared archive])
_LT_DECL([], [finish_cmds], [2],
[Commands used to finish a libtool library installation in a directory])
_LT_DECL([], [finish_eval], [1],
[[As "finish_cmds", except a single script fragment to be evaled but
not shown]])
_LT_DECL([], [hardcode_into_libs], [0],
[Whether we should hardcode library paths into libraries])
_LT_DECL([], [sys_lib_search_path_spec], [2],
[Compile-time system search path for libraries])
_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
[Run-time system search path for libraries])
])# _LT_SYS_DYNAMIC_LINKER
# _LT_PATH_TOOL_PREFIX(TOOL)
# --------------------------
# find a file program which can recognize shared library
AC_DEFUN([_LT_PATH_TOOL_PREFIX],
[m4_require([_LT_DECL_EGREP])dnl
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
[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
dnl $ac_dummy forces splitting on constant user-supplied paths.
dnl POSIX.2 word splitting is done only on the output of word expansions,
dnl not every word. This closes a longstanding sh security hole.
ac_dummy="m4_if([$2], , $PATH, [$2])"
for ac_dir in $ac_dummy; do
IFS="$lt_save_ifs"
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/$1; then
lt_cv_path_MAGIC_CMD="$ac_dir/$1"
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])
MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
if test -n "$MAGIC_CMD"; then
AC_MSG_RESULT($MAGIC_CMD)
else
AC_MSG_RESULT(no)
fi
_LT_DECL([], [MAGIC_CMD], [0],
[Used to examine libraries when file_magic_cmd begins with "file"])dnl
])# _LT_PATH_TOOL_PREFIX
# Old name:
AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
# _LT_PATH_MAGIC
# --------------
# find a file program which can recognize a shared library
m4_defun([_LT_PATH_MAGIC],
[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
_LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
else
MAGIC_CMD=:
fi
fi
])# _LT_PATH_MAGIC
# LT_PATH_LD
# ----------
# find the pathname to the GNU or non-GNU linker
AC_DEFUN([LT_PATH_LD],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
AC_ARG_WITH([gnu-ld],
[AS_HELP_STRING([--with-gnu-ld],
[assume the C compiler uses GNU ld @<:@default=no@:>@])],
[test "$withval" = no || with_gnu_ld=yes],
[with_gnu_ld=no])dnl
ac_prog=ld
if test "$GCC" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by $CC])
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
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(lt_cv_path_LD,
[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])
LD="$lt_cv_path_LD"
if test -n "$LD"; then
AC_MSG_RESULT($LD)
else
AC_MSG_RESULT(no)
fi
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
_LT_PATH_LD_GNU
AC_SUBST([LD])
_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
])# LT_PATH_LD
# Old names:
AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_PROG_LD], [])
dnl AC_DEFUN([AC_PROG_LD], [])
# _LT_PATH_LD_GNU
#- --------------
m4_defun([_LT_PATH_LD_GNU],
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
[# 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])
with_gnu_ld=$lt_cv_prog_gnu_ld
])# _LT_PATH_LD_GNU
# _LT_CMD_RELOAD
# --------------
# find reload flag for linker
# -- PORTME Some linkers may need a different reload flag.
m4_defun([_LT_CMD_RELOAD],
[AC_CACHE_CHECK([for $LD option to reload object files],
lt_cv_ld_reload_flag,
[lt_cv_ld_reload_flag='-r'])
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
_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
_LT_TAGDECL([], [reload_cmds], [2])dnl
])# _LT_CMD_RELOAD
# _LT_CHECK_MAGIC_METHOD
# ----------------------
# how to check for library dependencies
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_MAGIC_METHOD],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
AC_CACHE_CHECK([how to recognize dependent libraries],
lt_cv_deplibs_check_method,
[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
])
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
_LT_DECL([], [deplibs_check_method], [1],
[Method to check whether dependent libraries are shared objects])
_LT_DECL([], [file_magic_cmd], [1],
[Command to use when deplibs_check_method = "file_magic"])
_LT_DECL([], [file_magic_glob], [1],
[How to find potential files when deplibs_check_method = "file_magic"])
_LT_DECL([], [want_nocaseglob], [1],
[Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
])# _LT_CHECK_MAGIC_METHOD
# LT_PATH_NM
# ----------
# find the pathname to a BSD- or MS-compatible name lister
AC_DEFUN([LT_PATH_NM],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
[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])
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
AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols"
;;
*)
DUMPBIN=:
;;
esac
fi
AC_SUBST([DUMPBIN])
if test "$DUMPBIN" != ":"; then
NM="$DUMPBIN"
fi
fi
test -z "$NM" && NM=nm
AC_SUBST([NM])
_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
[lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
cat conftest.out >&AS_MESSAGE_LOG_FD
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
fi
rm -f conftest*])
])# LT_PATH_NM
# Old names:
AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_PROG_NM], [])
dnl AC_DEFUN([AC_PROG_NM], [])
# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# --------------------------------
# how to determine the name of the shared library
# associated with a specific link library.
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
m4_require([_LT_DECL_DLLTOOL])
AC_CACHE_CHECK([how to associate runtime and link libraries],
lt_cv_sharedlib_from_linklib_cmd,
[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
])
sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
[Command to associate shared and link libraries])
])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# _LT_PATH_MANIFEST_TOOL
# ----------------------
# locate the manifest tool
m4_defun([_LT_PATH_MANIFEST_TOOL],
[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
[lt_cv_path_mainfest_tool=no
echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
$MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
cat conftest.err >&AS_MESSAGE_LOG_FD
if $GREP 'Manifest Tool' conftest.out > /dev/null; then
lt_cv_path_mainfest_tool=yes
fi
rm -f conftest*])
if test "x$lt_cv_path_mainfest_tool" != xyes; then
MANIFEST_TOOL=:
fi
_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
])# _LT_PATH_MANIFEST_TOOL
# LT_LIB_M
# --------
# check for math library
AC_DEFUN([LT_LIB_M],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
LIBM=
case $host in
*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
# These system don't have libm, or don't need it
;;
*-ncr-sysv4.3*)
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
;;
*)
AC_CHECK_LIB(m, cos, LIBM="-lm")
;;
esac
AC_SUBST([LIBM])
])# LT_LIB_M
# Old name:
AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_CHECK_LIBM], [])
# _LT_COMPILER_NO_RTTI([TAGNAME])
# -------------------------------
m4_defun([_LT_COMPILER_NO_RTTI],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
if test "$GCC" = yes; then
case $cc_basename in
nvcc*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
esac
_LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
lt_cv_prog_compiler_rtti_exceptions,
[-fno-rtti -fno-exceptions], [],
[_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
fi
_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
[Compiler flag to turn off builtin functions])
])# _LT_COMPILER_NO_RTTI
# _LT_CMD_GLOBAL_SYMBOLS
# ----------------------
m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([LT_PATH_NM])dnl
AC_REQUIRE([LT_PATH_LD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_TAG_COMPILER])dnl
# Check for command to grab the raw symbol name followed by C symbol from nm.
AC_MSG_CHECKING([command to parse $NM output from $compiler object])
AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
[
# 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 AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && 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@&t@_DLSYM_CONST
#elif defined(__osf__)
/* This system does not cope well with relocations in const data. */
# define LT@&t@_DLSYM_CONST
#else
# define LT@&t@_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@&t@_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_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
if AC_TRY_EVAL(ac_link) && 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" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
fi
else
echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
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
])
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
AC_MSG_RESULT(failed)
else
AC_MSG_RESULT(ok)
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
_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
[Take the output of nm and produce a listing of raw symbols and C names])
_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
[Transform the output of nm in a proper C declaration])
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
[lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
[Transform the output of nm in a C name address pair when lib prefix is needed])
_LT_DECL([], [nm_file_list_spec], [1],
[Specify filename containing input files for $NM])
]) # _LT_CMD_GLOBAL_SYMBOLS
# _LT_COMPILER_PIC([TAGNAME])
# ---------------------------
m4_defun([_LT_COMPILER_PIC],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_wl, $1)=
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)=
m4_if([$1], [CXX], [
# C++ specific cases for pic, static, wl, etc.
if test "$GXX" = yes; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test "$host_cpu" = ia64; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | cygwin* | os2* | pw32* | 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
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
*djgpp*)
# DJGPP does not support shared libraries at all
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
interix[[3-9]]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
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*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
else
case $host_os in
aix[[4-9]]*)
# All AIX code is PIC.
if test "$host_cpu" = ia64; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
fi
;;
chorus*)
case $cc_basename in
cxch68*)
# Green Hills C++ Compiler
# _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
;;
esac
;;
mingw* | cygwin* | os2* | pw32* | 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).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
dgux*)
case $cc_basename in
ec++*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
ghcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
freebsd* | dragonfly*)
# FreeBSD uses GNU C++
;;
hpux9* | hpux10* | hpux11*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
if test "$host_cpu" != ia64; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
fi
;;
aCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
;;
*)
;;
esac
;;
interix*)
# This is c89, which is MS Visual C++ (no shared libs)
# Anyone wants to do a port?
;;
irix5* | irix6* | nonstopux*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
# CC pic flag -KPIC is the default.
;;
*)
;;
esac
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu)
case $cc_basename in
KCC*)
# KAI C++ Compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
ecpc* )
# old Intel C++ for x86_64 which still supported -KPIC.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
icpc* )
# Intel C++, used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
cxx*)
# Compaq C++
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
# IBM XL 8.0, 9.0 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
esac
;;
esac
;;
lynxos*)
;;
m88k*)
;;
mvs*)
case $cc_basename in
cxx*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
;;
*)
;;
esac
;;
netbsd* | netbsdelf*-gnu)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
;;
RCC*)
# Rational C++ 2.4.1
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
cxx*)
# Digital/Compaq C++
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
*)
;;
esac
;;
psos*)
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
;;
*)
;;
esac
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
lcc*)
# Lucid
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
*)
;;
esac
;;
vxworks*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
],
[
if test "$GCC" = yes; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test "$host_cpu" = ia64; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-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
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
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_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
enable_shared=no
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
case $cc_basename in
nvcc*) # Cuda Compiler Driver 2.2
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
fi
;;
esac
else
# PORTME Check for flag to pass linker flags through the system compiler.
case $host_os in
aix*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
if test "$host_cpu" = ia64; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-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).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
hpux9* | hpux10* | hpux11*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
# Is there a better lt_prog_compiler_static that works with the bundled CC?
_LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
;;
irix5* | irix6* | nonstopux*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# PIC (with -KPIC) is the default.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu)
case $cc_basename in
# old Intel for x86_64 which still supported -KPIC.
ecc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# Lahey Fortran 8.1.
lf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
;;
nagfor*)
# NAG Fortran compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group compilers (*not* the Pentium gcc compiler,
# which looks to be a dead project)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
ccc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All Alpha code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xl* | bgxl* | bgf* | mpixl*)
# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)=''
;;
*Sun\ F* | *Sun*Fortran*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
*Sun\ C*)
# Sun C 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
;;
*Intel*\ [[CF]]*Compiler*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*Portland\ Group*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
esac
;;
newsos6)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All OSF/1 code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
rdos*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
solaris*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
esac
;;
sunos4*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4*MP*)
if test -d /usr/nec ;then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
unicos*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
uts4*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
])
case $host_os in
# For platforms which do not support PIC, -DPIC is meaningless:
*djgpp*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
;;
esac
AC_CACHE_CHECK([for $compiler option to produce PIC],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
#
# Check to make sure the PIC flag actually works.
#
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
[_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
[$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
[case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
"" | " "*) ;;
*) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
esac],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
fi
_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
[Additional compiler flags for building library objects])
_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
[How to pass a linker flag through the compiler])
#
# Check to make sure the static flag actually works.
#
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
_LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
$lt_tmp_static_flag,
[],
[_LT_TAGVAR(lt_prog_compiler_static, $1)=])
_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
[Compiler flag to prevent dynamic linking])
])# _LT_COMPILER_PIC
# _LT_LINKER_SHLIBS([TAGNAME])
# ----------------------------
# See if the linker supports building shared libraries.
m4_defun([_LT_LINKER_SHLIBS],
[AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
m4_if([$1], [CXX], [
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
case $host_os in
aix[[4-9]]*)
# 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
_LT_TAGVAR(export_symbols_cmds, $1)='$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
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
fi
;;
pw32*)
_LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
;;
cygwin* | mingw* | cegcc*)
case $cc_basename in
cl*)
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
;;
esac
;;
linux* | k*bsd*-gnu | gnu*)
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
;;
esac
], [
runpath_var=
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_cmds, $1)=
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(old_archive_from_new_cmds, $1)=
_LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
_LT_TAGVAR(thread_safe_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
# include_expsyms should be a list of space-separated symbols to be *always*
# included in the symbol list
_LT_TAGVAR(include_expsyms, $1)=
# 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'.
_LT_TAGVAR(exclude_expsyms, $1)=['_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.
dnl Note also adjust exclude_expsyms for C++ above.
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*)
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
esac
_LT_TAGVAR(ld_shlibs, $1)=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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${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
_LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
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
_LT_TAGVAR(ld_shlibs, $1)=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
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$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)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
cygwin* | mingw* | pw32* | cegcc*)
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+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
_LT_TAGVAR(archive_cmds, $1)='$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...
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${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.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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
_LT_TAGVAR(whole_archive_flag_spec, $1)=
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
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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'
_LT_TAGVAR(compiler_needs_object, $1)=yes
;;
esac
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*) # Sun C 5.9
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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'
_LT_TAGVAR(compiler_needs_object, $1)=yes
tmp_sharedflag='-G' ;;
*Sun\ F*) # Sun Fortran 8.3
tmp_sharedflag='-G' ;;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
if test "x$supports_anon_versioning" = xyes; then
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test "x$supports_anon_versioning" = xyes; then
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$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
_LT_TAGVAR(ld_shlibs, $1)=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
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
_LT_TAGVAR(ld_shlibs, $1)=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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
sunos4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
runpath_var=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
# PORTME fill in a description of your system's linker (not GNU ld)
case $host_os in
aix3*)
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$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.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
_LT_TAGVAR(hardcode_direct, $1)=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
_LT_TAGVAR(export_symbols_cmds, $1)='$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
_LT_TAGVAR(export_symbols_cmds, $1)='$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.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='${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
_LT_TAGVAR(hardcode_direct, $1)=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
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
;;
esac
shared_flag='-shared'
if test "$aix_use_runtimelinking" = yes; then
shared_flag="$shared_flag "'${wl}-G'
fi
_LT_TAGVAR(link_all_deplibs, $1)=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
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${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.
_LT_TAGVAR(always_export_symbols, $1)=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.
_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$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.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${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.
_LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
if test "$with_gnu_ld" = yes; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
# This is similar to how AIX traditionally builds its shared libraries.
_LT_TAGVAR(archive_expsym_cmds, $1)="\$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
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$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)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
bsdi[[45]]*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)=-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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# 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.
_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='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, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=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.
_LT_TAGVAR(archive_cmds, $1)='$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.
_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
# FIXME: Should let the user specify the lib program.
_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
dgux*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=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*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
freebsd2.*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
hpux9*)
if test "$GCC" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$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
_LT_TAGVAR(archive_cmds, $1)='$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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
;;
hpux10*)
if test "$GCC" = yes && test "$with_gnu_ld" = no; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
fi
if test "$with_gnu_ld" = no; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
fi
;;
hpux11*)
if test "$GCC" = yes && test "$with_gnu_ld" = no; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$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*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
m4_if($1, [], [
# 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)
_LT_LINKER_OPTION([if $CC understands -b],
_LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
[_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
;;
esac
fi
if test "$with_gnu_ld" = no; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
if test "$GCC" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$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.
AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
[lt_cv_irix_exported_symbol],
[save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
[C++], [[int foo (void) { return 0; }]],
[Fortran 77], [[
subroutine foo
end]],
[Fortran], [[
subroutine foo
end]])])],
[lt_cv_irix_exported_symbol=yes],
[lt_cv_irix_exported_symbol=no])
LDFLAGS="$save_LDFLAGS"])
if test "$lt_cv_irix_exported_symbol" = yes; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$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
_LT_TAGVAR(archive_cmds, $1)='$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'
_LT_TAGVAR(archive_expsym_cmds, $1)='$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
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
newsos6)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*nto* | *qnx*)
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
else
case $host_os in
openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
;;
esac
fi
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(archive_cmds, $1)='$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'
_LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
;;
osf3*)
if test "$GCC" = yes; then
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
_LT_TAGVAR(archive_cmds, $1)='$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
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$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
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
osf4* | osf5*) # as osf3* with the addition of -msym flag
if test "$GCC" = yes; then
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
_LT_TAGVAR(archive_cmds, $1)='$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'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
else
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$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'
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
solaris*)
_LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
if test "$GCC" = yes; then
wlarc='${wl}'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='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=''
_LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='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}'
_LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=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
_LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
fi
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=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.
_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4)
case $host_vendor in
sni)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
;;
siemens)
## LD is ld it makes a PLAMLIB
## CC just makes a GrossModule.
_LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
_LT_TAGVAR(hardcode_direct, $1)=no
;;
motorola)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
;;
esac
runpath_var='LD_RUN_PATH'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4.3*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var=LD_RUN_PATH
hardcode_runpath_var=yes
_LT_TAGVAR(ld_shlibs, $1)=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
if test "$GCC" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$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.
_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
runpath_var='LD_RUN_PATH'
if test "$GCC" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
uts4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
if test x$host_vendor = xsni; then
case $host in
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
;;
esac
fi
fi
])
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
_LT_DECL([], [extract_expsyms_cmds], [2],
[The commands to extract the exported symbol list from a shared archive])
#
# Do we need to explicitly link libc?
#
case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
x|xyes)
# Assume -lc should be added
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
if test "$enable_shared" = yes && test "$GCC" = yes; then
case $_LT_TAGVAR(archive_cmds, $1) 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.
AC_CACHE_CHECK([whether -lc should be explicitly linked in],
[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
[$RM conftest*
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
soname=conftest
lib=conftest
libobjs=conftest.$ac_objext
deplibs=
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
compiler_flags=-v
linker_flags=-v
verstring=
output_objdir=.
libname=conftest
lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
_LT_TAGVAR(allow_undefined_flag, $1)=
if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
then
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
else
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
fi
_LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
else
cat conftest.err 1>&5
fi
$RM conftest*
])
_LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
;;
esac
fi
;;
esac
_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
[Whether or not to add -lc for building shared libraries])
_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
[enable_shared_with_static_runtimes], [0],
[Whether or not to disallow shared libs when runtime libs are static])
_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
[Compiler flag to allow reflexive dlopens])
_LT_TAGDECL([], [whole_archive_flag_spec], [1],
[Compiler flag to generate shared objects directly from archives])
_LT_TAGDECL([], [compiler_needs_object], [1],
[Whether the compiler copes with passing no objects directly])
_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
[Create an old-style archive from a shared archive])
_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
[Create a temporary old-style archive to link instead of a shared archive])
_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
_LT_TAGDECL([], [archive_expsym_cmds], [2])
_LT_TAGDECL([], [module_cmds], [2],
[Commands used to build a loadable module if different from building
a shared archive.])
_LT_TAGDECL([], [module_expsym_cmds], [2])
_LT_TAGDECL([], [with_gnu_ld], [1],
[Whether we are building with GNU ld or not])
_LT_TAGDECL([], [allow_undefined_flag], [1],
[Flag that allows shared libraries with undefined symbols to be built])
_LT_TAGDECL([], [no_undefined_flag], [1],
[Flag that enforces no undefined symbols])
_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
[Flag to hardcode $libdir into a binary during linking.
This must work even if $libdir does not exist])
_LT_TAGDECL([], [hardcode_libdir_separator], [1],
[Whether we need a single "-rpath" flag with a separated argument])
_LT_TAGDECL([], [hardcode_direct], [0],
[Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
DIR into the resulting binary])
_LT_TAGDECL([], [hardcode_direct_absolute], [0],
[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])
_LT_TAGDECL([], [hardcode_minus_L], [0],
[Set to "yes" if using the -LDIR flag during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
[Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_automatic], [0],
[Set to "yes" if building a shared library automatically hardcodes DIR
into the library and all subsequent libraries and executables linked
against it])
_LT_TAGDECL([], [inherit_rpath], [0],
[Set to yes if linker adds runtime paths of dependent libraries
to runtime path list])
_LT_TAGDECL([], [link_all_deplibs], [0],
[Whether libtool must link a program against all its dependency libraries])
_LT_TAGDECL([], [always_export_symbols], [0],
[Set to "yes" if exported symbols are required])
_LT_TAGDECL([], [export_symbols_cmds], [2],
[The commands to list exported symbols])
_LT_TAGDECL([], [exclude_expsyms], [1],
[Symbols that should not be listed in the preloaded symbols])
_LT_TAGDECL([], [include_expsyms], [1],
[Symbols that must always be exported])
_LT_TAGDECL([], [prelink_cmds], [2],
[Commands necessary for linking programs (against libraries) with templates])
_LT_TAGDECL([], [postlink_cmds], [2],
[Commands necessary for finishing linking programs])
_LT_TAGDECL([], [file_list_spec], [1],
[Specify filename containing input files])
dnl FIXME: Not yet implemented
dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
dnl [Compiler flag to generate thread safe objects])
])# _LT_LINKER_SHLIBS
# _LT_LANG_C_CONFIG([TAG])
# ------------------------
# Ensure that the configuration variables for a C compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to `libtool'.
m4_defun([_LT_LANG_C_CONFIG],
[m4_require([_LT_DECL_EGREP])dnl
lt_save_CC="$CC"
AC_LANG_PUSH(C)
# Source file extension for C test sources.
ac_ext=c
# Object file extension for compiled C test sources.
objext=o
_LT_TAGVAR(objext, $1)=$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);}'
_LT_TAG_COMPILER
# 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
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
## 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_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
LT_SYS_DLOPEN_SELF
_LT_CMD_STRIPLIB
# Report which library types will actually be built
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
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
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test "$enable_shared" = yes || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_CONFIG($1)
fi
AC_LANG_POP
CC="$lt_save_CC"
])# _LT_LANG_C_CONFIG
# _LT_LANG_CXX_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a C++ compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to `libtool'.
m4_defun([_LT_LANG_CXX_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
(test "X$CXX" != "Xg++"))) ; then
AC_PROG_CXXCPP
else
_lt_caught_CXX_error=yes
fi
AC_LANG_PUSH(C++)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for C++ test sources.
ac_ext=cpp
# Object file extension for compiled C++ test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the CXX compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test "$_lt_caught_CXX_error" != yes; then
# 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(int, char *[[]]) { return(0); }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_LD=$LD
lt_save_GCC=$GCC
GCC=$GXX
lt_save_with_gnu_ld=$with_gnu_ld
lt_save_path_LD=$lt_cv_path_LD
if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
else
$as_unset lt_cv_prog_gnu_ld
fi
if test -n "${lt_cv_path_LDCXX+set}"; then
lt_cv_path_LD=$lt_cv_path_LDCXX
else
$as_unset lt_cv_path_LD
fi
test -z "${LDCXX+set}" || LD=$LDCXX
CC=${CXX-"c++"}
CFLAGS=$CXXFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
# We don't want -fno-exception when compiling C++ code, so set the
# no_builtin_flag separately
if test "$GXX" = yes; then
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
else
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
fi
if test "$GXX" = yes; then
# Set up default GNU C++ configuration
LT_PATH_LD
# Check if GNU C++ uses GNU ld as the underlying linker, since the
# archiving commands below assume that GNU ld is being used.
if test "$with_gnu_ld" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
# If archive_cmds runs LD, not CC, wlarc should be empty
# XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
# investigate it a little bit more. (MM)
wlarc='${wl}'
# ancient GNU ld didn't support --whole-archive et. al.
if eval "`$CC -print-prog-name=ld` --help 2>&1" |
$GREP 'no-whole-archive' > /dev/null; then
_LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
with_gnu_ld=no
wlarc=
# A generic and very simple default shared library creation
# command for GNU C++ for the case where it uses the native
# linker, instead of GNU ld. If possible, this setting should
# overridden to take advantage of the native linker features on
# the platform it is being used on.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
fi
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
GXX=no
with_gnu_ld=no
wlarc=
fi
# PORTME: fill in a description of your system's C++ link characteristics
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
_LT_TAGVAR(ld_shlibs, $1)=yes
case $host_os in
aix3*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
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
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
case $ld_flag in
*-brtl*)
aix_use_runtimelinking=yes
break
;;
esac
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.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
if test "$GXX" = 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
_LT_TAGVAR(hardcode_direct, $1)=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
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
esac
shared_flag='-shared'
if test "$aix_use_runtimelinking" = yes; then
shared_flag="$shared_flag "'${wl}-G'
fi
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
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${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.
_LT_TAGVAR(always_export_symbols, $1)=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.
_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
# Determine the default libpath from the value encoded in an empty
# executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$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
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$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.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${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.
_LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
if test "$with_gnu_ld" = yes; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
# This is similar to how AIX traditionally builds its shared
# libraries.
_LT_TAGVAR(archive_expsym_cmds, $1)="\$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
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach <jrb3@best.com> says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
chorus*)
case $cc_basename in
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
cygwin* | mingw* | pw32* | cegcc*)
case $GXX,$cc_basename in
,cl* | no,cl*)
# Native MSVC
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# 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.
_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='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, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='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~
func_to_tool_file "$lt_outputfile"~
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'
;;
*)
# g++
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $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...
_LT_TAGVAR(archive_expsym_cmds, $1)='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 -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
dgux*)
case $cc_basename in
ec++*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
ghcx*)
# Green Hills C++ Compiler
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
_LT_TAGVAR(ld_shlibs, $1)=no
;;
freebsd-elf*)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
;;
freebsd* | dragonfly*)
# FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
# conventions
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
gnu*)
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
hpux9*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test "$GXX" = yes; then
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
hpux10*|hpux11*)
if test $with_gnu_ld = no; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
;;
*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
;;
esac
fi
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
;;
esac
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test "$GXX" = yes; then
if test $with_gnu_ld = no; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
fi
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${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.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='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'
;;
irix5* | irix6*)
case $cc_basename in
CC*)
# SGI C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
# Archives containing C++ object files must be created using
# "CC -ar", where "CC" is the IRIX C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
;;
*)
if test "$GXX" = yes; then
if test "$with_gnu_ld" = no; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $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
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
fi
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
# Archives containing C++ object files must be created using
# "CC -Bstatic", where "CC" is the KAI C++ compiler.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
;;
icpc* | ecpc* )
# Intel C++
with_gnu_ld=yes
# version 8.0 and above of icpc choke on multiply defined symbols
# if we add $predep_objects and $postdep_objects, however 7.1 and
# earlier do not add the objects themselves.
case `$CC -V 2>&1` in
*"Version 7."*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
;;
*) # Version 8.0 or newer
tmp_idyn=
case $host_cpu in
ia64*) tmp_idyn=' -i_dynamic';;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
case `$CC -V` in
*pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
_LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
_LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
$RANLIB $oldlib'
_LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
;;
*) # Version 6 and above use weak symbols
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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'
;;
cxx*)
# Compaq C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
runpath_var=LD_RUN_PATH
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
;;
xl* | mpixl* | bgxl*)
# IBM XL 8.0 on PPC, with GNU ld
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
_LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
if test "x$supports_anon_versioning" = xyes; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
fi
;;
*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(whole_archive_flag_spec, $1)='${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'
_LT_TAGVAR(compiler_needs_object, $1)=yes
# Not sure whether something based on
# $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
# would be better.
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
esac
;;
esac
;;
lynxos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
m88k*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
mvs*)
case $cc_basename in
cxx*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
fi
# Workaround some broken pre-1.5 toolchains
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
;;
*nto* | *qnx*)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
openbsd2*)
# C++ shared libraries are fairly broken
_LT_TAGVAR(ld_shlibs, $1)=no
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
_LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
fi
output_verbose_link_cmd=func_echo_all
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Archives containing C++ object files must be created using
# the KAI C++ compiler.
case $host in
osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
esac
;;
RCC*)
# Rational C++ 2.4.1
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
cxx*)
case $host in
osf3*)
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
;;
*)
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
echo "-hidden">> $lib.exp~
$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
$RM $lib.exp'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
;;
esac
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test "$GXX" = yes && test "$with_gnu_ld" = no; then
_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
case $host in
osf3*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $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'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $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'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
psos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
lcc*)
# Lucid
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(archive_cmds_need_lc,$1)=yes
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=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'.
# Supported since Solaris 2.6 (maybe 2.5.1?)
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=yes
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
# The C++ compiler must be used to create the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
;;
*)
# GNU C++ compiler with Solaris linker
if test "$GXX" = yes && test "$with_gnu_ld" = no; then
_LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
if $CC --version | $GREP -v '^2\.7' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
else
# g++ 2.7 appears to require `-G' NOT `-shared' on this
# platform.
_LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
$CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
_LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
;;
esac
fi
;;
esac
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
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.
_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
'"$_LT_TAGVAR(old_archive_cmds, $1)"
_LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
'"$_LT_TAGVAR(reload_cmds, $1)"
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
vxworks*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
_LT_TAGVAR(GCC, $1)="$GXX"
_LT_TAGVAR(LD, $1)="$LD"
## 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...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
LDCXX=$LD
LD=$lt_save_LD
GCC=$lt_save_GCC
with_gnu_ld=$lt_save_with_gnu_ld
lt_cv_path_LDCXX=$lt_cv_path_LD
lt_cv_path_LD=$lt_save_path_LD
lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
fi # test "$_lt_caught_CXX_error" != yes
AC_LANG_POP
])# _LT_LANG_CXX_CONFIG
# _LT_FUNC_STRIPNAME_CNF
# ----------------------
# func_stripname_cnf prefix suffix name
# strip PREFIX and SUFFIX off of NAME.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
#
# This function is identical to the (non-XSI) version of func_stripname,
# except this one can be used by m4 code that may be executed by configure,
# rather than the libtool script.
m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
AC_REQUIRE([_LT_DECL_SED])
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
func_stripname_cnf ()
{
case ${2} in
.*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
esac
} # func_stripname_cnf
])# _LT_FUNC_STRIPNAME_CNF
# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
# ---------------------------------
# Figure out "hidden" library dependencies from verbose
# compiler output when linking a shared library.
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
# Dependencies to place before and after the object being linked:
_LT_TAGVAR(predep_objects, $1)=
_LT_TAGVAR(postdep_objects, $1)=
_LT_TAGVAR(predeps, $1)=
_LT_TAGVAR(postdeps, $1)=
_LT_TAGVAR(compiler_lib_search_path, $1)=
dnl we can't use the lt_simple_compile_test_code here,
dnl because it contains code intended for an executable,
dnl not a library. It's possible we should let each
dnl tag define a new lt_????_link_test_code variable,
dnl but it's only used here...
m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
int a;
void foo (void) { a = 0; }
_LT_EOF
], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
class Foo
{
public:
Foo (void) { a = 0; }
private:
int a;
};
_LT_EOF
], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer*4 a
a=0
return
end
_LT_EOF
], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer a
a=0
return
end
_LT_EOF
], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
public class foo {
private int a;
public void bar (void) {
a = 0;
}
};
_LT_EOF
], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
package foo
func foo() {
}
_LT_EOF
])
_lt_libdeps_save_CFLAGS=$CFLAGS
case "$CC $CFLAGS " in #(
*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
esac
dnl Parse the compiler output and extract the necessary
dnl objects, libraries and library flags.
if AC_TRY_EVAL(ac_compile); then
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
# Sentinel used to keep track of whether or not we are before
# the conftest object file.
pre_test_object_deps_done=no
for p in `eval "$output_verbose_link_cmd"`; do
case ${prev}${p} in
-L* | -R* | -l*)
# Some compilers place space between "-{L,R}" and the path.
# Remove the space.
if test $p = "-L" ||
test $p = "-R"; then
prev=$p
continue
fi
# Expand the sysroot to ease extracting the directories later.
if test -z "$prev"; then
case $p in
-L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
-R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
-l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
esac
fi
case $p in
=*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
esac
if test "$pre_test_object_deps_done" = no; then
case ${prev} in
-L | -R)
# Internal compiler library paths should come after those
# provided the user. The postdeps already come after the
# user supplied libs so there is no need to process them.
if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
_LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
else
_LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
fi
;;
# The "-l" case would never come before the object being
# linked, so don't bother handling this case.
esac
else
if test -z "$_LT_TAGVAR(postdeps, $1)"; then
_LT_TAGVAR(postdeps, $1)="${prev}${p}"
else
_LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
fi
fi
prev=
;;
*.lto.$objext) ;; # Ignore GCC LTO objects
*.$objext)
# This assumes that the test object file only shows up
# once in the compiler output.
if test "$p" = "conftest.$objext"; then
pre_test_object_deps_done=yes
continue
fi
if test "$pre_test_object_deps_done" = no; then
if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
_LT_TAGVAR(predep_objects, $1)="$p"
else
_LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
fi
else
if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
_LT_TAGVAR(postdep_objects, $1)="$p"
else
_LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
fi
fi
;;
*) ;; # Ignore the rest.
esac
done
# Clean up.
rm -f a.out a.exe
else
echo "libtool.m4: error: problem compiling $1 test program"
fi
$RM -f confest.$objext
CFLAGS=$_lt_libdeps_save_CFLAGS
# PORTME: override above test on systems where it is broken
m4_if([$1], [CXX],
[case $host_os in
interix[[3-9]]*)
# Interix 3.5 installs completely hosed .la files for C++, so rather than
# hack all around it, let's just trust "g++" to DTRT.
_LT_TAGVAR(predep_objects,$1)=
_LT_TAGVAR(postdep_objects,$1)=
_LT_TAGVAR(postdeps,$1)=
;;
linux*)
case `$CC -V 2>&1 | sed 5q` in
*Sun\ C*)
# Sun C++ 5.9
# The more standards-conforming stlport4 library is
# incompatible with the Cstd library. Avoid specifying
# it if it's in CXXFLAGS. Ignore libCrun as
# -library=stlport4 depends on it.
case " $CXX $CXXFLAGS " in
*" -library=stlport4 "*)
solaris_use_stlport4=yes
;;
esac
if test "$solaris_use_stlport4" != yes; then
_LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
fi
;;
esac
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# The more standards-conforming stlport4 library is
# incompatible with the Cstd library. Avoid specifying
# it if it's in CXXFLAGS. Ignore libCrun as
# -library=stlport4 depends on it.
case " $CXX $CXXFLAGS " in
*" -library=stlport4 "*)
solaris_use_stlport4=yes
;;
esac
# Adding this requires a known-good setup of shared libraries for
# Sun compiler versions before 5.6, else PIC objects from an old
# archive will be linked into the output, leading to subtle bugs.
if test "$solaris_use_stlport4" != yes; then
_LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
fi
;;
esac
;;
esac
])
case " $_LT_TAGVAR(postdeps, $1) " in
*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
esac
_LT_TAGVAR(compiler_lib_search_dirs, $1)=
if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
_LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
fi
_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
[The directories searched by this compiler when creating a shared library])
_LT_TAGDECL([], [predep_objects], [1],
[Dependencies to place before and after the objects being linked to
create a shared library])
_LT_TAGDECL([], [postdep_objects], [1])
_LT_TAGDECL([], [predeps], [1])
_LT_TAGDECL([], [postdeps], [1])
_LT_TAGDECL([], [compiler_lib_search_path], [1],
[The library search path used internally by the compiler when linking
a shared library])
])# _LT_SYS_HIDDEN_LIBDEPS
# _LT_LANG_F77_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a Fortran 77 compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to `libtool'.
m4_defun([_LT_LANG_F77_CONFIG],
[AC_LANG_PUSH(Fortran 77)
if test -z "$F77" || test "X$F77" = "Xno"; then
_lt_disable_F77=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for f77 test sources.
ac_ext=f
# Object file extension for compiled f77 test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the F77 compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test "$_lt_disable_F77" != yes; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC="$CC"
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${F77-"f77"}
CFLAGS=$FFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
GCC=$G77
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
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
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test "$enable_shared" = yes || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)="$G77"
_LT_TAGVAR(LD, $1)="$LD"
## 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...
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC="$lt_save_CC"
CFLAGS="$lt_save_CFLAGS"
fi # test "$_lt_disable_F77" != yes
AC_LANG_POP
])# _LT_LANG_F77_CONFIG
# _LT_LANG_FC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for a Fortran compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to `libtool'.
m4_defun([_LT_LANG_FC_CONFIG],
[AC_LANG_PUSH(Fortran)
if test -z "$FC" || test "X$FC" = "Xno"; then
_lt_disable_FC=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for fc test sources.
ac_ext=${ac_fc_srcext-f}
# Object file extension for compiled fc test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the FC compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test "$_lt_disable_FC" != yes; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC="$CC"
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${FC-"f95"}
CFLAGS=$FCFLAGS
compiler=$CC
GCC=$ac_cv_fc_compiler_gnu
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
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
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test "$enable_shared" = yes || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
_LT_TAGVAR(LD, $1)="$LD"
## 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...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
fi # test "$_lt_disable_FC" != yes
AC_LANG_POP
])# _LT_LANG_FC_CONFIG
# _LT_LANG_GCJ_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Java Compiler compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to `libtool'.
m4_defun([_LT_LANG_GCJ_CONFIG],
[AC_REQUIRE([LT_PROG_GCJ])dnl
AC_LANG_SAVE
# Source file extension for Java test sources.
ac_ext=java
# Object file extension for compiled Java test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="class foo {}"
# Code to be used in simple link tests
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GCJ-"gcj"}
CFLAGS=$GCJFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)="$LD"
_LT_CC_BASENAME([$compiler])
# GCJ did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## 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_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GCJ_CONFIG
# _LT_LANG_GO_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Go compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to `libtool'.
m4_defun([_LT_LANG_GO_CONFIG],
[AC_REQUIRE([LT_PROG_GO])dnl
AC_LANG_SAVE
# Source file extension for Go test sources.
ac_ext=go
# Object file extension for compiled Go test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="package main; func main() { }"
# Code to be used in simple link tests
lt_simple_link_test_code='package main; func main() { }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GOC-"gccgo"}
CFLAGS=$GOFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)="$LD"
_LT_CC_BASENAME([$compiler])
# Go did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## 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_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GO_CONFIG
# _LT_LANG_RC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for the Windows resource compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to `libtool'.
m4_defun([_LT_LANG_RC_CONFIG],
[AC_REQUIRE([LT_PROG_RC])dnl
AC_LANG_SAVE
# Source file extension for RC test sources.
ac_ext=rc
# Object file extension for compiled RC test sources.
objext=o
_LT_TAGVAR(objext, $1)=$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.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# 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
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
if test -n "$compiler"; then
:
_LT_CONFIG($1)
fi
GCC=$lt_save_GCC
AC_LANG_RESTORE
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_RC_CONFIG
# LT_PROG_GCJ
# -----------
AC_DEFUN([LT_PROG_GCJ],
[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
[m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
[AC_CHECK_TOOL(GCJ, gcj,)
test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
AC_SUBST(GCJFLAGS)])])[]dnl
])
# Old name:
AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
# LT_PROG_GO
# ----------
AC_DEFUN([LT_PROG_GO],
[AC_CHECK_TOOL(GOC, gccgo,)
])
# LT_PROG_RC
# ----------
AC_DEFUN([LT_PROG_RC],
[AC_CHECK_TOOL(RC, windres,)
])
# Old name:
AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_RC], [])
# _LT_DECL_EGREP
# --------------
# If we don't have a new enough Autoconf to choose the best grep
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_EGREP],
[AC_REQUIRE([AC_PROG_EGREP])dnl
AC_REQUIRE([AC_PROG_FGREP])dnl
test -z "$GREP" && GREP=grep
_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
_LT_DECL([], [EGREP], [1], [An ERE matcher])
_LT_DECL([], [FGREP], [1], [A literal string matcher])
dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
AC_SUBST([GREP])
])
# _LT_DECL_OBJDUMP
# --------------
# If we don't have a new enough Autoconf to choose the best objdump
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_OBJDUMP],
[AC_CHECK_TOOL(OBJDUMP, objdump, false)
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
AC_SUBST([OBJDUMP])
])
# _LT_DECL_DLLTOOL
# ----------------
# Ensure DLLTOOL variable is set.
m4_defun([_LT_DECL_DLLTOOL],
[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])
# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates
# as few characters as possible. Prefer GNU sed if found.
m4_defun([_LT_DECL_SED],
[AC_PROG_SED
test -z "$SED" && SED=sed
Xsed="$SED -e 1s/^X//"
_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
[Sed that helps us avoid accidentally triggering echo(1) options like -n])
])# _LT_DECL_SED
m4_ifndef([AC_PROG_SED], [
############################################################
# NOTE: This macro has been submitted for inclusion into #
# GNU Autoconf as AC_PROG_SED. When it is available in #
# a released version of Autoconf we should remove this #
# macro and use it instead. #
############################################################
m4_defun([AC_PROG_SED],
[AC_MSG_CHECKING([for a sed that does not truncate output])
AC_CACHE_VAL(lt_cv_path_SED,
[# Loop through the user's path and test for sed and gsed.
# Then use that list of sed's as ones to test for truncation.
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for lt_ac_prog in sed gsed; do
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
fi
done
done
done
IFS=$as_save_IFS
lt_ac_max=0
lt_ac_count=0
# Add /usr/xpg4/bin/sed as it is typically found on Solaris
# along with /bin/sed that truncates output.
for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
test ! -f $lt_ac_sed && continue
cat /dev/null > conftest.in
lt_ac_count=0
echo $ECHO_N "0123456789$ECHO_C" >conftest.in
# Check for GNU sed and select it if it is found.
if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
lt_cv_path_SED=$lt_ac_sed
break
fi
while true; do
cat conftest.in conftest.in >conftest.tmp
mv conftest.tmp conftest.in
cp conftest.in conftest.nl
echo >>conftest.nl
$lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
cmp -s conftest.out conftest.nl || break
# 10000 chars as input seems more than enough
test $lt_ac_count -gt 10 && break
lt_ac_count=`expr $lt_ac_count + 1`
if test $lt_ac_count -gt $lt_ac_max; then
lt_ac_max=$lt_ac_count
lt_cv_path_SED=$lt_ac_sed
fi
done
done
])
SED=$lt_cv_path_SED
AC_SUBST([SED])
AC_MSG_RESULT([$SED])
])#AC_PROG_SED
])#m4_ifndef
# Old name:
AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_SED], [])
# _LT_CHECK_SHELL_FEATURES
# ------------------------
# Find out whether the shell is Bourne or XSI compatible,
# or has some other useful features.
m4_defun([_LT_CHECK_SHELL_FEATURES],
[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
# 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
AC_MSG_RESULT([$xsi_shell])
_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
AC_MSG_CHECKING([whether the shell understands "+="])
lt_shell_append=no
( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
>/dev/null 2>&1 \
&& lt_shell_append=yes
AC_MSG_RESULT([$lt_shell_append])
_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
lt_unset=unset
else
lt_unset=false
fi
_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
# 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
_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
])# _LT_CHECK_SHELL_FEATURES
# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
# ------------------------------------------------------
# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
m4_defun([_LT_PROG_FUNCTION_REPLACE],
[dnl {
sed -e '/^$1 ()$/,/^} # $1 /c\
$1 ()\
{\
m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1])
} # Extended-shell $1 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=:
])
# _LT_PROG_REPLACE_SHELLFNS
# -------------------------
# Replace existing portable implementations of several shell functions with
# equivalent extended shell implementations where those features are available..
m4_defun([_LT_PROG_REPLACE_SHELLFNS],
[if test x"$xsi_shell" = xyes; then
_LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
case ${1} in
*/*) func_dirname_result="${1%/*}${2}" ;;
* ) func_dirname_result="${3}" ;;
esac])
_LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
func_basename_result="${1##*/}"])
_LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
case ${1} in
*/*) func_dirname_result="${1%/*}${2}" ;;
* ) func_dirname_result="${3}" ;;
esac
func_basename_result="${1##*/}"])
_LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
# 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}"}])
_LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
func_split_long_opt_name=${1%%=*}
func_split_long_opt_arg=${1#*=}])
_LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
func_split_short_opt_arg=${1#??}
func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
_LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
case ${1} in
*.lo) func_lo2o_result=${1%.lo}.${objext} ;;
*) func_lo2o_result=${1} ;;
esac])
_LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo])
_LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))])
_LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}])
fi
if test x"$lt_shell_append" = xyes; then
_LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"])
_LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
func_quote_for_eval "${2}"
dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
# 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
AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
fi
])
# _LT_PATH_CONVERSION_FUNCTIONS
# -----------------------------
# Determine which file name conversion functions should be used by
# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
# for certain cross-compile configurations and native mingw.
m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_MSG_CHECKING([how to convert $build file names to $host format])
AC_CACHE_VAL(lt_cv_to_host_file_cmd,
[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
])
to_host_file_cmd=$lt_cv_to_host_file_cmd
AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
[0], [convert $build file names to $host format])dnl
AC_MSG_CHECKING([how to convert $build file names to toolchain format])
AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
[#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
])
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
[0], [convert $build files to toolchain format])dnl
])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/mpi/aarch64/mpih-add1.S b/mpi/aarch64/mpih-add1.S
index bc62cf98..dce6564e 100644
--- a/mpi/aarch64/mpih-add1.S
+++ b/mpi/aarch64/mpih-add1.S
@@ -1,74 +1,74 @@
/* ARM64 add_n -- Add two limb vectors of the same length > 0 and store
* sum in a third limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#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) w3
*/
.text
.globl _gcry_mpih_add_n
ELF(.type _gcry_mpih_add_n,%function)
_gcry_mpih_add_n:
CFI_STARTPROC()
and w5, w3, #3;
adds xzr, xzr, xzr; /* clear carry flag */
cbz w5, .Large_loop;
.Loop:
ldr x4, [x1], #8;
sub w3, w3, #1;
ldr x11, [x2], #8;
and w5, w3, #3;
adcs x4, x4, x11;
str x4, [x0], #8;
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 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 w3, .Large_loop;
.Lend:
adc x0, xzr, xzr;
ret;
CFI_ENDPROC()
ELF(.size _gcry_mpih_add_n,.-_gcry_mpih_add_n;)
diff --git a/mpi/aarch64/mpih-mul1.S b/mpi/aarch64/mpih-mul1.S
index 92fcd141..608808a7 100644
--- a/mpi/aarch64/mpih-mul1.S
+++ b/mpi/aarch64/mpih-mul1.S
@@ -1,99 +1,99 @@
/* ARM64 mul_1 -- Multiply a limb vector with a limb and store the result in
* a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#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, w2
* mpi_limb_t s2_limb) x3
*/
.text
.globl _gcry_mpih_mul_1
ELF(.type _gcry_mpih_mul_1,%function)
_gcry_mpih_mul_1:
CFI_STARTPROC()
and w5, w2, #3;
mov x4, xzr;
cbz w5, .Large_loop;
.Loop:
ldr x5, [x1], #8;
sub w2, w2, #1;
mul x9, x5, x3;
umulh x10, x5, x3;
and w5, w2, #3;
adds x4, x4, x9;
str x4, [x0], #8;
adc x4, x10, xzr;
cbz w2, .Lend;
cbnz w5, .Loop;
.Large_loop:
ldp x5, x6, [x1];
sub w2, w2, #4;
mul x9, x5, x3;
ldp x7, x8, [x1, #16];
umulh x10, x5, x3;
add x1, x1, #32;
adds x4, x4, x9;
str x4, [x0], #8;
mul x11, x6, x3;
adc x4, x10, xzr;
umulh x12, x6, x3;
adds x4, x4, x11;
str x4, [x0], #8;
mul x13, x7, x3;
adc x4, x12, xzr;
umulh x14, x7, x3;
adds x4, x4, x13;
str x4, [x0], #8;
mul x15, x8, x3;
adc x4, x14, xzr;
umulh x16, x8, x3;
adds x4, x4, x15;
str x4, [x0], #8;
adc x4, x16, xzr;
cbnz w2, .Large_loop;
.Lend:
mov x0, x4;
ret;
CFI_ENDPROC()
ELF(.size _gcry_mpih_mul_1,.-_gcry_mpih_mul_1;)
diff --git a/mpi/aarch64/mpih-mul2.S b/mpi/aarch64/mpih-mul2.S
index aa0e5a2d..1052add0 100644
--- a/mpi/aarch64/mpih-mul2.S
+++ b/mpi/aarch64/mpih-mul2.S
@@ -1,111 +1,111 @@
/* ARM64 mul_2 -- Multiply a limb vector with a limb and add the result to
* a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#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, w2
* mpi_limb_t s2_limb) x3
*/
.text
.globl _gcry_mpih_addmul_1
ELF(.type _gcry_mpih_addmul_1,%function)
_gcry_mpih_addmul_1:
CFI_STARTPROC()
and w5, w2, #3;
mov x6, xzr;
mov x7, xzr;
cbz w5, .Large_loop;
.Loop:
ldr x5, [x1], #8;
mul x12, x5, x3;
ldr x4, [x0];
umulh x13, x5, x3;
sub w2, w2, #1;
adds x12, x12, x4;
and w5, w2, #3;
adc x13, x13, x7;
adds x12, x12, x6;
str x12, [x0], #8;
adc x6, x7, x13;
cbz w2, .Lend;
cbnz w5, .Loop;
.Large_loop:
ldp x5, x9, [x1], #16;
sub w2, w2, #4;
ldp x4, x8, [x0];
mul x12, x5, x3;
umulh x13, x5, x3;
adds x12, x12, x4;
mul x14, x9, x3;
adc x13, x13, x7;
adds x12, x12, x6;
umulh x15, x9, x3;
str x12, [x0], #8;
adc x6, x7, x13;
adds x14, x14, x8;
ldp x5, x9, [x1], #16;
adc x15, x15, x7;
adds x14, x14, x6;
mul x12, x5, x3;
str x14, [x0], #8;
ldp x4, x8, [x0];
umulh x13, x5, x3;
adc x6, x7, x15;
adds x12, x12, x4;
mul x14, x9, x3;
adc x13, x13, x7;
adds x12, x12, x6;
umulh x15, x9, x3;
str x12, [x0], #8;
adc x6, x7, x13;
adds x14, x14, x8;
adc x15, x15, x7;
adds x14, x14, x6;
str x14, [x0], #8;
adc x6, x7, x15;
cbnz w2, .Large_loop;
.Lend:
mov x0, x6;
ret;
CFI_ENDPROC()
ELF(.size _gcry_mpih_addmul_1,.-_gcry_mpih_addmul_1;)
diff --git a/mpi/aarch64/mpih-mul3.S b/mpi/aarch64/mpih-mul3.S
index 5a40b354..71404b1b 100644
--- a/mpi/aarch64/mpih-mul3.S
+++ b/mpi/aarch64/mpih-mul3.S
@@ -1,124 +1,124 @@
/* ARM mul_3 -- Multiply a limb vector with a limb and subtract the result
* from a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#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, w2
* mpi_limb_t s2_limb) x3
*/
.text
.globl _gcry_mpih_submul_1
ELF(.type _gcry_mpih_submul_1,%function)
_gcry_mpih_submul_1:
CFI_STARTPROC()
and w5, w2, #3;
mov x7, xzr;
cbz w5, .Large_loop;
subs xzr, xzr, xzr;
.Loop:
ldr x4, [x1], #8;
cinc x7, x7, cc;
ldr x5, [x0];
sub w2, w2, #1;
mul x6, x4, x3;
subs x5, x5, x7;
umulh x4, x4, x3;
and w10, w2, #3;
cset x7, cc;
subs x5, x5, x6;
add x7, x7, x4;
str x5, [x0], #8;
cbz w2, .Loop_end;
cbnz w10, .Loop;
cinc x7, x7, cc;
.Large_loop:
ldp x4, x8, [x1], #16;
sub w2, w2, #4;
ldp x5, x9, [x0];
mul x6, x4, x3;
subs x5, x5, x7;
umulh x4, x4, x3;
cset x7, cc;
subs x5, x5, x6;
mul x6, x8, x3;
add x7, x7, x4;
str x5, [x0], #8;
cinc x7, x7, cc;
umulh x8, x8, x3;
subs x9, x9, x7;
cset x7, cc;
subs x9, x9, x6;
ldp x4, x10, [x1], #16;
str x9, [x0], #8;
add x7, x7, x8;
ldp x5, x9, [x0];
cinc x7, x7, cc;
mul x6, x4, x3;
subs x5, x5, x7;
umulh x4, x4, x3;
cset x7, cc;
subs x5, x5, x6;
mul x6, x10, x3;
add x7, x7, x4;
str x5, [x0], #8;
cinc x7, x7, cc;
umulh x10, x10, x3;
subs x9, x9, x7;
cset x7, cc;
subs x9, x9, x6;
add x7, x7, x10;
str x9, [x0], #8;
cinc x7, x7, cc;
cbnz w2, .Large_loop;
mov x0, x7;
ret;
.Loop_end:
cinc x0, x7, cc;
ret;
CFI_ENDPROC()
ELF(.size _gcry_mpih_submul_1,.-_gcry_mpih_submul_1;)
diff --git a/mpi/aarch64/mpih-sub1.S b/mpi/aarch64/mpih-sub1.S
index 4f279a12..46078c2a 100644
--- a/mpi/aarch64/mpih-sub1.S
+++ b/mpi/aarch64/mpih-sub1.S
@@ -1,74 +1,74 @@
/* ARM64 sub_n -- Subtract two limb vectors of the same length > 0 and store
* sum in a third limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
*/
#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) w3
*/
.text
.globl _gcry_mpih_sub_n
ELF(.type _gcry_mpih_sub_n,%function)
_gcry_mpih_sub_n:
CFI_STARTPROC()
and w5, w3, #3;
subs xzr, xzr, xzr; /* prepare carry flag for sub */
cbz w5, .Large_loop;
.Loop:
ldr x4, [x1], #8;
sub w3, w3, #1;
ldr x11, [x2], #8;
and w5, w3, #3;
sbcs x4, x4, x11;
str x4, [x0], #8;
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 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 w3, .Large_loop;
.Lend:
cset x0, cc;
ret;
CFI_ENDPROC()
ELF(.size _gcry_mpih_sub_n,.-_gcry_mpih_sub_n;)
diff --git a/mpi/arm/mpih-add1.S b/mpi/arm/mpih-add1.S
index 09e8b3b2..8d6886f8 100644
--- a/mpi/arm/mpih-add1.S
+++ b/mpi/arm/mpih-add1.S
@@ -1,76 +1,76 @@
/* ARM add_n -- Add two limb vectors of the same length > 0 and store
* sum in a third limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* Note: This code is heavily based on the GNU MP Library (version 4.2.1).
*/
#include "sysdep.h"
#include "asm-syntax.h"
.syntax unified
.arm
/*******************
* mpi_limb_t
* _gcry_mpih_add_n( mpi_ptr_t res_ptr, %r0
* mpi_ptr_t s1_ptr, %r1
* mpi_ptr_t s2_ptr, %r2
* mpi_size_t size) %r3
*/
.text
.globl _gcry_mpih_add_n
.type _gcry_mpih_add_n,%function
_gcry_mpih_add_n:
push {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %lr};
cmn %r0, #0; /* clear carry flag */
tst %r3, #3;
beq .Large_loop;
.Loop:
ldr %r4, [%r1], #4;
sub %r3, #1;
ldr %lr, [%r2], #4;
adcs %r4, %lr;
tst %r3, #3;
str %r4, [%r0], #4;
bne .Loop;
teq %r3, #0;
beq .Lend;
.Large_loop:
ldm %r1!, {%r4, %r6, %r8, %r10};
ldm %r2!, {%r5, %r7, %r9, %lr};
sub %r3, #4;
adcs %r4, %r5;
adcs %r6, %r7;
adcs %r8, %r9;
adcs %r10, %lr;
teq %r3, #0;
stm %r0!, {%r4, %r6, %r8, %r10};
bne .Large_loop;
.Lend:
adc %r0, %r3, #0;
pop {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %pc};
.size _gcry_mpih_add_n,.-_gcry_mpih_add_n;
diff --git a/mpi/arm/mpih-mul1.S b/mpi/arm/mpih-mul1.S
index c2e2854b..3ec57e28 100644
--- a/mpi/arm/mpih-mul1.S
+++ b/mpi/arm/mpih-mul1.S
@@ -1,80 +1,80 @@
/* ARM mul_1 -- Multiply a limb vector with a limb and store the result in
* a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* Note: This code is heavily based on the GNU MP Library (version 4.2.1).
*/
#include "sysdep.h"
#include "asm-syntax.h"
.syntax unified
.arm
/*******************
* mpi_limb_t
* _gcry_mpih_mul_1( mpi_ptr_t res_ptr, %r0
* mpi_ptr_t s1_ptr, %r1
* mpi_size_t s1_size, %r2
* mpi_limb_t s2_limb) %r3
*/
.text
.globl _gcry_mpih_mul_1
.type _gcry_mpih_mul_1,%function
_gcry_mpih_mul_1:
push {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %r11, %lr};
mov %r4, #0;
tst %r2, #3;
beq .Large_loop;
.Loop:
ldr %r5, [%r1], #4;
mov %lr, #0;
umlal %r4, %lr, %r5, %r3;
sub %r2, #1;
str %r4, [%r0], #4;
tst %r2, #3;
mov %r4, %lr;
bne .Loop;
teq %r2, #0;
beq .Lend;
.Large_loop:
ldm %r1!, {%r5, %r6, %r7, %r8};
mov %r9, #0;
mov %r10, #0;
umlal %r4, %r9, %r5, %r3;
mov %r11, #0;
umlal %r9, %r10, %r6, %r3;
str %r4, [%r0], #4;
mov %r4, #0;
umlal %r10, %r11, %r7, %r3;
subs %r2, #4;
umlal %r11, %r4, %r8, %r3;
stm %r0!, {%r9, %r10, %r11};
bne .Large_loop;
.Lend:
mov %r0, %r4;
pop {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %r11, %pc};
.size _gcry_mpih_mul_1,.-_gcry_mpih_mul_1;
diff --git a/mpi/arm/mpih-mul2.S b/mpi/arm/mpih-mul2.S
index bce932e9..6efb8003 100644
--- a/mpi/arm/mpih-mul2.S
+++ b/mpi/arm/mpih-mul2.S
@@ -1,94 +1,94 @@
/* ARM mul_2 -- Multiply a limb vector with a limb and add the result to
* a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* Note: This code is heavily based on the GNU MP Library (version 4.2.1).
*/
#include "sysdep.h"
#include "asm-syntax.h"
.syntax unified
.arm
/*******************
* mpi_limb_t
* _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, %r0
* mpi_ptr_t s1_ptr, %r1
* mpi_size_t s1_size, %r2
* mpi_limb_t s2_limb) %r3
*/
.text
.globl _gcry_mpih_addmul_1
.type _gcry_mpih_addmul_1,%function
_gcry_mpih_addmul_1:
push {%r4, %r5, %r6, %r8, %r10, %lr};
mov %lr, #0;
cmn %r0, #0; /* clear carry flag */
tst %r2, #3;
beq .Large_loop;
.Loop:
ldr %r5, [%r1], #4;
ldr %r4, [%r0];
sub %r2, #1;
adcs %r4, %lr;
mov %lr, #0;
umlal %r4, %lr, %r5, %r3;
tst %r2, #3;
str %r4, [%r0], #4;
bne .Loop;
teq %r2, #0;
beq .Lend;
.Large_loop:
ldr %r5, [%r1], #4;
ldm %r0, {%r4, %r6, %r8, %r10};
sub %r2, #4;
adcs %r4, %lr;
mov %lr, #0;
umlal %r4, %lr, %r5, %r3;
ldr %r5, [%r1], #4;
adcs %r6, %lr;
mov %lr, #0;
umlal %r6, %lr, %r5, %r3;
ldr %r5, [%r1], #4;
adcs %r8, %lr;
mov %lr, #0;
umlal %r8, %lr, %r5, %r3;
ldr %r5, [%r1], #4;
adcs %r10, %lr;
mov %lr, #0;
umlal %r10, %lr, %r5, %r3;
teq %r2, #0;
stm %r0!, {%r4, %r6, %r8, %r10};
bne .Large_loop;
.Lend:
adc %r0, %lr, #0;
pop {%r4, %r5, %r6, %r8, %r10, %pc};
.size _gcry_mpih_addmul_1,.-_gcry_mpih_addmul_1;
diff --git a/mpi/arm/mpih-mul3.S b/mpi/arm/mpih-mul3.S
index 33326c78..980b39b2 100644
--- a/mpi/arm/mpih-mul3.S
+++ b/mpi/arm/mpih-mul3.S
@@ -1,100 +1,100 @@
/* ARM mul_3 -- Multiply a limb vector with a limb and subtract the result
* from a second limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* Note: This code is heavily based on the GNU MP Library (version 4.2.1).
*/
#include "sysdep.h"
#include "asm-syntax.h"
.syntax unified
.arm
/*******************
* mpi_limb_t
* _gcry_mpih_submul_1( mpi_ptr_t res_ptr, %r0
* mpi_ptr_t s1_ptr, %r1
* mpi_size_t s1_size, %r2
* mpi_limb_t s2_limb) %r3
*/
.text
.globl _gcry_mpih_submul_1
.type _gcry_mpih_submul_1,%function
_gcry_mpih_submul_1:
push {%r4, %r5, %r6, %r8, %r9, %r10, %lr};
mov %lr, #0;
cmp %r0, #0; /* prepare carry flag for sbc */
tst %r2, #3;
beq .Large_loop;
.Loop:
ldr %r5, [%r1], #4;
mov %r4, %lr;
mov %lr, #0;
ldr %r6, [%r0];
umlal %r4, %lr, %r5, %r3;
sub %r2, #1;
sbcs %r4, %r6, %r4;
tst %r2, #3;
str %r4, [%r0], #4;
bne .Loop;
teq %r2, #0;
beq .Lend;
.Large_loop:
ldr %r5, [%r1], #4;
mov %r9, #0;
ldr %r4, [%r0, #0];
umlal %lr, %r9, %r5, %r3;
ldr %r6, [%r0, #4];
ldr %r5, [%r1], #4;
sbcs %r4, %r4, %lr;
mov %lr, #0;
umlal %r9, %lr, %r5, %r3;
ldr %r8, [%r0, #8];
ldr %r5, [%r1], #4;
sbcs %r6, %r6, %r9;
mov %r9, #0;
umlal %lr, %r9, %r5, %r3;
ldr %r10, [%r0, #12];
ldr %r5, [%r1], #4;
sbcs %r8, %r8, %lr;
mov %lr, #0;
umlal %r9, %lr, %r5, %r3;
sub %r2, #4;
sbcs %r10, %r10, %r9;
teq %r2, #0;
stm %r0!, {%r4, %r6, %r8, %r10};
bne .Large_loop;
.Lend:
it cc
movcc %r2, #1;
add %r0, %lr, %r2;
pop {%r4, %r5, %r6, %r8, %r9, %r10, %pc};
.size _gcry_mpih_submul_1,.-_gcry_mpih_submul_1;
diff --git a/mpi/arm/mpih-sub1.S b/mpi/arm/mpih-sub1.S
index 593e3cde..88b4a335 100644
--- a/mpi/arm/mpih-sub1.S
+++ b/mpi/arm/mpih-sub1.S
@@ -1,77 +1,77 @@
/* ARM sub_n -- Subtract two limb vectors of the same length > 0 and store
* sum in a third limb vector.
*
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* Note: This code is heavily based on the GNU MP Library (version 4.2.1).
*/
#include "sysdep.h"
#include "asm-syntax.h"
.syntax unified
.arm
/*******************
* mpi_limb_t
* _gcry_mpih_sub_n( mpi_ptr_t res_ptr, %r0
* mpi_ptr_t s1_ptr, %r1
* mpi_ptr_t s2_ptr, %r2
* mpi_size_t size) %r3
*/
.text
.globl _gcry_mpih_sub_n
.type _gcry_mpih_sub_n,%function
_gcry_mpih_sub_n:
push {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %lr};
cmp %r0, #0; /* prepare carry flag for sub */
tst %r3, #3;
beq .Large_loop;
.Loop:
ldr %r4, [%r1], #4;
sub %r3, #1;
ldr %lr, [%r2], #4;
sbcs %r4, %lr;
tst %r3, #3;
str %r4, [%r0], #4;
bne .Loop;
teq %r3, #0;
beq .Lend;
.Large_loop:
ldm %r1!, {%r4, %r6, %r8, %r10};
sub %r3, #4;
ldm %r2!, {%r5, %r7, %r9, %lr};
sbcs %r4, %r5;
sbcs %r6, %r7;
sbcs %r8, %r9;
sbcs %r10, %lr;
teq %r3, #0;
stm %r0!, {%r4, %r6, %r8, %r10};
bne .Large_loop;
.Lend:
sbc %r0, %r3, #0;
neg %r0, %r0;
pop {%r4, %r5, %r6, %r7, %r8, %r9, %r10, %pc};
.size _gcry_mpih_sub_n,.-_gcry_mpih_sub_n;
diff --git a/mpi/asm-common-aarch64.h b/mpi/asm-common-aarch64.h
index cf4bdb85..c86a5be3 100644
--- a/mpi/asm-common-aarch64.h
+++ b/mpi/asm-common-aarch64.h
@@ -1,26 +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/>.
+ * License along with this program; if not, see <https://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/ec-ed25519.c b/mpi/ec-ed25519.c
index acfe2a69..831cc927 100644
--- a/mpi/ec-ed25519.c
+++ b/mpi/ec-ed25519.c
@@ -1,37 +1,37 @@
/* ec-ed25519.c - Ed25519 optimized elliptic curve functions
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "mpi-internal.h"
#include "longlong.h"
#include "g10lib.h"
#include "context.h"
#include "ec-context.h"
void
_gcry_mpi_ec_ed25519_mod (gcry_mpi_t a)
{
(void)a;
}
diff --git a/mpi/ec-internal.h b/mpi/ec-internal.h
index 759335aa..4eedebf3 100644
--- a/mpi/ec-internal.h
+++ b/mpi/ec-internal.h
@@ -1,25 +1,25 @@
/* ec-internal.h - Internal declarations of ec*.c
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_EC_INTERNAL_H
#define GCRY_EC_INTERNAL_H
void _gcry_mpi_ec_ed25519_mod (gcry_mpi_t a);
#endif /*GCRY_EC_INTERNAL_H*/
diff --git a/mpi/ec.c b/mpi/ec.c
index 97afbfed..7977b409 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1,1843 +1,1843 @@
/* ec.c - Elliptic Curve functions
* Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "mpi-internal.h"
#include "longlong.h"
#include "g10lib.h"
#include "context.h"
#include "ec-context.h"
#include "ec-internal.h"
#define point_init(a) _gcry_mpi_point_init ((a))
#define point_free(a) _gcry_mpi_point_free_parts ((a))
/* Print a point using the log functions. If CTX is not NULL affine
coordinates will be printed. */
void
_gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx)
{
gcry_mpi_t x, y;
char buf[100];
if (!point)
{
snprintf (buf, sizeof buf - 1, "%s.*", name);
log_mpidump (buf, NULL);
return;
}
snprintf (buf, sizeof buf - 1, "%s.X", name);
if (ctx)
{
x = mpi_new (0);
y = mpi_new (0);
}
if (!ctx || _gcry_mpi_ec_get_affine (x, y, point, ctx))
{
log_mpidump (buf, point->x);
buf[strlen(buf)-1] = 'Y';
log_mpidump (buf, point->y);
buf[strlen(buf)-1] = 'Z';
log_mpidump (buf, point->z);
}
else
{
buf[strlen(buf)-1] = 'x';
log_mpidump (buf, x);
buf[strlen(buf)-1] = 'y';
log_mpidump (buf, y);
}
if (ctx)
{
_gcry_mpi_release (x);
_gcry_mpi_release (y);
}
}
/* Create a new point option. NBITS gives the size in bits of one
coordinate; it is only used to pre-allocate some resources and
might also be passed as 0 to use a default value. */
mpi_point_t
_gcry_mpi_point_new (unsigned int nbits)
{
mpi_point_t p;
(void)nbits; /* Currently not used. */
p = xmalloc (sizeof *p);
_gcry_mpi_point_init (p);
return p;
}
/* Release the point object P. P may be NULL. */
void
_gcry_mpi_point_release (mpi_point_t p)
{
if (p)
{
_gcry_mpi_point_free_parts (p);
xfree (p);
}
}
/* Initialize the fields of a point object. gcry_mpi_point_free_parts
may be used to release the fields. */
void
_gcry_mpi_point_init (mpi_point_t p)
{
p->x = mpi_new (0);
p->y = mpi_new (0);
p->z = mpi_new (0);
}
/* Release the parts of a point object. */
void
_gcry_mpi_point_free_parts (mpi_point_t p)
{
mpi_free (p->x); p->x = NULL;
mpi_free (p->y); p->y = NULL;
mpi_free (p->z); p->z = NULL;
}
/* Set the value from S into D. */
static void
point_set (mpi_point_t d, mpi_point_t s)
{
mpi_set (d->x, s->x);
mpi_set (d->y, s->y);
mpi_set (d->z, s->z);
}
/* Return a copy of POINT. */
gcry_mpi_point_t
_gcry_mpi_point_copy (gcry_mpi_point_t point)
{
mpi_point_t newpoint;
newpoint = _gcry_mpi_point_new (0);
if (point)
point_set (newpoint, point);
return newpoint;
}
static void
point_resize (mpi_point_t p, mpi_ec_t ctx)
{
size_t nlimbs = ctx->p->nlimbs;
mpi_resize (p->x, 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;
}
}
static void
point_swap_cond (mpi_point_t d, mpi_point_t s, unsigned long swap,
mpi_ec_t ctx)
{
mpi_swap_cond (d->x, s->x, swap);
if (ctx->model != MPI_EC_MONTGOMERY)
mpi_swap_cond (d->y, s->y, swap);
mpi_swap_cond (d->z, s->z, swap);
}
/* Set the projective coordinates from POINT into X, Y, and Z. If a
coordinate is not required, X, Y, or Z may be passed as NULL. */
void
_gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
mpi_point_t point)
{
if (x)
mpi_set (x, point->x);
if (y)
mpi_set (y, point->y);
if (z)
mpi_set (z, point->z);
}
/* Set the projective coordinates from POINT into X, Y, and Z and
release POINT. If a coordinate is not required, X, Y, or Z may be
passed as NULL. */
void
_gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
mpi_point_t point)
{
mpi_snatch (x, point->x);
mpi_snatch (y, point->y);
mpi_snatch (z, point->z);
xfree (point);
}
/* Set the projective coordinates from X, Y, and Z into POINT. If a
coordinate is given as NULL, the value 0 is stored into point. If
POINT is given as NULL a new point object is allocated. Returns
POINT or the newly allocated point object. */
mpi_point_t
_gcry_mpi_point_set (mpi_point_t point,
gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
{
if (!point)
point = mpi_point_new (0);
if (x)
mpi_set (point->x, x);
else
mpi_clear (point->x);
if (y)
mpi_set (point->y, y);
else
mpi_clear (point->y);
if (z)
mpi_set (point->z, z);
else
mpi_clear (point->z);
return point;
}
/* Set the projective coordinates from X, Y, and Z into POINT. If a
coordinate is given as NULL, the value 0 is stored into point. If
POINT is given as NULL a new point object is allocated. The
coordinates X, Y, and Z are released. Returns POINT or the newly
allocated point object. */
mpi_point_t
_gcry_mpi_point_snatch_set (mpi_point_t point,
gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z)
{
if (!point)
point = mpi_point_new (0);
if (x)
mpi_snatch (point->x, x);
else
mpi_clear (point->x);
if (y)
mpi_snatch (point->y, y);
else
mpi_clear (point->y);
if (z)
mpi_snatch (point->z, z);
else
mpi_clear (point->z);
return point;
}
/* W = W mod P. */
static void
ec_mod (gcry_mpi_t w, mpi_ec_t ec)
{
if (0 && ec->dialect == ECC_DIALECT_ED25519)
_gcry_mpi_ec_ed25519_mod (w);
else if (ec->t.p_barrett)
_gcry_mpi_mod_barrett (w, w, ec->t.p_barrett);
else
_gcry_mpi_mod (w, w, ec->p);
}
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);
}
static void
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);*/
}
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);
}
/* W = 2 * U mod P. */
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);
}
static void
ec_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e,
mpi_ec_t ctx)
{
mpi_powm (w, b, e, ctx->p);
/* _gcry_mpi_abs (w); */
}
/* Shortcut for
ec_powm (B, B, mpi_const (MPI_C_TWO), ctx);
for easier optimization. */
static void
ec_pow2 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
{
/* Using mpi_mul is slightly faster (at least on amd64). */
/* mpi_powm (w, b, mpi_const (MPI_C_TWO), ctx->p); */
ec_mulm (w, b, b, ctx);
}
/* Shortcut for
ec_powm (B, B, mpi_const (MPI_C_THREE), ctx);
for easier optimization. */
static void
ec_pow3 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
{
mpi_powm (w, b, mpi_const (MPI_C_THREE), ctx->p);
}
static void
ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
{
if (!mpi_invm (x, a, ctx->p))
{
log_error ("ec_invm: inverse does not exist:\n");
log_mpidump (" a", a);
log_mpidump (" p", ctx->p);
}
}
static void
mpih_set_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned long set)
{
mpi_size_t i;
mpi_limb_t mask = ((mpi_limb_t)0) - set;
mpi_limb_t x;
for (i = 0; i < usize; i++)
{
x = mask & (wp[i] ^ up[i]);
wp[i] = wp[i] ^ x;
}
}
/* 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");
memset (n, 0, sizeof n);
up = u->d;
vp = v->d;
wp = w->d;
_gcry_mpih_add_n (wp, up, vp, wsize);
borrow = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize);
mpih_set_cond (n, ctx->p->d, wsize, (borrow != 0UL));
_gcry_mpih_add_n (wp, wp, n, wsize);
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");
memset (n, 0, sizeof n);
up = u->d;
vp = v->d;
wp = w->d;
borrow = _gcry_mpih_sub_n (wp, up, vp, wsize);
mpih_set_cond (n, ctx->p->d, wsize, (borrow != 0UL));
_gcry_mpih_add_n (wp, wp, n, wsize);
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 m[LIMB_SIZE_25519+1];
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));
memcpy (m, n+LIMB_SIZE_25519-1, (wsize+1) * BYTES_PER_MPI_LIMB);
_gcry_mpih_rshift (m, m, LIMB_SIZE_25519+1, (255 % BITS_PER_MPI_LIMB));
memcpy (n, m, wsize * BYTES_PER_MPI_LIMB);
cy = _gcry_mpih_lshift (m, m, LIMB_SIZE_25519, 4);
m[LIMB_SIZE_25519] = cy;
cy = _gcry_mpih_add_n (m, m, n, wsize);
m[LIMB_SIZE_25519] += cy;
cy = _gcry_mpih_add_n (m, m, n, wsize);
m[LIMB_SIZE_25519] += cy;
cy = _gcry_mpih_add_n (m, m, n, wsize);
m[LIMB_SIZE_25519] += cy;
cy = _gcry_mpih_add_n (wp, wp, m, wsize);
m[LIMB_SIZE_25519] += cy;
memset (m, 0, wsize * BYTES_PER_MPI_LIMB);
msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
m[0] = (m[LIMB_SIZE_25519] * 2 + msb) * 19;
wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
_gcry_mpih_add_n (wp, wp, m, wsize);
m[0] = 0;
cy = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize);
mpih_set_cond (m, ctx->p->d, wsize, (cy != 0UL));
_gcry_mpih_add_n (wp, wp, m, wsize);
}
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);
}
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);
};
static const struct field_table field_table[] = {
{
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
ec_addm_25519,
ec_subm_25519,
ec_mulm_25519,
ec_mul2_25519,
ec_pow2_25519
},
{ NULL, NULL, NULL, NULL, NULL, NULL },
};
/* Force recomputation of all helper variables. */
void
_gcry_mpi_ec_get_reset (mpi_ec_t ec)
{
ec->t.valid.a_is_pminus3 = 0;
ec->t.valid.two_inv_p = 0;
}
/* Accessor for helper variable. */
static int
ec_get_a_is_pminus3 (mpi_ec_t ec)
{
gcry_mpi_t tmp;
if (!ec->t.valid.a_is_pminus3)
{
ec->t.valid.a_is_pminus3 = 1;
tmp = mpi_alloc_like (ec->p);
mpi_sub_ui (tmp, ec->p, 3);
ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
mpi_free (tmp);
}
return ec->t.a_is_pminus3;
}
/* Accessor for helper variable. */
static gcry_mpi_t
ec_get_two_inv_p (mpi_ec_t ec)
{
if (!ec->t.valid.two_inv_p)
{
ec->t.valid.two_inv_p = 1;
if (!ec->t.two_inv_p)
ec->t.two_inv_p = mpi_alloc (0);
ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
}
return ec->t.two_inv_p;
}
static const char *curve25519_bad_points[] = {
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
"0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
NULL
};
static gcry_mpi_t
scanval (const char *string)
{
gpg_err_code_t rc;
gcry_mpi_t val;
rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (rc)
log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
return val;
}
/* This function initialized a context for elliptic curve based on the
field GF(p). P is the prime specifying this field, A is the first
coefficient. CTX is expected to be zeroized. */
static void
ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
int i;
static int use_barrett;
if (!use_barrett)
{
if (getenv ("GCRYPT_BARRETT"))
use_barrett = 1;
else
use_barrett = -1;
}
/* Fixme: Do we want to check some constraints? e.g. a < p */
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->p = mpi_copy (p);
ctx->a = mpi_copy (a);
ctx->b = mpi_copy (b);
ctx->t.p_barrett = use_barrett > 0? _gcry_mpi_barrett_init (ctx->p, 0):NULL;
_gcry_mpi_ec_get_reset (ctx);
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]);
}
else
{
/* Allocate scratch variables. */
for (i=0; i< DIM(ctx->t.scratch); i++)
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;
for (i=0; field_table[i].p; i++)
{
gcry_mpi_t f_p;
gpg_err_code_t rc;
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));
if (!mpi_cmp (p, f_p))
{
ctx->addm = field_table[i].addm;
ctx->subm = field_table[i].subm;
ctx->mulm = field_table[i].mulm;
ctx->mul2 = field_table[i].mul2;
ctx->pow2 = field_table[i].pow2;
_gcry_mpi_release (f_p);
mpi_resize (ctx->a, ctx->p->nlimbs);
ctx->a->nlimbs = ctx->p->nlimbs;
mpi_resize (ctx->b, ctx->p->nlimbs);
ctx->b->nlimbs = ctx->p->nlimbs;
for (i=0; i< DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++)
ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs;
break;
}
_gcry_mpi_release (f_p);
}
/* 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
mpi_mulm. */
/* ctx->nist_nbits = mpi_get_nbits (ctx->p); */
/* if (ctx->nist_nbits == 192) */
/* { */
/* for (i=0; i < 4; i++) */
/* ctx->s[i] = mpi_new (192); */
/* ctx->c = mpi_new (192*2); */
/* } */
/* else if (ctx->nist_nbits == 384) */
/* { */
/* for (i=0; i < 10; i++) */
/* ctx->s[i] = mpi_new (384); */
/* ctx->c = mpi_new (384*2); */
/* } */
}
static void
ec_deinit (void *opaque)
{
mpi_ec_t ctx = opaque;
int i;
_gcry_mpi_barrett_free (ctx->t.p_barrett);
/* Domain parameter. */
mpi_free (ctx->p);
mpi_free (ctx->a);
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);
mpi_free (ctx->d);
/* Private data of ec.c. */
mpi_free (ctx->t.two_inv_p);
for (i=0; i< DIM(ctx->t.scratch); i++)
mpi_free (ctx->t.scratch[i]);
/* if (ctx->nist_nbits == 192) */
/* { */
/* for (i=0; i < 4; i++) */
/* mpi_free (ctx->s[i]); */
/* mpi_free (ctx->c); */
/* } */
/* else if (ctx->nist_nbits == 384) */
/* { */
/* for (i=0; i < 10; i++) */
/* mpi_free (ctx->s[i]); */
/* mpi_free (ctx->c); */
/* } */
}
/* This function returns a new context for elliptic curve based on the
field GF(p). P is the prime specifying this field, A is the first
coefficient, B is the second coefficient, and MODEL is the model
for the curve. This function is only used within Libgcrypt and not
part of the public API.
This context needs to be released using _gcry_mpi_ec_free. */
mpi_ec_t
_gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
mpi_ec_t ctx;
ctx = xcalloc (1, sizeof *ctx);
ec_p_init (ctx, model, dialect, flags, p, a, b);
return ctx;
}
/* This is a variant of _gcry_mpi_ec_p_internal_new which returns an
public context and does some error checking on the supplied
arguments. On success the new context is stored at R_CTX and 0 is
returned; 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_p_new (gcry_ctx_t *r_ctx,
enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
gcry_ctx_t ctx;
mpi_ec_t ec;
*r_ctx = NULL;
if (!p || !a)
return GPG_ERR_EINVAL;
ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit);
if (!ctx)
return gpg_err_code_from_syserror ();
ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
ec_p_init (ec, model, dialect, flags, p, a, b);
*r_ctx = ctx;
return 0;
}
void
_gcry_mpi_ec_free (mpi_ec_t ctx)
{
if (ctx)
{
ec_deinit (ctx);
xfree (ctx);
}
}
gcry_mpi_t
_gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
return _gcry_ecc_get_mpi (name, ec, copy);
}
gcry_mpi_point_t
_gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
(void)copy; /* Not used. */
return _gcry_ecc_get_point (name, ec);
}
gpg_err_code_t
_gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
gcry_ctx_t ctx)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
return _gcry_ecc_set_mpi (name, newvalue, ec);
}
gpg_err_code_t
_gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
gcry_ctx_t ctx)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
return _gcry_ecc_set_point (name, newvalue, ec);
}
/* Given an encoded point in the MPI VALUE and a context EC, decode
* the point according to the context and store it in RESULT. On
* error an error code is return but RESULT might have been changed.
* If no context is given the function tries to decode VALUE by
* assuming a 0x04 prefixed uncompressed encoding. */
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;
if (ec && ec->dialect == ECC_DIALECT_ED25519)
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);
return rc;
}
/* Compute the affine coordinates from the projective coordinates in
POINT. Set them into X and Y. If one coordinate is not required,
X or Y may be passed as NULL. CTX is the usual context. Returns: 0
on success or !0 if POINT is at infinity. */
int
_gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
mpi_ec_t ctx)
{
if (!mpi_cmp_ui (point->z, 0))
return -1;
switch (ctx->model)
{
case MPI_EC_WEIERSTRASS: /* Using Jacobian coordinates. */
{
gcry_mpi_t z1, z2, z3;
z1 = mpi_new (0);
z2 = mpi_new (0);
ec_invm (z1, point->z, ctx); /* z1 = z^(-1) mod p */
ec_mulm (z2, z1, z1, ctx); /* z2 = z^(-2) mod p */
if (x)
ec_mulm (x, point->x, z2, ctx);
if (y)
{
z3 = mpi_new (0);
ec_mulm (z3, z2, z1, ctx); /* z3 = z^(-3) mod p */
ec_mulm (y, point->y, z3, ctx);
mpi_free (z3);
}
mpi_free (z2);
mpi_free (z1);
}
return 0;
case MPI_EC_MONTGOMERY:
{
if (x)
mpi_set (x, point->x);
if (y)
{
log_fatal ("%s: Getting Y-coordinate on %s is not supported\n",
"_gcry_mpi_ec_get_affine", "Montgomery");
return -1;
}
}
return 0;
case MPI_EC_EDWARDS:
{
gcry_mpi_t z;
z = mpi_new (0);
ec_invm (z, point->z, ctx);
mpi_resize (z, ctx->p->nlimbs);
z->nlimbs = ctx->p->nlimbs;
if (x)
{
mpi_resize (x, ctx->p->nlimbs);
x->nlimbs = ctx->p->nlimbs;
ctx->mulm (x, point->x, z, ctx);
}
if (y)
{
mpi_resize (y, ctx->p->nlimbs);
y->nlimbs = ctx->p->nlimbs;
ctx->mulm (y, point->y, z, ctx);
}
_gcry_mpi_release (z);
}
return 0;
default:
return -1;
}
}
/* RESULT = 2 * POINT (Weierstrass version). */
static void
dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
{
#define x3 (result->x)
#define y3 (result->y)
#define z3 (result->z)
#define t1 (ctx->t.scratch[0])
#define t2 (ctx->t.scratch[1])
#define t3 (ctx->t.scratch[2])
#define l1 (ctx->t.scratch[3])
#define l2 (ctx->t.scratch[4])
#define l3 (ctx->t.scratch[5])
if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0))
{
/* P_y == 0 || P_z == 0 => [1:1:0] */
mpi_set_ui (x3, 1);
mpi_set_ui (y3, 1);
mpi_set_ui (z3, 0);
}
else
{
if (ec_get_a_is_pminus3 (ctx)) /* Use the faster case. */
{
/* L1 = 3(X - Z^2)(X + Z^2) */
/* T1: used for Z^2. */
/* T2: used for the right term. */
ec_pow2 (t1, point->z, ctx);
ec_subm (l1, point->x, t1, ctx);
ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
ec_addm (t2, point->x, t1, ctx);
ec_mulm (l1, l1, t2, ctx);
}
else /* Standard case. */
{
/* L1 = 3X^2 + aZ^4 */
/* T1: used for aZ^4. */
ec_pow2 (l1, point->x, ctx);
ec_mulm (l1, l1, mpi_const (MPI_C_THREE), ctx);
ec_powm (t1, point->z, mpi_const (MPI_C_FOUR), ctx);
ec_mulm (t1, t1, ctx->a, ctx);
ec_addm (l1, l1, t1, ctx);
}
/* Z3 = 2YZ */
ec_mulm (z3, point->y, point->z, ctx);
ec_mul2 (z3, z3, ctx);
/* L2 = 4XY^2 */
/* T2: used for Y2; required later. */
ec_pow2 (t2, point->y, ctx);
ec_mulm (l2, t2, point->x, ctx);
ec_mulm (l2, l2, mpi_const (MPI_C_FOUR), ctx);
/* X3 = L1^2 - 2L2 */
/* T1: used for L2^2. */
ec_pow2 (x3, l1, ctx);
ec_mul2 (t1, l2, ctx);
ec_subm (x3, x3, t1, ctx);
/* L3 = 8Y^4 */
/* T2: taken from above. */
ec_pow2 (t2, t2, ctx);
ec_mulm (l3, t2, mpi_const (MPI_C_EIGHT), ctx);
/* Y3 = L1(L2 - X3) - L3 */
ec_subm (y3, l2, x3, ctx);
ec_mulm (y3, y3, l1, ctx);
ec_subm (y3, y3, l3, ctx);
}
#undef x3
#undef y3
#undef z3
#undef t1
#undef t2
#undef t3
#undef l1
#undef l2
#undef l3
}
/* RESULT = 2 * POINT (Montgomery version). */
static void
dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
{
(void)result;
(void)point;
(void)ctx;
log_fatal ("%s: %s not yet supported\n",
"_gcry_mpi_ec_dup_point", "Montgomery");
}
/* RESULT = 2 * POINT (Twisted Edwards version). */
static void
dup_point_edwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
{
#define X1 (point->x)
#define Y1 (point->y)
#define Z1 (point->z)
#define X3 (result->x)
#define Y3 (result->y)
#define Z3 (result->z)
#define B (ctx->t.scratch[0])
#define C (ctx->t.scratch[1])
#define D (ctx->t.scratch[2])
#define E (ctx->t.scratch[3])
#define F (ctx->t.scratch[4])
#define H (ctx->t.scratch[5])
#define J (ctx->t.scratch[6])
/* Compute: (X_3 : Y_3 : Z_3) = 2( X_1 : Y_1 : Z_1 ) */
/* B = (X_1 + Y_1)^2 */
ctx->addm (B, X1, Y1, ctx);
ctx->pow2 (B, B, ctx);
/* C = X_1^2 */
/* D = Y_1^2 */
ctx->pow2 (C, X1, ctx);
ctx->pow2 (D, Y1, ctx);
/* E = aC */
if (ctx->dialect == ECC_DIALECT_ED25519)
ctx->subm (E, ctx->p, C, ctx);
else
ctx->mulm (E, ctx->a, C, ctx);
/* F = E + D */
ctx->addm (F, E, D, ctx);
/* H = Z_1^2 */
ctx->pow2 (H, Z1, ctx);
/* J = F - 2H */
ctx->mul2 (J, H, ctx);
ctx->subm (J, F, J, ctx);
/* X_3 = (B - C - D) · J */
ctx->subm (X3, B, C, ctx);
ctx->subm (X3, X3, D, ctx);
ctx->mulm (X3, X3, J, ctx);
/* Y_3 = F · (E - D) */
ctx->subm (Y3, E, D, ctx);
ctx->mulm (Y3, Y3, F, ctx);
/* Z_3 = F · J */
ctx->mulm (Z3, F, J, ctx);
#undef X1
#undef Y1
#undef Z1
#undef X3
#undef Y3
#undef Z3
#undef B
#undef C
#undef D
#undef E
#undef F
#undef H
#undef J
}
/* RESULT = 2 * POINT */
void
_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
{
switch (ctx->model)
{
case MPI_EC_WEIERSTRASS:
dup_point_weierstrass (result, point, ctx);
break;
case MPI_EC_MONTGOMERY:
dup_point_montgomery (result, point, ctx);
break;
case MPI_EC_EDWARDS:
dup_point_edwards (result, point, ctx);
break;
}
}
/* RESULT = P1 + P2 (Weierstrass version).*/
static void
add_points_weierstrass (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
#define x1 (p1->x )
#define y1 (p1->y )
#define z1 (p1->z )
#define x2 (p2->x )
#define y2 (p2->y )
#define z2 (p2->z )
#define x3 (result->x)
#define y3 (result->y)
#define z3 (result->z)
#define l1 (ctx->t.scratch[0])
#define l2 (ctx->t.scratch[1])
#define l3 (ctx->t.scratch[2])
#define l4 (ctx->t.scratch[3])
#define l5 (ctx->t.scratch[4])
#define l6 (ctx->t.scratch[5])
#define l7 (ctx->t.scratch[6])
#define l8 (ctx->t.scratch[7])
#define l9 (ctx->t.scratch[8])
#define t1 (ctx->t.scratch[9])
#define t2 (ctx->t.scratch[10])
if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) )
{
/* Same point; need to call the duplicate function. */
_gcry_mpi_ec_dup_point (result, p1, ctx);
}
else if (!mpi_cmp_ui (z1, 0))
{
/* P1 is at infinity. */
mpi_set (x3, p2->x);
mpi_set (y3, p2->y);
mpi_set (z3, p2->z);
}
else if (!mpi_cmp_ui (z2, 0))
{
/* P2 is at infinity. */
mpi_set (x3, p1->x);
mpi_set (y3, p1->y);
mpi_set (z3, p1->z);
}
else
{
int z1_is_one = !mpi_cmp_ui (z1, 1);
int z2_is_one = !mpi_cmp_ui (z2, 1);
/* l1 = x1 z2^2 */
/* l2 = x2 z1^2 */
if (z2_is_one)
mpi_set (l1, x1);
else
{
ec_pow2 (l1, z2, ctx);
ec_mulm (l1, l1, x1, ctx);
}
if (z1_is_one)
mpi_set (l2, x2);
else
{
ec_pow2 (l2, z1, ctx);
ec_mulm (l2, l2, x2, ctx);
}
/* l3 = l1 - l2 */
ec_subm (l3, l1, l2, ctx);
/* l4 = y1 z2^3 */
ec_powm (l4, z2, mpi_const (MPI_C_THREE), ctx);
ec_mulm (l4, l4, y1, ctx);
/* l5 = y2 z1^3 */
ec_powm (l5, z1, mpi_const (MPI_C_THREE), ctx);
ec_mulm (l5, l5, y2, ctx);
/* l6 = l4 - l5 */
ec_subm (l6, l4, l5, ctx);
if (!mpi_cmp_ui (l3, 0))
{
if (!mpi_cmp_ui (l6, 0))
{
/* P1 and P2 are the same - use duplicate function. */
_gcry_mpi_ec_dup_point (result, p1, ctx);
}
else
{
/* P1 is the inverse of P2. */
mpi_set_ui (x3, 1);
mpi_set_ui (y3, 1);
mpi_set_ui (z3, 0);
}
}
else
{
/* l7 = l1 + l2 */
ec_addm (l7, l1, l2, ctx);
/* l8 = l4 + l5 */
ec_addm (l8, l4, l5, ctx);
/* z3 = z1 z2 l3 */
ec_mulm (z3, z1, z2, ctx);
ec_mulm (z3, z3, l3, ctx);
/* x3 = l6^2 - l7 l3^2 */
ec_pow2 (t1, l6, ctx);
ec_pow2 (t2, l3, ctx);
ec_mulm (t2, t2, l7, ctx);
ec_subm (x3, t1, t2, ctx);
/* l9 = l7 l3^2 - 2 x3 */
ec_mul2 (t1, x3, ctx);
ec_subm (l9, t2, t1, ctx);
/* y3 = (l9 l6 - l8 l3^3)/2 */
ec_mulm (l9, l9, l6, ctx);
ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/
ec_mulm (t1, t1, l8, ctx);
ec_subm (y3, l9, t1, ctx);
ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
}
}
#undef x1
#undef y1
#undef z1
#undef x2
#undef y2
#undef z2
#undef x3
#undef y3
#undef z3
#undef l1
#undef l2
#undef l3
#undef l4
#undef l5
#undef l6
#undef l7
#undef l8
#undef l9
#undef t1
#undef t2
}
/* RESULT = P1 + P2 (Montgomery version).*/
static void
add_points_montgomery (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
(void)result;
(void)p1;
(void)p2;
(void)ctx;
log_fatal ("%s: %s not yet supported\n",
"_gcry_mpi_ec_add_points", "Montgomery");
}
/* RESULT = P1 + P2 (Twisted Edwards version).*/
static void
add_points_edwards (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
#define X1 (p1->x)
#define Y1 (p1->y)
#define Z1 (p1->z)
#define X2 (p2->x)
#define Y2 (p2->y)
#define Z2 (p2->z)
#define X3 (result->x)
#define Y3 (result->y)
#define Z3 (result->z)
#define A (ctx->t.scratch[0])
#define B (ctx->t.scratch[1])
#define C (ctx->t.scratch[2])
#define D (ctx->t.scratch[3])
#define E (ctx->t.scratch[4])
#define F (ctx->t.scratch[5])
#define G (ctx->t.scratch[6])
#define tmp (ctx->t.scratch[7])
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 */
ctx->mulm (A, Z1, Z2, ctx);
/* B = A^2 */
ctx->pow2 (B, A, ctx);
/* C = X1 · X2 */
ctx->mulm (C, X1, X2, ctx);
/* D = Y1 · Y2 */
ctx->mulm (D, Y1, Y2, ctx);
/* E = d · C · D */
ctx->mulm (E, ctx->b, C, ctx);
ctx->mulm (E, E, D, ctx);
/* F = B - E */
ctx->subm (F, B, E, ctx);
/* G = B + E */
ctx->addm (G, B, E, ctx);
/* X_3 = A · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
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)
{
ctx->addm (Y3, D, C, ctx);
}
else
{
ctx->mulm (Y3, ctx->a, C, ctx);
ctx->subm (Y3, D, Y3, ctx);
}
ctx->mulm (Y3, Y3, G, ctx);
ctx->mulm (Y3, Y3, A, ctx);
/* Z_3 = F · G */
ctx->mulm (Z3, F, G, ctx);
#undef X1
#undef Y1
#undef Z1
#undef X2
#undef Y2
#undef Z2
#undef X3
#undef Y3
#undef Z3
#undef A
#undef B
#undef C
#undef D
#undef E
#undef F
#undef G
#undef tmp
}
/* Compute a step of Montgomery Ladder (only use X and Z in the point).
Inputs: P1, P2, and x-coordinate of DIF = P1 - P1.
Outputs: PRD = 2 * P1 and SUM = P1 + P2. */
static void
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)
{
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);
}
/* RESULT = P1 + P2 */
void
_gcry_mpi_ec_add_points (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
switch (ctx->model)
{
case MPI_EC_WEIERSTRASS:
add_points_weierstrass (result, p1, p2, ctx);
break;
case MPI_EC_MONTGOMERY:
add_points_montgomery (result, p1, p2, ctx);
break;
case MPI_EC_EDWARDS:
add_points_edwards (result, p1, p2, ctx);
break;
}
}
/* RESULT = P1 - P2 (Weierstrass version).*/
static void
sub_points_weierstrass (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
(void)result;
(void)p1;
(void)p2;
(void)ctx;
log_fatal ("%s: %s not yet supported\n",
"_gcry_mpi_ec_sub_points", "Weierstrass");
}
/* RESULT = P1 - P2 (Montgomery version).*/
static void
sub_points_montgomery (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
(void)result;
(void)p1;
(void)p2;
(void)ctx;
log_fatal ("%s: %s not yet supported\n",
"_gcry_mpi_ec_sub_points", "Montgomery");
}
/* RESULT = P1 - P2 (Twisted Edwards version).*/
static void
sub_points_edwards (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
mpi_point_t p2i = _gcry_mpi_point_new (0);
point_set (p2i, p2);
ctx->subm (p2i->x, ctx->p, p2i->x, ctx);
add_points_edwards (result, p1, p2i, ctx);
_gcry_mpi_point_release (p2i);
}
/* RESULT = P1 - P2 */
void
_gcry_mpi_ec_sub_points (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx)
{
switch (ctx->model)
{
case MPI_EC_WEIERSTRASS:
sub_points_weierstrass (result, p1, p2, ctx);
break;
case MPI_EC_MONTGOMERY:
sub_points_montgomery (result, p1, p2, ctx);
break;
case MPI_EC_EDWARDS:
sub_points_edwards (result, p1, p2, ctx);
break;
}
}
/* Scalar point multiplication - the main function for ECC. If takes
an integer SCALAR and a POINT as well as the usual context CTX.
RESULT will be set to the resulting point. */
void
_gcry_mpi_ec_mul_point (mpi_point_t result,
gcry_mpi_t scalar, mpi_point_t point,
mpi_ec_t ctx)
{
gcry_mpi_t x1, y1, z1, k, h, yy;
unsigned int i, loops;
mpi_point_struct p1, p2, p1inv;
if (ctx->model == MPI_EC_EDWARDS
|| (ctx->model == MPI_EC_WEIERSTRASS
&& mpi_is_secure (scalar)))
{
/* Simple left to right binary method. Algorithm 3.27 from
* {author={Hankerson, Darrel and Menezes, Alfred J. and Vanstone, Scott},
* title = {Guide to Elliptic Curve Cryptography},
* year = {2003}, isbn = {038795273X},
* url = {http://www.cacr.math.uwaterloo.ca/ecc/},
* publisher = {Springer-Verlag New York, Inc.}} */
unsigned int nbits;
int j;
nbits = mpi_get_nbits (scalar);
if (ctx->model == MPI_EC_WEIERSTRASS)
{
mpi_set_ui (result->x, 1);
mpi_set_ui (result->y, 1);
mpi_set_ui (result->z, 0);
}
else
{
mpi_set_ui (result->x, 0);
mpi_set_ui (result->y, 1);
mpi_set_ui (result->z, 1);
point_resize (point, ctx);
}
if (mpi_is_secure (scalar))
{
/* If SCALAR is in secure memory we assume that it is the
secret key we use constant time operation. */
mpi_point_struct tmppnt;
point_init (&tmppnt);
point_resize (result, ctx);
point_resize (&tmppnt, ctx);
for (j=nbits-1; j >= 0; j--)
{
_gcry_mpi_ec_dup_point (result, result, ctx);
_gcry_mpi_ec_add_points (&tmppnt, result, point, ctx);
point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
}
point_free (&tmppnt);
}
else
{
if (ctx->model == MPI_EC_EDWARDS)
{
point_resize (result, ctx);
point_resize (point, ctx);
}
for (j=nbits-1; j >= 0; j--)
{
_gcry_mpi_ec_dup_point (result, result, ctx);
if (mpi_test_bit (scalar, j))
_gcry_mpi_ec_add_points (result, result, point, ctx);
}
}
return;
}
else if (ctx->model == MPI_EC_MONTGOMERY)
{
unsigned int nbits;
int j;
mpi_point_struct p1_, p2_;
mpi_point_t q1, q2, prd, sum;
unsigned long sw;
mpi_size_t rsize;
/* Compute scalar point multiplication with Montgomery Ladder.
Note that we don't use Y-coordinate in the points at all.
RESULT->Y will be filled by zero. */
nbits = mpi_get_nbits (scalar);
point_init (&p1);
point_init (&p2);
point_init (&p1_);
point_init (&p2_);
mpi_set_ui (p1.x, 1);
mpi_free (p2.x);
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);
mpi_resize (point->x, ctx->p->nlimbs);
point->x->nlimbs = ctx->p->nlimbs;
q1 = &p1;
q2 = &p2;
prd = &p1_;
sum = &p2_;
for (j=nbits-1; j >= 0; j--)
{
mpi_point_t t;
sw = mpi_test_bit (scalar, j);
point_swap_cond (q1, q2, sw, ctx);
montgomery_ladder (prd, sum, q1, q2, point->x, ctx);
point_swap_cond (prd, sum, sw, ctx);
t = q1; q1 = prd; prd = t;
t = q2; q2 = sum; sum = t;
}
mpi_clear (result->y);
sw = (nbits & 1);
point_swap_cond (&p1, &p1_, sw, ctx);
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);
}
else
{
z1 = mpi_new (0);
ec_invm (z1, p1.z, ctx);
ec_mulm (result->x, p1.x, z1, ctx);
mpi_set_ui (result->z, 1);
mpi_free (z1);
}
point_free (&p1);
point_free (&p2);
point_free (&p1_);
point_free (&p2_);
return;
}
x1 = mpi_alloc_like (ctx->p);
y1 = mpi_alloc_like (ctx->p);
h = mpi_alloc_like (ctx->p);
k = mpi_copy (scalar);
yy = mpi_copy (point->y);
if ( mpi_has_sign (k) )
{
k->sign = 0;
ec_invm (yy, yy, ctx);
}
if (!mpi_cmp_ui (point->z, 1))
{
mpi_set (x1, point->x);
mpi_set (y1, yy);
}
else
{
gcry_mpi_t z2, z3;
z2 = mpi_alloc_like (ctx->p);
z3 = mpi_alloc_like (ctx->p);
ec_mulm (z2, point->z, point->z, ctx);
ec_mulm (z3, point->z, z2, ctx);
ec_invm (z2, z2, ctx);
ec_mulm (x1, point->x, z2, ctx);
ec_invm (z3, z3, ctx);
ec_mulm (y1, yy, z3, ctx);
mpi_free (z2);
mpi_free (z3);
}
z1 = mpi_copy (mpi_const (MPI_C_ONE));
mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */
loops = mpi_get_nbits (h);
if (loops < 2)
{
/* If SCALAR is zero, the above mpi_mul sets H to zero and thus
LOOPs will be zero. To avoid an underflow of I in the main
loop we set LOOP to 2 and the result to (0,0,0). */
loops = 2;
mpi_clear (result->x);
mpi_clear (result->y);
mpi_clear (result->z);
}
else
{
mpi_set (result->x, point->x);
mpi_set (result->y, yy);
mpi_set (result->z, point->z);
}
mpi_free (yy); yy = NULL;
p1.x = x1; x1 = NULL;
p1.y = y1; y1 = NULL;
p1.z = z1; z1 = NULL;
point_init (&p2);
point_init (&p1inv);
/* Invert point: y = p - y mod p */
point_set (&p1inv, &p1);
ec_subm (p1inv.y, ctx->p, p1inv.y, ctx);
for (i=loops-2; i > 0; i--)
{
_gcry_mpi_ec_dup_point (result, result, ctx);
if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0)
{
point_set (&p2, result);
_gcry_mpi_ec_add_points (result, &p2, &p1, ctx);
}
if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1)
{
point_set (&p2, result);
_gcry_mpi_ec_add_points (result, &p2, &p1inv, ctx);
}
}
point_free (&p1);
point_free (&p2);
point_free (&p1inv);
mpi_free (h);
mpi_free (k);
}
/* Return true if POINT is on the curve described by CTX. */
int
_gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
{
int res = 0;
gcry_mpi_t x, y, w;
x = mpi_new (0);
y = mpi_new (0);
w = mpi_new (0);
/* Check that the point is in range. This needs to be done here and
* not after conversion to affine coordinates. */
if (mpi_cmpabs (point->x, ctx->p) >= 0)
goto leave;
if (mpi_cmpabs (point->y, ctx->p) >= 0)
goto leave;
if (mpi_cmpabs (point->z, ctx->p) >= 0)
goto leave;
switch (ctx->model)
{
case MPI_EC_WEIERSTRASS:
{
gcry_mpi_t xxx;
if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
goto leave;
xxx = mpi_new (0);
/* y^2 == x^3 + a·x + b */
ec_pow2 (y, y, ctx);
ec_pow3 (xxx, x, ctx);
ec_mulm (w, ctx->a, x, ctx);
ec_addm (w, w, ctx->b, ctx);
ec_addm (w, w, xxx, ctx);
if (!mpi_cmp (y, w))
res = 1;
_gcry_mpi_release (xxx);
}
break;
case MPI_EC_MONTGOMERY:
{
#define xx y
/* With Montgomery curve, only X-coordinate is valid. */
if (_gcry_mpi_ec_get_affine (x, NULL, point, ctx))
goto leave;
/* The equation is: b * y^2 == x^3 + a · x^2 + x */
/* We check if right hand is quadratic residue or not by
Euler's criterion. */
/* CTX->A has (a-2)/4 and CTX->B has b^-1 */
ec_mulm (w, ctx->a, mpi_const (MPI_C_FOUR), ctx);
ec_addm (w, w, mpi_const (MPI_C_TWO), ctx);
ec_mulm (w, w, x, ctx);
ec_pow2 (xx, x, ctx);
ec_addm (w, w, xx, ctx);
ec_addm (w, w, mpi_const (MPI_C_ONE), ctx);
ec_mulm (w, w, x, ctx);
ec_mulm (w, w, ctx->b, ctx);
#undef xx
/* Compute Euler's criterion: w^(p-1)/2 */
#define p_minus1 y
ec_subm (p_minus1, ctx->p, mpi_const (MPI_C_ONE), ctx);
mpi_rshift (p_minus1, p_minus1, 1);
ec_powm (w, w, p_minus1, ctx);
res = !mpi_cmp_ui (w, 1);
#undef p_minus1
}
break;
case MPI_EC_EDWARDS:
{
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 */
ctx->pow2 (x, x, ctx);
ctx->pow2 (y, y, ctx);
if (ctx->dialect == ECC_DIALECT_ED25519)
ctx->subm (w, ctx->p, x, ctx);
else
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;
}
leave:
_gcry_mpi_release (w);
_gcry_mpi_release (x);
_gcry_mpi_release (y);
return res;
}
int
_gcry_mpi_ec_bad_point (gcry_mpi_point_t point, mpi_ec_t ctx)
{
int i;
gcry_mpi_t x_bad;
for (i = 0; (x_bad = ctx->t.scratch[i]); i++)
if (!mpi_cmp (point->x, x_bad))
return 1;
return 0;
}
diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c
index ee6813b1..becdb581 100644
--- a/mpi/mpi-inv.c
+++ b/mpi/mpi-inv.c
@@ -1,272 +1,272 @@
/* mpi-inv.c - MPI functions
* Copyright (C) 1998, 2001, 2002, 2003 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "g10lib.h"
/****************
* 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)
{
#if 0
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);
u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_alloc_set_ui(0);
v2 = mpi_alloc_set_ui(1);
v3 = mpi_copy(v);
q = mpi_alloc( mpi_get_nlimbs(u)+1 );
t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
while( mpi_cmp_ui( v3, 0 ) ) {
mpi_fdiv_q( q, u3, v3 );
mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
}
/* log_debug("result:\n");
log_mpidump("q =", q );
log_mpidump("u1=", u1);
log_mpidump("u2=", u2);
log_mpidump("u3=", u3);
log_mpidump("v1=", v1);
log_mpidump("v2=", v2); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1);
mpi_free(v2);
mpi_free(v3);
mpi_free(q);
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
mpi_free(u);
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 */
/* FIXME: we can simplify this in most cases (see Knuth) */
gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
unsigned k;
int sign;
u = mpi_copy(a);
v = mpi_copy(n);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
}
u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v); /* !-- used as const 1 */
v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u );
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
Y4:
;
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1);
mpi_free(v2);
mpi_free(v3);
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
#else
/* 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 */
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);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
}
odd = mpi_test_bit(v,0);
u1 = mpi_alloc_set_ui(1);
if( !odd )
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v);
if( !odd ) {
v2 = mpi_alloc( mpi_get_nlimbs(u) );
mpi_sub( v2, u1, u ); /* U is used as const 1 */
}
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
if( !odd ) {
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
}
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
if( !odd )
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( !odd ) {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
}
else {
if( mpi_test_bit(t1, 0) )
mpi_add(t1, t1, v);
mpi_rshift(t1, t1, 1);
mpi_rshift(t3, t3, 1);
}
Y4:
;
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
if( !odd )
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
if( !odd )
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
if( !odd )
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
if( !odd )
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(v1);
mpi_free(t1);
if( !odd ) {
mpi_free(u2);
mpi_free(v2);
mpi_free(t2);
}
mpi_free(u3);
mpi_free(v3);
mpi_free(t3);
mpi_free(u);
mpi_free(v);
#endif
return 1;
}
diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c
index 62b4a808..f6778dd9 100644
--- a/mpi/mpi-pow.c
+++ b/mpi/mpi-pow.c
@@ -1,772 +1,772 @@
/* mpi-pow.c - MPI functions for exponentiation
* Copyright (C) 1994, 1996, 1998, 2000, 2002
* 2003 Free Software Foundation, Inc.
* 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* 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 <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi-internal.h"
#include "longlong.h"
/*
* When you need old implementation, please add compilation option
* -DUSE_ALGORITHM_SIMPLE_EXPONENTIATION
* or expose this line:
#define USE_ALGORITHM_SIMPLE_EXPONENTIATION 1
*/
#if defined(USE_ALGORITHM_SIMPLE_EXPONENTIATION)
/****************
* RES = BASE ^ EXPO mod MOD
*/
void
_gcry_mpi_powm (gcry_mpi_t res,
gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod)
{
/* Pointer to the limbs of the arguments, their size and signs. */
mpi_ptr_t rp, ep, mp, bp;
mpi_size_t esize, msize, bsize, rsize;
int msign, bsign, rsign;
/* Flags telling the secure allocation status of the arguments. */
int esec, msec, bsec;
/* Size of the result including space for temporary values. */
mpi_size_t size;
/* Helper. */
int mod_shift_cnt;
int negative_result;
mpi_ptr_t mp_marker = NULL;
mpi_ptr_t bp_marker = NULL;
mpi_ptr_t ep_marker = NULL;
mpi_ptr_t xp_marker = NULL;
unsigned int mp_nlimbs = 0;
unsigned int bp_nlimbs = 0;
unsigned int ep_nlimbs = 0;
unsigned int xp_nlimbs = 0;
mpi_ptr_t tspace = NULL;
mpi_size_t tsize = 0;
esize = expo->nlimbs;
msize = mod->nlimbs;
size = 2 * msize;
msign = mod->sign;
esec = mpi_is_secure(expo);
msec = mpi_is_secure(mod);
bsec = mpi_is_secure(base);
rp = res->d;
ep = expo->d;
MPN_NORMALIZE(ep, esize);
if (!msize)
_gcry_divide_by_zero();
if (!esize)
{
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending
on if MOD equals 1. */
res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
if (res->nlimbs)
{
RESIZE_IF_NEEDED (res, 1);
rp = res->d;
rp[0] = 1;
}
res->sign = 0;
goto leave;
}
/* Normalize MOD (i.e. make its most significant bit set) as
required by mpn_divrem. This will make the intermediate values
in the calculation slightly larger, but the correct result is
obtained after a final reduction using the original MOD value. */
mp_nlimbs = msec? msize:0;
mp = mp_marker = mpi_alloc_limb_space(msize, msec);
count_leading_zeros (mod_shift_cnt, mod->d[msize-1]);
if (mod_shift_cnt)
_gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt);
else
MPN_COPY( mp, mod->d, msize );
bsize = base->nlimbs;
bsign = base->sign;
if (bsize > msize)
{
/* The base is larger than the module. Reduce it.
Allocate (BSIZE + 1) with space for remainder and quotient.
(The quotient is (bsize - msize + 1) limbs.) */
bp_nlimbs = bsec ? (bsize + 1):0;
bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec );
MPN_COPY ( bp, base->d, bsize );
/* We don't care about the quotient, store it above the
* remainder, at BP + MSIZE. */
_gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize );
bsize = msize;
/* Canonicalize the base, since we are going to multiply with it
quite a few times. */
MPN_NORMALIZE( bp, bsize );
}
else
bp = base->d;
if (!bsize)
{
res->nlimbs = 0;
res->sign = 0;
goto leave;
}
/* Make BASE, EXPO and MOD not overlap with RES. */
if ( rp == bp )
{
/* RES and BASE are identical. Allocate temp. space for BASE. */
gcry_assert (!bp_marker);
bp_nlimbs = bsec? bsize:0;
bp = bp_marker = mpi_alloc_limb_space( bsize, bsec );
MPN_COPY(bp, rp, bsize);
}
if ( rp == ep )
{
/* RES and EXPO are identical. Allocate temp. space for EXPO. */
ep_nlimbs = esec? esize:0;
ep = ep_marker = mpi_alloc_limb_space( esize, esec );
MPN_COPY(ep, rp, esize);
}
if ( rp == mp )
{
/* RES and MOD are identical. Allocate temporary space for MOD.*/
gcry_assert (!mp_marker);
mp_nlimbs = msec?msize:0;
mp = mp_marker = mpi_alloc_limb_space( msize, msec );
MPN_COPY(mp, rp, msize);
}
/* Copy base to the result. */
if (res->alloced < size)
{
mpi_resize (res, size);
rp = res->d;
}
MPN_COPY ( rp, bp, bsize );
rsize = bsize;
rsign = 0;
/* Main processing. */
{
mpi_size_t i;
mpi_ptr_t xp;
int c;
mpi_limb_t e;
mpi_limb_t carry_limb;
struct karatsuba_ctx karactx;
struct gcry_mpi w, u;
xp_nlimbs = msec? size:0;
xp = xp_marker = mpi_alloc_limb_space( size, msec );
w.sign = u.sign = 0;
w.flags = u.flags = 0;
w.alloced = w.nlimbs = size; /* RES->alloc may be longer. */
u.alloced = u.nlimbs = size;
memset( &karactx, 0, sizeof karactx );
negative_result = (ep[0] & 1) && bsign;
i = esize - 1;
e = ep[i];
count_leading_zeros (c, e);
e = (e << c) << 1; /* Shift the expo bits to the left, lose msb. */
c = BITS_PER_MPI_LIMB - 1 - c;
/* Main loop.
Make the result be pointed to alternately by XP and RP. This
helps us avoid block copying, which would otherwise be
necessary with the overlap restrictions of
_gcry_mpih_divmod. With 50% probability the result after this
loop will be in the area originally pointed by RP (==RES->d),
and with 50% probability in the area originally pointed to by XP. */
for (;;)
{
while (c)
{
mpi_ptr_t tp;
mpi_size_t xsize;
/*mpih_mul_n(xp, rp, rp, rsize);*/
if ( rsize < KARATSUBA_THRESHOLD )
_gcry_mpih_sqr_n_basecase( xp, rp, rsize );
else
{
if ( !tspace )
{
tsize = 2 * rsize;
tspace = mpi_alloc_limb_space( tsize, 0 );
}
else if ( tsize < (2*rsize) )
{
_gcry_mpi_free_limb_space (tspace, 0);
tsize = 2 * rsize;
tspace = mpi_alloc_limb_space (tsize, 0 );
}
_gcry_mpih_sqr_n (xp, rp, rsize, tspace);
}
xsize = 2 * rsize;
if ( xsize > msize )
{
_gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize);
xsize = msize;
}
tp = rp; rp = xp; xp = tp;
rsize = xsize;
/* To mitigate the Yarom/Falkner flush+reload cache
* side-channel attack on the RSA secret exponent, we do
* the multiplication regardless of the value of the
* high-bit of E. But to avoid this performance penalty
* we do it only if the exponent has been stored in secure
* memory and we can thus assume it is a secret exponent. */
if (esec || (mpi_limb_signed_t)e < 0)
{
/*mpih_mul( xp, rp, rsize, bp, bsize );*/
if( bsize < KARATSUBA_THRESHOLD )
_gcry_mpih_mul ( xp, rp, rsize, bp, bsize );
else
_gcry_mpih_mul_karatsuba_case (xp, rp, rsize, bp, bsize,
&karactx);
xsize = rsize + bsize;
if ( xsize > msize )
{
_gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize);
xsize = msize;
}
}
w.d = rp;
u.d = xp;
mpi_set_cond (&w, &u, ((mpi_limb_signed_t)e < 0));
e <<= 1;
c--;
}
i--;
if ( i < 0 )
break;
e = ep[i];
c = BITS_PER_MPI_LIMB;
}
/* We shifted MOD, the modulo reduction argument, left
MOD_SHIFT_CNT steps. Adjust the result by reducing it with the
original MOD.
Also make sure the result is put in RES->d (where it already
might be, see above). */
if ( mod_shift_cnt )
{
carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt);
rp = res->d;
if ( carry_limb )
{
rp[rsize] = carry_limb;
rsize++;
}
}
else if (res->d != rp)
{
MPN_COPY (res->d, rp, rsize);
rp = res->d;
}
if ( rsize >= msize )
{
_gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize);
rsize = msize;
}
/* Remove any leading zero words from the result. */
if ( mod_shift_cnt )
_gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt);
MPN_NORMALIZE (rp, rsize);
_gcry_mpih_release_karatsuba_ctx (&karactx );
}
/* Fixup for negative results. */
if ( negative_result && rsize )
{
if ( mod_shift_cnt )
_gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt);
_gcry_mpih_sub( rp, mp, msize, rp, rsize);
rsize = msize;
rsign = msign;
MPN_NORMALIZE(rp, rsize);
}
gcry_assert (res->d == rp);
res->nlimbs = rsize;
res->sign = rsign;
leave:
if (mp_marker)
_gcry_mpi_free_limb_space( mp_marker, mp_nlimbs );
if (bp_marker)
_gcry_mpi_free_limb_space( bp_marker, bp_nlimbs );
if (ep_marker)
_gcry_mpi_free_limb_space( ep_marker, ep_nlimbs );
if (xp_marker)
_gcry_mpi_free_limb_space( xp_marker, xp_nlimbs );
if (tspace)
_gcry_mpi_free_limb_space( tspace, 0 );
}
#else
/**
* Internal function to compute
*
* X = R * S mod M
*
* and set the size of X at the pointer XSIZE_P.
* Use karatsuba structure at KARACTX_P.
*
* Condition:
* RSIZE >= SSIZE
* Enough space for X is allocated beforehand.
*
* For generic cases, we can/should use gcry_mpi_mulm.
* This function is use for specific internal case.
*/
static void
mul_mod (mpi_ptr_t xp, mpi_size_t *xsize_p,
mpi_ptr_t rp, mpi_size_t rsize,
mpi_ptr_t sp, mpi_size_t ssize,
mpi_ptr_t mp, mpi_size_t msize,
struct karatsuba_ctx *karactx_p)
{
if( ssize < KARATSUBA_THRESHOLD )
_gcry_mpih_mul ( xp, rp, rsize, sp, ssize );
else
_gcry_mpih_mul_karatsuba_case (xp, rp, rsize, sp, ssize, karactx_p);
if (rsize + ssize > msize)
{
_gcry_mpih_divrem (xp + msize, 0, xp, rsize + ssize, mp, msize);
*xsize_p = msize;
}
else
*xsize_p = rsize + ssize;
}
#define SIZE_PRECOMP ((1 << (5 - 1)))
/****************
* RES = BASE ^ EXPO mod MOD
*
* To mitigate the Yarom/Falkner flush+reload cache side-channel
* attack on the RSA secret exponent, we don't use the square
* routine but multiplication.
*
* Reference:
* Handbook of Applied Cryptography
* Algorithm 14.83: Modified left-to-right k-ary exponentiation
*/
void
_gcry_mpi_powm (gcry_mpi_t res,
gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod)
{
/* Pointer to the limbs of the arguments, their size and signs. */
mpi_ptr_t rp, ep, mp, bp;
mpi_size_t esize, msize, bsize, rsize;
int msign, bsign, rsign;
/* Flags telling the secure allocation status of the arguments. */
int esec, msec, bsec;
/* Size of the result including space for temporary values. */
mpi_size_t size;
/* Helper. */
int mod_shift_cnt;
int negative_result;
mpi_ptr_t mp_marker = NULL;
mpi_ptr_t bp_marker = NULL;
mpi_ptr_t ep_marker = NULL;
mpi_ptr_t xp_marker = NULL;
unsigned int mp_nlimbs = 0;
unsigned int bp_nlimbs = 0;
unsigned int ep_nlimbs = 0;
unsigned int xp_nlimbs = 0;
mpi_ptr_t precomp[SIZE_PRECOMP]; /* Pre-computed array: BASE^1, ^3, ^5, ... */
mpi_size_t precomp_size[SIZE_PRECOMP];
mpi_size_t W;
mpi_ptr_t base_u;
mpi_size_t base_u_size;
mpi_size_t max_u_size;
esize = expo->nlimbs;
msize = mod->nlimbs;
size = 2 * msize;
msign = mod->sign;
ep = expo->d;
MPN_NORMALIZE(ep, esize);
if (esize * BITS_PER_MPI_LIMB > 512)
W = 5;
else if (esize * BITS_PER_MPI_LIMB > 256)
W = 4;
else if (esize * BITS_PER_MPI_LIMB > 128)
W = 3;
else if (esize * BITS_PER_MPI_LIMB > 64)
W = 2;
else
W = 1;
esec = mpi_is_secure(expo);
msec = mpi_is_secure(mod);
bsec = mpi_is_secure(base);
rp = res->d;
if (!msize)
_gcry_divide_by_zero();
if (!esize)
{
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending
on if MOD equals 1. */
res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
if (res->nlimbs)
{
RESIZE_IF_NEEDED (res, 1);
rp = res->d;
rp[0] = 1;
}
res->sign = 0;
goto leave;
}
/* Normalize MOD (i.e. make its most significant bit set) as
required by mpn_divrem. This will make the intermediate values
in the calculation slightly larger, but the correct result is
obtained after a final reduction using the original MOD value. */
mp_nlimbs = msec? msize:0;
mp = mp_marker = mpi_alloc_limb_space(msize, msec);
count_leading_zeros (mod_shift_cnt, mod->d[msize-1]);
if (mod_shift_cnt)
_gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt);
else
MPN_COPY( mp, mod->d, msize );
bsize = base->nlimbs;
bsign = base->sign;
if (bsize > msize)
{
/* The base is larger than the module. Reduce it.
Allocate (BSIZE + 1) with space for remainder and quotient.
(The quotient is (bsize - msize + 1) limbs.) */
bp_nlimbs = bsec ? (bsize + 1):0;
bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec );
MPN_COPY ( bp, base->d, bsize );
/* We don't care about the quotient, store it above the
* remainder, at BP + MSIZE. */
_gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize );
bsize = msize;
/* Canonicalize the base, since we are going to multiply with it
quite a few times. */
MPN_NORMALIZE( bp, bsize );
}
else
bp = base->d;
if (!bsize)
{
res->nlimbs = 0;
res->sign = 0;
goto leave;
}
/* Make BASE, EXPO not overlap with RES. We don't need to check MOD
because that has already been copied to the MP var. */
if ( rp == bp )
{
/* RES and BASE are identical. Allocate temp. space for BASE. */
gcry_assert (!bp_marker);
bp_nlimbs = bsec? bsize:0;
bp = bp_marker = mpi_alloc_limb_space( bsize, bsec );
MPN_COPY(bp, rp, bsize);
}
if ( rp == ep )
{
/* RES and EXPO are identical. Allocate temp. space for EXPO. */
ep_nlimbs = esec? esize:0;
ep = ep_marker = mpi_alloc_limb_space( esize, esec );
MPN_COPY(ep, rp, esize);
}
/* Copy base to the result. */
if (res->alloced < size)
{
mpi_resize (res, size);
rp = res->d;
}
/* Main processing. */
{
mpi_size_t i, j, k;
mpi_ptr_t xp;
mpi_size_t xsize;
int c;
mpi_limb_t e;
mpi_limb_t carry_limb;
struct karatsuba_ctx karactx;
mpi_ptr_t tp;
xp_nlimbs = msec? size:0;
xp = xp_marker = mpi_alloc_limb_space( size, msec );
memset( &karactx, 0, sizeof karactx );
negative_result = (ep[0] & 1) && bsign;
/* Precompute PRECOMP[], BASE^(2 * i + 1), BASE^1, ^3, ^5, ... */
if (W > 1) /* X := BASE^2 */
mul_mod (xp, &xsize, bp, bsize, bp, bsize, mp, msize, &karactx);
base_u = precomp[0] = mpi_alloc_limb_space (bsize, esec);
base_u_size = max_u_size = precomp_size[0] = bsize;
MPN_COPY (precomp[0], bp, bsize);
for (i = 1; i < (1 << (W - 1)); i++)
{ /* PRECOMP[i] = BASE^(2 * i + 1) */
if (xsize >= base_u_size)
mul_mod (rp, &rsize, xp, xsize, base_u, base_u_size,
mp, msize, &karactx);
else
mul_mod (rp, &rsize, base_u, base_u_size, xp, xsize,
mp, msize, &karactx);
base_u = precomp[i] = mpi_alloc_limb_space (rsize, esec);
base_u_size = precomp_size[i] = rsize;
if (max_u_size < base_u_size)
max_u_size = base_u_size;
MPN_COPY (precomp[i], rp, rsize);
}
if (msize > max_u_size)
max_u_size = msize;
base_u = mpi_alloc_limb_space (max_u_size, esec);
MPN_ZERO (base_u, max_u_size);
i = esize - 1;
/* Main loop.
Make the result be pointed to alternately by XP and RP. This
helps us avoid block copying, which would otherwise be
necessary with the overlap restrictions of
_gcry_mpih_divmod. With 50% probability the result after this
loop will be in the area originally pointed by RP (==RES->d),
and with 50% probability in the area originally pointed to by XP. */
rsign = 0;
if (W == 1)
{
rsize = bsize;
}
else
{
rsize = msize;
MPN_ZERO (rp, rsize);
}
MPN_COPY ( rp, bp, bsize );
e = ep[i];
count_leading_zeros (c, e);
e = (e << c) << 1;
c = BITS_PER_MPI_LIMB - 1 - c;
j = 0;
for (;;)
if (e == 0)
{
j += c;
if ( --i < 0 )
break;
e = ep[i];
c = BITS_PER_MPI_LIMB;
}
else
{
int c0;
mpi_limb_t e0;
struct gcry_mpi w, u;
w.sign = u.sign = 0;
w.flags = u.flags = 0;
w.d = base_u;
count_leading_zeros (c0, e);
e = (e << c0);
c -= c0;
j += c0;
e0 = (e >> (BITS_PER_MPI_LIMB - W));
if (c >= W)
c0 = 0;
else
{
if ( --i < 0 )
{
e0 = (e >> (BITS_PER_MPI_LIMB - c));
j += c - W;
goto last_step;
}
else
{
c0 = c;
e = ep[i];
c = BITS_PER_MPI_LIMB;
e0 |= (e >> (BITS_PER_MPI_LIMB - (W - c0)));
}
}
e = e << (W - c0);
c -= (W - c0);
last_step:
count_trailing_zeros (c0, e0);
e0 = (e0 >> c0) >> 1;
for (j += W - c0; j >= 0; j--)
{
/*
* base_u <= precomp[e0]
* base_u_size <= precomp_size[e0]
*/
base_u_size = 0;
for (k = 0; k < (1<< (W - 1)); k++)
{
w.alloced = w.nlimbs = precomp_size[k];
u.alloced = u.nlimbs = precomp_size[k];
u.d = precomp[k];
mpi_set_cond (&w, &u, k == e0);
base_u_size |= ( precomp_size[k] & (0UL - (k == e0)) );
}
w.alloced = w.nlimbs = rsize;
u.alloced = u.nlimbs = rsize;
u.d = rp;
mpi_set_cond (&w, &u, j != 0);
base_u_size ^= ((base_u_size ^ rsize) & (0UL - (j != 0)));
mul_mod (xp, &xsize, rp, rsize, base_u, base_u_size,
mp, msize, &karactx);
tp = rp; rp = xp; xp = tp;
rsize = xsize;
}
j = c0;
if ( i < 0 )
break;
}
while (j--)
{
mul_mod (xp, &xsize, rp, rsize, rp, rsize, mp, msize, &karactx);
tp = rp; rp = xp; xp = tp;
rsize = xsize;
}
/* We shifted MOD, the modulo reduction argument, left
MOD_SHIFT_CNT steps. Adjust the result by reducing it with the
original MOD.
Also make sure the result is put in RES->d (where it already
might be, see above). */
if ( mod_shift_cnt )
{
carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt);
rp = res->d;
if ( carry_limb )
{
rp[rsize] = carry_limb;
rsize++;
}
}
else if (res->d != rp)
{
MPN_COPY (res->d, rp, rsize);
rp = res->d;
}
if ( rsize >= msize )
{
_gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize);
rsize = msize;
}
/* Remove any leading zero words from the result. */
if ( mod_shift_cnt )
_gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt);
MPN_NORMALIZE (rp, rsize);
_gcry_mpih_release_karatsuba_ctx (&karactx );
for (i = 0; i < (1 << (W - 1)); i++)
_gcry_mpi_free_limb_space( precomp[i], esec ? precomp_size[i] : 0 );
_gcry_mpi_free_limb_space (base_u, esec ? max_u_size : 0);
}
/* Fixup for negative results. */
if ( negative_result && rsize )
{
if ( mod_shift_cnt )
_gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt);
_gcry_mpih_sub( rp, mp, msize, rp, rsize);
rsize = msize;
rsign = msign;
MPN_NORMALIZE(rp, rsize);
}
gcry_assert (res->d == rp);
res->nlimbs = rsize;
res->sign = rsign;
leave:
if (mp_marker)
_gcry_mpi_free_limb_space( mp_marker, mp_nlimbs );
if (bp_marker)
_gcry_mpi_free_limb_space( bp_marker, bp_nlimbs );
if (ep_marker)
_gcry_mpi_free_limb_space( ep_marker, ep_nlimbs );
if (xp_marker)
_gcry_mpi_free_limb_space( xp_marker, xp_nlimbs );
}
#endif
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index 4c63a147..8f059978 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -1,947 +1,947 @@
/* mpicoder.c - Coder for the external representation of MPIs
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2008 Free Software Foundation, Inc.
* Copyright (C) 2013, 2014 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "g10lib.h"
/* The maximum length we support in the functions converting an
* external representation to an MPI. This limit is used to catch
* programming errors and to avoid DoS due to insane long allocations.
* The 16 MiB limit is actually ridiculous large but some of those PQC
* algorithms use quite large keys and they might end up using MPIs
* for that. */
#define MAX_EXTERN_SCAN_BYTES (16*1024*1024)
/* The maximum length (in bits) we support for OpenPGP MPIs. Note
* that OpenPGP's MPI format uses only two bytes and thus would be
* limited to 64k anyway. Note that this limit matches that used by
* GnuPG. */
#define MAX_EXTERN_MPI_BITS 16384
/* Helper used to scan PGP style MPIs. Returns NULL on failure. */
static gcry_mpi_t
mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
int secure)
{
int i, j;
unsigned int nbits, nbytes, nlimbs, nread=0;
mpi_limb_t a;
gcry_mpi_t val = MPI_NULL;
if ( *ret_nread < 2 )
goto leave;
nbits = buffer[0] << 8 | buffer[1];
if ( nbits > MAX_EXTERN_MPI_BITS )
{
/* log_debug ("mpi too large (%u bits)\n", nbits); */
goto leave;
}
buffer += 2;
nread = 2;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs);
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
j= val->nlimbs = nlimbs;
val->sign = 0;
for ( ; j > 0; j-- )
{
a = 0;
for (; i < BYTES_PER_MPI_LIMB; i++ )
{
if ( ++nread > *ret_nread )
{
/* log_debug ("mpi larger than buffer"); */
mpi_free (val);
val = NULL;
goto leave;
}
a <<= 8;
a |= *buffer++;
}
i = 0;
val->d[j-1] = a;
}
leave:
*ret_nread = nread;
return val;
}
/****************
* Fill the mpi VAL from the hex string in STR.
*/
static int
mpi_fromstr (gcry_mpi_t val, const char *str)
{
int sign = 0;
int prepend_zero = 0;
int i, j, c, c1, c2;
unsigned int nbits, nbytes, nlimbs;
mpi_limb_t a;
if ( *str == '-' )
{
sign = 1;
str++;
}
/* 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. */
}
nbits *= 4;
if ((nbits % 8))
prepend_zero = 1;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
if ( val->alloced < nlimbs )
mpi_resize (val, nlimbs);
i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
i %= BYTES_PER_MPI_LIMB;
j = val->nlimbs = nlimbs;
val->sign = sign;
for (; j > 0; j--)
{
a = 0;
for (; i < BYTES_PER_MPI_LIMB; i++)
{
if (prepend_zero)
{
c1 = '0';
prepend_zero = 0;
}
else
c1 = *str++;
if (!c1)
{
mpi_clear (val);
return 1; /* Error. */
}
c2 = *str++;
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
{
mpi_clear(val);
return 1; /* Error. */
}
a <<= 8;
a |= c;
}
i = 0;
val->d[j-1] = a;
}
return 0; /* Okay. */
}
/* Return an allocated buffer with the MPI (msb first). NBYTES
receives the length of this buffer. If FILL_LE is not 0, the
returned value is stored as little endian and right padded with
zeroes so that the returned buffer has at least FILL_LE bytes.
If EXTRAALLOC > 0 the returned buffer has these number of bytes
extra allocated at the end; if EXTRAALLOC < 0 the returned buffer
has the absolute value of EXTRAALLOC allocated at the begin of the
buffer (the are not initialized) and the MPI is stored right after
this. This feature is useful to allow the caller to prefix the
returned value. EXTRAALLOC is _not_ included in the value stored
at NBYTES.
Caller must free the return string. This function returns an
allocated buffer with NBYTES set to zero if the value of A is zero.
If sign is not NULL, it will be set to the sign of the A. On error
NULL is returned and ERRNO set appropriately. */
static unsigned char *
do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
unsigned int *nbytes, int *sign, int force_secure)
{
unsigned char *p, *buffer, *retbuffer;
unsigned int length, tmp;
mpi_limb_t alimb;
int i;
size_t n, n2;
if (sign)
*sign = a->sign;
*nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
n = *nbytes? *nbytes:1; /* Allocate at least one byte. */
if (n < fill_le)
n = fill_le;
if (extraalloc < 0)
n2 = n + -extraalloc;
else
n2 = n + extraalloc;
retbuffer = (force_secure || mpi_is_secure(a))? xtrymalloc_secure (n2)
: xtrymalloc (n2);
if (!retbuffer)
return NULL;
if (extraalloc < 0)
buffer = retbuffer + -extraalloc;
else
buffer = retbuffer;
p = buffer;
for (i=a->nlimbs-1; i >= 0; i--)
{
alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
*p++ = alimb >> 24;
*p++ = alimb >> 16;
*p++ = alimb >> 8;
*p++ = alimb ;
#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 ;
#else
# error please implement for this limb size.
#endif
}
if (fill_le)
{
length = *nbytes;
/* Reverse buffer and pad with zeroes. */
for (i=0; i < length/2; i++)
{
tmp = buffer[i];
buffer[i] = buffer[length-1-i];
buffer[length-1-i] = tmp;
}
/* Pad with zeroes. */
for (p = buffer + length; length < fill_le; length++)
*p++ = 0;
*nbytes = length;
return retbuffer;
}
/* This is sub-optimal but we need to do the shift operation because
the caller has to free the returned buffer. */
for (p=buffer; *nbytes && !*p; p++, --*nbytes)
;
if (p != buffer)
memmove (buffer, p, *nbytes);
return retbuffer;
}
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);
}
byte *
_gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
unsigned int *r_nbytes, int *sign)
{
return do_get_buffer (a, fill_le, extraalloc, r_nbytes, sign, 0);
}
byte *
_gcry_mpi_get_secure_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, 1);
}
/*
* Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to
* SIGN.
*/
void
_gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
unsigned int nbytes, int sign)
{
const unsigned char *buffer = (const unsigned char*)buffer_arg;
const unsigned char *p;
mpi_limb_t alimb;
int nlimbs;
int i;
if (mpi_is_immutable (a))
{
mpi_immutable_failed ();
return;
}
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
RESIZE_IF_NEEDED(a, nlimbs);
a->sign = sign;
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 ;
#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 ;
#else
# error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
if ( p >= buffer )
{
#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;
#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;
#else
# error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
a->nlimbs = i;
gcry_assert (i == nlimbs);
}
static void
onecompl (gcry_mpi_t a)
{
mpi_ptr_t ap;
mpi_size_t n;
unsigned int i;
unsigned int nbits;
if (!a || mpi_is_immutable (a))
{
mpi_immutable_failed ();
return;
}
nbits = mpi_get_nbits (a);
mpi_normalize (a);
ap = a->d;
n = a->nlimbs;
for( i = 0; i < n; i++ )
ap[i] ^= (mpi_limb_t)(-1);
a->sign = 0;
mpi_clear_highbit (a, nbits-1);
}
/* Perform a two's complement operation on buffer P of size N bytes. */
static void
twocompl (unsigned char *p, unsigned int n)
{
int i;
for (i=n-1; i >= 0 && !p[i]; i--)
;
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;
for (i--; i >= 0; i--)
p[i] ^= 0xff;
}
}
/* Convert the external representation of an integer stored in BUFFER
* with a length of BUFLEN into a newly create MPI returned in
* RET_MPI. If NSCANNED is not NULL, it will receive the number of
* bytes actually scanned after a successful operation. */
gcry_err_code_t
_gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
const void *buffer_arg, size_t buflen, size_t *nscanned)
{
const unsigned char *buffer = (const unsigned char*)buffer_arg;
struct gcry_mpi *a = NULL;
unsigned int len;
int secure = (buffer && _gcry_is_secure (buffer));
if (buflen > MAX_EXTERN_SCAN_BYTES)
{
if (nscanned)
*nscanned = 0;
return GPG_ERR_INV_OBJ;
}
if (format == GCRYMPI_FMT_SSH)
len = 0;
else
len = buflen;
if (format == GCRYMPI_FMT_STD)
{
const unsigned char *s = buffer;
a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
/BYTES_PER_MPI_LIMB)
: mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
if (len)
{
_gcry_mpi_set_buffer (a, s, len, 0);
a->sign = !!(*s & 0x80);
if (a->sign)
{
onecompl (a);
mpi_add_ui (a, a, 1);
a->sign = 1;
}
}
if (ret_mpi)
{
mpi_normalize ( a );
*ret_mpi = a;
}
else
mpi_free(a);
if (nscanned)
*nscanned = len;
return 0;
}
else if (format == GCRYMPI_FMT_USG)
{
a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
/BYTES_PER_MPI_LIMB)
: mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
if (len)
_gcry_mpi_set_buffer (a, buffer, len, 0);
if (ret_mpi)
{
mpi_normalize ( a );
*ret_mpi = a;
}
else
mpi_free(a);
if (nscanned)
*nscanned = len;
return 0;
}
else if (format == GCRYMPI_FMT_PGP)
{
a = mpi_read_from_buffer (buffer, &len, secure);
if (nscanned)
*nscanned = len;
if (ret_mpi && a)
{
mpi_normalize (a);
*ret_mpi = a;
}
else if (a)
{
mpi_free(a);
a = NULL;
}
return a? 0 : GPG_ERR_INV_OBJ;
}
else if (format == GCRYMPI_FMT_SSH)
{
const unsigned char *s = buffer;
size_t n;
/* This test is not strictly necessary and an assert (!len)
would be sufficient. We keep this test in case we later
allow the BUFLEN argument to act as a sanitiy check. Same
below. */
if (len && len < 4)
return GPG_ERR_TOO_SHORT;
n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
s += 4;
if (len)
len -= 4;
if (len && n > len)
return GPG_ERR_TOO_LARGE;
a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
/BYTES_PER_MPI_LIMB)
: mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
if (n)
{
_gcry_mpi_set_buffer( a, s, n, 0 );
a->sign = !!(*s & 0x80);
if (a->sign)
{
onecompl (a);
mpi_add_ui (a, a, 1);
a->sign = 1;
}
}
if (nscanned)
*nscanned = n+4;
if (ret_mpi)
{
mpi_normalize ( a );
*ret_mpi = a;
}
else
mpi_free(a);
return 0;
}
else if (format == GCRYMPI_FMT_HEX)
{
/* 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))
{
mpi_free (a);
return GPG_ERR_INV_OBJ;
}
if (ret_mpi)
{
mpi_normalize ( a );
*ret_mpi = a;
}
else
mpi_free(a);
if (nscanned)
*nscanned = strlen ((const char*)buffer);
return 0;
}
else
return GPG_ERR_INV_ARG;
}
/* Convert the big integer A into the external representation
described by FORMAT and store it in the provided BUFFER which has
been allocated by the user with a size of BUFLEN bytes. NWRITTEN
receives the actual length of the external representation unless it
has been passed as NULL. BUFFER may be NULL to query the required
length. */
gcry_err_code_t
_gcry_mpi_print (enum gcry_mpi_format format,
unsigned char *buffer, size_t buflen,
size_t *nwritten, struct gcry_mpi *a)
{
unsigned int nbits = mpi_get_nbits (a);
size_t len;
size_t dummy_nwritten;
int negative;
if (!nwritten)
nwritten = &dummy_nwritten;
/* Libgcrypt does no always care to set clear the sign if the value
is 0. For printing this is a bit of a surprise, in particular
because if some of the formats don't support negative numbers but
should be able to print a zero. Thus we need this extra test
for a negative number. */
if (a->sign && _gcry_mpi_cmp_ui (a, 0))
negative = 1;
else
negative = 0;
len = buflen;
*nwritten = 0;
if (format == GCRYMPI_FMT_STD)
{
unsigned char *tmp;
int extra = 0;
unsigned int n;
tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
if (!tmp)
return gpg_err_code_from_syserror ();
if (negative)
{
twocompl (tmp, n);
if (!(*tmp & 0x80))
{
/* Need to extend the sign. */
n++;
extra = 2;
}
}
else if (n && (*tmp & 0x80))
{
/* Positive but the high bit of the returned buffer is set.
Thus we need to print an extra leading 0x00 so that the
output is interpreted as a positive number. */
n++;
extra = 1;
}
if (buffer && n > len)
{
/* The provided buffer is too short. */
xfree (tmp);
return GPG_ERR_TOO_SHORT;
}
if (buffer)
{
unsigned char *s = buffer;
if (extra == 1)
*s++ = 0;
else if (extra)
*s++ = 0xff;
memcpy (s, tmp, n-!!extra);
}
xfree (tmp);
*nwritten = n;
return 0;
}
else if (format == GCRYMPI_FMT_USG)
{
unsigned int n = (nbits + 7)/8;
/* Note: We ignore the sign for this format. */
/* FIXME: for performance reasons we should put this into
mpi_aprint because we can then use the buffer directly. */
if (buffer && n > len)
return GPG_ERR_TOO_SHORT;
if (buffer)
{
unsigned char *tmp;
tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
if (!tmp)
return gpg_err_code_from_syserror ();
memcpy (buffer, tmp, n);
xfree (tmp);
}
*nwritten = n;
return 0;
}
else if (format == GCRYMPI_FMT_PGP)
{
unsigned int n = (nbits + 7)/8;
/* The PGP format can only handle unsigned integers. */
if (negative)
return GPG_ERR_INV_ARG;
if (buffer && n+2 > len)
return GPG_ERR_TOO_SHORT;
if (buffer)
{
unsigned char *tmp;
unsigned char *s = buffer;
s[0] = nbits >> 8;
s[1] = nbits;
tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
if (!tmp)
return gpg_err_code_from_syserror ();
memcpy (s+2, tmp, n);
xfree (tmp);
}
*nwritten = n+2;
return 0;
}
else if (format == GCRYMPI_FMT_SSH)
{
unsigned char *tmp;
int extra = 0;
unsigned int n;
tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
if (!tmp)
return gpg_err_code_from_syserror ();
if (negative)
{
twocompl (tmp, n);
if (!(*tmp & 0x80))
{
/* Need to extend the sign. */
n++;
extra = 2;
}
}
else if (n && (*tmp & 0x80))
{
n++;
extra=1;
}
if (buffer && n+4 > len)
{
xfree(tmp);
return GPG_ERR_TOO_SHORT;
}
if (buffer)
{
unsigned char *s = buffer;
*s++ = n >> 24;
*s++ = n >> 16;
*s++ = n >> 8;
*s++ = n;
if (extra == 1)
*s++ = 0;
else if (extra)
*s++ = 0xff;
memcpy (s, tmp, n-!!extra);
}
xfree (tmp);
*nwritten = 4+n;
return 0;
}
else if (format == GCRYMPI_FMT_HEX)
{
unsigned char *tmp;
int i;
int extra = 0;
unsigned int n = 0;
tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
if (!tmp)
return gpg_err_code_from_syserror ();
if (!n || (*tmp & 0x80))
extra = 2;
if (buffer && 2*n + extra + negative + 1 > len)
{
xfree(tmp);
return GPG_ERR_TOO_SHORT;
}
if (buffer)
{
unsigned char *s = buffer;
if (negative)
*s++ = '-';
if (extra)
{
*s++ = '0';
*s++ = '0';
}
for (i=0; 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++ = 0;
*nwritten = s - buffer;
}
else
{
*nwritten = 2*n + extra + negative + 1;
}
xfree (tmp);
return 0;
}
else
return GPG_ERR_INV_ARG;
}
/*
* Like gcry_mpi_print but this function allocates the buffer itself.
* The caller has to supply the address of a pointer. NWRITTEN may be
* NULL.
*/
gcry_err_code_t
_gcry_mpi_aprint (enum gcry_mpi_format format,
unsigned char **buffer, size_t *nwritten,
struct gcry_mpi *a)
{
size_t n;
gcry_err_code_t rc;
*buffer = NULL;
rc = _gcry_mpi_print (format, NULL, 0, &n, a);
if (rc)
return rc;
*buffer = mpi_is_secure(a) ? xtrymalloc_secure (n?n:1) : xtrymalloc (n?n:1);
if (!*buffer)
return gpg_err_code_from_syserror ();
/* If the returned buffer will have a length of 0, we nevertheless
allocated 1 byte (malloc needs it anyway) and store a 0. */
if (!n)
**buffer = 0;
rc = _gcry_mpi_print( format, *buffer, n, &n, a );
if (rc)
{
xfree (*buffer);
*buffer = NULL;
}
else if (nwritten)
*nwritten = n;
return rc;
}
/* Turn VALUE into an octet string and store it in an allocated buffer
at R_FRAME or - if R_RAME is NULL - copy it into the caller
provided buffer SPACE; either SPACE or R_FRAME may be used. If
SPACE if not NULL, the caller must provide a buffer of at least
NBYTES. If the resulting octet string is shorter than NBYTES pad
it to the left with zeroes. If VALUE does not fit into NBYTES
return an error code. */
gpg_err_code_t
_gcry_mpi_to_octet_string (unsigned char **r_frame, void *space,
gcry_mpi_t value, size_t nbytes)
{
gpg_err_code_t rc;
size_t nframe, noff, n;
unsigned char *frame;
if (!r_frame == !space)
return GPG_ERR_INV_ARG; /* Only one may be used. */
if (r_frame)
*r_frame = NULL;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value);
if (rc)
return rc;
if (nframe > nbytes)
return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */
noff = (nframe < nbytes)? nbytes - nframe : 0;
n = nframe + noff;
if (space)
frame = space;
else
{
frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n);
if (!frame)
{
rc = gpg_err_code_from_syserror ();
return rc;
}
}
if (noff)
memset (frame, 0, noff);
nframe += noff;
rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value);
if (rc)
{
xfree (frame);
return rc;
}
if (r_frame)
*r_frame = frame;
return 0;
}
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 9dde37fb..857160a0 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -1,762 +1,762 @@
/* mpiutil.ac - Utility functions for MPI
* Copyright (C) 1998, 2000, 2001, 2002, 2003,
* 2007 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "g10lib.h"
#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];
const char *
_gcry_mpi_get_hw_config (void)
{
return mod_source_info + 1;
}
/* Initialize the MPI subsystem. This is called early and allows to
do some initialization without taking care of threading issues. */
gcry_err_code_t
_gcry_mpi_init (void)
{
int idx;
unsigned long value;
for (idx=0; idx < MPI_NUMBER_OF_CONSTANTS; idx++)
{
switch (idx)
{
case MPI_C_ZERO: value = 0; break;
case MPI_C_ONE: value = 1; break;
case MPI_C_TWO: value = 2; break;
case MPI_C_THREE: value = 3; break;
case MPI_C_FOUR: value = 4; break;
case MPI_C_EIGHT: value = 8; break;
default: log_bug ("invalid mpi_const selector %d\n", idx);
}
constants[idx] = mpi_alloc_set_ui (value);
constants[idx]->flags = (16|32);
}
return 0;
}
/****************
* Note: It was a bad idea to use the number of limbs to allocate
* because on a alpha the limbs are large but we normally need
* integers of n bits - So we should change this to bits (or bytes).
*
* But mpi_alloc is used in a lot of places :-(. New code
* should use mpi_new.
*/
gcry_mpi_t
_gcry_mpi_alloc( unsigned nlimbs )
{
gcry_mpi_t a;
a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
a->alloced = nlimbs;
a->nlimbs = 0;
a->sign = 0;
a->flags = 0;
return a;
}
void
_gcry_mpi_m_check( gcry_mpi_t a )
{
_gcry_check_heap(a);
_gcry_check_heap(a->d);
}
gcry_mpi_t
_gcry_mpi_alloc_secure( unsigned nlimbs )
{
gcry_mpi_t a;
a = xmalloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
a->alloced = nlimbs;
a->flags = 1;
a->nlimbs = 0;
a->sign = 0;
return a;
}
mpi_ptr_t
_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
{
mpi_ptr_t p;
size_t len;
len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
p = secure ? xmalloc_secure (len) : xmalloc (len);
if (! nlimbs)
*p = 0;
return p;
}
void
_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
{
if (a)
{
size_t len = nlimbs * sizeof(mpi_limb_t);
/* If we have information on the number of allocated limbs, we
better wipe that space out. This is a failsafe feature if
secure memory has been disabled or was not properly
implemented in user provided allocation functions. */
if (len)
wipememory (a, len);
xfree(a);
}
}
void
_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
{
_gcry_mpi_free_limb_space (a->d, a->alloced);
a->d = ap;
a->alloced = nlimbs;
}
/****************
* Resize the array of A to NLIMBS. The additional space is cleared
* (set to 0).
*/
void
_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
{
size_t i;
if (nlimbs <= a->alloced)
{
/* We only need to clear the new space (this is a nop if the
limb space is already of the correct size. */
for (i=a->nlimbs; i < a->alloced; i++)
a->d[i] = 0;
return;
}
/* Actually resize the limb space. */
if (a->d)
{
a->d = xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
for (i=a->alloced; i < nlimbs; i++)
a->d[i] = 0;
}
else
{
if (a->flags & 1)
/* Secure memory is wanted. */
a->d = xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
else
/* Standard memory. */
a->d = xcalloc (nlimbs , sizeof (mpi_limb_t));
}
a->alloced = nlimbs;
}
void
_gcry_mpi_clear( gcry_mpi_t a )
{
if (mpi_is_immutable (a))
{
mpi_immutable_failed ();
return;
}
a->nlimbs = 0;
a->flags = 0;
}
void
_gcry_mpi_free( gcry_mpi_t a )
{
if (!a )
return;
if ((a->flags & 32))
{
#if GPGRT_VERSION_NUMBER >= 0x011600 /* 1.22 */
gpgrt_annotate_leaked_object(a);
#endif
return; /* Never release a constant. */
}
if ((a->flags & 4))
xfree( a->d );
else
{
_gcry_mpi_free_limb_space(a->d, a->alloced);
}
/* Check that the flags makes sense. We better allow for bit 1
(value 2) for backward ABI compatibility. */
if ((a->flags & ~(1|2|4|16
|GCRYMPI_FLAG_USER1
|GCRYMPI_FLAG_USER2
|GCRYMPI_FLAG_USER3
|GCRYMPI_FLAG_USER4)))
log_bug("invalid flag value in mpi_free\n");
xfree (a);
}
void
_gcry_mpi_immutable_failed (void)
{
log_info ("Warning: trying to change an immutable MPI\n");
}
static void
mpi_set_secure( gcry_mpi_t a )
{
mpi_ptr_t ap, bp;
if ( (a->flags & 1) )
return;
a->flags |= 1;
ap = a->d;
if (!a->nlimbs)
{
gcry_assert (!ap);
return;
}
bp = mpi_alloc_limb_space (a->alloced, 1);
MPN_COPY( bp, ap, a->nlimbs );
a->d = bp;
_gcry_mpi_free_limb_space (ap, a->alloced);
}
gcry_mpi_t
_gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits)
{
if (!a)
a = mpi_alloc(0);
if (mpi_is_immutable (a))
{
mpi_immutable_failed ();
return a;
}
if( a->flags & 4 )
xfree (a->d);
else
_gcry_mpi_free_limb_space (a->d, a->alloced);
a->d = p;
a->alloced = 0;
a->nlimbs = 0;
a->sign = nbits;
a->flags = 4 | (a->flags & (GCRYMPI_FLAG_USER1|GCRYMPI_FLAG_USER2
|GCRYMPI_FLAG_USER3|GCRYMPI_FLAG_USER4));
if (_gcry_is_secure (a->d))
a->flags |= 1;
return a;
}
gcry_mpi_t
_gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits)
{
void *d;
unsigned int n;
n = (nbits+7)/8;
d = _gcry_is_secure (p)? xtrymalloc_secure (n) : xtrymalloc (n);
if (!d)
return NULL;
memcpy (d, p, n);
return mpi_set_opaque (a, d, nbits);
}
void *
_gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits)
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
if( nbits )
*nbits = a->sign;
return a->d;
}
void *
_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits)
{
const void *s;
void *d;
unsigned int n;
s = mpi_get_opaque (a, nbits);
if (!s && nbits)
return NULL;
n = (*nbits+7)/8;
d = _gcry_is_secure (s)? xtrymalloc_secure (n) : xtrymalloc (n);
if (d)
memcpy (d, s, n);
return d;
}
/****************
* Note: This copy function should not interpret the MPI
* but copy it transparently.
*/
gcry_mpi_t
_gcry_mpi_copy (gcry_mpi_t a)
{
int i;
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 );
b->flags &= ~(16|32); /* Reset the immutable and constant flags. */
}
else if( a ) {
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
b->nlimbs = a->nlimbs;
b->sign = a->sign;
b->flags = a->flags;
b->flags &= ~(16|32); /* Reset the immutable and constant flags. */
for(i=0; i < b->nlimbs; i++ )
b->d[i] = a->d[i];
}
else
b = NULL;
return b;
}
/* Return true if A is negative. */
int
_gcry_mpi_is_neg (gcry_mpi_t a)
{
if (a->sign && _gcry_mpi_cmp_ui (a, 0))
return 1;
else
return 0;
}
/* W = - U */
void
_gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u)
{
if (w != u)
mpi_set (w, u);
else if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
w->sign = !u->sign;
}
/* W = [W] */
void
_gcry_mpi_abs (gcry_mpi_t w)
{
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
w->sign = 0;
}
/****************
* This function allocates an MPI which is optimized to hold
* a value as large as the one given in the argument and allocates it
* with the same flags as A.
*/
gcry_mpi_t
_gcry_mpi_alloc_like( gcry_mpi_t a )
{
gcry_mpi_t b;
if( a && (a->flags & 4) ) {
int n = (a->sign+7)/8;
void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
: xtrymalloc (n);
memcpy( p, a->d, n );
b = mpi_set_opaque( NULL, p, a->sign );
}
else if( a ) {
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
b->nlimbs = 0;
b->sign = 0;
b->flags = a->flags;
}
else
b = NULL;
return b;
}
/* Set U into W and release U. If W is NULL only U will be released. */
void
_gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u)
{
if (w)
{
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
_gcry_mpi_assign_limb_space (w, u->d, u->alloced);
w->nlimbs = u->nlimbs;
w->sign = u->sign;
w->flags = u->flags;
u->alloced = 0;
u->nlimbs = 0;
u->d = NULL;
}
_gcry_mpi_free (u);
}
gcry_mpi_t
_gcry_mpi_set (gcry_mpi_t w, gcry_mpi_t u)
{
mpi_ptr_t wp, up;
mpi_size_t usize = u->nlimbs;
int usign = u->sign;
if (!w)
w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return w;
}
RESIZE_IF_NEEDED(w, usize);
wp = w->d;
up = u->d;
MPN_COPY( wp, up, usize );
w->nlimbs = usize;
w->flags = u->flags;
w->flags &= ~(16|32); /* Reset the immutable and constant flags. */
w->sign = usign;
return w;
}
/****************
* Set the value of W by the one of U, when SET is 1.
* Leave the value when SET is 0.
* This implementation should be constant-time regardless of SET.
*/
gcry_mpi_t
_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;
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;
}
x = mask & (w->nlimbs ^ u->nlimbs);
w->nlimbs = w->nlimbs ^ x;
x = mask & (w->sign ^ u->sign);
w->sign = w->sign ^ x;
return w;
}
gcry_mpi_t
_gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
{
if (!w)
w = _gcry_mpi_alloc (1);
/* FIXME: If U is 0 we have no need to resize and thus possible
allocating the the limbs. */
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return w;
}
RESIZE_IF_NEEDED(w, 1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
w->flags = 0;
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 U is not changed. */
gcry_err_code_t
_gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
{
mpi_limb_t x;
if (u->nlimbs > 1 || u->sign)
return GPG_ERR_ERANGE;
x = (u->nlimbs == 1) ? u->d[0] : 0;
if (sizeof (x) > sizeof (unsigned int) && x > MY_UINT_MAX)
return GPG_ERR_ERANGE;
*w = x;
return 0;
}
gcry_mpi_t
_gcry_mpi_alloc_set_ui( unsigned long u)
{
gcry_mpi_t w = mpi_alloc(1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
return w;
}
void
_gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
{
struct gcry_mpi tmp;
tmp = *a; *a = *b; *b = tmp;
}
/****************
* Swap the value of A and B, when SWAP is 1.
* Leave the value when SWAP is 0.
* This implementation should be constant-time regardless of SWAP.
*/
void
_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;
if (a->alloced > b->alloced)
nlimbs = b->alloced;
else
nlimbs = a->alloced;
if (a->nlimbs > nlimbs || b->nlimbs > nlimbs)
log_bug ("mpi_swap_cond: different sizes\n");
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;
}
x = mask & (a->nlimbs ^ b->nlimbs);
a->nlimbs = a->nlimbs ^ x;
b->nlimbs = b->nlimbs ^ x;
x = mask & (a->sign ^ b->sign);
a->sign = a->sign ^ x;
b->sign = b->sign ^ x;
}
gcry_mpi_t
_gcry_mpi_new (unsigned int nbits)
{
return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
/ BITS_PER_MPI_LIMB );
}
gcry_mpi_t
_gcry_mpi_snew (unsigned int nbits)
{
return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
/ BITS_PER_MPI_LIMB );
}
void
_gcry_mpi_release( gcry_mpi_t a )
{
_gcry_mpi_free( a );
}
void
_gcry_mpi_randomize (gcry_mpi_t w,
unsigned int nbits, enum gcry_random_level level)
{
unsigned char *p;
size_t nbytes = (nbits+7)/8;
if (mpi_is_immutable (w))
{
mpi_immutable_failed ();
return;
}
if (level == GCRY_WEAK_RANDOM)
{
p = mpi_is_secure(w) ? xmalloc_secure (nbytes)
: xmalloc (nbytes);
_gcry_create_nonce (p, nbytes);
}
else
{
p = mpi_is_secure(w) ? _gcry_random_bytes_secure (nbytes, level)
: _gcry_random_bytes (nbytes, level);
}
_gcry_mpi_set_buffer( w, p, nbytes, 0 );
xfree (p);
}
void
_gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
switch (flag)
{
case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break;
case GCRYMPI_FLAG_CONST: a->flags |= (16|32); break;
case GCRYMPI_FLAG_IMMUTABLE: a->flags |= 16; break;
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4: a->flags |= flag; break;
case GCRYMPI_FLAG_OPAQUE:
default: log_bug("invalid flag value\n");
}
}
void
_gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
(void)a; /* Not yet used. */
switch (flag)
{
case GCRYMPI_FLAG_IMMUTABLE:
if (!(a->flags & 32))
a->flags &= ~16;
break;
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4:
a->flags &= ~flag;
break;
case GCRYMPI_FLAG_CONST:
case GCRYMPI_FLAG_SECURE:
case GCRYMPI_FLAG_OPAQUE:
default: log_bug("invalid flag value\n");
}
}
int
_gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
switch (flag)
{
case GCRYMPI_FLAG_SECURE: return !!(a->flags & 1);
case GCRYMPI_FLAG_OPAQUE: return !!(a->flags & 4);
case GCRYMPI_FLAG_IMMUTABLE: return !!(a->flags & 16);
case GCRYMPI_FLAG_CONST: return !!(a->flags & 32);
case GCRYMPI_FLAG_USER1:
case GCRYMPI_FLAG_USER2:
case GCRYMPI_FLAG_USER3:
case GCRYMPI_FLAG_USER4: return !!(a->flags & flag);
default: log_bug("invalid flag value\n");
}
/*NOTREACHED*/
return 0;
}
/* Return a constant MPI descripbed by NO which is one of the
MPI_C_xxx macros. There is no need to copy this returned value; it
may be used directly. */
gcry_mpi_t
_gcry_mpi_const (enum gcry_mpi_constants no)
{
if ((int)no < 0 || no > MPI_NUMBER_OF_CONSTANTS)
log_bug("invalid mpi_const selector %d\n", no);
if (!constants[no])
log_bug("MPI subsystem not initialized\n");
return constants[no];
}
diff --git a/random/Makefile.am b/random/Makefile.am
index 60af5b4a..701d55c4 100644
--- a/random/Makefile.am
+++ b/random/Makefile.am
@@ -1,69 +1,69 @@
# 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/>.
+# License along with this program; if not, see <https://www.gnu.org/licenses/>.
# Process this file with automake to produce Makefile.in
# 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
if USE_RANDOM_DAEMON
librandom_la_SOURCES += random-daemon.c
endif USE_RANDOM_DAEMON
EXTRA_librandom_la_SOURCES = \
rndlinux.c \
rndegd.c \
rndunix.c \
rndw32.c \
rndw32ce.c \
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'
else
o_flag_munging = cat
endif
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) `
diff --git a/random/rand-internal.h b/random/rand-internal.h
index d99c6671..daf09f62 100644
--- a/random/rand-internal.h
+++ b/random/rand-internal.h
@@ -1,148 +1,148 @@
/* rand-internal.h - header to glue the random functions
* Copyright (C) 1998, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef G10_RAND_INTERNAL_H
#define G10_RAND_INTERNAL_H
#include "../src/cipher-proto.h"
/* Constants used to define the origin of random added to the pool.
The code is sensitive to the order of the values. */
enum random_origins
{
RANDOM_ORIGIN_INIT = 0, /* Used only for initialization. */
RANDOM_ORIGIN_EXTERNAL = 1, /* Added from an external source. */
RANDOM_ORIGIN_FASTPOLL = 2, /* Fast random poll function. */
RANDOM_ORIGIN_SLOWPOLL = 3, /* Slow poll function. */
RANDOM_ORIGIN_EXTRAPOLL = 4 /* Used to mark an extra pool seed
due to a GCRY_VERY_STRONG_RANDOM
random request. */
};
#define RANDOM_CONF_DISABLE_JENT 1
#define RANDOM_CONF_ONLY_URANDOM 2
/*-- random.c --*/
unsigned int _gcry_random_read_conf (void);
void _gcry_random_progress (const char *what, int printchar,
int current, int total);
/*-- random-csprng.c --*/
void _gcry_rngcsprng_initialize (int full);
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);
void *_gcry_rngcsprng_get_bytes (size_t nbytes,
enum gcry_random_level level);
void *_gcry_rngcsprng_get_bytes_secure (size_t nbytes,
enum gcry_random_level level);
void _gcry_rngcsprng_randomize (void *buffer, size_t length,
enum gcry_random_level level);
void _gcry_rngcsprng_set_seed_file (const char *name);
void _gcry_rngcsprng_update_seed_file (void);
void _gcry_rngcsprng_fast_poll (void);
/*-- random-drbg.c --*/
void _gcry_rngdrbg_inititialize (int full);
void _gcry_rngdrbg_close_fds (void);
void _gcry_rngdrbg_dump_stats (void);
int _gcry_rngdrbg_is_faked (void);
gcry_error_t _gcry_rngdrbg_add_bytes (const void *buf, size_t buflen,
int quality);
void _gcry_rngdrbg_randomize (void *buffer, size_t length,
enum gcry_random_level level);
gcry_error_t _gcry_rngdrbg_selftest (selftest_report_func_t report);
/*-- random-system.c --*/
void _gcry_rngsystem_initialize (int full);
void _gcry_rngsystem_close_fds (void);
void _gcry_rngsystem_dump_stats (void);
int _gcry_rngsystem_is_faked (void);
gcry_error_t _gcry_rngsystem_add_bytes (const void *buf, size_t buflen,
int quality);
void _gcry_rngsystem_randomize (void *buffer, size_t length,
enum gcry_random_level level);
/*-- 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);
/*-- rndunix.c --*/
int _gcry_rndunix_gather_random (void (*add) (const void *, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level);
/*-- rndegd.c --*/
int _gcry_rndegd_gather_random (void (*add) (const void *, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level);
int _gcry_rndegd_connect_socket (int nofail);
/*-- rndw32.c --*/
int _gcry_rndw32_gather_random (void (*add) (const void *, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level);
void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin );
/*-- rndw32ce.c --*/
int _gcry_rndw32ce_gather_random (void (*add) (const void *, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level);
void _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin );
/*-- rndjent.c --*/
size_t _gcry_rndjent_poll (void (*add)(const void*,
size_t, enum random_origins),
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);
void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin);
size_t _gcry_rndhw_poll_slow (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin);
#endif /*G10_RAND_INTERNAL_H*/
diff --git a/random/random-csprng.c b/random/random-csprng.c
index b06810a0..88f5ba0d 100644
--- a/random/random-csprng.c
+++ b/random/random-csprng.c
@@ -1,1285 +1,1285 @@
/* random-csprng.c - CSPRNG style random number generator (libgcrypt classic)
* Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
* 2007, 2008, 2010, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
This random number generator is modelled after the one described in
Peter Gutmann's 1998 Usenix Security Symposium paper: "Software
Generation of Practically Strong Random Numbers". See also chapter
6 in his book "Cryptographic Security Architecture", New York,
2004, ISBN 0-387-95387-6.
Note that the acronym CSPRNG stands for "Continuously Seeded
PseudoRandom Number Generator" as used in Peter's implementation of
the paper and not only for "Cryptographically Secure PseudoRandom
Number Generator".
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_GETHRTIME
#include <sys/times.h>
#endif
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#endif
#ifdef __MINGW32__
#include <process.h>
#endif
#include "g10lib.h"
#include "random.h"
#include "rand-internal.h"
#include "cipher.h" /* _gcry_sha1_hash_buffer */
#include "../cipher/sha1.h" /* _gcry_sha1_mixblock */
#ifndef RAND_MAX /* For SunOS. */
#define RAND_MAX 32767
#endif
/* Check whether we can lock the seed file read write. */
#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
#define LOCK_SEED_FILE 1
#else
#define LOCK_SEED_FILE 0
#endif
/* Define the constant we use for transforming the pool at read-out. */
#if SIZEOF_UNSIGNED_LONG == 8
#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
#elif SIZEOF_UNSIGNED_LONG == 4
#define ADD_VALUE 0xa5a5a5a5
#else
#error weird size for an unsigned long
#endif
/* Contstants pertaining to the hash pool. */
#define BLOCKLEN 64 /* Hash this amount of bytes... */
#define DIGESTLEN 20 /* ... into a digest of this length (sha-1). */
/* POOLBLOCKS is the number of digests which make up the pool. */
#define POOLBLOCKS 30
/* POOLSIZE must be a multiple of the digest length to make the AND
operations faster, the size should also be a multiple of unsigned
long. */
#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
#error Please make sure that poolsize is a multiple of unsigned long
#endif
#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
/* RNDPOOL is the pool we use to collect the entropy and to stir it
up. Its allocated size is POOLSIZE+BLOCKLEN. Note that this is
also an indication on whether the module has been fully
initialized. */
static unsigned char *rndpool;
/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
Its allocated size is also POOLSIZE+BLOCKLEN. */
static unsigned char *keypool;
/* This is the offset into RNDPOOL where the next random bytes are to
be mixed in. */
static size_t pool_writepos;
/* When reading data out of KEYPOOL, we start the read at different
positions. This variable keeps track on where to read next. */
static size_t pool_readpos;
/* This flag is set to true as soon as the pool has been completely
filled the first time. This may happen either by reading a seed
file or by adding enough entropy. */
static int pool_filled;
/* This counter is used to track whether the initial seeding has been
done with enough bytes from a reliable entropy source. */
static size_t pool_filled_counter;
/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
have stricter requirements on what kind of entropy is in the pool.
In particular POOL_FILLED is not sufficient. Thus we add some
extra seeding and set this flag to true if the extra seeding has
been done. */
static int did_initial_extra_seeding;
/* This variable is used to estimated the amount of fresh entropy
available in RNDPOOL. */
static int pool_balance;
/* After a mixing operation this variable will be set to true and
cleared if new entropy has been added or a remix is required for
other reasons. */
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
keep a malloced copy here. */
static char *seed_file_name;
/* If a seed file has been registered and maybe updated on exit this
flag set. */
static int allow_seed_file_update;
/* Option flag set at initialiation time to force allocation of the
pool in secure memory. */
static int secure_alloc;
/* This function pointer is set to the actual entropy gathering
function during initialization. After initialization it is
guaranteed to point to function. (On systems without a random
gatherer module a dummy function is used).*/
static int (*slow_gather_fnc)(void (*)(const void*, size_t,
enum random_origins),
enum random_origins, size_t, int);
/* This function is set to the actual fast entropy gathering function
during initialization. If it is NULL, no such function is
available. */
static void (*fast_gather_fnc)(void (*)(const void*, size_t,
enum random_origins),
enum random_origins);
/* Option flag useful for debugging and the test suite. If set
requests for very strong random are degraded to strong random. Not
used by regular applications. */
static int quick_test;
/* This is the lock we use to protect all pool operations. */
GPGRT_LOCK_DEFINE (pool_lock);
/* This is a helper for assert calls. These calls are used to assert
that functions are called in a locked state. It is not meant to be
thread-safe but as a method to get aware of missing locks in the
test suite. */
static int pool_is_locked;
/* We keep some counters in this structure for the sake of the
_gcry_random_dump_stats () function. */
static struct
{
unsigned long mixrnd;
unsigned long mixkey;
unsigned long slowpolls;
unsigned long fastpolls;
unsigned long getbytes1;
unsigned long ngetbytes1;
unsigned long getbytes2;
unsigned long ngetbytes2;
unsigned long addbytes;
unsigned long naddbytes;
} rndstats;
/* --- 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,
enum random_origins origin);
static void random_poll (void);
static void do_fast_random_poll (void);
static int (*getfnc_gather_random (void))(void (*)(const void*, size_t,
enum random_origins),
enum random_origins, size_t, int);
static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t,
enum random_origins),
enum random_origins);
static void read_random_source (enum random_origins origin,
size_t length, int level);
/* --- Functions --- */
/* Basic initialization which is required to initialize mutexes and
such. It does not run a full initialization so that the filling of
the random pool can be delayed until it is actually needed. We
assume that this function is used before any concurrent access
happens. */
static void
initialize_basics(void)
{
static int initialized;
if (!initialized)
{
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
&& GCRY_STRONG_RANDOM == 1
&& GCRY_VERY_STRONG_RANDOM == 2);
}
}
/* Take the pool lock. */
static void
lock_pool (void)
{
int err;
err = gpgrt_lock_lock (&pool_lock);
if (err)
log_fatal ("failed to acquire the pool lock: %s\n", gpg_strerror (err));
pool_is_locked = 1;
}
/* Release the pool lock. */
static void
unlock_pool (void)
{
int err;
pool_is_locked = 0;
err = gpgrt_lock_unlock (&pool_lock);
if (err)
log_fatal ("failed to release the pool lock: %s\n", gpg_strerror (err));
}
/* Full initialization of this module. */
static void
initialize(void)
{
/* Although the basic initialization should have happened already,
we call it here to make sure that all prerequisites are met. */
initialize_basics ();
/* Now we can look the pool and complete the initialization if
necessary. */
lock_pool ();
if (!rndpool)
{
/* The data buffer is allocated somewhat larger, so that we can
use this extra space (which is allocated in secure memory) as
a temporary hash buffer */
rndpool = (secure_alloc
? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
: xcalloc (1, POOLSIZE + BLOCKLEN));
keypool = (secure_alloc
? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
: xcalloc (1, POOLSIZE + BLOCKLEN));
/* Setup the slow entropy gathering function. The code requires
that this function exists. */
slow_gather_fnc = getfnc_gather_random ();
/* Setup the fast entropy gathering function. */
fast_gather_fnc = getfnc_fast_random_poll ();
}
unlock_pool ();
}
/* Initialize this random subsystem. If FULL is false, this function
merely calls the initialize and does not do anything more. Doing
this is not really required but when running in a threaded
environment we might get a race condition otherwise. */
void
_gcry_rngcsprng_initialize (int full)
{
if (!full)
initialize_basics ();
else
initialize ();
}
/* Try to close the FDs of the random gather module. This is
currently only implemented for rndlinux. */
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. */
#endif
unlock_pool ();
}
void
_gcry_rngcsprng_dump_stats (void)
{
/* In theory we would need to lock the stats here. However this
function is usually called during cleanup and then we _might_ run
into problems. */
log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
" outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n",
POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
rndstats.naddbytes, rndstats.addbytes,
rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
rndstats.ngetbytes2, rndstats.getbytes2,
_gcry_rndhw_failed_p()? " (hwrng failed)":"");
}
/* This function should be called during initialization and before
initialization of this module to place the random pools into secure
memory. */
void
_gcry_rngcsprng_secure_alloc (void)
{
secure_alloc = 1;
}
/* This may be called before full initialization to degrade the
quality of the RNG for the sake of a faster running test suite. */
void
_gcry_rngcsprng_enable_quick_gen (void)
{
quick_test = 1;
}
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
_gcry_rngcsprng_is_faked (void)
{
/* We need to initialize due to the runtime determination of
available entropy gather modules. */
initialize();
return quick_test;
}
/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
should be in the range of 0..100 to indicate the goodness of the
entropy added, or -1 for goodness not known. */
gcry_error_t
_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
{
size_t nbytes;
const char *bufptr;
if (quality == -1)
quality = 35;
else if (quality > 100)
quality = 100;
else if (quality < 0)
quality = 0;
if (!buf)
return gpg_error (GPG_ERR_INV_ARG);
if (!buflen || quality < 10)
return 0; /* Take a shortcut. */
/* Because we don't increment the entropy estimation with FASTPOLL,
we don't need to take lock that estimation while adding from an
external source. This limited entropy estimation also means that
we can't take QUALITY into account. */
initialize_basics ();
bufptr = buf;
while (buflen)
{
nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
lock_pool ();
if (rndpool)
add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
unlock_pool ();
bufptr += nbytes;
buflen -= nbytes;
}
return 0;
}
/* Public function to fill the buffer with LENGTH bytes of
cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
not very strong, GCRY_STRONG_RANDOM is strong enough for most
usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
may be very slow. */
void
_gcry_rngcsprng_randomize (void *buffer, size_t length,
enum gcry_random_level level)
{
unsigned char *p;
/* Make sure we are initialized. */
initialize ();
/* Handle our hack used for regression tests of Libgcrypt. */
if ( quick_test && level > GCRY_STRONG_RANDOM )
level = GCRY_STRONG_RANDOM;
/* 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 ();
/* Update the statistics. */
if (level >= GCRY_VERY_STRONG_RANDOM)
{
rndstats.getbytes2 += length;
rndstats.ngetbytes2++;
}
else
{
rndstats.getbytes1 += length;
rndstats.ngetbytes1++;
}
/* Read the random into the provided buffer. */
for (p = buffer; length > 0;)
{
size_t n;
n = length > POOLSIZE? POOLSIZE : length;
read_pool (p, n, level);
length -= n;
p += n;
}
/* Release the pool lock. */
unlock_pool ();
}
/*
* Mix the 600 byte pool. Note that the 64 byte scratch area directly
* follows the pool. The numbers in the diagram give the number of
* bytes.
* <................600...............> <.64.>
* pool |------------------------------------| |------|
* <20><.24.> <20>
* | | +-----+
* +-----|-------------------------------|-+
* +-------------------------------|-|-+
* v v v
* |------|
* <hash>
* +---------------------------------------+
* v
* <20>
* pool' |------------------------------------|
* <20><20><.24.>
* +---|-----|---------------------------+
* +-----|---------------------------|-+
* +---------------------------|-|-+
* v v v
* |------|
* <hash>
* |
* +-----------------------------------+
* v
* <20>
* pool'' |------------------------------------|
* <20><20><20><.24.>
* +---|-----|-----------------------+
* +-----|-----------------------|-+
* +-----------------------|-|-+
* v v v
*
* and so on until we did this for all 30 blocks.
*
* To better protect against implementation errors in this code, we
* xor a digest of the entire pool into the pool before mixing.
*
* Note: this function must only be called with a locked pool.
*/
static void
mix_pool(unsigned char *pool)
{
static unsigned char failsafe_digest[DIGESTLEN];
static int failsafe_digest_valid;
unsigned char *hashbuf = pool + POOLSIZE;
unsigned char *p, *pend;
int i, n;
SHA1_CONTEXT md;
unsigned int nburn;
#if DIGESTLEN != 20
#error must have a digest length of 20 for SHA-1
#endif
gcry_assert (pool_is_locked);
_gcry_sha1_mixblock_init (&md);
/* pool_0 -> pool'. */
pend = pool + POOLSIZE;
memcpy (hashbuf, pend - DIGESTLEN, DIGESTLEN);
memcpy (hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
nburn = _gcry_sha1_mixblock (&md, hashbuf);
memcpy (pool, hashbuf, DIGESTLEN);
if (failsafe_digest_valid && pool == rndpool)
{
for (i=0; i < DIGESTLEN; i++)
pool[i] ^= failsafe_digest[i];
}
/* Loop for the remaining iterations. */
p = pool;
for (n=1; n < POOLBLOCKS; n++)
{
if (p + BLOCKLEN < pend)
memcpy (hashbuf, p, BLOCKLEN);
else
{
unsigned char *pp = p;
for (i=0; i < BLOCKLEN; i++ )
{
if ( pp >= pend )
pp = pool;
hashbuf[i] = *pp++;
}
}
_gcry_sha1_mixblock (&md, hashbuf);
p += DIGESTLEN;
memcpy (p, hashbuf, DIGESTLEN);
}
/* Our hash implementation does only leave small parts (64 bytes)
of the pool on the stack, so it is okay not to require secure
memory here. Before we use this pool, it will be copied to the
help buffer anyway. */
if ( pool == rndpool)
{
_gcry_sha1_hash_buffer (failsafe_digest, pool, POOLSIZE);
failsafe_digest_valid = 1;
}
_gcry_burn_stack (nburn);
}
void
_gcry_rngcsprng_set_seed_file (const char *name)
{
if (seed_file_name)
BUG ();
seed_file_name = xstrdup (name);
}
/* 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
on success or -1 on error. */
static int
lock_seed_file (int fd, const char *fname, int for_write)
{
#ifdef __GCC__
#warning Check whether we can lock on Windows.
#endif
#if LOCK_SEED_FILE
struct flock lck;
struct timeval tv;
int backoff=0;
/* We take a lock on the entire file. */
memset (&lck, 0, sizeof lck);
lck.l_type = for_write? F_WRLCK : F_RDLCK;
lck.l_whence = SEEK_SET;
while (fcntl (fd, F_SETLK, &lck) == -1)
{
if (errno != EAGAIN && errno != EACCES)
{
log_info (_("can't lock `%s': %s\n"), fname, strerror (errno));
return -1;
}
if (backoff > 2) /* Show the first message after ~2.25 seconds. */
log_info( _("waiting for lock on `%s'...\n"), fname);
tv.tv_sec = backoff;
tv.tv_usec = 250000;
select (0, NULL, NULL, NULL, &tv);
if (backoff < 10)
backoff++ ;
}
#else
(void)fd;
(void)fname;
(void)for_write;
#endif /*!LOCK_SEED_FILE*/
return 0;
}
/* Read in a seed from the random_seed file and return true if this
was successful.
Note: Multiple instances of 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 32 bytes from a non-blocking entropy source. The
consequence is that the output of these different instances is
correlated to some extent. In the perfect 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 32 bytes" above to 0. Then the dependencies of the initial
states of the pools are completely known. */
static int
read_seed_file (void)
{
int fd;
struct stat sb;
unsigned char buffer[POOLSIZE];
int n;
gcry_assert (pool_is_locked);
if (!seed_file_name)
return 0;
#ifdef HAVE_DOSISH_SYSTEM
fd = open( seed_file_name, O_RDONLY | O_BINARY );
#else
fd = open( seed_file_name, O_RDONLY );
#endif
if( fd == -1 && errno == ENOENT)
{
allow_seed_file_update = 1;
return 0;
}
if (fd == -1 )
{
log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
return 0;
}
if (lock_seed_file (fd, seed_file_name, 0))
{
close (fd);
return 0;
}
if (fstat( fd, &sb ) )
{
log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
close(fd);
return 0;
}
if (!S_ISREG(sb.st_mode) )
{
log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
close(fd);
return 0;
}
if (!sb.st_size )
{
log_info(_("note: random_seed file is empty\n") );
close(fd);
allow_seed_file_update = 1;
return 0;
}
if (sb.st_size != POOLSIZE )
{
log_info(_("warning: invalid size of random_seed file - not used\n") );
close(fd);
return 0;
}
do
{
n = read( fd, buffer, POOLSIZE );
}
while (n == -1 && errno == EINTR );
if (n != POOLSIZE)
{
log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
close(fd);/*NOTREACHED*/
return 0;
}
close(fd);
add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
/* add some minor entropy to the pool now (this will also force a mixing) */
{
pid_t x = getpid();
add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
}
{
time_t x = time(NULL);
add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
}
{
clock_t x = clock();
add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
}
/* And read a few bytes from our entropy source. If we have the
* Jitter RNG we can fast get a lot of entropy. Thus we read 1024
* bits from that source.
*
* Without the Jitter RNG we keep the old method of reading only a
* few bytes usually from /dev/urandom which won't block. */
if (_gcry_rndjent_get_version (NULL))
read_random_source (RANDOM_ORIGIN_INIT, 128, GCRY_STRONG_RANDOM);
else
read_random_source (RANDOM_ORIGIN_INIT, 32, GCRY_STRONG_RANDOM);
allow_seed_file_update = 1;
return 1;
}
void
_gcry_rngcsprng_update_seed_file (void)
{
unsigned long *sp, *dp;
int fd, i;
/* We do only a basic initialization so that we can lock the pool.
This is required to cope with the case that this function is
called by some cleanup code at a point where the RNG has never
been initialized. */
initialize_basics ();
lock_pool ();
if ( !seed_file_name || !rndpool || !pool_filled )
{
unlock_pool ();
return;
}
if ( !allow_seed_file_update )
{
unlock_pool ();
log_info(_("note: random_seed file not updated\n"));
return;
}
/* At this point we know that there is something in the pool and
thus we can conclude that the pool has been fully initialized. */
/* Copy the entropy pool to a scratch pool and mix both of them. */
for (i=0,dp=(unsigned long*)(void*)keypool, sp=(unsigned long*)(void*)rndpool;
i < POOLWORDS; i++, dp++, sp++ )
{
*dp = *sp + ADD_VALUE;
}
mix_pool(rndpool); rndstats.mixrnd++;
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 );
#else
# if LOCK_SEED_FILE
fd = 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 );
# endif
#endif
if (fd == -1 )
log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
else if (lock_seed_file (fd, seed_file_name, 1))
{
close (fd);
}
#if LOCK_SEED_FILE
else if (ftruncate (fd, 0))
{
log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
close (fd);
}
#endif /*LOCK_SEED_FILE*/
else
{
do
{
i = write (fd, keypool, POOLSIZE );
}
while (i == -1 && errno == EINTR);
if (i != POOLSIZE)
log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
if (close(fd))
log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
}
unlock_pool ();
}
/* Read random out of the pool. This function is the core of the
public random functions. Note that Level GCRY_WEAK_RANDOM is not
anymore handled special and in fact is an alias in the API for
level GCRY_STRONG_RANDOM. Must be called with the pool already
locked. */
static void
read_pool (byte *buffer, size_t length, int level)
{
int i;
unsigned long *sp, *dp;
/* The volatile is there to make sure the compiler does not optimize
the code away in case the getpid function is badly attributed.
Note that we keep a pid in a static variable as well as in a
stack based one; the latter is to detect ill behaving thread
libraries, ignoring the pool mutexes. */
static volatile pid_t my_pid = (pid_t)(-1);
volatile pid_t my_pid2;
gcry_assert (pool_is_locked);
retry:
/* Get our own pid, so that we can detect a fork. */
my_pid2 = getpid ();
if (my_pid == (pid_t)(-1))
my_pid = my_pid2;
if ( my_pid != my_pid2 )
{
/* We detected a plain fork; i.e. we are now the child. Update
the static pid and add some randomness. */
pid_t x;
my_pid = my_pid2;
x = my_pid;
add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
just_mixed = 0; /* Make sure it will get mixed. */
}
gcry_assert (pool_is_locked);
/* Our code does not allow to extract more than POOLSIZE. Better
check it here. */
if (length > POOLSIZE)
{
log_bug("too many random bits requested\n");
}
if (!pool_filled)
{
if (read_seed_file() )
pool_filled = 1;
}
/* For level 2 quality (key generation) we always make sure that the
pool has been seeded enough initially. */
if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding)
{
size_t needed;
pool_balance = 0;
needed = length - pool_balance;
if (needed < 16) /* At least 128 bits. */
needed = 16;
else if( needed > POOLSIZE )
BUG ();
read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
GCRY_VERY_STRONG_RANDOM);
pool_balance += needed;
did_initial_extra_seeding = 1;
}
/* For level 2 make sure that there is enough random in the pool. */
if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length)
{
size_t needed;
if (pool_balance < 0)
pool_balance = 0;
needed = length - pool_balance;
if (needed > POOLSIZE)
BUG ();
read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
GCRY_VERY_STRONG_RANDOM);
pool_balance += needed;
}
/* Make sure the pool is filled. */
while (!pool_filled)
random_poll();
/* Always do a fast random poll (we have to use the unlocked version). */
do_fast_random_poll();
/* Mix the pid in so that we for sure won't deliver the same random
after a fork. */
{
pid_t apid = my_pid;
add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT);
}
/* Mix the pool (if add_randomness() didn't it). */
if (!just_mixed)
{
mix_pool(rndpool);
rndstats.mixrnd++;
}
/* Create a new pool. */
for(i=0,dp=(unsigned long*)(void*)keypool, sp=(unsigned long*)(void*)rndpool;
i < POOLWORDS; i++, dp++, sp++ )
*dp = *sp + ADD_VALUE;
/* Mix both pools. */
mix_pool(rndpool); rndstats.mixrnd++;
mix_pool(keypool); rndstats.mixkey++;
/* Read the requested data. We use a read pointer to read from a
different position each time. */
while (length--)
{
*buffer++ = keypool[pool_readpos++];
if (pool_readpos >= POOLSIZE)
pool_readpos = 0;
pool_balance--;
}
if (pool_balance < 0)
pool_balance = 0;
/* Clear the keypool. */
memset (keypool, 0, POOLSIZE);
/* We need to detect whether a fork has happened. A fork might have
an identical pool and thus the child and the parent could emit
the very same random number. This test here is to detect forks
in a multi-threaded process. It does not work with all thread
implementations in particular not with pthreads. However it is
good enough for GNU Pth. */
if ( getpid () != my_pid2 )
{
pid_t x = getpid();
add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
just_mixed = 0; /* Make sure it will get mixed. */
my_pid = x; /* Also update the static pid. */
goto retry;
}
}
/* Add LENGTH bytes of randomness from buffer to the pool. ORIGIN is
used to specify the randomness origin. This is one of the
RANDOM_ORIGIN_* values. */
static void
add_randomness (const void *buffer, size_t length, enum random_origins origin)
{
const unsigned char *p = buffer;
size_t count = 0;
gcry_assert (pool_is_locked);
rndstats.addbytes += length;
rndstats.naddbytes++;
while (length-- )
{
rndpool[pool_writepos++] ^= *p++;
count++;
if (pool_writepos >= POOLSIZE )
{
/* It is possible that we are invoked before the pool is
filled using an unreliable origin of entropy, for example
the fast random poll. To avoid flagging the pool as
filled in this case, we track the initial filling state
separately. See also the remarks about the seed file. */
if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
{
pool_filled_counter += count;
count = 0;
if (pool_filled_counter >= POOLSIZE)
pool_filled = 1;
}
pool_writepos = 0;
mix_pool(rndpool); rndstats.mixrnd++;
just_mixed = !length;
}
}
}
static void
random_poll()
{
rndstats.slowpolls++;
read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM);
}
/* Runtime determination of the slow entropy gathering module. */
static int (*
getfnc_gather_random (void))(void (*)(const void*, size_t,
enum random_origins),
enum random_origins, size_t, int)
{
int (*fnc)(void (*)(const void*, size_t, enum random_origins),
enum random_origins, size_t, int);
#if USE_RNDLINUX
if ( !access (NAME_OF_DEV_RANDOM, R_OK)
&& !access (NAME_OF_DEV_URANDOM, R_OK))
{
fnc = _gcry_rndlinux_gather_random;
return fnc;
}
#endif
#if USE_RNDEGD
if ( _gcry_rndegd_connect_socket (1) != -1 )
{
fnc = _gcry_rndegd_gather_random;
return fnc;
}
#endif
#if USE_RNDUNIX
fnc = _gcry_rndunix_gather_random;
return fnc;
#endif
#if USE_RNDW32
fnc = _gcry_rndw32_gather_random;
return fnc;
#endif
#if USE_RNDW32CE
fnc = _gcry_rndw32ce_gather_random;
return fnc;
#endif
log_fatal (_("no entropy gathering module detected\n"));
return NULL; /*NOTREACHED*/
}
/* Runtime determination of the fast entropy gathering function.
(Currently a compile time method is used.) */
static void (*
getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
enum random_origins),
enum random_origins)
{
#if USE_RNDW32
return _gcry_rndw32_gather_random_fast;
#endif
#if USE_RNDW32CE
return _gcry_rndw32ce_gather_random_fast;
#endif
return NULL;
}
static void
do_fast_random_poll (void)
{
gcry_assert (pool_is_locked);
rndstats.fastpolls++;
if (fast_gather_fnc)
fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL);
/* Continue with the generic functions. */
#if HAVE_GETHRTIME
{
hrtime_t tv;
tv = gethrtime();
add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL );
}
#elif HAVE_GETTIMEOFDAY
{
struct timeval tv;
if( gettimeofday( &tv, NULL ) )
BUG();
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL );
}
#elif HAVE_CLOCK_GETTIME
{ struct timespec tv;
if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
BUG();
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL );
}
#else /* use times */
# ifndef HAVE_DOSISH_SYSTEM
{ struct tms buf;
times( &buf );
add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
}
# endif
#endif
#ifdef HAVE_GETRUSAGE
# ifdef RUSAGE_SELF
{
struct rusage buf;
/* QNX/Neutrino does return ENOSYS - so we just ignore it and add
whatever is in buf. In a chroot environment it might not work
at all (i.e. because /proc/ is not accessible), so we better
ignore all error codes and hope for the best. */
getrusage (RUSAGE_SELF, &buf );
add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
memset( &buf, 0, sizeof buf );
}
# else /*!RUSAGE_SELF*/
# ifdef __GCC__
# warning There is no RUSAGE_SELF on this system
# endif
# endif /*!RUSAGE_SELF*/
#endif /*HAVE_GETRUSAGE*/
/* Time and clock are available on all systems - so we better do it
just in case one of the above functions didn't work. */
{
time_t x = time(NULL);
add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
}
{
clock_t x = clock();
add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
}
/* If the system features a fast hardware RNG, read some bytes from
there. */
_gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL);
}
/* The fast random pool function as called at some places in
libgcrypt. This is merely a wrapper to make sure that this module
is initialized and to lock the pool. Note, that this function is a
NOP unless a random function has been used or _gcry_initialize (1)
has been used. We use this hack so that the internal use of this
function in cipher_open and md_open won't start filling up the
random pool, even if no random will be required by the process. */
void
_gcry_rngcsprng_fast_poll (void)
{
initialize_basics ();
lock_pool ();
if (rndpool)
{
/* Yes, we are fully initialized. */
do_fast_random_poll ();
}
unlock_pool ();
}
static void
read_random_source (enum random_origins origin, size_t length, int level)
{
if ( !slow_gather_fnc )
log_fatal ("Slow entropy gathering module not yet initialized\n");
if (slow_gather_fnc (add_randomness, origin, length, level) < 0)
log_fatal ("No way to gather entropy for the RNG\n");
}
diff --git a/random/random-drbg.c b/random/random-drbg.c
index e0b4230e..8d662651 100644
--- a/random/random-drbg.c
+++ b/random/random-drbg.c
@@ -1,2668 +1,2668 @@
/* random-drbg.c - Deterministic Random Bits Generator
* Copyright 2014 Stephan Mueller <smueller@chronox.de>
*
* DRBG: Deterministic Random Bits Generator
* Based on NIST Recommended DRBG from NIST SP800-90A with the following
* properties:
* * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
* * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
* * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
* * with and without prediction resistance
*
* 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
* LGPLv2+, in which case the provisions of the LGPL are
* required INSTEAD OF the above restrictions. (This clause is
* necessary due to a potential bad interaction between the LGPL 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.
*
*
* gcry_control GCRYCTL_DRBG_REINIT
* ================================
* This control request re-initializes the DRBG completely, i.e. the entire
* state of the DRBG is zeroized (with two exceptions listed in
* GCRYCTL_DRBG_SET_ENTROPY).
*
* The control request takes the following values which influences how
* the DRBG is re-initialized:
*
* - const char *flagstr
*
* This variable specifies the DRBG type to be used for the next
* initialization. If set to NULL, the previous DRBG type is
* used for the initialization. If not NULL a space separated
* list of tokens with associated flag values is expected which
* are ORed to form the mandatory flags of the requested DRBG
* strength and cipher type. Optionally, the prediction
* resistance flag can be ORed into the flags variable.
*
* | String token | Flag value |
* |--------------+------------------------|
* | aes | DRBG_CTRAES |
* | serpent | DRBG_CTRSERPENT |
* | twofish | DRBG_CTRTWOFISH |
* | sha1 | DRBG_HASHSHA1 |
* | sha256 | DRBG_HASHSHA256 |
* | sha512 | DRBG_HASHSHA512 |
* | hmac | DRBG_HMAC |
* | sym128 | DRBG_SYM128 |
* | sym192 | DRBG_SYM192 |
* | sym256 | DRBG_SYM256 |
* | pr | DRBG_PREDICTION_RESIST |
*
* For example:
*
* - CTR-DRBG with AES-128 without prediction resistance:
* "aes sym128"
* - HMAC-DRBG with SHA-512 with prediction resistance:
* "hmac sha512 pr"
*
* - gcry_buffer_t *pers
*
* NULL terminated array with personalization strings to be used
* for initialization.
*
* - int npers
*
* Size of PERS.
*
* - void *guard
*
* A value of NULL must be passed for this.
*
* The variable of flags is independent from the pers/perslen variables. If
* flags is set to 0 and perslen is set to 0, the current DRBG type is
* completely reset without using a personalization string.
*
* DRBG Usage
* ==========
* The SP 800-90A DRBG allows the user to specify a personalization string
* for initialization as well as an additional information string for each
* random number request. The following code fragments show how a caller
* uses the API to use the full functionality of the DRBG.
*
* Usage without any additional data
* ---------------------------------
* gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
*
*
* Usage with personalization string during initialization
* -------------------------------------------------------
* drbg_string_t pers;
* char personalization[11] = "some-string";
*
* drbg_string_fill(&pers, personalization, strlen(personalization));
* // The reset completely re-initializes the DRBG with the provided
* // personalization string without changing the DRBG type
* ret = gcry_control(GCRYCTL_DRBG_REINIT, 0, &pers);
* gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
*
*
* Usage with additional information string during random number request
* ---------------------------------------------------------------------
* drbg_string_t addtl;
* char addtl_string[11] = "some-string";
*
* drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
* // The following call is a wrapper to gcry_randomize() and returns
* // the same error codes.
* gcry_randomize_drbg(outbuf, OUTLEN, GCRY_STRONG_RANDOM, &addtl);
*
*
* Usage with personalization and additional information strings
* -------------------------------------------------------------
* Just mix both scenarios above.
*
*
* Switch the DRBG type to some other type
* ---------------------------------------
* // Switch to CTR DRBG AES-128 without prediction resistance
* ret = gcry_control(GCRYCTL_DRBG_REINIT, DRBG_NOPR_CTRAES128, NULL);
* gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
*/
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <config.h>
#include "g10lib.h"
#include "random.h"
#include "rand-internal.h"
#include "../cipher/bufhelp.h"
/******************************************************************
* Constants
******************************************************************/
/*
* DRBG flags bitmasks
*
* 31 (B) 28 19 (A) 0
* +-+-+-+--------+---+-----------+-----+
* |~|~|u|~~~~~~~~| 3 | 2 | 1 |
* +-+-+-+--------+- -+-----------+-----+
* ctl flg| |drbg use selection flags
*
*/
/* Internal state control flags (B) */
#define DRBG_PREDICTION_RESIST ((u32)1<<28)
/* CTR type modifiers (A.1)*/
#define DRBG_CTRAES ((u32)1<<0)
#define DRBG_CTRSERPENT ((u32)1<<1)
#define DRBG_CTRTWOFISH ((u32)1<<2)
#define DRBG_CTR_MASK (DRBG_CTRAES | DRBG_CTRSERPENT \
| DRBG_CTRTWOFISH)
/* HASH type modifiers (A.2)*/
#define DRBG_HASHSHA1 ((u32)1<<4)
#define DRBG_HASHSHA224 ((u32)1<<5)
#define DRBG_HASHSHA256 ((u32)1<<6)
#define DRBG_HASHSHA384 ((u32)1<<7)
#define DRBG_HASHSHA512 ((u32)1<<8)
#define DRBG_HASH_MASK (DRBG_HASHSHA1 | DRBG_HASHSHA224 \
| DRBG_HASHSHA256 | DRBG_HASHSHA384 \
| DRBG_HASHSHA512)
/* type modifiers (A.3)*/
#define DRBG_HMAC ((u32)1<<12)
#define DRBG_SYM128 ((u32)1<<13)
#define DRBG_SYM192 ((u32)1<<14)
#define DRBG_SYM256 ((u32)1<<15)
#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_SYM128 | DRBG_SYM192 \
| DRBG_SYM256)
#define DRBG_CIPHER_MASK (DRBG_CTR_MASK | DRBG_HASH_MASK \
| DRBG_TYPE_MASK)
#define DRBG_PR_CTRAES128 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM128)
#define DRBG_PR_CTRAES192 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM192)
#define DRBG_PR_CTRAES256 (DRBG_PREDICTION_RESIST | DRBG_CTRAES | DRBG_SYM256)
#define DRBG_NOPR_CTRAES128 (DRBG_CTRAES | DRBG_SYM128)
#define DRBG_NOPR_CTRAES192 (DRBG_CTRAES | DRBG_SYM192)
#define DRBG_NOPR_CTRAES256 (DRBG_CTRAES | DRBG_SYM256)
#define DRBG_PR_HASHSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1)
#define DRBG_PR_HASHSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256)
#define DRBG_PR_HASHSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384)
#define DRBG_PR_HASHSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512)
#define DRBG_NOPR_HASHSHA1 (DRBG_HASHSHA1)
#define DRBG_NOPR_HASHSHA256 (DRBG_HASHSHA256)
#define DRBG_NOPR_HASHSHA384 (DRBG_HASHSHA384)
#define DRBG_NOPR_HASHSHA512 (DRBG_HASHSHA512)
#define DRBG_PR_HMACSHA1 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA1 \
| DRBG_HMAC)
#define DRBG_PR_HMACSHA256 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA256 \
| DRBG_HMAC)
#define DRBG_PR_HMACSHA384 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA384 \
| DRBG_HMAC)
#define DRBG_PR_HMACSHA512 (DRBG_PREDICTION_RESIST | DRBG_HASHSHA512 \
| DRBG_HMAC)
#define DRBG_NOPR_HMACSHA1 (DRBG_HASHSHA1 | DRBG_HMAC)
#define DRBG_NOPR_HMACSHA256 (DRBG_HASHSHA256 | DRBG_HMAC)
#define DRBG_NOPR_HMACSHA384 (DRBG_HASHSHA384 | DRBG_HMAC)
#define DRBG_NOPR_HMACSHA512 (DRBG_HASHSHA512 | DRBG_HMAC)
/* The default DRGB type. */
#define DRBG_DEFAULT_TYPE DRBG_NOPR_HMACSHA256
#define DRBG_CTR_NULL_LEN 128
/******************************************************************
* Common data structures
******************************************************************/
/*
* SP800-90A requires the concatenation of different data. To avoid copying
* buffers around or allocate additional memory, the following data structure
* is used to point to the original memory with its size. In addition, it
* is used to build a linked list. The linked list defines the concatenation
* of individual buffers. The order of memory block referenced in that
* linked list determines the order of concatenation.
*/
struct drbg_string_s
{
const unsigned char *buf;
size_t len;
struct drbg_string_s *next;
};
typedef struct drbg_string_s drbg_string_t;
/* DRBG input data structure for DRBG generate with additional
* information string. */
struct drbg_gen_s
{
unsigned char *outbuf; /* output buffer for random numbers */
unsigned int outlen; /* size of output buffer */
drbg_string_t *addtl; /* input buffer for
* additional information string */
};
typedef struct drbg_gen_s drbg_gen_t;
/* Forward declaration of the state object pointer. */
struct drbg_state_s;
typedef struct drbg_state_s *drbg_state_t;
struct drbg_core_s
{
u32 flags; /* flags for the cipher */
ushort statelen; /* maximum state length */
ushort blocklen_bytes; /* block size of output in bytes */
int backend_cipher; /* libgcrypt backend cipher */
};
struct drbg_state_ops_s
{
gpg_err_code_t (*update) (drbg_state_t drbg,
drbg_string_t *seed, int reseed);
gpg_err_code_t (*generate) (drbg_state_t drbg,
unsigned char *buf, unsigned int buflen,
drbg_string_t *addtl);
gpg_err_code_t (*crypto_init) (drbg_state_t drbg);
void (*crypto_fini) (drbg_state_t drbg);
};
struct drbg_test_data_s
{
drbg_string_t *testentropy; /* TEST PARAMETER: test entropy */
int fail_seed_source:1; /* If set, the seed function will
* return an error. */
};
/* This state object keeps the state of an DRBG instance. */
struct drbg_state_s
{
unsigned char *V; /* internal state 10.1.1.1 1a) */
unsigned char *C; /* hash: static value 10.1.1.1 1b)
* hmac / ctr: key */
size_t reseed_ctr; /* Number of RNG requests since last reseed --
* 10.1.1.1 1c) */
unsigned char *scratchpad; /* some memory the DRBG can use for its
* operation -- allocated during init */
void *priv_data; /* Cipher handle */
gcry_cipher_hd_t ctr_handle; /* CTR mode cipher handle */
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
* process which did the initialization so that we can detect a fork.
* The volatile modifier is required so that the compiler does not
* optimize it away in case the getpid function is badly attributed. */
pid_t seed_init_pid;
const struct drbg_state_ops_s *d_ops;
const struct drbg_core_s *core;
struct drbg_test_data_s *test_data;
};
enum drbg_prefixes
{
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
DRBG_PREFIX2,
DRBG_PREFIX3
};
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/***************************************************************
* Global variables
***************************************************************/
/* Global state variable holding the current instance of the DRBG. */
static drbg_state_t drbg_state;
/* This is the lock variable we use to serialize access to this RNG. */
GPGRT_LOCK_DEFINE(drbg_lock_var);
/***************************************************************
* Backend cipher definitions available to DRBG
***************************************************************/
static const struct drbg_core_s drbg_cores[] = {
/* Hash DRBGs */
{DRBG_HASHSHA1, 55, 20, GCRY_MD_SHA1},
{DRBG_HASHSHA256, 55, 32, GCRY_MD_SHA256},
{DRBG_HASHSHA384, 111, 48, GCRY_MD_SHA384},
{DRBG_HASHSHA512, 111, 64, GCRY_MD_SHA512},
/* HMAC DRBGs */
{DRBG_HASHSHA1 | DRBG_HMAC, 20, 20, GCRY_MD_SHA1},
{DRBG_HASHSHA256 | DRBG_HMAC, 32, 32, GCRY_MD_SHA256},
{DRBG_HASHSHA384 | DRBG_HMAC, 48, 48, GCRY_MD_SHA384},
{DRBG_HASHSHA512 | DRBG_HMAC, 64, 64, GCRY_MD_SHA512},
/* block ciphers */
{DRBG_CTRAES | DRBG_SYM128, 32, 16, GCRY_CIPHER_AES128},
{DRBG_CTRAES | DRBG_SYM192, 40, 16, GCRY_CIPHER_AES192},
{DRBG_CTRAES | DRBG_SYM256, 48, 16, GCRY_CIPHER_AES256}
};
static gpg_err_code_t drbg_hash_init (drbg_state_t drbg);
static gpg_err_code_t drbg_hmac_init (drbg_state_t drbg);
static gpg_err_code_t drbg_hmac_setkey (drbg_state_t drbg,
const unsigned char *key);
static void drbg_hash_fini (drbg_state_t drbg);
static byte *drbg_hash (drbg_state_t drbg, const drbg_string_t *buf);
static gpg_err_code_t drbg_sym_init (drbg_state_t drbg);
static void drbg_sym_fini (drbg_state_t drbg);
static gpg_err_code_t drbg_sym_setkey (drbg_state_t drbg,
const unsigned char *key);
static gpg_err_code_t drbg_sym (drbg_state_t drbg, unsigned char *outval,
const drbg_string_t *buf);
static gpg_err_code_t drbg_sym_ctr (drbg_state_t drbg,
const unsigned char *inbuf, unsigned int inbuflen,
unsigned char *outbuf, unsigned int outbuflen);
/******************************************************************
******************************************************************
******************************************************************
* Generic DRBG code
******************************************************************
******************************************************************
******************************************************************/
/******************************************************************
* Generic helper functions
******************************************************************/
#if 0
#define dbg(x) do { log_debug x; } while(0)
#else
#define dbg(x)
#endif
/*
* Parse a string of flags and store the flag values at R_FLAGS.
* Return 0 on success.
*/
static gpg_err_code_t
parse_flag_string (const char *string, u32 *r_flags)
{
struct {
const char *name;
u32 flag;
} table[] = {
{ "aes", DRBG_CTRAES },
{ "serpent", DRBG_CTRSERPENT },
{ "twofish", DRBG_CTRTWOFISH },
{ "sha1", DRBG_HASHSHA1 },
{ "sha256", DRBG_HASHSHA256 },
{ "sha512", DRBG_HASHSHA512 },
{ "hmac", DRBG_HMAC },
{ "sym128", DRBG_SYM128 },
{ "sym192", DRBG_SYM192 },
{ "sym256", DRBG_SYM256 },
{ "pr", DRBG_PREDICTION_RESIST }
};
*r_flags = 0;
if (string)
{
char **tl;
const char *s;
int i, j;
tl = _gcry_strtokenize (string, NULL);
if (!tl)
return gpg_err_code_from_syserror ();
for (i=0; (s=tl[i]); i++)
{
for (j=0; j < DIM (table); j++)
if (!strcmp (s, table[j].name))
{
*r_flags |= table[j].flag;
break;
}
if (!(j < DIM (table)))
{
xfree (tl);
return GPG_ERR_INV_FLAG;
}
}
xfree (tl);
}
return 0;
}
static inline void
drbg_string_fill (drbg_string_t *string,
const unsigned char *buf, size_t len)
{
string->buf = buf;
string->len = len;
string->next = NULL;
}
static inline ushort
drbg_statelen (drbg_state_t drbg)
{
if (drbg && drbg->core)
return drbg->core->statelen;
return 0;
}
static inline ushort
drbg_blocklen (drbg_state_t drbg)
{
if (drbg && drbg->core)
return drbg->core->blocklen_bytes;
return 0;
}
static inline ushort
drbg_keylen (drbg_state_t drbg)
{
if (drbg && drbg->core)
return (drbg->core->statelen - drbg->core->blocklen_bytes);
return 0;
}
static inline size_t
drbg_max_request_bytes (void)
{
/* SP800-90A requires the limit 2**19 bits, but we return bytes */
return (1 << 16);
}
static inline size_t
drbg_max_addtl (void)
{
/* SP800-90A requires 2**35 bytes additional info str / pers str */
#ifdef __LP64__
return (1UL << 35);
#else
/*
* SP800-90A allows smaller maximum numbers to be returned -- we
* return SIZE_MAX - 1 to allow the verification of the enforcement
* of this value in drbg_healthcheck_sanity.
*/
return (SIZE_MAX - 1);
#endif
}
static inline size_t
drbg_max_requests (void)
{
/* SP800-90A requires 2**48 maximum requests before reseeding */
#ifdef __LP64__
return (1UL << 48);
#else
return SIZE_MAX;
#endif
}
/*
* Return strength of DRBG according to SP800-90A section 8.4
*
* flags: DRBG flags reference
*
* Return: normalized strength value or 32 as a default to counter
* programming errors
*/
static inline unsigned short
drbg_sec_strength (u32 flags)
{
if ((flags & DRBG_HASHSHA1) || (flags & DRBG_SYM128))
return 16;
else if (flags & DRBG_SYM192)
return 24;
else if ((flags & DRBG_SYM256) || (flags & DRBG_HASHSHA256) ||
(flags & DRBG_HASHSHA384) || (flags & DRBG_HASHSHA512))
return 32;
else
return 32;
}
static void
drbg_add_buf (unsigned char *dst, size_t dstlen,
unsigned char *add, size_t addlen)
{
/* implied: dstlen > addlen */
unsigned char *dstptr, *addptr;
unsigned int remainder = 0;
size_t len = addlen;
dstptr = dst + (dstlen - 1);
addptr = add + (addlen - 1);
while (len)
{
remainder += *dstptr + *addptr;
*dstptr = remainder & 0xff;
remainder >>= 8;
len--;
dstptr--;
addptr--;
}
len = dstlen - addlen;
while (len && remainder > 0)
{
remainder = *dstptr + 1;
*dstptr = remainder & 0xff;
remainder >>= 8;
len--;
dstptr--;
}
}
/* Helper variables for read_cb().
*
* The _gcry_rnd*_gather_random interface does not allow to provide a
* data pointer. Thus we need to use a global variable for
* communication. However, the then required locking is anyway a good
* idea because it does not make sense to have several readers of (say
* /dev/random). It is easier to serve them one after the other.
*/
static unsigned char *read_cb_buffer; /* The buffer. */
static size_t read_cb_size; /* Size of the buffer. */
static size_t read_cb_len; /* Used length. */
/* Callback for generating seed from kernel device. */
static void
drbg_read_cb (const void *buffer, size_t length,
enum random_origins origin)
{
const unsigned char *p = buffer;
(void) origin;
gcry_assert (read_cb_buffer);
/* Note that we need to protect against gatherers returning more
* than the requested bytes (e.g. rndw32). */
while (length-- && read_cb_len < read_cb_size)
read_cb_buffer[read_cb_len++] = *p++;
}
static inline int
drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer,
size_t len)
{
int rc = 0;
/* Perform testing as defined in 11.3.2 */
if (drbg->test_data && drbg->test_data->fail_seed_source)
return -1;
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);
#elif USE_RNDUNIX
rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len,
GCRY_VERY_STRONG_RANDOM);
#elif USE_RNDW32
do
{
rc = _gcry_rndw32_gather_random (drbg_read_cb, 0, len,
GCRY_VERY_STRONG_RANDOM);
}
while (rc >= 0 && read_cb_len < read_cb_size);
#else
rc = -1;
#endif
return rc;
}
/******************************************************************
* CTR DRBG callback functions
******************************************************************/
/* BCC function for CTR DRBG as defined in 10.4.3 */
static gpg_err_code_t
drbg_ctr_bcc (drbg_state_t drbg,
unsigned char *out, const unsigned char *key,
drbg_string_t *in)
{
gpg_err_code_t ret = GPG_ERR_GENERAL;
drbg_string_t *curr = in;
size_t inpos = curr->len;
const unsigned char *pos = curr->buf;
drbg_string_t data;
drbg_string_fill (&data, out, drbg_blocklen (drbg));
/* 10.4.3 step 1 */
memset (out, 0, drbg_blocklen (drbg));
ret = drbg_sym_setkey(drbg, key);
if (ret)
return ret;
/* 10.4.3 step 2 / 4 */
while (inpos)
{
short cnt = 0;
/* 10.4.3 step 4.1 */
for (cnt = 0; cnt < drbg_blocklen (drbg); cnt++)
{
out[cnt] ^= *pos;
pos++;
inpos--;
/* the following branch implements the linked list
* iteration. If we are at the end of the current data
* set, we have to start using the next data set if
* available -- the inpos value always points to the
* current byte and will be zero if we have processed
* the last byte of the last linked list member */
if (0 == inpos)
{
curr = curr->next;
if (NULL != curr)
{
pos = curr->buf;
inpos = curr->len;
}
else
{
inpos = 0;
break;
}
}
}
/* 10.4.3 step 4.2 */
ret = drbg_sym (drbg, out, &data);
if (ret)
return ret;
/* 10.4.3 step 2 */
}
return 0;
}
/*
* scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
* (and drbg_ctr_bcc, but this function does not need any temporary buffers),
* the scratchpad is used as follows:
* drbg_ctr_update:
* temp
* start: drbg->scratchpad
* length: drbg_statelen(drbg) + drbg_blocklen(drbg)
* note: the cipher writing into this variable works
* blocklen-wise. Now, when the statelen is not a multiple
* of blocklen, the generateion loop below "spills over"
* by at most blocklen. Thus, we need to give sufficient
* memory.
* df_data
* start: drbg->scratchpad +
* drbg_statelen(drbg) +
* drbg_blocklen(drbg)
* length: drbg_statelen(drbg)
*
* drbg_ctr_df:
* pad
* start: df_data + drbg_statelen(drbg)
* length: drbg_blocklen(drbg)
* iv
* start: pad + drbg_blocklen(drbg)
* length: drbg_blocklen(drbg)
* temp
* start: iv + drbg_blocklen(drbg)
* length: drbg_satelen(drbg) + drbg_blocklen(drbg)
* note: temp is the buffer that the BCC function operates
* on. BCC operates blockwise. drbg_statelen(drbg)
* is sufficient when the DRBG state length is a multiple
* of the block size. For AES192 (and maybe other ciphers)
* this is not correct and the length for temp is
* insufficient (yes, that also means for such ciphers,
* the final output of all BCC rounds are truncated).
* Therefore, add drbg_blocklen(drbg) to cover all
* possibilities.
*/
/* Derivation Function for CTR DRBG as defined in 10.4.2 */
static gpg_err_code_t
drbg_ctr_df (drbg_state_t drbg, unsigned char *df_data,
size_t bytes_to_return, drbg_string_t *addtl)
{
gpg_err_code_t ret = GPG_ERR_GENERAL;
unsigned char L_N[8];
/* S3 is input */
drbg_string_t S1, S2, S4, cipherin;
drbg_string_t *tempstr = addtl;
unsigned char *pad = df_data + drbg_statelen (drbg);
unsigned char *iv = pad + drbg_blocklen (drbg);
unsigned char *temp = iv + drbg_blocklen (drbg);
size_t padlen = 0;
unsigned int templen = 0;
/* 10.4.2 step 7 */
unsigned int i = 0;
/* 10.4.2 step 8 */
const unsigned char *K = (unsigned char *)
"\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";
unsigned char *X;
size_t generated_len = 0;
size_t inputlen = 0;
memset (pad, 0, drbg_blocklen (drbg));
memset (iv, 0, drbg_blocklen (drbg));
memset (temp, 0, drbg_statelen (drbg));
/* 10.4.2 step 1 is implicit as we work byte-wise */
/* 10.4.2 step 2 */
if ((512 / 8) < bytes_to_return)
return GPG_ERR_INV_ARG;
/* 10.4.2 step 2 -- calculate the entire length of all input data */
for (; NULL != tempstr; tempstr = tempstr->next)
inputlen += tempstr->len;
buf_put_be32 (&L_N[0], inputlen);
/* 10.4.2 step 3 */
buf_put_be32 (&L_N[4], bytes_to_return);
/* 10.4.2 step 5: length is size of L_N, input_string, one byte, padding */
padlen = (inputlen + sizeof (L_N) + 1) % (drbg_blocklen (drbg));
/* wrap the padlen appropriately */
if (padlen)
padlen = drbg_blocklen (drbg) - padlen;
/* pad / padlen contains the 0x80 byte and the following zero bytes, so
* add one for byte for 0x80 */
padlen++;
pad[0] = 0x80;
/* 10.4.2 step 4 -- first fill the linked list and then order it */
drbg_string_fill (&S1, iv, drbg_blocklen (drbg));
drbg_string_fill (&S2, L_N, sizeof (L_N));
drbg_string_fill (&S4, pad, padlen);
S1.next = &S2;
S2.next = addtl;
/* Splice in addtl between S2 and S4 -- we place S4 at the end of the
* input data chain. As this code is only triggered when addtl is not
* NULL, no NULL checks are necessary.*/
tempstr = addtl;
while (tempstr->next)
tempstr = tempstr->next;
tempstr->next = &S4;
/* 10.4.2 step 9 */
while (templen < (drbg_keylen (drbg) + (drbg_blocklen (drbg))))
{
/* 10.4.2 step 9.1 - the padding is implicit as the buffer
* holds zeros after allocation -- even the increment of i
* is irrelevant as the increment remains within length of i */
buf_put_be32 (iv, i);
/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
ret = drbg_ctr_bcc (drbg, temp + templen, K, &S1);
if (ret)
goto out;
/* 10.4.2 step 9.3 */
i++;
templen += drbg_blocklen (drbg);
}
/* 10.4.2 step 11 */
/* implicit key len with seedlen - blocklen according to table 3 */
X = temp + (drbg_keylen (drbg));
drbg_string_fill (&cipherin, X, drbg_blocklen (drbg));
/* 10.4.2 step 12: overwriting of outval */
/* 10.4.2 step 13 */
ret = drbg_sym_setkey(drbg, temp);
if (ret)
goto out;
while (generated_len < bytes_to_return)
{
short blocklen = 0;
/* 10.4.2 step 13.1 */
/* the truncation of the key length is implicit as the key
* is only drbg_blocklen in size -- check for the implementation
* of the cipher function callback */
ret = drbg_sym (drbg, X, &cipherin);
if (ret)
goto out;
blocklen = (drbg_blocklen (drbg) < (bytes_to_return - generated_len)) ?
drbg_blocklen (drbg) : (bytes_to_return - generated_len);
/* 10.4.2 step 13.2 and 14 */
memcpy (df_data + generated_len, X, blocklen);
generated_len += blocklen;
}
ret = 0;
out:
memset (iv, 0, drbg_blocklen (drbg));
memset (temp, 0, drbg_statelen (drbg));
memset (pad, 0, drbg_blocklen (drbg));
return ret;
}
/*
* Update function of CTR DRBG as defined in 10.2.1.2
*
* The reseed variable has an enhanced meaning compared to the update
* functions of the other DRBGs as follows:
* 0 => initial seed from initialization
* 1 => reseed via drbg_seed
* 2 => first invocation from drbg_ctr_update when addtl is present. In
* this case, the df_data scratchpad is not deleted so that it is
* available for another calls to prevent calling the DF function
* again.
* 3 => second invocation from drbg_ctr_update. When the update function
* was called with addtl, the df_data memory already contains the
* DFed addtl information and we do not need to call DF again.
*/
static gpg_err_code_t
drbg_ctr_update (drbg_state_t drbg, drbg_string_t *addtl, int reseed)
{
gpg_err_code_t ret = GPG_ERR_GENERAL;
/* 10.2.1.2 step 1 */
unsigned char *temp = drbg->scratchpad;
unsigned char *df_data = drbg->scratchpad +
drbg_statelen (drbg) + drbg_blocklen (drbg);
unsigned char prefix = DRBG_PREFIX1;
memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg));
if (3 > reseed)
memset (df_data, 0, drbg_statelen (drbg));
if (!reseed)
{
/*
* The DRBG uses the CTR mode of the underlying AES cipher. The
* CTR mode increments the counter value after the AES operation
* but SP800-90A requires that the counter is incremented before
* the AES operation. Hence, we increment it at the time we set
* it by one.
*/
drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
ret = _gcry_cipher_setkey (drbg->ctr_handle, drbg->C, drbg_keylen (drbg));
if (ret)
goto out;
}
/* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
if (addtl && 0 < addtl->len)
{
ret =
drbg_ctr_df (drbg, df_data, drbg_statelen (drbg), addtl);
if (ret)
goto out;
}
ret = drbg_sym_ctr (drbg, df_data, drbg_statelen(drbg),
temp, drbg_statelen(drbg));
if (ret)
goto out;
/* 10.2.1.2 step 5 */
ret = _gcry_cipher_setkey (drbg->ctr_handle, temp, drbg_keylen (drbg));
if (ret)
goto out;
/* 10.2.1.2 step 6 */
memcpy (drbg->V, temp + drbg_keylen (drbg), drbg_blocklen (drbg));
/* See above: increment counter by one to compensate timing of CTR op */
drbg_add_buf (drbg->V, drbg_blocklen (drbg), &prefix, 1);
ret = 0;
out:
memset (temp, 0, drbg_statelen (drbg) + drbg_blocklen (drbg));
if (2 != reseed)
memset (df_data, 0, drbg_statelen (drbg));
return ret;
}
/*
* scratchpad use: drbg_ctr_update is called independently from
* drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
*/
/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
static gpg_err_code_t
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));
/* 10.2.1.5.2 step 2 */
if (addtl && 0 < addtl->len)
{
addtl->next = NULL;
ret = drbg_ctr_update (drbg, addtl, 2);
if (ret)
return ret;
}
/* 10.2.1.5.2 step 4.1 */
ret = drbg_sym_ctr (drbg, drbg_ctr_null, sizeof(drbg_ctr_null), buf, buflen);
if (ret)
goto out;
/* 10.2.1.5.2 step 6 */
if (addtl)
addtl->next = NULL;
ret = drbg_ctr_update (drbg, addtl, 3);
out:
return ret;
}
static struct drbg_state_ops_s drbg_ctr_ops = {
drbg_ctr_update,
drbg_ctr_generate,
drbg_sym_init,
drbg_sym_fini,
};
/******************************************************************
* HMAC DRBG callback functions
******************************************************************/
static gpg_err_code_t
drbg_hmac_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
{
gpg_err_code_t ret = GPG_ERR_GENERAL;
int i = 0;
drbg_string_t seed1, seed2, cipherin;
if (!reseed)
{
/* 10.1.2.3 step 2 already implicitly covered with
* the initial memset(0) of drbg->C */
memset (drbg->V, 1, drbg_statelen (drbg));
ret = drbg_hmac_setkey (drbg, drbg->C);
if (ret)
return ret;
}
/* build linked list which implements the concatenation and fill
* first part*/
drbg_string_fill (&seed1, drbg->V, drbg_statelen (drbg));
/* buffer will be filled in for loop below with one byte */
drbg_string_fill (&seed2, NULL, 1);
seed1.next = &seed2;
/* seed may be NULL */
seed2.next = seed;
drbg_string_fill (&cipherin, drbg->V, drbg_statelen (drbg));
/* we execute two rounds of V/K massaging */
for (i = 2; 0 < i; i--)
{
byte *retval;
/* first round uses 0x0, second 0x1 */
unsigned char prefix = DRBG_PREFIX0;
if (1 == i)
prefix = DRBG_PREFIX1;
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
seed2.buf = &prefix;
retval = drbg_hash (drbg, &seed1);
ret = drbg_hmac_setkey (drbg, retval);
if (ret)
return ret;
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
retval = drbg_hash (drbg, &cipherin);
memcpy(drbg->V, retval, drbg_blocklen (drbg));
/* 10.1.2.2 step 3 */
if (!seed || 0 == seed->len)
return ret;
}
return 0;
}
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
static gpg_err_code_t
drbg_hmac_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
drbg_string_t *addtl)
{
gpg_err_code_t ret = 0;
unsigned int len = 0;
drbg_string_t data;
/* 10.1.2.5 step 2 */
if (addtl && 0 < addtl->len)
{
addtl->next = NULL;
ret = drbg_hmac_update (drbg, addtl, 1);
if (ret)
return ret;
}
drbg_string_fill (&data, drbg->V, drbg_statelen (drbg));
while (len < buflen)
{
unsigned int outlen = 0;
/* 10.1.2.5 step 4.1 */
byte *retval = drbg_hash (drbg, &data);
memcpy(drbg->V, retval, drbg_blocklen (drbg));
outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
drbg_blocklen (drbg) : (buflen - len);
/* 10.1.2.5 step 4.2 */
memcpy (buf + len, drbg->V, outlen);
len += outlen;
}
/* 10.1.2.5 step 6 */
if (addtl)
addtl->next = NULL;
ret = drbg_hmac_update (drbg, addtl, 1);
return ret;
}
static struct drbg_state_ops_s drbg_hmac_ops = {
drbg_hmac_update,
drbg_hmac_generate,
drbg_hmac_init,
drbg_hash_fini,
};
/******************************************************************
* Hash DRBG callback functions
******************************************************************/
/*
* scratchpad usage: as drbg_hash_update and drbg_hash_df are used
* interlinked, the scratchpad is used as follows:
* drbg_hash_update
* start: drbg->scratchpad
* length: drbg_statelen(drbg)
* drbg_hash_df:
* start: drbg->scratchpad + drbg_statelen(drbg)
* length: drbg_blocklen(drbg)
*/
/* Derivation Function for Hash DRBG as defined in 10.4.1 */
static gpg_err_code_t
drbg_hash_df (drbg_state_t drbg,
unsigned char *outval, size_t outlen,
drbg_string_t *entropy)
{
size_t len = 0;
unsigned char input[5];
drbg_string_t data1;
/* 10.4.1 step 3 */
input[0] = 1;
buf_put_be32 (&input[1], (outlen * 8));
/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
drbg_string_fill (&data1, input, 5);
data1.next = entropy;
/* 10.4.1 step 4 */
while (len < outlen)
{
short blocklen = 0;
/* 10.4.1 step 4.1 */
byte *retval = drbg_hash (drbg, &data1);
/* 10.4.1 step 4.2 */
input[0]++;
blocklen = (drbg_blocklen (drbg) < (outlen - len)) ?
drbg_blocklen (drbg) : (outlen - len);
memcpy (outval + len, retval, blocklen);
len += blocklen;
}
return 0;
}
/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
static gpg_err_code_t
drbg_hash_update (drbg_state_t drbg, drbg_string_t *seed, int reseed)
{
gpg_err_code_t ret = 0;
drbg_string_t data1, data2;
unsigned char *V = drbg->scratchpad;
unsigned char prefix = DRBG_PREFIX1;
memset (drbg->scratchpad, 0, drbg_statelen (drbg));
if (!seed)
return GPG_ERR_INV_ARG;
if (reseed)
{
/* 10.1.1.3 step 1: string length is concatenation of
* 1 byte, V and seed (which is concatenated entropy/addtl
* input)
*/
memcpy (V, drbg->V, drbg_statelen (drbg));
drbg_string_fill (&data1, &prefix, 1);
drbg_string_fill (&data2, V, drbg_statelen (drbg));
data1.next = &data2;
data2.next = seed;
}
else
{
drbg_string_fill (&data1, seed->buf, seed->len);
data1.next = seed->next;
}
/* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
ret = drbg_hash_df (drbg, drbg->V, drbg_statelen (drbg), &data1);
if (ret)
goto out;
/* 10.1.1.2 / 10.1.1.3 step 4 -- concatenation */
prefix = DRBG_PREFIX0;
drbg_string_fill (&data1, &prefix, 1);
drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
data1.next = &data2;
/* 10.1.1.2 / 10.1.1.3 step 4 -- df operation */
ret = drbg_hash_df (drbg, drbg->C, drbg_statelen (drbg), &data1);
out:
memset (drbg->scratchpad, 0, drbg_statelen (drbg));
return ret;
}
/* Processing of additional information string for Hash DRBG. */
static gpg_err_code_t
drbg_hash_process_addtl (drbg_state_t drbg, drbg_string_t *addtl)
{
drbg_string_t data1, data2;
drbg_string_t *data3;
unsigned char prefix = DRBG_PREFIX2;
byte *retval;
/* 10.1.1.4 step 2 */
if (!addtl || 0 == addtl->len)
return 0;
/* 10.1.1.4 step 2a -- concatenation */
drbg_string_fill (&data1, &prefix, 1);
drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
data3 = addtl;
data1.next = &data2;
data2.next = data3;
data3->next = NULL;
/* 10.1.1.4 step 2a -- cipher invocation */
retval = drbg_hash (drbg, &data1);
/* 10.1.1.4 step 2b */
drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
return 0;
}
/*
* Hashgen defined in 10.1.1.4
*/
static gpg_err_code_t
drbg_hash_hashgen (drbg_state_t drbg, unsigned char *buf, unsigned int buflen)
{
unsigned int len = 0;
unsigned char *src = drbg->scratchpad;
drbg_string_t data;
unsigned char prefix = DRBG_PREFIX1;
/* 10.1.1.4 step hashgen 2 */
memcpy (src, drbg->V, drbg_statelen (drbg));
drbg_string_fill (&data, src, drbg_statelen (drbg));
while (len < buflen)
{
unsigned int outlen = 0;
/* 10.1.1.4 step hashgen 4.1 */
byte *retval = drbg_hash (drbg, &data);
outlen = (drbg_blocklen (drbg) < (buflen - len)) ?
drbg_blocklen (drbg) : (buflen - len);
/* 10.1.1.4 step hashgen 4.2 */
memcpy (buf + len, retval, outlen);
len += outlen;
/* 10.1.1.4 hashgen step 4.3 */
if (len < buflen)
drbg_add_buf (src, drbg_statelen (drbg), &prefix, 1);
}
memset (drbg->scratchpad, 0, drbg_statelen (drbg));
return 0;
}
/* Generate function for Hash DRBG as defined in 10.1.1.4 */
static gpg_err_code_t
drbg_hash_generate (drbg_state_t drbg, unsigned char *buf, unsigned int buflen,
drbg_string_t *addtl)
{
gpg_err_code_t ret;
unsigned char prefix = DRBG_PREFIX3;
drbg_string_t data1, data2;
byte *retval;
union
{
unsigned char req[8];
u64 req_int;
} u;
/* 10.1.1.4 step 2 */
ret = drbg_hash_process_addtl (drbg, addtl);
if (ret)
return ret;
/* 10.1.1.4 step 3 -- invocation of the Hashgen function defined in
* 10.1.1.4 */
ret = drbg_hash_hashgen (drbg, buf, buflen);
if (ret)
return ret;
/* 10.1.1.4 step 4 */
drbg_string_fill (&data1, &prefix, 1);
drbg_string_fill (&data2, drbg->V, drbg_statelen (drbg));
data1.next = &data2;
/* this is the value H as documented in 10.1.1.4 */
retval = drbg_hash (drbg, &data1);
/* 10.1.1.4 step 5 */
drbg_add_buf (drbg->V, drbg_statelen (drbg), retval, drbg_blocklen (drbg));
drbg_add_buf (drbg->V, drbg_statelen (drbg), drbg->C, drbg_statelen (drbg));
u.req_int = be_bswap64 (drbg->reseed_ctr);
drbg_add_buf (drbg->V, drbg_statelen (drbg), u.req, sizeof (u.req));
return ret;
}
/*
* scratchpad usage: as update and generate are used isolated, both
* can use the scratchpad
*/
static struct drbg_state_ops_s drbg_hash_ops = {
drbg_hash_update,
drbg_hash_generate,
drbg_hash_init,
drbg_hash_fini,
};
/******************************************************************
* Functions common for DRBG implementations
******************************************************************/
/*
* Seeding or reseeding of the DRBG
*
* @drbg: DRBG state struct
* @pers: personalization / additional information buffer
* @reseed: 0 for initial seed process, 1 for reseeding
*
* return:
* 0 on success
* error value otherwise
*/
static gpg_err_code_t
drbg_seed (drbg_state_t drbg, drbg_string_t *pers, int reseed)
{
gpg_err_code_t ret = 0;
unsigned char *entropy = NULL;
size_t entropylen = 0;
drbg_string_t data1;
/* 9.1 / 9.2 / 9.3.1 step 3 */
if (pers && pers->len > (drbg_max_addtl ()))
{
dbg (("DRBG: personalization string too long %lu\n", pers->len));
return GPG_ERR_INV_ARG;
}
if (drbg->test_data && drbg->test_data->testentropy)
{
drbg_string_fill (&data1, drbg->test_data->testentropy->buf,
drbg->test_data->testentropy->len);
dbg (("DRBG: using test entropy\n"));
}
else
{
/* Gather entropy equal to the security strength of the DRBG.
* With a derivation function, a nonce is required in addition
* to the entropy. A nonce must be at least 1/2 of the security
* strength of the DRBG in size. Thus, entropy * nonce is 3/2
* of the strength. The consideration of a nonce is only
* applicable during initial seeding. */
entropylen = drbg_sec_strength (drbg->core->flags);
if (!entropylen)
return GPG_ERR_GENERAL;
if (0 == reseed)
/* make sure we round up strength/2 in
* case it is not divisible by 2 */
entropylen = ((entropylen + 1) / 2) * 3;
dbg (("DRBG: (re)seeding with %lu bytes of entropy\n", entropylen));
entropy = xcalloc_secure (1, entropylen);
if (!entropy)
return GPG_ERR_ENOMEM;
ret = drbg_get_entropy (drbg, entropy, entropylen);
if (ret)
goto out;
drbg_string_fill (&data1, entropy, entropylen);
}
/* concatenation of entropy with personalization str / addtl input)
* the variable pers is directly handed by the caller, check its
* contents whether it is appropriate */
if (pers && pers->buf && 0 < pers->len && NULL == pers->next)
{
data1.next = pers;
dbg (("DRBG: using personalization string\n"));
}
ret = drbg->d_ops->update (drbg, &data1, reseed);
dbg (("DRBG: state updated with seed\n"));
if (ret)
goto out;
drbg->seeded = 1;
/* 10.1.1.2 / 10.1.1.3 step 5 */
drbg->reseed_ctr = 1;
out:
xfree (entropy);
return ret;
}
/*************************************************************************
* Exported interfaces.
*************************************************************************/
/*
* DRBG generate function as required by SP800-90A - this function
* generates random numbers
*
* @drbg DRBG state handle
* @buf Buffer where to store the random numbers -- the buffer must already
* be pre-allocated by caller
* @buflen Length of output buffer - this value defines the number of random
* bytes pulled from DRBG
* @addtl Additional input that is mixed into state, may be NULL -- note
* the entropy is pulled by the DRBG internally unconditionally
* as defined in SP800-90A. The additional input is mixed into
* the state in addition to the pulled entropy.
*
* return: Generated number of bytes.
*/
static gpg_err_code_t
drbg_generate (drbg_state_t drbg,
unsigned char *buf, unsigned int buflen,
drbg_string_t *addtl)
{
gpg_err_code_t ret = GPG_ERR_INV_ARG;
if (0 == buflen || !buf)
{
dbg (("DRBG: no buffer provided\n"));
return ret;
}
if (addtl && NULL == addtl->buf && 0 < addtl->len)
{
dbg (("DRBG: wrong format of additional information\n"));
return ret;
}
/* 9.3.1 step 2 */
if (buflen > (drbg_max_request_bytes ()))
{
dbg (("DRBG: requested random numbers too large %u\n", buflen));
return ret;
}
/* 9.3.1 step 3 is implicit with the chosen DRBG */
/* 9.3.1 step 4 */
if (addtl && addtl->len > (drbg_max_addtl ()))
{
dbg (("DRBG: additional information string too long %lu\n",
addtl->len));
return ret;
}
/* 9.3.1 step 5 is implicit with the chosen DRBG */
/* 9.3.1 step 6 and 9 supplemented by 9.3.2 step c -- the spec is a
* bit convoluted here, we make it simpler */
if ((drbg_max_requests ()) < drbg->reseed_ctr)
drbg->seeded = 0;
if (drbg->pr || !drbg->seeded)
{
dbg (("DRBG: reseeding before generation (prediction resistance: %s, state %s)\n", drbg->pr ? "true" : "false", drbg->seeded ? "seeded" : "unseeded"));
/* 9.3.1 steps 7.1 through 7.3 */
ret = drbg_seed (drbg, addtl, 1);
if (ret)
return ret;
/* 9.3.1 step 7.4 */
addtl = NULL;
}
if (addtl && addtl->buf)
{
dbg (("DRBG: using additional information string\n"));
}
/* 9.3.1 step 8 and 10 */
ret = drbg->d_ops->generate (drbg, buf, buflen, addtl);
/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
drbg->reseed_ctr++;
if (ret)
return ret;
/* 11.3.3 -- re-perform self tests after some generated random
* numbers, the chosen value after which self test is performed
* is arbitrary, but it should be reasonable */
/* Here we do not perform the self tests because of the following
* reasons: it is mathematically impossible that the initial self tests
* were successfully and the following are not. If the initial would
* pass and the following would not, the system integrity is violated.
* In this case, the entire system operation is questionable and it
* is unlikely that the integrity violation only affects to the
* correct operation of the DRBG.
*/
#if 0
if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096))
{
dbg (("DRBG: start to perform self test\n"));
ret = drbg_healthcheck ();
if (ret)
{
log_fatal (("DRBG: self test failed\n"));
return ret;
}
else
{
dbg (("DRBG: self test successful\n"));
}
}
#endif
return ret;
}
/*
* Wrapper around drbg_generate which can pull arbitrary long strings
* from the DRBG without hitting the maximum request limitation.
*
* Parameters: see drbg_generate
* Return codes: see drbg_generate -- if one drbg_generate request fails,
* the entire drbg_generate_long request fails
*/
static gpg_err_code_t
drbg_generate_long (drbg_state_t drbg,
unsigned char *buf, unsigned int buflen,
drbg_string_t *addtl)
{
gpg_err_code_t ret = 0;
unsigned int slice = 0;
unsigned char *buf_p = buf;
unsigned len = 0;
do
{
unsigned int chunk = 0;
slice = ((buflen - len) / drbg_max_request_bytes ());
chunk = slice ? drbg_max_request_bytes () : (buflen - len);
ret = drbg_generate (drbg, buf_p, chunk, addtl);
if (ret)
return ret;
buf_p += chunk;
len += chunk;
}
while (slice > 0 && (len < buflen));
return ret;
}
/*
* DRBG uninstantiate function as required by SP800-90A - this function
* frees all buffers and the DRBG handle
*
* @drbg DRBG state handle
*
* return
* 0 on success
*/
static gpg_err_code_t
drbg_uninstantiate (drbg_state_t drbg)
{
if (!drbg)
return GPG_ERR_INV_ARG;
drbg->d_ops->crypto_fini(drbg);
xfree (drbg->V);
drbg->V = NULL;
xfree (drbg->C);
drbg->C = NULL;
drbg->reseed_ctr = 0;
xfree (drbg->scratchpad);
drbg->scratchpad = NULL;
drbg->seeded = 0;
drbg->pr = 0;
drbg->seed_init_pid = 0;
return 0;
}
/*
* DRBG instantiation function as required by SP800-90A - this function
* sets up the DRBG handle, performs the initial seeding and all sanity
* checks required by SP800-90A
*
* @drbg memory of state -- if NULL, new memory is allocated
* @pers Personalization string that is mixed into state, may be NULL -- note
* the entropy is pulled by the DRBG internally unconditionally
* as defined in SP800-90A. The additional input is mixed into
* the state in addition to the pulled entropy.
* @coreref reference to core
* @flags Flags defining the requested DRBG type and cipher type. The flags
* are defined in drbg.h and may be XORed. Beware, if you XOR multiple
* cipher types together, the code picks the core on a first come first
* serve basis as it iterates through the available cipher cores and
* uses the one with the first match. The minimum required flags are:
* cipher type flag
*
* return
* 0 on success
* error value otherwise
*/
static gpg_err_code_t
drbg_instantiate (drbg_state_t drbg,
drbg_string_t *pers, int coreref, int pr)
{
gpg_err_code_t ret = GPG_ERR_ENOMEM;
unsigned int sb_size = 0;
if (!drbg)
return GPG_ERR_INV_ARG;
dbg (("DRBG: Initializing DRBG core %d with prediction resistance %s\n",
coreref, pr ? "enabled" : "disabled"));
drbg->core = &drbg_cores[coreref];
drbg->pr = pr;
drbg->seeded = 0;
if (drbg->core->flags & DRBG_HMAC)
drbg->d_ops = &drbg_hmac_ops;
else if (drbg->core->flags & DRBG_HASH_MASK)
drbg->d_ops = &drbg_hash_ops;
else if (drbg->core->flags & DRBG_CTR_MASK)
drbg->d_ops = &drbg_ctr_ops;
else
return GPG_ERR_GENERAL;
/* 9.1 step 1 is implicit with the selected DRBG type -- see
* drbg_sec_strength() */
/* 9.1 step 2 is implicit as caller can select prediction resistance
* and the flag is copied into drbg->flags --
* all DRBG types support prediction resistance */
/* 9.1 step 4 is implicit in drbg_sec_strength */
ret = drbg->d_ops->crypto_init(drbg);
if (ret)
goto err;
drbg->V = xcalloc_secure (1, drbg_statelen (drbg));
if (!drbg->V)
goto fini;
drbg->C = xcalloc_secure (1, drbg_statelen (drbg));
if (!drbg->C)
goto fini;
/* scratchpad is only generated for CTR and Hash */
if (drbg->core->flags & DRBG_HMAC)
sb_size = 0;
else if (drbg->core->flags & DRBG_CTR_MASK)
sb_size = drbg_statelen (drbg) + drbg_blocklen (drbg) + /* temp */
drbg_statelen (drbg) + /* df_data */
drbg_blocklen (drbg) + /* pad */
drbg_blocklen (drbg) + /* iv */
drbg_statelen (drbg) + drbg_blocklen (drbg); /* temp */
else
sb_size = drbg_statelen (drbg);
if (0 < sb_size)
{
drbg->scratchpad = xcalloc_secure (1, sb_size);
if (!drbg->scratchpad)
goto fini;
}
dbg (("DRBG: state allocated with scratchpad size %u bytes\n", sb_size));
/* 9.1 step 6 through 11 */
ret = drbg_seed (drbg, pers, 0);
if (ret)
goto fini;
dbg (("DRBG: core %d %s prediction resistance successfully initialized\n",
coreref, pr ? "with" : "without"));
return 0;
fini:
drbg->d_ops->crypto_fini(drbg);
err:
drbg_uninstantiate (drbg);
return ret;
}
/*
* DRBG reseed function as required by SP800-90A
*
* @drbg DRBG state handle
* @addtl Additional input that is mixed into state, may be NULL -- note
* the entropy is pulled by the DRBG internally unconditionally
* as defined in SP800-90A. The additional input is mixed into
* the state in addition to the pulled entropy.
*
* return
* 0 on success
* error value otherwise
*/
static gpg_err_code_t
drbg_reseed (drbg_state_t drbg,drbg_string_t *addtl)
{
gpg_err_code_t ret = 0;
ret = drbg_seed (drbg, addtl, 1);
return ret;
}
/******************************************************************
* Libgcrypt integration code.
******************************************************************/
/***************************************************
* Libgcrypt backend functions to the RNG API code.
***************************************************/
static inline void
drbg_lock (void)
{
gpg_err_code_t ec;
ec = gpgrt_lock_lock (&drbg_lock_var);
if (ec)
log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (ec));
}
static inline void
drbg_unlock (void)
{
gpg_err_code_t ec;
ec = gpgrt_lock_unlock (&drbg_lock_var);
if (ec)
log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (ec));
}
/* Basic initialization is required to initialize mutexes and
do a few checks on the implementation. */
static void
basic_initialization (void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
/* Make sure that we are still using the values we have
traditionally used for the random levels. */
gcry_assert (GCRY_WEAK_RANDOM == 0
&& GCRY_STRONG_RANDOM == 1
&& GCRY_VERY_STRONG_RANDOM == 2);
}
/****** helper functions where lock must be held by caller *****/
/* Check whether given flags are known to point to an applicable DRBG */
static gpg_err_code_t
drbg_algo_available (u32 flags, int *coreref)
{
int i = 0;
for (i = 0; ARRAY_SIZE (drbg_cores) > i; i++)
{
if ((drbg_cores[i].flags & DRBG_CIPHER_MASK) ==
(flags & DRBG_CIPHER_MASK))
{
*coreref = i;
return 0;
}
}
return GPG_ERR_GENERAL;
}
static gpg_err_code_t
_drbg_init_internal (u32 flags, drbg_string_t *pers)
{
static u32 oldflags;
gpg_err_code_t ret = 0;
int coreref = 0;
int pr = 0;
/* If a caller provides 0 as flags, use the flags of the previous
* initialization, otherwise use the current flags and remember them
* for the next invocation. If no flag is given and no global state
* is set this is the first initialization and we set the default
* type.
*/
if (!flags && !drbg_state)
flags = oldflags = DRBG_DEFAULT_TYPE;
else if (!flags)
flags = oldflags;
else
oldflags = flags;
ret = drbg_algo_available (flags, &coreref);
if (ret)
return ret;
if (drbg_state)
{
drbg_uninstantiate (drbg_state);
}
else
{
drbg_state = xtrycalloc_secure (1, sizeof *drbg_state);
if (!drbg_state)
return gpg_err_code_from_syserror ();
}
if (flags & DRBG_PREDICTION_RESIST)
pr = 1;
ret = drbg_instantiate (drbg_state, pers, coreref, pr);
if (ret)
fips_signal_error ("DRBG cannot be initialized");
else
drbg_state->seed_init_pid = getpid ();
return ret;
}
/************* calls available to common RNG code **************/
/*
* Initialize one DRBG invoked by the libgcrypt API
*/
void
_gcry_rngdrbg_inititialize (int full)
{
basic_initialization ();
if (!full)
return;
drbg_lock ();
if (!drbg_state)
_drbg_init_internal (0, NULL);
drbg_unlock ();
}
/*
* Backend handler function for GCRYCTL_DRBG_REINIT
*
* Select a different DRBG type and initialize it.
* Function checks whether requested DRBG type exists and returns an error in
* case it does not. In case of an error, the previous instantiated DRBG is
* left untouched and alive. Thus, in case of an error, a DRBG is always
* available, even if it is not the chosen one.
*
* Re-initialization will be performed in any case regardless whether flags
* or personalization string are set.
*
* If flags is NULL, do not change current DRBG. If PERS is NULL and
* NPERS is 0, re-initialize without personalization string. If PERS
* is not NULL NPERS must be one and PERS and the first ietm from the
* bufer is take as personalization string.
*/
gpg_err_code_t
_gcry_rngdrbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers)
{
gpg_err_code_t ret;
unsigned int flags;
/* If PERS is not given we expect NPERS to be zero; if given we
expect a one-item array. */
if ((!pers && npers) || (pers && npers != 1))
return GPG_ERR_INV_ARG;
ret = parse_flag_string (flagstr, &flags);
if (!ret)
{
dbg (("DRBG: reinitialize internal DRBG state with flags %u\n", flags));
drbg_lock ();
if (pers)
{
drbg_string_t persbuf;
drbg_string_fill
(&persbuf, (const unsigned char *)pers[0].data + pers[0].off,
pers[0].len);
ret = _drbg_init_internal (flags, &persbuf);
}
else
ret = _drbg_init_internal (flags, NULL);
drbg_unlock ();
}
return ret;
}
/* Try to close the FDs of the random gather module. This is
* currently only implemented for rndlinux. */
void
_gcry_rngdrbg_close_fds (void)
{
#if USE_RNDLINUX
drbg_lock ();
_gcry_rndlinux_gather_random (NULL, 0, 0, 0);
drbg_unlock ();
#endif
}
/* Print some statistics about the RNG. */
void
_gcry_rngdrbg_dump_stats (void)
{
/* Not yet implemented. */
/* Maybe dumping of reseed counter? */
}
/* This function returns true if no real RNG is available or the
* quality of the RNG has been degraded for test purposes. */
int
_gcry_rngdrbg_is_faked (void)
{
return 0; /* Faked random is not allowed. */
}
/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
* should be in the range of 0..100 to indicate the goodness of the
* entropy added, or -1 for goodness not known. */
gcry_error_t
_gcry_rngdrbg_add_bytes (const void *buf, size_t buflen, int quality)
{
gpg_err_code_t ret = 0;
drbg_string_t seed;
(void) quality;
_gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */
if (!drbg_state)
return GPG_ERR_GENERAL;
drbg_string_fill (&seed, (unsigned char *) buf, buflen);
drbg_lock ();
ret = drbg_reseed (drbg_state, &seed);
drbg_unlock ();
return ret;
}
/* This function is to be used for all types of random numbers, including
* nonces
*/
void
_gcry_rngdrbg_randomize (void *buffer, size_t length,
enum gcry_random_level level)
{
(void) level;
_gcry_rngdrbg_inititialize (1); /* Auto-initialize if needed */
drbg_lock ();
if (!drbg_state)
{
fips_signal_error ("DRBG is not initialized");
goto bailout;
}
/* As reseeding changes the entire state of the DRBG, including any
* key, either a re-init or a reseed is sufficient for a fork */
if (drbg_state->seed_init_pid != getpid ())
{
/* We are in a child of us. Perform a reseeding. */
if (drbg_reseed (drbg_state, NULL))
{
fips_signal_error ("reseeding upon fork failed");
log_fatal ("severe error getting random\n");
goto bailout;
}
}
/* potential integer overflow is covered by drbg_generate which
* ensures that length cannot overflow an unsigned int */
if (0 < length)
{
if (!buffer)
goto bailout;
if (drbg_generate_long (drbg_state, buffer, (unsigned int) length, NULL))
log_fatal ("No random numbers generated\n");
}
else
{
drbg_gen_t *data = (drbg_gen_t *)buffer;
/* catch NULL pointer */
if (!data || !data->outbuf)
{
fips_signal_error ("No output buffer provided");
goto bailout;
}
if (drbg_generate_long (drbg_state, data->outbuf, data->outlen,
data->addtl))
log_fatal ("No random numbers generated\n");
}
bailout:
drbg_unlock ();
return;
}
/***************************************************************
* Self-test code
***************************************************************/
/*
* Test vectors from
- * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ * https://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
*/
struct gcry_drbg_test_vector drbg_test_pr[] = {
{
/* .flags = */ "sha256 pr" /* DRBG_PR_HASHSHA256 */,
/* .entropy = */ (unsigned char *)
"\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
"\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
"\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
"\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
/* .entropylen = */ 48,
/* .entpra = */ (unsigned char *)
"\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
"\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
"\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
/* .entprb = */ (unsigned char *)
"\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
"\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
"\x76\xaa\x55\x04\x8b\x0a\x72\x95",
/* .entprlen = */ 32,
/* .addtla = */ (unsigned char *)
"\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
"\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
"\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
/* .addtlb = */ (unsigned char *)
"\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
"\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
"\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
/* .addtllen = */ 32,
/* .pers = */ NULL,
/* .perslen = */ 0,
/* .expected = */ (unsigned char *)
"\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
"\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
"\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
"\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
"\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
"\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
"\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
"\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
"\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
"\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
"\x50\x47\xa3\x63\x81\x16\xaf\x19",
/* .expectedlen = */ 128,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* flags = */ "hmac sha256 pr" /* DRBG_PR_HMACSHA256 */,
/* .entropy = */ (unsigned char *)
"\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
"\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
"\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
"\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
/* .entropylen = */ 48,
/* .entpra = */ (unsigned char *)
"\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
"\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
"\x20\x28\xad\xf2\x60\xd7\xcd\x45",
/* .entprb = */ (unsigned char *)
"\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
"\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
"\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
/* .entprlen = */ 32,
/* .addtla = */ NULL,
/* .addtlb = */ NULL,
/* .addtllen = */ 0,
/* .pers = */ (unsigned char *)
"\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
"\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
"\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
/* .perslen = */ 32,
/* .expected = */ (unsigned char *)
"\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
"\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
"\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
"\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
"\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
"\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
"\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
"\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
"\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
"\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
"\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
/* .expectedlen = */ 128,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* .flags = */ "aes sym128 pr", /* DRBG_PR_CTRAES128 */
/* .entropy = */ (unsigned char *)
"\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
"\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
/* .entropylen = */ 24,
/* .entpra = */ (unsigned char *)
"\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
"\xc4\x2c\xe8\x10",
/* .entprb = */ (unsigned char *)
"\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
"\x08\xf7\xa5\x01",
/* .entprlen = */ 16,
/* .addtla = */ (unsigned char *)
"\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
"\x23\x6d\xad\x1d",
/* .addtlb = */ (unsigned char *)
"\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
"\xbc\x59\x31\x8c",
/* .addtllen = */ 16,
/* .pers = */ (unsigned char *)
"\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
"\x37\x3c\x5c\x0b",
/* .perslen = */ 16,
/* .expected = */ (unsigned char *)
"\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
"\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
"\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
"\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
"\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
"\x23\xc5\x1f\x68",
/* .expectedlen = */ 64,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
}
};
struct gcry_drbg_test_vector drbg_test_nopr[] = {
{
/* .flags = */ "sha256" /* DRBG_NOPR_HASHSHA256 */,
/* .entropy = */ (unsigned char *)
"\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
"\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
"\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
"\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
/* .entropylen = */ 48,
/* .entpra = */ NULL,
/* .entprb = */ NULL,
/* .entprlen = */ 0,
/* .addtla = */ (unsigned char *)
"\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
"\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
"\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
/* .addtlb = */ (unsigned char *)
"\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
"\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
"\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
/* .addtllen = */ 32,
/* .pers = */ NULL,
/* .perslen = */ 0,
/* .expected = */ (unsigned char *)
"\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
"\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
"\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
"\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
"\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
"\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
"\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
"\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
"\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
"\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
"\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
/* .expectedlen = */ 128,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* .flags = */ "hmac sha256" /* DRBG_NOPR_HMACSHA256 */,
/* .entropy = */ (unsigned char *)
"\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
"\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
"\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
"\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
/* .entropylen = */ 48,
/* .entpra = */ NULL,
/* .entprb = */ NULL,
/* .entprlen = */ 0,
/* .addtla = */ NULL,
/* .addtlb = */ NULL,
/* .addtllen = */ 0,
/* .pers = */ (unsigned char *)
"\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
"\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
"\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
/* .perslen = */ 32,
/* .expected = */ (unsigned char *)
"\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
"\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
"\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
"\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
"\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
"\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
"\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
"\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
"\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
"\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
"\x10\x37\x41\x03\x0c\xcc\x3a\x56",
/* .expectedlen = */ 128,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* .flags = */ "aes sym128" /* DRBG_NOPR_CTRAES128 */,
/* .entropy = */ (unsigned char *)
"\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
"\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
/* .entropylen = */ 24,
/* .entpra = */ NULL,
/* .entprb = */ NULL,
/* .entprlen = */ 0,
/* .addtla = */ (unsigned char *)
"\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
"\x44\x85\xe7\xfe",
/* .addtlb = */ (unsigned char *)
"\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
"\x82\x16\x62\x7f",
/* .addtllen = */ 16,
/* .pers = */ (unsigned char *)
"\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
"\x8e\xcf\xe0\x02",
/* .perslen = */ 16,
/* .expected = */ (unsigned char *)
"\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
"\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
"\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
"\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
"\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
"\x2b\x49\x1e\x5c",
/* .expectedlen = */ 64,
/* .entropyreseed = */ NULL,
/* .entropyreseed_len = */ 0,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */,
/* .entropy = */ (unsigned char *)
"\x16\x10\xb8\x28\xcc\xd2\x7d\xe0\x8c\xee\xa0\x32"
"\xa2\x0e\x92\x08\x49\x2c\xf1\x70\x92\x42\xf6\xb5",
/* .entropylen = */ 24,
/* .entpra = */ NULL,
/* .entprb = */ NULL,
/* .entprlen = */ 0,
/* .addtla = */ NULL,
/* .addtlb = */ NULL,
/* .addtllen = */ 0,
/* .pers = */ NULL,
/* .perslen = */ 0,
/* .expected = */ (unsigned char *)
"\x56\xf3\x3d\x4f\xdb\xb9\xa5\xb6\x4d\x26\x23\x44"
"\x97\xe9\xdc\xb8\x77\x98\xc6\x8d\x08\xf7\xc4\x11"
"\x99\xd4\xbd\xdf\x97\xeb\xbf\x6c\xb5\x55\x0e\x5d"
"\x14\x9f\xf4\xd5\xbd\x0f\x05\xf2\x5a\x69\x88\xc1"
"\x74\x36\x39\x62\x27\x18\x4a\xf8\x4a\x56\x43\x35"
"\x65\x8e\x2f\x85\x72\xbe\xa3\x33\xee\xe2\xab\xff"
"\x22\xff\xa6\xde\x3e\x22\xac\xa2",
/* .expectedlen = */ 80,
/* .entropyreseed = */ (unsigned char *)
"\x72\xd2\x8c\x90\x8e\xda\xf9\xa4\xd1\xe5\x26\xd8"
"\xf2\xde\xd5\x44",
/* .entropyreseed_len = */ 16,
/* .addtl_reseed = */ NULL,
/* .addtl_reseed_len = */ 0
},
{
/* .flags = */ "sha1" /* DRBG_NOPR_HASHSHA1 */,
/* .entropy = */ (unsigned char *)
"\xd9\xba\xb5\xce\xdc\xa9\x6f\x61\x78\xd6\x45\x09"
"\xa0\xdf\xdc\x5e\xda\xd8\x98\x94\x14\x45\x0e\x01",
/* .entropylen = */ 24,
/* .entpra = */ NULL,
/* .entprb = */ NULL,
/* .entprlen = */ 0,
/* .addtla = */ (unsigned char *)
"\x04\xfa\x28\x95\xaa\x5a\x6f\x8c\x57\x43\x34\x3b"
"\x80\x5e\x5e\xa4",
/* .addtlb = */ (unsigned char *)
"\xdf\x5d\xc4\x59\xdf\xf0\x2a\xa2\xf0\x52\xd7\x21"
"\xec\x60\x72\x30",
/* .addtllen = */ 16,
/* .pers = */ NULL,
/* .perslen = */ 0,
/* .expected = */ (unsigned char *)
"\xc4\x8b\x89\xf9\xda\x3f\x74\x82\x45\x55\x5d\x5d"
"\x03\x3b\x69\x3d\xd7\x1a\x4d\xf5\x69\x02\x05\xce"
"\xfc\xd7\x20\x11\x3c\xc2\x4e\x09\x89\x36\xff\x5e"
"\x77\xb5\x41\x53\x58\x70\xb3\x39\x46\x8c\xdd\x8d"
"\x6f\xaf\x8c\x56\x16\x3a\x70\x0a\x75\xb2\x3e\x59"
"\x9b\x5a\xec\xf1\x6f\x3b\xaf\x6d\x5f\x24\x19\x97"
"\x1f\x24\xf4\x46\x72\x0f\xea\xbe",
/* .expectedlen = */ 80,
/* .entropyreseed = */ (unsigned char *)
"\xc6\xba\xd0\x74\xc5\x90\x67\x86\xf5\xe1\xf3\x20"
"\x99\xf5\xb4\x91",
/* .entropyreseed_len = */ 16,
/* .addtl_reseed = */ (unsigned char *)
"\x3e\x6b\xf4\x6f\x4d\xaa\x38\x25\xd7\x19\x4e\x69"
"\x4e\x77\x52\xf7",
/* .addtl_reseed_len = */ 16
}
};
/*
* Tests implement the CAVS test approach as documented in
- * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf
+ * https://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf
*/
/*
* CAVS test
*
* This function is not static as it is needed for as a private API
* call for the CAVS test tool.
*/
gpg_err_code_t
_gcry_rngdrbg_cavs_test (struct gcry_drbg_test_vector *test, unsigned char *buf)
{
gpg_err_code_t ret = 0;
drbg_state_t drbg = NULL;
struct drbg_test_data_s test_data;
drbg_string_t addtl, pers, testentropy;
int coreref = 0;
int pr = 0;
u32 flags;
ret = parse_flag_string (test->flagstr, &flags);
if (ret)
goto outbuf;
ret = drbg_algo_available (flags, &coreref);
if (ret)
goto outbuf;
drbg = xtrycalloc_secure (1, sizeof *drbg);
if (!drbg)
{
ret = gpg_err_code_from_syserror ();
goto outbuf;
}
if ((flags & DRBG_PREDICTION_RESIST))
pr = 1;
test_data.testentropy = &testentropy;
drbg_string_fill (&testentropy, test->entropy, test->entropylen);
drbg->test_data = &test_data;
drbg_string_fill (&pers, test->pers, test->perslen);
ret = drbg_instantiate (drbg, &pers, coreref, pr);
if (ret)
goto outbuf;
if (test->entropyreseed)
{
drbg_string_fill (&testentropy, test->entropyreseed,
test->entropyreseed_len);
drbg_string_fill (&addtl, test->addtl_reseed,
test->addtl_reseed_len);
if (drbg_reseed (drbg, &addtl))
goto outbuf;
}
drbg_string_fill (&addtl, test->addtla, test->addtllen);
if (test->entpra)
{
drbg_string_fill (&testentropy, test->entpra, test->entprlen);
drbg->test_data = &test_data;
}
drbg_generate_long (drbg, buf, test->expectedlen, &addtl);
drbg_string_fill (&addtl, test->addtlb, test->addtllen);
if (test->entprb)
{
drbg_string_fill (&testentropy, test->entprb, test->entprlen);
drbg->test_data = &test_data;
}
drbg_generate_long (drbg, buf, test->expectedlen, &addtl);
drbg_uninstantiate (drbg);
outbuf:
xfree (drbg);
return ret;
}
/*
* Invoke the CAVS test and perform the final check whether the
* calculated random value matches the expected one.
*
* This function is not static as it is needed for as a private API
* call for the CAVS test tool.
*/
gpg_err_code_t
_gcry_rngdrbg_healthcheck_one (struct gcry_drbg_test_vector * test)
{
gpg_err_code_t ret = GPG_ERR_ENOMEM;
unsigned char *buf = xcalloc_secure (1, test->expectedlen);
if (!buf)
return GPG_ERR_ENOMEM;
ret = _gcry_rngdrbg_cavs_test (test, buf);
/* FIXME: The next line is wrong. */
ret = memcmp (test->expected, buf, test->expectedlen);
xfree (buf);
return ret;
}
/*
* Tests as defined in 11.3.2 in addition to the cipher tests: testing
* of the error handling.
*
* Note, testing the reseed counter is not done as an automatic reseeding
* is performed in drbg_generate when the reseed counter is too large.
*/
static gpg_err_code_t
drbg_healthcheck_sanity (struct gcry_drbg_test_vector *test)
{
unsigned int len = 0;
drbg_state_t drbg = NULL;
gpg_err_code_t ret = GPG_ERR_GENERAL;
gpg_err_code_t tmpret = GPG_ERR_GENERAL;
struct drbg_test_data_s test_data;
drbg_string_t addtl, testentropy;
int coreref = 0;
unsigned char *buf = NULL;
size_t max_addtllen, max_request_bytes;
u32 flags;
/* only perform test in FIPS mode */
if (0 == fips_mode ())
return 0;
ret = parse_flag_string (test->flagstr, &flags);
if (ret)
return ret;
ret = GPG_ERR_GENERAL; /* Fixme: Improve handling of RET. */
buf = xtrycalloc_secure (1, test->expectedlen);
if (!buf)
return gpg_err_code_from_syserror ();
tmpret = drbg_algo_available (flags, &coreref);
if (tmpret)
goto outbuf;
drbg = xtrycalloc_secure (1, sizeof *drbg);
if (!drbg)
{
ret = gpg_err_code_from_syserror ();
goto outbuf;
}
/* if the following tests fail, it is likely that there is a buffer
* overflow and we get a SIGSEV */
ret = drbg_instantiate (drbg, NULL, coreref, 1);
if (ret)
goto outbuf;
max_addtllen = drbg_max_addtl ();
max_request_bytes = drbg_max_request_bytes ();
/* overflow addtllen with additional info string */
drbg_string_fill (&addtl, test->addtla, (max_addtllen + 1));
len = drbg_generate (drbg, buf, test->expectedlen, &addtl);
if (len)
goto outdrbg;
/* overflow max_bits */
len = drbg_generate (drbg, buf, (max_request_bytes + 1), NULL);
if (len)
goto outdrbg;
drbg_uninstantiate (drbg);
/* test failing entropy source as defined in 11.3.2 */
test_data.testentropy = NULL;
test_data.fail_seed_source = 1;
drbg->test_data = &test_data;
tmpret = drbg_instantiate (drbg, NULL, coreref, 0);
if (!tmpret)
goto outdrbg;
test_data.fail_seed_source = 0;
test_data.testentropy = &testentropy;
drbg_string_fill (&testentropy, test->entropy, test->entropylen);
/* overflow max addtllen with personalization string */
tmpret = drbg_instantiate (drbg, &addtl, coreref, 0);
if (!tmpret)
goto outdrbg;
dbg (("DRBG: Sanity tests for failure code paths successfully completed\n"));
ret = 0;
outdrbg:
drbg_uninstantiate (drbg);
outbuf:
xfree (buf);
xfree (drbg);
return ret;
}
/*
* DRBG Healthcheck function as required in SP800-90A
*
* return:
* 0 on success (all tests pass)
* >0 on error (return code indicate the number of failures)
*/
static int
drbg_healthcheck (void)
{
int ret = 0;
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[0]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[1]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[2]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[3]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_nopr[4]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[0]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[1]);
ret += _gcry_rngdrbg_healthcheck_one (&drbg_test_pr[2]);
ret += drbg_healthcheck_sanity (&drbg_test_nopr[0]);
return ret;
}
/* Run the self-tests. */
gcry_error_t
_gcry_rngdrbg_selftest (selftest_report_func_t report)
{
gcry_err_code_t ec;
const char *errtxt = NULL;
drbg_lock ();
if (0 != drbg_healthcheck ())
errtxt = "RNG output does not match known value";
drbg_unlock ();
if (report && errtxt)
report ("random", 0, "KAT", errtxt);
ec = errtxt ? GPG_ERR_SELFTEST_FAILED : 0;
return gpg_error (ec);
}
/***************************************************************
* Cipher invocations requested by DRBG
***************************************************************/
static gpg_err_code_t
drbg_hash_init (drbg_state_t drbg)
{
gcry_md_hd_t hd;
gpg_error_t err;
err = _gcry_md_open (&hd, drbg->core->backend_cipher, 0);
if (err)
return err;
drbg->priv_data = hd;
return 0;
}
static gpg_err_code_t
drbg_hmac_init (drbg_state_t drbg)
{
gcry_md_hd_t hd;
gpg_error_t err;
err = _gcry_md_open (&hd, drbg->core->backend_cipher, GCRY_MD_FLAG_HMAC);
if (err)
return err;
drbg->priv_data = hd;
return 0;
}
static gpg_err_code_t
drbg_hmac_setkey (drbg_state_t drbg, const unsigned char *key)
{
gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
return _gcry_md_setkey (hd, key, drbg_statelen (drbg));
}
static void
drbg_hash_fini (drbg_state_t drbg)
{
gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
_gcry_md_close (hd);
}
static byte *
drbg_hash (drbg_state_t drbg, const drbg_string_t *buf)
{
gcry_md_hd_t hd = (gcry_md_hd_t)drbg->priv_data;
_gcry_md_reset(hd);
for (; NULL != buf; buf = buf->next)
_gcry_md_write (hd, buf->buf, buf->len);
_gcry_md_final (hd);
return _gcry_md_read (hd, drbg->core->backend_cipher);
}
static void
drbg_sym_fini (drbg_state_t drbg)
{
gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
if (hd)
_gcry_cipher_close (hd);
if (drbg->ctr_handle)
_gcry_cipher_close (drbg->ctr_handle);
}
static gpg_err_code_t
drbg_sym_init (drbg_state_t drbg)
{
gcry_cipher_hd_t hd;
gpg_error_t err;
err = _gcry_cipher_open (&hd, drbg->core->backend_cipher,
GCRY_CIPHER_MODE_ECB, 0);
if (err)
{
drbg_sym_fini (drbg);
return err;
}
drbg->priv_data = hd;
err = _gcry_cipher_open (&drbg->ctr_handle, drbg->core->backend_cipher,
GCRY_CIPHER_MODE_CTR, 0);
if (err)
{
drbg_sym_fini (drbg);
return err;
}
if (drbg_blocklen (drbg) !=
_gcry_cipher_get_algo_blklen (drbg->core->backend_cipher))
{
drbg_sym_fini (drbg);
return -GPG_ERR_NO_ERROR;
}
return 0;
}
static gpg_err_code_t
drbg_sym_setkey (drbg_state_t drbg, const unsigned char *key)
{
gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
return _gcry_cipher_setkey (hd, key, drbg_keylen (drbg));
}
static gpg_err_code_t
drbg_sym (drbg_state_t drbg, unsigned char *outval, const drbg_string_t *buf)
{
gcry_cipher_hd_t hd = (gcry_cipher_hd_t)drbg->priv_data;
_gcry_cipher_reset(hd);
if (drbg_blocklen (drbg) < buf->len)
return -GPG_ERR_NO_ERROR;
/* in is only component */
return _gcry_cipher_encrypt (hd, outval, drbg_blocklen (drbg), buf->buf,
buf->len);
}
static gpg_err_code_t
drbg_sym_ctr (drbg_state_t drbg,
const unsigned char *inbuf, unsigned int inbuflen,
unsigned char *outbuf, unsigned int outbuflen)
{
gpg_error_t err;
_gcry_cipher_reset(drbg->ctr_handle);
err = _gcry_cipher_setctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
if (err)
return err;
while (outbuflen)
{
unsigned int cryptlen = (inbuflen > outbuflen) ? outbuflen : inbuflen;
err = _gcry_cipher_encrypt (drbg->ctr_handle, outbuf, cryptlen, inbuf,
cryptlen);
if (err)
return err;
outbuflen -= cryptlen;
outbuf += cryptlen;
}
return _gcry_cipher_getctr(drbg->ctr_handle, drbg->V, drbg_blocklen (drbg));
}
diff --git a/random/random-fips.c b/random/random-fips.c
index 3a641b25..6ba4e04a 100644
--- a/random/random-fips.c
+++ b/random/random-fips.c
@@ -1,1124 +1,1124 @@
/* random-fips.c - FIPS style random number generator
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
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" (2005-01-31). This implementation
uses the AES variant.
There are 3 random context which map to the different levels of
random quality:
Generator Seed and Key Kernel entropy (init/reseed)
------------------------------------------------------------
GCRY_VERY_STRONG_RANDOM /dev/random 256/128 bits
GCRY_STRONG_RANDOM /dev/random 256/128 bits
gcry_create_nonce GCRY_STRONG_RANDOM n/a
All random generators return their data in 128 bit blocks. If the
caller requested less bits, the extra bits are not used. The key
for each generator is only set once at the first time a generator
is used. The seed value is set with the key and again after 1000
(SEED_TTL) output blocks; the re-seeding is disabled in test mode.
The GCRY_VERY_STRONG_RANDOM and GCRY_STRONG_RANDOM generators are
keyed and seeded from the /dev/random device. Thus these
generators may block until the kernel has collected enough entropy.
The gcry_create_nonce generator is keyed and seeded from the
GCRY_STRONG_RANDOM generator. It 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.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#include "g10lib.h"
#include "random.h"
#include "rand-internal.h"
/* 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,
it is not meant to be thread-safe but merely as a failsafe feature
to assert proper locking. */
GPGRT_LOCK_DEFINE (fips_rng_lock);
static int fips_rng_is_locked;
/* The required size for the temporary buffer of the x931_aes_driver
function and the buffer itself which will be allocated in secure
memory. This needs to be global variable for proper initialization
and to allow shutting down the RNG without leaking memory. May
only be used while holding the FIPS_RNG_LOCK.
This variable is also used to avoid duplicate initialization. */
#define TEMPVALUE_FOR_X931_AES_DRIVER_SIZE 48
static unsigned char *tempvalue_for_x931_aes_driver;
/* After having retrieved this number of blocks from the RNG, we want
to do a reseeding. */
#define SEED_TTL 1000
/* The length of the key we use: 16 bytes (128 bit) for AES128. */
#define X931_AES_KEYLEN 16
/* A global buffer used to communicate between the x931_generate_key
and x931_generate_seed functions and the entropy_collect_cb
function. It may only be used by these functions. */
static unsigned char *entropy_collect_buffer; /* Buffer. */
static size_t entropy_collect_buffer_len; /* Used length. */
static size_t entropy_collect_buffer_size; /* Allocated length. */
/* This random context type is used to track properties of one random
generator. Thee context are usually allocated in secure memory so
that the seed value is well protected. There are a couble of guard
fields to help detecting applications accidentally overwriting parts
of the memory. */
struct rng_context
{
unsigned char guard_0[1];
/* The handle of the cipher used by the RNG. If this one is not
NULL a cipher handle along with a random key has been
established. */
gcry_cipher_hd_t cipher_hd;
/* If this flag is true, the SEED_V buffer below carries a valid
seed. */
int is_seeded:1;
/* The very first block generated is used to compare the result
against the last result. This flag indicates that such a block
is available. */
int compare_value_valid:1;
/* A counter used to trigger re-seeding. */
unsigned int use_counter;
unsigned char guard_1[1];
/* The buffer containing the seed value V. */
unsigned char seed_V[16];
unsigned char guard_2[1];
/* The last result from the x931_aes function. Only valid if
compare_value_valid is set. */
unsigned char compare_value[16];
unsigned char guard_3[1];
/* The external test may want to suppress the duplicate bock check.
This is done if the this flag is set. */
unsigned char test_no_dup_check;
/* To implement a KAT we need to provide a know DT value. To
accomplish this the x931_get_dt function checks whether this
field is not NULL and then uses the 16 bytes at this address for
the DT value. However the last 4 bytes are replaced by the
value of field TEST_DT_COUNTER which will be incremented after
each invocation of x931_get_dt. We use a pointer and not a buffer
because there is no need to put this value into secure memory. */
const unsigned char *test_dt_ptr;
u32 test_dt_counter;
/* We need to keep track of the process which did the initialization
so that we can detect a fork. The volatile modifier is required
so that the compiler does not optimize it away in case the getpid
function is badly attributed. */
pid_t key_init_pid;
pid_t seed_init_pid;
};
typedef struct rng_context *rng_context_t;
/* The random context used for the nonce generator. May only be used
while holding the FIPS_RNG_LOCK. */
static rng_context_t nonce_context;
/* The random context used for the standard random generator. May
only be used while holding the FIPS_RNG_LOCK. */
static rng_context_t std_rng_context;
/* The random context used for the very strong random generator. May
only be used while holding the FIPS_RNG_LOCK. */
static rng_context_t strong_rng_context;
/* --- Local prototypes --- */
static void x931_reseed (rng_context_t rng_ctx);
static void get_random (void *buffer, size_t length, rng_context_t rng_ctx);
/* --- Functions --- */
/* Basic initialization is required to initialize mutexes and
do a few checks on the implementation. */
static void
basic_initialization (void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
fips_rng_is_locked = 0;
/* Make sure that we are still using the values we have
traditionally used for the random levels. */
gcry_assert (GCRY_WEAK_RANDOM == 0
&& GCRY_STRONG_RANDOM == 1
&& GCRY_VERY_STRONG_RANDOM == 2);
}
/* Acquire the fips_rng_lock. */
static void
lock_rng (void)
{
gpg_err_code_t rc;
rc = gpgrt_lock_lock (&fips_rng_lock);
if (rc)
log_fatal ("failed to acquire the RNG lock: %s\n", gpg_strerror (rc));
fips_rng_is_locked = 1;
}
/* Release the fips_rng_lock. */
static void
unlock_rng (void)
{
gpg_err_code_t rc;
fips_rng_is_locked = 0;
rc = gpgrt_lock_unlock (&fips_rng_lock);
if (rc)
log_fatal ("failed to release the RNG lock: %s\n", gpg_strerror (rc));
}
static void
setup_guards (rng_context_t rng_ctx)
{
/* Set the guards to some arbitrary values. */
rng_ctx->guard_0[0] = 17;
rng_ctx->guard_1[0] = 42;
rng_ctx->guard_2[0] = 137;
rng_ctx->guard_3[0] = 252;
}
static void
check_guards (rng_context_t rng_ctx)
{
if ( rng_ctx->guard_0[0] != 17
|| rng_ctx->guard_1[0] != 42
|| rng_ctx->guard_2[0] != 137
|| rng_ctx->guard_3[0] != 252 )
log_fatal ("memory corruption detected in RNG context %p\n", rng_ctx);
}
/* Get the DT vector for use with the core PRNG function. Buffer
needs to be provided by the caller with a size of at least LENGTH
bytes. RNG_CTX needs to be passed to allow for a KAT. The 16 byte
timestamp we construct is made up the real time and three counters:
Buffer: 00112233445566778899AABBCCDDEEFF
!--+---!!-+-!!+!!--+---!!--+---!
seconds ---------/ | | | |
microseconds -----------/ | | |
counter2 -------------------/ | |
counter1 ------------------------/ |
counter0 --------------------------------/
Counter 2 is just 12 bits wide and used to track fractions of
milliseconds whereas counters 1 and 0 are combined to a free
running 64 bit counter. */
static void
x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx)
{
gcry_assert (length == 16); /* This length is required for use with AES. */
gcry_assert (fips_rng_is_locked);
/* If the random context indicates that a test DT should be used,
take the DT value from the context. For safety reasons we do
this only if the context is not one of the regular contexts. */
if (rng_ctx->test_dt_ptr
&& rng_ctx != nonce_context
&& rng_ctx != std_rng_context
&& rng_ctx != strong_rng_context)
{
memcpy (buffer, rng_ctx->test_dt_ptr, 16);
buffer[12] = (rng_ctx->test_dt_counter >> 24);
buffer[13] = (rng_ctx->test_dt_counter >> 16);
buffer[14] = (rng_ctx->test_dt_counter >> 8);
buffer[15] = rng_ctx->test_dt_counter;
rng_ctx->test_dt_counter++;
return;
}
#if HAVE_GETTIMEOFDAY
{
static u32 last_sec, last_usec;
static u32 counter1, counter0;
static u16 counter2;
unsigned int usec;
struct timeval tv;
if (!last_sec)
{
/* This is the very first time we are called: Set the counters
to an not so easy predictable value to avoid always
starting at 0. Not really needed but it doesn't harm. */
counter1 = (u32)getpid ();
#ifndef HAVE_W32_SYSTEM
counter0 = (u32)getppid ();
#endif
}
if (gettimeofday (&tv, NULL))
log_fatal ("gettimeofday() failed: %s\n", strerror (errno));
/* The microseconds part is always less than 1 million (0x0f4240).
Thus we don't care about the MSB and in addition shift it to
the left by 4 bits. */
usec = tv.tv_usec;
usec <<= 4;
/* If we got the same time as by the last invocation, bump up
counter2 and save the time for the next invocation. */
if (tv.tv_sec == last_sec && usec == last_usec)
{
counter2++;
counter2 &= 0x0fff;
}
else
{
counter2 = 0;
last_sec = tv.tv_sec;
last_usec = usec;
}
/* Fill the buffer with the timestamp. */
buffer[0] = ((tv.tv_sec >> 24) & 0xff);
buffer[1] = ((tv.tv_sec >> 16) & 0xff);
buffer[2] = ((tv.tv_sec >> 8) & 0xff);
buffer[3] = (tv.tv_sec & 0xff);
buffer[4] = ((usec >> 16) & 0xff);
buffer[5] = ((usec >> 8) & 0xff);
buffer[6] = ((usec & 0xf0) | ((counter2 >> 8) & 0x0f));
buffer[7] = (counter2 & 0xff);
/* Add the free running counter. */
buffer[8] = ((counter1 >> 24) & 0xff);
buffer[9] = ((counter1 >> 16) & 0xff);
buffer[10] = ((counter1 >> 8) & 0xff);
buffer[11] = ((counter1) & 0xff);
buffer[12] = ((counter0 >> 24) & 0xff);
buffer[13] = ((counter0 >> 16) & 0xff);
buffer[14] = ((counter0 >> 8) & 0xff);
buffer[15] = ((counter0) & 0xff);
/* Bump up that counter. */
if (!++counter0)
++counter1;
}
#else
log_fatal ("gettimeofday() not available on this system\n");
#endif
/* log_printhex ("x931_get_dt: ", buffer, 16); */
}
/* XOR the buffers A and B which are each of LENGTH bytes and store
the result at R. R needs to be provided by the caller with a size
of at least LENGTH bytes. */
static void
xor_buffer (unsigned char *r,
const unsigned char *a, const unsigned char *b, size_t length)
{
for ( ; length; length--, a++, b++, r++)
*r = (*a ^ *b);
}
/* Encrypt LENGTH bytes of INPUT to OUTPUT using KEY. LENGTH
needs to be 16. */
static void
encrypt_aes (gcry_cipher_hd_t key,
unsigned char *output, const unsigned char *input, size_t length)
{
gpg_error_t err;
gcry_assert (length == 16);
err = _gcry_cipher_encrypt (key, output, length, input, length);
if (err)
log_fatal ("AES encryption in RNG failed: %s\n", _gcry_strerror (err));
}
/* The core ANSI X9.31, Appendix A.2.4 function using AES. The caller
needs to pass a 16 byte buffer for the result, the 16 byte
datetime_DT value and the 16 byte seed value V. The caller also
needs to pass an appropriate KEY and make sure to pass a valid
seed_V. The caller also needs to provide two 16 bytes buffer for
intermediate results, they may be reused by the caller later.
On return the result is stored at RESULT_R and the SEED_V is
updated. May only be used while holding the lock. */
static void
x931_aes (unsigned char result_R[16],
unsigned char datetime_DT[16], unsigned char seed_V[16],
gcry_cipher_hd_t key,
unsigned char intermediate_I[16], unsigned char temp_xor[16])
{
/* Let ede*X(Y) represent the AES encryption of Y under the key *X.
Let V be a 128-bit seed value which is also kept secret, and XOR
be the exclusive-or operator. Let DT be a date/time vector which
is updated on each iteration. I is a intermediate value.
I = ede*K(DT) */
encrypt_aes (key, intermediate_I, datetime_DT, 16);
/* R = ede*K(I XOR V) */
xor_buffer (temp_xor, intermediate_I, seed_V, 16);
encrypt_aes (key, result_R, temp_xor, 16);
/* V = ede*K(R XOR I). */
xor_buffer (temp_xor, result_R, intermediate_I, 16);
encrypt_aes (key, seed_V, temp_xor, 16);
/* Zero out temporary values. */
wipememory (intermediate_I, 16);
wipememory (temp_xor, 16);
}
/* The high level driver to x931_aes. This one does the required
tests and calls the core function until the entire buffer has been
filled. OUTPUT is a caller provided buffer of LENGTH bytes to
receive the random, RNG_CTX is the context of the RNG. The context
must be properly initialized. Returns 0 on success. */
static int
x931_aes_driver (unsigned char *output, size_t length, rng_context_t rng_ctx)
{
unsigned char datetime_DT[16];
unsigned char *intermediate_I, *temp_buffer, *result_buffer;
size_t nbytes;
gcry_assert (fips_rng_is_locked);
gcry_assert (rng_ctx->cipher_hd);
gcry_assert (rng_ctx->is_seeded);
gcry_assert (tempvalue_for_x931_aes_driver);
gcry_assert (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE == 48);
intermediate_I = tempvalue_for_x931_aes_driver;
temp_buffer = tempvalue_for_x931_aes_driver + 16;
result_buffer = tempvalue_for_x931_aes_driver + 32;
while (length)
{
/* Unless we are running with a test context, we require a new
seed after some time. */
if (!rng_ctx->test_dt_ptr && rng_ctx->use_counter > SEED_TTL)
{
x931_reseed (rng_ctx);
rng_ctx->use_counter = 0;
}
/* Due to the design of the RNG, we always receive 16 bytes (128
bit) of random even if we require less. The extra bytes
returned are not used. Intheory we could save them for the
next invocation, but that would make the control flow harder
to read. */
nbytes = length < 16? length : 16;
x931_get_dt (datetime_DT, 16, rng_ctx);
x931_aes (result_buffer,
datetime_DT, rng_ctx->seed_V, rng_ctx->cipher_hd,
intermediate_I, temp_buffer);
rng_ctx->use_counter++;
if (rng_ctx->test_no_dup_check
&& rng_ctx->test_dt_ptr
&& rng_ctx != nonce_context
&& rng_ctx != std_rng_context
&& rng_ctx != strong_rng_context)
{
/* This is a test context which does not want the duplicate
block check. */
}
else
{
/* Do a basic check on the output to avoid a stuck generator. */
if (!rng_ctx->compare_value_valid)
{
/* First time used, only save the result. */
memcpy (rng_ctx->compare_value, result_buffer, 16);
rng_ctx->compare_value_valid = 1;
continue;
}
if (!memcmp (rng_ctx->compare_value, result_buffer, 16))
{
/* Ooops, we received the same 128 bit block - that should
in theory never happen. The FIPS requirement says that
we need to put ourself into the error state in such
case. */
fips_signal_error ("duplicate 128 bit block returned by RNG");
return -1;
}
memcpy (rng_ctx->compare_value, result_buffer, 16);
}
/* Append to outbut. */
memcpy (output, result_buffer, nbytes);
wipememory (result_buffer, 16);
output += nbytes;
length -= nbytes;
}
return 0;
}
/* Callback for x931_generate_key. Note that this callback uses the
global ENTROPY_COLLECT_BUFFER which has been setup by get_entropy.
ORIGIN is not used but required due to the design of entropy
gathering module. */
static void
entropy_collect_cb (const void *buffer, size_t length,
enum random_origins origin)
{
const unsigned char *p = buffer;
(void)origin;
gcry_assert (fips_rng_is_locked);
gcry_assert (entropy_collect_buffer);
/* Note that we need to protect against gatherers returning more
than the requested bytes (e.g. rndw32). */
while (length-- && entropy_collect_buffer_len < entropy_collect_buffer_size)
{
entropy_collect_buffer[entropy_collect_buffer_len++] ^= *p++;
}
}
/* Get NBYTES of entropy from the kernel device. The callers needs to
free the returned buffer. The function either succeeds or
terminates the process in case of a fatal error. */
static void *
get_entropy (size_t nbytes)
{
void *result;
int rc;
gcry_assert (!entropy_collect_buffer);
entropy_collect_buffer = xmalloc_secure (nbytes);
entropy_collect_buffer_size = nbytes;
entropy_collect_buffer_len = 0;
#if USE_RNDLINUX
rc = _gcry_rndlinux_gather_random (entropy_collect_cb, 0,
X931_AES_KEYLEN,
GCRY_VERY_STRONG_RANDOM);
#elif USE_RNDW32
do
{
rc = _gcry_rndw32_gather_random (entropy_collect_cb, 0,
X931_AES_KEYLEN,
GCRY_VERY_STRONG_RANDOM);
}
while (rc >= 0 && entropy_collect_buffer_len < entropy_collect_buffer_size);
#else
rc = -1;
#endif
if (rc < 0 || entropy_collect_buffer_len != entropy_collect_buffer_size)
{
xfree (entropy_collect_buffer);
entropy_collect_buffer = NULL;
log_fatal ("error getting entropy data\n");
}
result = entropy_collect_buffer;
entropy_collect_buffer = NULL;
return result;
}
/* Generate a key for use with x931_aes. The function returns a
handle to the cipher context readily prepared for ECB encryption.
If FOR_NONCE is true, the key is retrieved by readong random from
the standard generator. On error NULL is returned. */
static gcry_cipher_hd_t
x931_generate_key (int for_nonce)
{
gcry_cipher_hd_t hd;
gpg_err_code_t rc;
void *buffer;
gcry_assert (fips_rng_is_locked);
/* Allocate a cipher context. */
rc = _gcry_cipher_open (&hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB,
GCRY_CIPHER_SECURE);
if (rc)
{
log_error ("error creating cipher context for RNG: %s\n",
_gcry_strerror (rc));
return NULL;
}
/* Get a key from the standard RNG or from the entropy source. */
if (for_nonce)
{
buffer = xmalloc (X931_AES_KEYLEN);
get_random (buffer, X931_AES_KEYLEN, std_rng_context);
}
else
{
buffer = get_entropy (X931_AES_KEYLEN);
}
/* Set the key and delete the buffer because the key is now part of
the cipher context. */
rc = _gcry_cipher_setkey (hd, buffer, X931_AES_KEYLEN);
wipememory (buffer, X931_AES_KEYLEN);
xfree (buffer);
if (rc)
{
log_error ("error creating key for RNG: %s\n", _gcry_strerror (rc));
_gcry_cipher_close (hd);
return NULL;
}
return hd;
}
/* Generate a key for use with x931_aes. The function copies a seed
of LENGTH bytes into SEED_BUFFER. LENGTH needs to by given as 16. */
static void
x931_generate_seed (unsigned char *seed_buffer, size_t length)
{
void *buffer;
gcry_assert (fips_rng_is_locked);
gcry_assert (length == 16);
buffer = get_entropy (X931_AES_KEYLEN);
memcpy (seed_buffer, buffer, X931_AES_KEYLEN);
wipememory (buffer, X931_AES_KEYLEN);
xfree (buffer);
}
/* Reseed a generator. This is also used for the initial seeding. */
static void
x931_reseed (rng_context_t rng_ctx)
{
gcry_assert (fips_rng_is_locked);
if (rng_ctx == nonce_context)
{
/* The nonce context is special. It will be seeded using the
standard random generator. */
get_random (rng_ctx->seed_V, 16, std_rng_context);
rng_ctx->is_seeded = 1;
rng_ctx->seed_init_pid = getpid ();
}
else
{
/* The other two generators are seeded from /dev/random. */
x931_generate_seed (rng_ctx->seed_V, 16);
rng_ctx->is_seeded = 1;
rng_ctx->seed_init_pid = getpid ();
}
}
/* Core random function. This is used for both nonce and random
generator. The actual RNG to be used depends on the random context
RNG_CTX passed. Note that this function is called with the RNG not
yet locked. */
static void
get_random (void *buffer, size_t length, rng_context_t rng_ctx)
{
gcry_assert (buffer);
gcry_assert (rng_ctx);
check_guards (rng_ctx);
/* Initialize the cipher handle and thus setup the key if needed. */
if (!rng_ctx->cipher_hd)
{
if (rng_ctx == nonce_context)
rng_ctx->cipher_hd = x931_generate_key (1);
else
rng_ctx->cipher_hd = x931_generate_key (0);
if (!rng_ctx->cipher_hd)
goto bailout;
rng_ctx->key_init_pid = getpid ();
}
/* Initialize the seed value if needed. */
if (!rng_ctx->is_seeded)
x931_reseed (rng_ctx);
if (rng_ctx->key_init_pid != getpid ()
|| rng_ctx->seed_init_pid != getpid ())
{
/* We are in a child of us. Because we have no way yet to do
proper re-initialization (including self-checks etc), the
only chance we have is to bail out. Obviusly a fork/exec
won't harm because the exec overwrites the old image. */
fips_signal_error ("fork without proper re-initialization "
"detected in RNG");
goto bailout;
}
if (x931_aes_driver (buffer, length, rng_ctx))
goto bailout;
check_guards (rng_ctx);
return;
bailout:
log_fatal ("severe error getting random\n");
/*NOTREACHED*/
}
/* --- Public Functions --- */
/* Initialize this random subsystem. If FULL is false, this function
merely calls the basic initialization of the module and does not do
anything more. Doing this is not really required but when running
in a threaded environment we might get a race condition
otherwise. */
void
_gcry_rngfips_initialize (int full)
{
basic_initialization ();
if (!full)
return;
/* Allocate temporary buffers. If that buffer already exists we
know that we are already initialized. */
lock_rng ();
if (!tempvalue_for_x931_aes_driver)
{
tempvalue_for_x931_aes_driver
= xmalloc_secure (TEMPVALUE_FOR_X931_AES_DRIVER_SIZE);
/* Allocate the random contexts. Note that we do not need to use
secure memory for the nonce context. */
nonce_context = xcalloc (1, sizeof *nonce_context);
setup_guards (nonce_context);
std_rng_context = xcalloc_secure (1, sizeof *std_rng_context);
setup_guards (std_rng_context);
strong_rng_context = xcalloc_secure (1, sizeof *strong_rng_context);
setup_guards (strong_rng_context);
}
else
{
/* Already initialized. Do some sanity checks. */
gcry_assert (!nonce_context->test_dt_ptr);
gcry_assert (!std_rng_context->test_dt_ptr);
gcry_assert (!strong_rng_context->test_dt_ptr);
check_guards (nonce_context);
check_guards (std_rng_context);
check_guards (strong_rng_context);
}
unlock_rng ();
}
/* Try to close the FDs of the random gather module. This is
currently only implemented for rndlinux. */
void
_gcry_rngfips_close_fds (void)
{
lock_rng ();
#if USE_RNDLINUX
_gcry_rndlinux_gather_random (NULL, 0, 0, 0);
#endif
unlock_rng ();
}
/* Print some statistics about the RNG. */
void
_gcry_rngfips_dump_stats (void)
{
/* Not yet implemented. */
}
/* This function returns true if no real RNG is available or the
quality of the RNG has been degraded for test purposes. */
int
_gcry_rngfips_is_faked (void)
{
return 0; /* Faked random is not allowed. */
}
/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
should be in the range of 0..100 to indicate the goodness of the
entropy added, or -1 for goodness not known. */
gcry_error_t
_gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality)
{
(void)buf;
(void)buflen;
(void)quality;
return 0; /* Not implemented. */
}
/* Public function to fill the buffer with LENGTH bytes of
cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong
enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
generation stuff but may be very slow. */
void
_gcry_rngfips_randomize (void *buffer, size_t length,
enum gcry_random_level level)
{
_gcry_rngfips_initialize (1); /* Auto-initialize if needed. */
lock_rng ();
if (level == GCRY_VERY_STRONG_RANDOM)
get_random (buffer, length, strong_rng_context);
else
get_random (buffer, length, std_rng_context);
unlock_rng ();
}
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void
_gcry_rngfips_create_nonce (void *buffer, size_t length)
{
_gcry_rngfips_initialize (1); /* Auto-initialize if needed. */
lock_rng ();
get_random (buffer, length, nonce_context);
unlock_rng ();
}
/* Run a Know-Answer-Test using a dedicated test context. Note that
we can't use the samples from the NISR RNGVS document because they
don't take the requirement to throw away the first block and use
that for duplicate check in account. Thus we made up our own test
vectors. */
static gcry_err_code_t
selftest_kat (selftest_report_func_t report)
{
static struct
{
const unsigned char key[16];
const unsigned char dt[16];
const unsigned char v[16];
const unsigned char r[3][16];
} tv[] =
{
{ { 0xb9, 0xca, 0x7f, 0xd6, 0xa0, 0xf5, 0xd3, 0x42,
0x19, 0x6d, 0x84, 0x91, 0x76, 0x1c, 0x3b, 0xbe },
{ 0x48, 0xb2, 0x82, 0x98, 0x68, 0xc2, 0x80, 0x00,
0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x25, 0x00 },
{ 0x52, 0x17, 0x8d, 0x29, 0xa2, 0xd5, 0x84, 0x12,
0x9d, 0x89, 0x9a, 0x45, 0x82, 0x02, 0xf7, 0x77 },
{ { 0x42, 0x9c, 0x08, 0x3d, 0x82, 0xf4, 0x8a, 0x40,
0x66, 0xb5, 0x49, 0x27, 0xab, 0x42, 0xc7, 0xc3 },
{ 0x0e, 0xb7, 0x61, 0x3c, 0xfe, 0xb0, 0xbe, 0x73,
0xf7, 0x6e, 0x6d, 0x6f, 0x1d, 0xa3, 0x14, 0xfa },
{ 0xbb, 0x4b, 0xc1, 0x0e, 0xc5, 0xfb, 0xcd, 0x46,
0xbe, 0x28, 0x61, 0xe7, 0x03, 0x2b, 0x37, 0x7d } } },
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ { 0xf7, 0x95, 0xbd, 0x4a, 0x52, 0xe2, 0x9e, 0xd7,
0x13, 0xd3, 0x13, 0xfa, 0x20, 0xe9, 0x8d, 0xbc },
{ 0xc8, 0xd1, 0xe5, 0x11, 0x59, 0x52, 0xf7, 0xfa,
0x37, 0x38, 0xb4, 0xc5, 0xce, 0xb2, 0xb0, 0x9a },
{ 0x0d, 0x9c, 0xc5, 0x0d, 0x16, 0xe1, 0xbc, 0xed,
0xcf, 0x60, 0x62, 0x09, 0x9d, 0x20, 0x83, 0x7e } } },
{ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{ 0x80, 0x00, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03,
0xa0, 0x20, 0xa1, 0x21, 0xa2, 0x22, 0xa3, 0x23 },
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
{ { 0x96, 0xed, 0xcc, 0xc3, 0xdd, 0x04, 0x7f, 0x75,
0x63, 0x19, 0x37, 0x6f, 0x15, 0x22, 0x57, 0x56 },
{ 0x7a, 0x14, 0x76, 0x77, 0x95, 0x17, 0x7e, 0xc8,
0x92, 0xe8, 0xdd, 0x15, 0xcb, 0x1f, 0xbc, 0xb1 },
{ 0x25, 0x3e, 0x2e, 0xa2, 0x41, 0x1b, 0xdd, 0xf5,
0x21, 0x48, 0x41, 0x71, 0xb3, 0x8d, 0x2f, 0x4c } } }
};
int tvidx, ridx;
rng_context_t test_ctx;
gpg_err_code_t rc;
const char *errtxt = NULL;
unsigned char result[16];
gcry_assert (tempvalue_for_x931_aes_driver);
test_ctx = xcalloc (1, sizeof *test_ctx);
setup_guards (test_ctx);
lock_rng ();
for (tvidx=0; tvidx < DIM (tv); tvidx++)
{
/* Setup the key. */
rc = _gcry_cipher_open (&test_ctx->cipher_hd,
GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB,
GCRY_CIPHER_SECURE);
if (rc)
{
errtxt = "error creating cipher context for RNG";
goto leave;
}
rc = _gcry_cipher_setkey (test_ctx->cipher_hd, tv[tvidx].key, 16);
if (rc)
{
errtxt = "error setting key for RNG";
goto leave;
}
test_ctx->key_init_pid = getpid ();
/* Setup the seed. */
memcpy (test_ctx->seed_V, tv[tvidx].v, 16);
test_ctx->is_seeded = 1;
test_ctx->seed_init_pid = getpid ();
/* Setup a DT value. */
test_ctx->test_dt_ptr = tv[tvidx].dt;
test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24)
|(tv[tvidx].dt[13] << 16)
|(tv[tvidx].dt[14] << 8)
|(tv[tvidx].dt[15]) );
/* Get and compare the first three results. */
for (ridx=0; ridx < 3; ridx++)
{
/* Compute the next value. */
if (x931_aes_driver (result, 16, test_ctx))
{
errtxt = "X9.31 RNG core function failed";
goto leave;
}
/* Compare it to the known value. */
if (memcmp (result, tv[tvidx].r[ridx], 16))
{
/* log_printhex ("x931_aes got: ", result, 16); */
/* log_printhex ("x931_aes exp: ", tv[tvidx].r[ridx], 16); */
errtxt = "RNG output does not match known value";
goto leave;
}
}
/* This test is actual pretty pointless because we use a local test
context. */
if (test_ctx->key_init_pid != getpid ()
|| test_ctx->seed_init_pid != getpid ())
{
errtxt = "fork detection failed";
goto leave;
}
_gcry_cipher_close (test_ctx->cipher_hd);
test_ctx->cipher_hd = NULL;
test_ctx->is_seeded = 0;
check_guards (test_ctx);
}
leave:
unlock_rng ();
_gcry_cipher_close (test_ctx->cipher_hd);
check_guards (test_ctx);
xfree (test_ctx);
if (report && errtxt)
report ("random", 0, "KAT", errtxt);
return errtxt? GPG_ERR_SELFTEST_FAILED : 0;
}
/* Run the self-tests. */
gcry_error_t
_gcry_rngfips_selftest (selftest_report_func_t report)
{
gcry_err_code_t ec;
#if defined(USE_RNDLINUX) || defined(USE_RNDW32)
{
char buffer[8];
/* Do a simple test using the public interface. This will also
enforce full initialization of the RNG. We need to be fully
initialized due to the global requirement of the
tempvalue_for_x931_aes_driver stuff. */
_gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM);
}
ec = selftest_kat (report);
#else /*!(USE_RNDLINUX||USE_RNDW32)*/
report ("random", 0, "setup", "no entropy gathering module");
ec = GPG_ERR_SELFTEST_FAILED;
#endif
return gpg_error (ec);
}
/* Create a new test context for an external RNG test driver. On
success the test context is stored at R_CONTEXT; on failure NULL is
stored at R_CONTEXT and an error code is returned. */
gcry_err_code_t
_gcry_rngfips_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)
{
gpg_err_code_t rc;
rng_context_t test_ctx;
_gcry_rngfips_initialize (1); /* Auto-initialize if needed. */
if (!r_context
|| !key || keylen != 16
|| !seed || seedlen != 16
|| !dt || dtlen != 16 )
return GPG_ERR_INV_ARG;
test_ctx = xtrycalloc (1, sizeof *test_ctx + dtlen);
if (!test_ctx)
return gpg_err_code_from_syserror ();
setup_guards (test_ctx);
/* Setup the key. */
rc = _gcry_cipher_open (&test_ctx->cipher_hd,
GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB,
GCRY_CIPHER_SECURE);
if (rc)
goto leave;
rc = _gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen);
if (rc)
goto leave;
test_ctx->key_init_pid = getpid ();
/* Setup the seed. */
memcpy (test_ctx->seed_V, seed, seedlen);
test_ctx->is_seeded = 1;
test_ctx->seed_init_pid = getpid ();
/* Setup a DT value. Because our context structure only stores a
pointer we copy the DT value to the extra space we allocated in
the test_ctx and set the pointer to that address. */
memcpy ((unsigned char*)test_ctx + sizeof *test_ctx, dt, dtlen);
test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof *test_ctx;
test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24)
|(test_ctx->test_dt_ptr[13] << 16)
|(test_ctx->test_dt_ptr[14] << 8)
|(test_ctx->test_dt_ptr[15]) );
if ( (flags & 1) )
test_ctx->test_no_dup_check = 1;
check_guards (test_ctx);
/* All fine. */
rc = 0;
leave:
if (rc)
{
_gcry_cipher_close (test_ctx->cipher_hd);
xfree (test_ctx);
*r_context = NULL;
}
else
*r_context = test_ctx;
return rc;
}
/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them
at BUFFER. Return 0 on success or an error code. */
gcry_err_code_t
_gcry_rngfips_run_external_test (void *context, char *buffer, size_t buflen)
{
rng_context_t test_ctx = context;
if (!test_ctx || !buffer || buflen != 16)
return GPG_ERR_INV_ARG;
lock_rng ();
get_random (buffer, buflen, test_ctx);
unlock_rng ();
return 0;
}
/* Release the test CONTEXT. */
void
_gcry_rngfips_deinit_external_test (void *context)
{
rng_context_t test_ctx = context;
if (test_ctx)
{
_gcry_cipher_close (test_ctx->cipher_hd);
xfree (test_ctx);
}
}
diff --git a/random/random-system.c b/random/random-system.c
index 8b79511c..8e0dbe68 100644
--- a/random/random-system.c
+++ b/random/random-system.c
@@ -1,250 +1,250 @@
/* random-system.c - wrapper around the system's RNG
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
This RNG is merely wrapper around the system's native RNG. For
example on Unix systems it directly uses /dev/{u,}random.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#include "g10lib.h"
#include "random.h"
#include "rand-internal.h"
/* 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,
it is not meant to be thread-safe but merely as a failsafe feature
to assert proper locking. */
GPGRT_LOCK_DEFINE (system_rng_lock);
static int system_rng_is_locked;
/* --- Local prototypes --- */
/* --- Functions --- */
/* Basic initialization is required to initialize mutexes and
do a few checks on the implementation. */
static void
basic_initialization (void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
system_rng_is_locked = 0;
/* Make sure that we are still using the values we traditionally
used for the random levels. */
gcry_assert (GCRY_WEAK_RANDOM == 0
&& GCRY_STRONG_RANDOM == 1
&& GCRY_VERY_STRONG_RANDOM == 2);
}
/* Acquire the system_rng_lock. */
static void
lock_rng (void)
{
gpg_err_code_t rc;
rc = gpgrt_lock_lock (&system_rng_lock);
if (rc)
log_fatal ("failed to acquire the System RNG lock: %s\n",
gpg_strerror (rc));
system_rng_is_locked = 1;
}
/* Release the system_rng_lock. */
static void
unlock_rng (void)
{
gpg_err_code_t rc;
system_rng_is_locked = 0;
rc = gpgrt_lock_unlock (&system_rng_lock);
if (rc)
log_fatal ("failed to release the System RNG lock: %s\n",
gpg_strerror (rc));
}
/* Helper variables for read_cb().
The _gcry_rnd*_gather_random interface does not allow to provide a
data pointer. Thus we need to use a global variable for
communication. However, the then required locking is anyway a good
idea because it does not make sense to have several readers of (say
/dev/random). It is easier to serve them one after the other. */
static unsigned char *read_cb_buffer; /* The buffer. */
static size_t read_cb_size; /* Size of the buffer. */
static size_t read_cb_len; /* Used length. */
/* Callback for _gcry_rnd*_gather_random. */
static void
read_cb (const void *buffer, size_t length, enum random_origins origin)
{
const unsigned char *p = buffer;
(void)origin;
gcry_assert (system_rng_is_locked);
gcry_assert (read_cb_buffer);
/* Note that we need to protect against gatherers returning more
than the requested bytes (e.g. rndw32). */
while (length-- && read_cb_len < read_cb_size)
{
read_cb_buffer[read_cb_len++] = *p++;
}
}
/* Fill BUFFER with LENGTH bytes of random at quality LEVEL. The
function either succeeds or terminates the process in case of a
fatal error. */
static void
get_random (void *buffer, size_t length, int level)
{
int rc;
gcry_assert (buffer);
read_cb_buffer = buffer;
read_cb_size = length;
read_cb_len = 0;
#if USE_RNDLINUX
rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level);
#elif USE_RNDUNIX
rc = _gcry_rndunix_gather_random (read_cb, 0, length, level);
#elif USE_RNDW32
do
{
rc = _gcry_rndw32_gather_random (read_cb, 0, length, level);
}
while (rc >= 0 && read_cb_len < read_cb_size);
#else
rc = -1;
#endif
if (rc < 0 || read_cb_len != read_cb_size)
{
log_fatal ("error reading random from system RNG (rc=%d)\n", rc);
}
}
/* --- Public Functions --- */
/* Initialize this random subsystem. If FULL is false, this function
merely calls the basic initialization of the module and does not do
anything more. Doing this is not really required but when running
in a threaded environment we might get a race condition
otherwise. */
void
_gcry_rngsystem_initialize (int full)
{
basic_initialization ();
if (!full)
return;
/* Nothing more to initialize. */
return;
}
/* Try to close the FDs of the random gather module. This is
currently only implemented for rndlinux. */
void
_gcry_rngsystem_close_fds (void)
{
lock_rng ();
#if USE_RNDLINUX
_gcry_rndlinux_gather_random (NULL, 0, 0, 0);
#endif
unlock_rng ();
}
/* Print some statistics about the RNG. */
void
_gcry_rngsystem_dump_stats (void)
{
/* Not yet implemented. */
}
/* This function returns true if no real RNG is available or the
quality of the RNG has been degraded for test purposes. */
int
_gcry_rngsystem_is_faked (void)
{
return 0; /* Faked random is not supported. */
}
/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
should be in the range of 0..100 to indicate the goodness of the
entropy added, or -1 for goodness not known. */
gcry_error_t
_gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality)
{
(void)buf;
(void)buflen;
(void)quality;
return 0; /* Not implemented. */
}
/* Public function to fill the buffer with LENGTH bytes of
cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong
enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
generation stuff but may be very slow. */
void
_gcry_rngsystem_randomize (void *buffer, size_t length,
enum gcry_random_level level)
{
_gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */
if (level != GCRY_VERY_STRONG_RANDOM)
level = GCRY_STRONG_RANDOM;
lock_rng ();
get_random (buffer, length, level);
unlock_rng ();
}
diff --git a/random/random.c b/random/random.c
index 9aab7893..54356016 100644
--- a/random/random.c
+++ b/random/random.c
@@ -1,584 +1,584 @@
/* random.c - Random number switch
* Copyright (C) 2003, 2006, 2008, 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
This module switches between different implementations of random
number generators and provides a few help functions.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /*HAVE_SYSLOG*/
#include <ctype.h>
#include "g10lib.h"
#include "random.h"
#include "rand-internal.h"
#include "cipher.h" /* For _gcry_sha1_hash_buffer(). */
/* The name of a file used to globally configure the RNG. */
#define RANDOM_CONF_FILE "/etc/gcrypt/random.conf"
/* If not NULL a progress function called from certain places and the
opaque value passed along. Registered by
_gcry_register_random_progress (). */
static void (*progress_cb) (void *,const char*,int,int, int );
static void *progress_cb_data;
/* Flags indicating the requested RNG types. */
static struct
{
int standard;
int fips;
int system;
} rng_types;
/* This is the lock we use to protect the buffer used by the nonce
generation. */
GPGRT_LOCK_DEFINE (nonce_buffer_lock);
/* --- Functions --- */
/* Used to register a progress callback. This needs to be called
before any threads are created. */
void
_gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
void *cb_data )
{
progress_cb = cb;
progress_cb_data = cb_data;
}
/* This progress function is currently used by the random modules to
give hints on how much more entropy is required. */
void
_gcry_random_progress (const char *what, int printchar, int current, int total)
{
if (progress_cb)
progress_cb (progress_cb_data, what, printchar, current, total);
}
/* Read a file with configure options. The file is a simple text file
* where empty lines and lines with the first non white-space
* character being '#' are ignored. Supported configure options are:
*
* disable-jent - Disable the jitter based extra entropy generator.
* This sets the RANDOM_CONF_DISABLE_JENT bit.
* only-urandom - Always use /dev/urandom instead of /dev/random.
* This sets the RANDOM_CONF_ONLY_URANDOM bit.
*
* The function returns a bit vector with flags read from the file.
*/
unsigned int
_gcry_random_read_conf (void)
{
const char *fname = RANDOM_CONF_FILE;
FILE *fp;
char buffer[256];
char *p, *pend;
int lnr = 0;
unsigned int result = 0;
fp = fopen (fname, "r");
if (!fp)
return result;
for (;;)
{
if (!fgets (buffer, sizeof buffer, fp))
{
if (!feof (fp))
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING,
"Libgcrypt warning: error reading '%s', line %d",
fname, lnr);
#endif /*HAVE_SYSLOG*/
}
fclose (fp);
return result;
}
lnr++;
for (p=buffer; my_isascii (*p) && isspace (*p); p++)
;
pend = strchr (p, '\n');
if (pend)
*pend = 0;
pend = p + (*p? (strlen (p)-1):0);
for ( ;pend > p; pend--)
if (my_isascii (*pend) && isspace (*pend))
*pend = 0;
if (!*p || *p == '#')
continue;
if (!strcmp (p, "disable-jent"))
result |= RANDOM_CONF_DISABLE_JENT;
else if (!strcmp (p, "only-urandom"))
result |= RANDOM_CONF_ONLY_URANDOM;
else
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING,
"Libgcrypt warning: unknown option in '%s', line %d",
fname, lnr);
#endif /*HAVE_SYSLOG*/
}
}
}
/* Set the preferred RNG type. This may be called at any time even
before gcry_check_version. Thus we can't assume any thread system
initialization. A type of 0 is used to indicate that any Libgcrypt
initialization has been done.*/
void
_gcry_set_preferred_rng_type (int type)
{
static int any_init;
if (!type)
{
any_init = 1;
}
else if (type == GCRY_RNG_TYPE_STANDARD)
{
rng_types.standard = 1;
}
else if (any_init)
{
/* After any initialization has been done we only allow to
upgrade to the standard RNG (handled above). All other
requests are ignored. The idea is that the application needs
to declare a preference for a weaker RNG as soon as possible
and before any library sets a preference. We assume that a
library which uses Libgcrypt calls an init function very
early. This way --- even if the library gets initialized
early by the application --- it is unlikely that it can
select a lower priority RNG.
This scheme helps to ensure that existing unmodified
applications (e.g. gpg2), which don't known about the new RNG
selection system, will continue to use the standard RNG and
not be tricked by some library to use a lower priority RNG.
There are some loopholes here but at least most GnuPG stuff
should be save because it calls src_c{gcry_control
(GCRYCTL_SUSPEND_SECMEM_WARN);} quite early and thus inhibits
switching to a low priority RNG.
*/
}
else if (type == GCRY_RNG_TYPE_FIPS)
{
rng_types.fips = 1;
}
else if (type == GCRY_RNG_TYPE_SYSTEM)
{
rng_types.system = 1;
}
}
/* Initialize this random subsystem. If FULL is false, this function
merely calls the basic initialization of the module and does not do
anything more. Doing this is not really required but when running
in a threaded environment we might get a race condition
otherwise. */
void
_gcry_random_initialize (int full)
{
if (fips_mode ())
_gcry_rngdrbg_inititialize (full);
else if (rng_types.standard)
_gcry_rngcsprng_initialize (full);
else if (rng_types.fips)
_gcry_rngdrbg_inititialize (full);
else if (rng_types.system)
_gcry_rngsystem_initialize (full);
else
_gcry_rngcsprng_initialize (full);
}
/* If possible close file descriptors used by the RNG. */
void
_gcry_random_close_fds (void)
{
/* Note that we can't do that directly because each random system
has its own lock functions which need to be used for accessing
the entropy gatherer. */
if (fips_mode ())
_gcry_rngdrbg_close_fds ();
else if (rng_types.standard)
_gcry_rngcsprng_close_fds ();
else if (rng_types.fips)
_gcry_rngdrbg_close_fds ();
else if (rng_types.system)
_gcry_rngsystem_close_fds ();
else
_gcry_rngcsprng_close_fds ();
}
/* Return the current RNG type. IGNORE_FIPS_MODE is a flag used to
skip the test for FIPS. This is useful, so that we are able to
return the type of the RNG even before we have setup FIPS mode
(note that FIPS mode is enabled by default until it is switched off
by the initialization). This is mostly useful for the regression
test. */
int
_gcry_get_rng_type (int ignore_fips_mode)
{
if (!ignore_fips_mode && fips_mode ())
return GCRY_RNG_TYPE_FIPS;
else if (rng_types.standard)
return GCRY_RNG_TYPE_STANDARD;
else if (rng_types.fips)
return GCRY_RNG_TYPE_FIPS;
else if (rng_types.system)
return GCRY_RNG_TYPE_SYSTEM;
else
return GCRY_RNG_TYPE_STANDARD;
}
void
_gcry_random_dump_stats (void)
{
if (fips_mode ())
_gcry_rngdrbg_dump_stats ();
else
_gcry_rngcsprng_dump_stats ();
_gcry_rndjent_dump_stats ();
}
/* This function should be called during initialization and before
initialization of this module to place the random pools into secure
memory. */
void
_gcry_secure_random_alloc (void)
{
if (fips_mode ())
; /* Not used; the FIPS RNG is always in secure mode. */
else
_gcry_rngcsprng_secure_alloc ();
}
/* This may be called before full initialization to degrade the
quality of the RNG for the sake of a faster running test suite. */
void
_gcry_enable_quick_random_gen (void)
{
if (fips_mode ())
; /* Not used. */
else
_gcry_rngcsprng_enable_quick_gen ();
}
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
_gcry_random_is_faked (void)
{
if (fips_mode ())
return _gcry_rngdrbg_is_faked ();
else
return _gcry_rngcsprng_is_faked ();
}
/* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
should be in the range of 0..100 to indicate the goodness of the
entropy added, or -1 for goodness not known. */
gcry_err_code_t
_gcry_random_add_bytes (const void *buf, size_t buflen, int quality)
{
if (fips_mode ())
return 0; /* No need for this in fips mode. */
else if (rng_types.standard)
return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality));
else if (rng_types.fips)
return 0;
else if (rng_types.system)
return 0;
else /* default */
return gpg_err_code (_gcry_rngcsprng_add_bytes (buf, buflen, quality));
}
/* Helper function. */
static void
do_randomize (void *buffer, size_t length, enum gcry_random_level level)
{
if (fips_mode ())
_gcry_rngdrbg_randomize (buffer, length, level);
else if (rng_types.standard)
_gcry_rngcsprng_randomize (buffer, length, level);
else if (rng_types.fips)
_gcry_rngdrbg_randomize (buffer, length, level);
else if (rng_types.system)
_gcry_rngsystem_randomize (buffer, length, level);
else /* default */
_gcry_rngcsprng_randomize (buffer, length, level);
}
/* The public function to return random data of the quality LEVEL.
Returns a pointer to a newly allocated and randomized buffer of
LEVEL and NBYTES length. Caller must free the buffer. */
void *
_gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
{
void *buffer;
buffer = xmalloc (nbytes);
do_randomize (buffer, nbytes, level);
return buffer;
}
/* The public function to return random data of the quality LEVEL;
this version of the function returns the random in a buffer allocated
in secure memory. Caller must free the buffer. */
void *
_gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
{
void *buffer;
/* Historical note (1.3.0--1.4.1): The buffer was only allocated
in secure memory if the pool in random-csprng.c was also set to
use secure memory. */
buffer = xmalloc_secure (nbytes);
do_randomize (buffer, nbytes, level);
return buffer;
}
/* Public function to fill the buffer with LENGTH bytes of
cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
not very strong, GCRY_STRONG_RANDOM is strong enough for most
usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
may be very slow. */
void
_gcry_randomize (void *buffer, size_t length, enum gcry_random_level level)
{
do_randomize (buffer, length, level);
}
/* This function may be used to specify the file to be used as a seed
file for the PRNG. This function should be called prior to the
initialization of the random module. NAME may not be NULL. */
void
_gcry_set_random_seed_file (const char *name)
{
if (fips_mode ())
; /* No need for this in fips mode. */
else if (rng_types.standard)
_gcry_rngcsprng_set_seed_file (name);
else if (rng_types.fips)
;
else if (rng_types.system)
;
else /* default */
_gcry_rngcsprng_set_seed_file (name);
}
/* If a seed file has been setup, this function may be used to write
back the random numbers entropy pool. */
void
_gcry_update_random_seed_file (void)
{
if (fips_mode ())
; /* No need for this in fips mode. */
else if (rng_types.standard)
_gcry_rngcsprng_update_seed_file ();
else if (rng_types.fips)
;
else if (rng_types.system)
;
else /* default */
_gcry_rngcsprng_update_seed_file ();
}
/* The fast random pool function as called at some places in
libgcrypt. This is merely a wrapper to make sure that this module
is initialized and to lock the pool. Note, that this function is a
NOP unless a random function has been used or _gcry_initialize (1)
has been used. We use this hack so that the internal use of this
function in cipher_open and md_open won't start filling up the
random pool, even if no random will be required by the process. */
void
_gcry_fast_random_poll (void)
{
if (fips_mode ())
; /* No need for this in fips mode. */
else if (rng_types.standard)
_gcry_rngcsprng_fast_poll ();
else if (rng_types.fips)
;
else if (rng_types.system)
;
else /* default */
_gcry_rngcsprng_fast_poll ();
}
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void
_gcry_create_nonce (void *buffer, size_t length)
{
static unsigned char nonce_buffer[20+8];
static int nonce_buffer_initialized = 0;
static volatile pid_t my_pid; /* The volatile is there to make sure the
compiler does not optimize the code away
in case the getpid function is badly
attributed. */
volatile pid_t apid;
unsigned char *p;
size_t n;
int err;
/* First check whether we shall use the FIPS nonce generator. This
is only done in FIPS mode, in all other modes, we use our own
nonce generator which is seeded by the RNG actual in use. */
if (fips_mode ())
{
_gcry_rngdrbg_randomize (buffer, length, GCRY_WEAK_RANDOM);
return;
}
/* This is the nonce generator, which formerly lived in
random-csprng.c. It is now used by all RNG types except when in
FIPS mode (not that this means it is also used if the FIPS RNG
has been selected but we are not in fips mode). */
/* Make sure we are initialized. */
_gcry_random_initialize (1);
/* Acquire the nonce buffer lock. */
err = gpgrt_lock_lock (&nonce_buffer_lock);
if (err)
log_fatal ("failed to acquire the nonce buffer lock: %s\n",
gpg_strerror (err));
apid = getpid ();
/* The first time initialize our buffer. */
if (!nonce_buffer_initialized)
{
time_t atime = time (NULL);
pid_t xpid = apid;
my_pid = apid;
if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
BUG ();
/* Initialize the first 20 bytes with a reasonable value so that
a failure of gcry_randomize won't affect us too much. Don't
care about the uninitialized remaining bytes. */
p = nonce_buffer;
memcpy (p, &xpid, sizeof xpid);
p += sizeof xpid;
memcpy (p, &atime, sizeof atime);
/* Initialize the never changing private part of 64 bits. */
_gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
nonce_buffer_initialized = 1;
}
else if ( my_pid != apid )
{
/* We forked. Need to reseed the buffer - doing this for the
private part should be sufficient. */
do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
/* Update the pid so that we won't run into here again and
again. */
my_pid = apid;
}
/* Create the nonce by hashing the entire buffer, returning the hash
and updating the first 20 bytes of the buffer with this hash. */
for (p = buffer; length > 0; length -= n, p += n)
{
_gcry_sha1_hash_buffer (nonce_buffer,
nonce_buffer, sizeof nonce_buffer);
n = length > 20? 20 : length;
memcpy (p, nonce_buffer, n);
}
/* Release the nonce buffer lock. */
err = gpgrt_lock_unlock (&nonce_buffer_lock);
if (err)
log_fatal ("failed to release the nonce buffer lock: %s\n",
gpg_strerror (err));
}
/* Run the self-tests for the RNG. This is currently only implemented
for the FIPS generator. */
gpg_error_t
_gcry_random_selftest (selftest_report_func_t report)
{
if (fips_mode ())
return _gcry_rngdrbg_selftest (report);
else
return 0; /* No selftests yet. */
}
diff --git a/random/rndhw.c b/random/rndhw.c
index 2829382c..b67f227e 100644
--- a/random/rndhw.c
+++ b/random/rndhw.c
@@ -1,221 +1,221 @@
/* rndhw.c - Access to the external random daemon
* Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright (C) 2012 Dmitry Kasatkin
*
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "g10lib.h"
#include "rand-internal.h"
#undef USE_PADLOCK
#ifdef ENABLE_PADLOCK_SUPPORT
# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)
# define USE_PADLOCK 1
# endif
# endif
#endif /*ENABLE_PADLOCK_SUPPORT*/
#undef USE_DRNG
#ifdef ENABLE_DRNG_SUPPORT
# ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
# if (defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)
# define USE_DRNG 1
# endif
# endif
#endif /*ENABLE_RDRAND_SUPPORT*/
typedef void (*add_fn_t)(const void*, size_t, enum random_origins);
/* Keep track on whether the RNG has problems. */
static volatile int rng_failed;
#ifdef USE_PADLOCK
static size_t
poll_padlock (void (*add)(const void*, size_t, enum random_origins),
enum random_origins origin, int fast)
{
volatile char buffer[64+8] __attribute__ ((aligned (8)));
volatile char *p;
unsigned int nbytes, status;
/* Peter Gutmann's cryptlib tests again whether the RNG is enabled
but we don't do so. We would have to do this also for our AES
implementation and that is definitely too time consuming. There
would be a race condition anyway. Thus we assume that the OS
does not change the Padlock initialization while a user process
is running. */
p = buffer;
nbytes = 0;
while (nbytes < 64)
{
#if defined(__x86_64__) && SIZEOF_VOID_P == 8
asm volatile
("movq %1, %%rdi\n\t" /* Set buffer. */
"xorq %%rdx, %%rdx\n\t" /* Request up to 8 bytes. */
".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */
: "=a" (status)
: "g" (p)
: "%rdx", "%rdi", "cc", "memory"
);
#else
asm volatile
("movl %1, %%edi\n\t" /* Set buffer. */
"xorl %%edx, %%edx\n\t" /* Request up to 8 bytes. */
".byte 0x0f, 0xa7, 0xc0\n\t" /* XSTORE RNG. */
: "=a" (status)
: "g" (p)
: "%edx", "%edi", "cc", "memory"
);
#endif
if ((status & (1<<6)) /* RNG still enabled. */
&& !(status & (1<<13)) /* von Neumann corrector is enabled. */
&& !(status & (1<<14)) /* String filter is disabled. */
&& !(status & 0x1c00) /* BIAS voltage at default. */
&& (!(status & 0x1f) || (status & 0x1f) == 8) /* Sanity check. */
)
{
nbytes += (status & 0x1f);
if (fast)
break; /* Don't get into the loop with the fast flag set. */
p += (status & 0x1f);
}
else
{
/* If there was an error we need to break the loop and
record that there is something wrong with the padlock
RNG. */
rng_failed = 1;
break;
}
}
if (nbytes)
{
(*add) ((void*)buffer, nbytes, origin);
wipememory (buffer, nbytes);
}
return nbytes;
}
#endif /*USE_PADLOCK*/
#ifdef USE_DRNG
# define RDRAND_RETRY_LOOPS 10
# define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
# if defined(__x86_64__) && SIZEOF_UNSIGNED_LONG == 8
# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
# else
# define RDRAND_LONG RDRAND_INT
# endif
static inline int
rdrand_long (volatile unsigned long *v)
{
int ok;
asm volatile ("1: " RDRAND_LONG "\n\t"
"jc 2f\n\t"
"decl %0\n\t"
"jnz 1b\n\t"
"2:"
: "=r" (ok), "=a" (*v)
: "0" (RDRAND_RETRY_LOOPS)
: "cc", "memory");
return ok;
}
static inline int
rdrand_nlong (volatile unsigned long *v, int count)
{
while (count--)
if (!rdrand_long(v++))
return 0;
return 1;
}
static size_t
poll_drng (add_fn_t add, enum random_origins origin, int fast)
{
volatile unsigned long buffer[8] __attribute__ ((aligned (8)));
unsigned int nbytes = sizeof (buffer);
(void)fast;
if (!rdrand_nlong (buffer, DIM(buffer)))
return 0;
(*add)((void *)buffer, nbytes, origin);
return nbytes;
}
#endif /*USE_DRNG*/
int
_gcry_rndhw_failed_p (void)
{
return rng_failed;
}
/* Try to read random from a hardware RNG if a fast one is
available. */
void
_gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins),
enum random_origins origin)
{
(void)add;
(void)origin;
#ifdef USE_DRNG
if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
poll_drng (add, origin, 1);
#endif
#ifdef USE_PADLOCK
if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
poll_padlock (add, origin, 1);
#endif
}
/* Read 64 bytes from a hardware RNG and return the number of bytes
actually read. */
size_t
_gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins),
enum random_origins origin)
{
size_t nbytes = 0;
(void)add;
(void)origin;
#ifdef USE_DRNG
if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
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
return nbytes;
}
diff --git a/random/rndlinux.c b/random/rndlinux.c
index 04e2a464..e9924335 100644
--- a/random/rndlinux.c
+++ b/random/rndlinux.c
@@ -1,365 +1,365 @@
/* rndlinux.c - raw random number for OSes with /dev/random
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#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_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"
#include "g10lib.h"
#include "rand-internal.h"
static int open_device (const char *name, int retry);
static int
set_cloexec_flag (int fd)
{
int oldflags;
oldflags= fcntl (fd, F_GETFD, 0);
if (oldflags < 0)
return oldflags;
oldflags |= FD_CLOEXEC;
return fcntl (fd, F_SETFD, oldflags);
}
/*
* Used to open the /dev/random devices (Linux, xBSD, Solaris (if it
* exists)). If RETRY is true, the function does not terminate with
* a fatal error but retries until it is able to reopen the device.
*/
static int
open_device (const char *name, int retry)
{
int fd;
if (retry)
_gcry_random_progress ("open_dev_random", 'X', 1, 0);
again:
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);
goto again;
}
if (fd == -1)
log_fatal ("can't open %s: %s\n", name, strerror(errno) );
if (set_cloexec_flag (fd))
log_error ("error setting FD_CLOEXEC on fd %d: %s\n",
fd, strerror (errno));
/* We used to do the following check, however it turned out that this
is not portable since more OSes provide a random device which is
sometimes implemented as another device type.
struct stat sb;
if( fstat( fd, &sb ) )
log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
log_fatal("invalid random device!\n" );
*/
return fd;
}
/* Note that the caller needs to make sure that this function is only
* called by one thread at a time. The function returns 0 on success
* or true on failure (in which case the caller will signal a fatal
* 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 )
{
static int fd_urandom = -1;
static int fd_random = -1;
static int only_urandom = -1;
static unsigned char ever_opened;
static volatile pid_t my_pid; /* The volatile is there to make sure
* the compiler does not optimize the
* code away in case the getpid
* function is badly attributed. */
volatile pid_t apid;
int fd;
int n;
byte buffer[768];
size_t n_hw;
size_t want = length;
size_t last_so_far = 0;
int any_need_entropy = 0;
int delay;
/* On the first call read the conf file to check whether we want to
* use only urandom. */
if (only_urandom == -1)
{
my_pid = getpid ();
if ((_gcry_random_read_conf () & RANDOM_CONF_ONLY_URANDOM))
only_urandom = 1;
else
only_urandom = 0;
}
if (!add)
{
/* Special mode to close the descriptors. */
if (fd_random != -1)
{
close (fd_random);
fd_random = -1;
}
if (fd_urandom != -1)
{
close (fd_urandom);
fd_urandom = -1;
}
_gcry_rndjent_fini ();
return 0;
}
/* Detect a fork and close the devices so that we don't use the old
* file descriptors. Note that open_device will be called in retry
* mode if the devices was opened by the parent process. */
apid = getpid ();
if (my_pid != apid)
{
if (fd_random != -1)
{
close (fd_random);
fd_random = -1;
}
if (fd_urandom != -1)
{
close (fd_urandom);
fd_urandom = -1;
}
my_pid = apid;
}
/* 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;
}
if (length > 1)
length -= n_hw;
/* 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)
{
n_hw = _gcry_rndjent_poll (add, origin, length/2);
if (n_hw > length/2)
n_hw = length/2;
if (length > 1)
length -= n_hw;
}
/* Open the requested device. The first time a device is to be
opened we fail with a fatal error if the device does not exists.
In case the device has ever been closed, further open requests
will however retry indefinitely. The rationale for this behaviour is
that we always require the device to be existent but want a more
graceful behaviour if the rarely needed close operation has been
used and the device needs to be re-opened later. */
if (level >= GCRY_VERY_STRONG_RANDOM && !only_urandom)
{
if (fd_random == -1)
{
fd_random = open_device (NAME_OF_DEV_RANDOM, (ever_opened & 1));
ever_opened |= 1;
}
fd = fd_random;
}
else
{
if (fd_urandom == -1)
{
fd_urandom = open_device (NAME_OF_DEV_URANDOM, (ever_opened & 2));
ever_opened |= 2;
}
fd = fd_urandom;
}
/* Enter the read loop. */
delay = 0; /* Start with 0 seconds so that we do no block on the
first iteration and in turn call the progress function
before blocking. To give the OS a better chance to
return with something we will actually use 100ms. */
while (length)
{
fd_set rfds;
struct timeval tv;
int rc;
/* 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. */
#if defined(HAVE_GETENTROPY) || defined(__NR_getrandom)
{
long ret;
size_t nbytes;
do
{
nbytes = length < sizeof(buffer)? length : sizeof(buffer);
if (nbytes > 256)
nbytes = 256;
_gcry_pre_syscall ();
ret = getentropy (buffer, nbytes);
_gcry_post_syscall ();
}
while (ret == -1 && errno == EINTR);
if (ret == -1 && errno == ENOSYS)
; /* getentropy is not supported - fallback to pulling from fd. */
else
{ /* getentropy is supported. Some sanity checks. */
if (ret == -1)
log_fatal ("unexpected error from getentropy: %s\n",
strerror (errno));
#ifdef __NR_getrandom
else if (ret != nbytes)
log_fatal ("getentropy returned only"
" %ld of %zu requested bytes\n", ret, nbytes);
#endif
(*add)(buffer, nbytes, origin);
length -= nbytes;
continue; /* until LENGTH is zero. */
}
}
#endif
/* If we collected some bytes update the progress indicator. We
do this always and not just if the select timed out because
often just a few bytes are gathered within the timeout
period. */
if (any_need_entropy || last_so_far != (want - length) )
{
last_so_far = want - length;
_gcry_random_progress ("need_entropy", 'X',
(int)last_so_far, (int)want);
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
{
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;
}
}
do
{
size_t nbytes;
nbytes = length < sizeof(buffer)? length : sizeof(buffer);
n = read (fd, buffer, nbytes);
if (n >= 0 && n > nbytes)
{
log_error("bogus read from random device (n=%d)\n", n );
n = nbytes;
}
}
while (n == -1 && errno == EINTR);
if (n == -1)
log_fatal("read error on random device: %s\n", strerror(errno));
(*add)(buffer, n, origin);
length -= n;
}
wipememory (buffer, sizeof buffer);
if (any_need_entropy)
_gcry_random_progress ("need_entropy", 'X', (int)want, (int)want);
return 0; /* success */
}
diff --git a/random/rndw32ce.c b/random/rndw32ce.c
index b485eef2..9cd19082 100644
--- a/random/rndw32ce.c
+++ b/random/rndw32ce.c
@@ -1,199 +1,199 @@
/* rndw32ce.c - W32CE entropy gatherer
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <windows.h>
#include <wincrypt.h>
#include "types.h"
#include "g10lib.h"
#include "rand-internal.h"
/* The Microsoft docs say that it is suggested to see the buffer with
some extra random. We do this, despite that it is a questionable
suggestion as the OS as better means of collecting entropy than an
application. */
static size_t filler_used;
static size_t filler_length;
static unsigned char *filler_buffer;
static void
filler (const void *data, size_t datalen, enum random_origins dummy)
{
(void)dummy;
if (filler_used + datalen > filler_length)
datalen = filler_length - filler_used;
memcpy (filler_buffer + filler_used, data, datalen);
filler_used += datalen;
}
static void
fillup_buffer (unsigned char *buffer, size_t length)
{
filler_used = 0;
filler_length = length;
filler_buffer = buffer;
while (filler_used < length)
_gcry_rndw32ce_gather_random_fast (filler, 0);
}
int
_gcry_rndw32ce_gather_random (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level )
{
HCRYPTPROV prov;
unsigned char buffer [256];
DWORD buflen;
if (!level)
return 0;
/* Note that LENGTH is not really important because the caller
checks the returned lengths and calls this function until it
feels that enough entropy has been gathered. */
buflen = sizeof buffer;
if (length+8 < buflen)
buflen = length+8; /* Return a bit more than requested. */
if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ());
else
{
fillup_buffer (buffer, buflen);
if (!CryptGenRandom (prov, buflen, buffer))
log_debug ("CryptGenRandom(%d) failed: rc=%d\n",
(int)buflen, (int)GetLastError ());
else
(*add) (buffer, buflen, origin);
CryptReleaseContext (prov, 0);
wipememory (buffer, sizeof buffer);
}
return 0;
}
void
_gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin)
{
/* Add word sized values. */
{
# define ADD(t,f) do { \
t along = (f); \
memcpy (bufptr, &along, sizeof (along)); \
bufptr += sizeof (along); \
} while (0)
unsigned char buffer[20*sizeof(ulong)], *bufptr;
bufptr = buffer;
ADD (HWND, GetActiveWindow ());
ADD (HWND, GetCapture ());
ADD (HWND, GetClipboardOwner ());
ADD (HANDLE, GetCurrentProcess ());
ADD (DWORD, GetCurrentProcessId ());
ADD (HANDLE, GetCurrentThread ());
ADD (DWORD, GetCurrentThreadId ());
ADD (HWND, GetDesktopWindow ());
ADD (HWND, GetFocus ());
ADD (DWORD, GetMessagePos ());
ADD (HWND, GetOpenClipboardWindow ());
ADD (HWND, GetProcessHeap ());
ADD (DWORD, GetQueueStatus (QS_ALLEVENTS));
ADD (DWORD, GetTickCount ());
gcry_assert ( bufptr-buffer < sizeof (buffer) );
(*add) ( buffer, bufptr-buffer, origin );
# undef ADD
}
/* Get multiword system information: Current caret position, current
mouse cursor position. */
{
POINT point;
GetCaretPos (&point);
(*add) ( &point, sizeof (point), origin );
GetCursorPos (&point);
(*add) ( &point, sizeof (point), origin );
}
/* Get percent of memory in use, bytes of physical memory, bytes of
free physical memory, bytes in paging file, free bytes in paging
file, user bytes of address space, and free user bytes. */
{
MEMORYSTATUS memoryStatus;
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus (&memoryStatus);
(*add) ( &memoryStatus, sizeof (memoryStatus), origin );
}
/* Get thread and process creation time, exit time, time in kernel
mode, and time in user mode in 100ns intervals. */
{
HANDLE handle;
FILETIME creationTime, exitTime, kernelTime, userTime;
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
}
/* In case the OEM provides a high precision timer get this. If
none is available the default implementation returns the
GetTickCount. */
{
LARGE_INTEGER performanceCount;
if (QueryPerformanceCounter (&performanceCount))
(*add) (&performanceCount, sizeof (performanceCount), origin);
}
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 82d6e8a0..94c94e36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,162 +1,162 @@
# 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/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
## 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 libgcrypt.pc.in
bin_SCRIPTS = libgcrypt-config
m4datadir = $(datadir)/aclocal
m4data_DATA = libgcrypt.m4
nodist_include_HEADERS = gcrypt.h
lib_LTLIBRARIES = libgcrypt.la
bin_PROGRAMS = dumpsexp hmac256 mpicalc
if USE_RANDOM_DAEMON
sbin_PROGRAMS = gcryptrnd
bin_PROGRAMS += getrandom
endif USE_RANDOM_DAEMON
# Depending on the architecture some targets require libgpg-error.
if HAVE_W32CE_SYSTEM
arch_gpg_error_cflags = $(GPG_ERROR_CFLAGS)
arch_gpg_error_libs = $(GPG_ERROR_LIBS)
else
arch_gpg_error_cflags =
arch_gpg_error_libs =
endif
AM_CFLAGS = $(GPG_ERROR_CFLAGS)
AM_CCASFLAGS = $(NOEXECSTACK_FLAGS)
if HAVE_LD_VERSION_SCRIPT
libgcrypt_version_script_cmd = -Wl,--version-script=$(srcdir)/libgcrypt.vers
else
libgcrypt_version_script_cmd =
endif
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@
if HAVE_W32_SYSTEM
RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(libgcrypt_la_CPPFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS)
LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
SUFFIXES = .rc .lo
.rc.lo:
$(LTRCCOMPILE) -i "$<" -o "$@"
gcrypt_res = versioninfo.lo
no_undefined = -no-undefined
export_symbols = -export-symbols $(srcdir)/libgcrypt.def
extra_ltoptions = -XCClinker -static-libgcc
install-def-file:
-$(INSTALL) -d $(DESTDIR)$(libdir)
$(INSTALL) $(srcdir)/libgcrypt.def $(DESTDIR)$(libdir)/libgcrypt.def
uninstall-def-file:
-rm $(DESTDIR)$(libdir)/libgcrypt.def
gcrypt_deps = $(gcrypt_res) libgcrypt.def
else !HAVE_W32_SYSTEM
gcrypt_res =
gcrypt_res_ldflag =
no_undefined =
export_symbols =
extra_ltoptions =
install-def-file:
uninstall-def-file:
gcrypt_deps =
endif !HAVE_W32_SYSTEM
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)
if USE_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
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/cipher-proto.h b/src/cipher-proto.h
index 97eb0d9a..7cd3d273 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -1,276 +1,276 @@
/* cipher-proto.h - Internal declarations
* Copyright (C) 2008, 2011 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* This file has been factored out from cipher.h so that it can be
used standalone in visibility.c . */
#ifndef G10_CIPHER_PROTO_H
#define G10_CIPHER_PROTO_H
enum pk_encoding;
/* Definition of a function used to report selftest failures.
DOMAIN is a string describing the function block:
"cipher", "digest", "pubkey or "random",
ALGO is the algorithm under test,
WHAT is a string describing what has been tested,
DESC is a string describing the error. */
typedef void (*selftest_report_func_t)(const char *domain,
int algo,
const char *what,
const char *errdesc);
/* Definition of the selftest functions. */
typedef gpg_err_code_t (*selftest_func_t)
(int algo, int extended, selftest_report_func_t report);
/*
*
* Public key related definitions.
*
*/
/* Type for the pk_generate function. */
typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms,
gcry_sexp_t *r_skey);
/* Type for the pk_check_secret_key function. */
typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms);
/* Type for the pk_encrypt function. */
typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph,
gcry_sexp_t s_data,
gcry_sexp_t keyparms);
/* Type for the pk_decrypt function. */
typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain,
gcry_sexp_t s_data,
gcry_sexp_t keyparms);
/* Type for the pk_sign function. */
typedef gcry_err_code_t (*gcry_pk_sign_t) (gcry_sexp_t *r_sig,
gcry_sexp_t s_data,
gcry_sexp_t keyparms);
/* Type for the pk_verify function. */
typedef gcry_err_code_t (*gcry_pk_verify_t) (gcry_sexp_t s_sig,
gcry_sexp_t s_data,
gcry_sexp_t keyparms);
/* Type for the pk_get_nbits function. */
typedef unsigned (*gcry_pk_get_nbits_t) (gcry_sexp_t keyparms);
/* The type used to compute the keygrip. */
typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md,
gcry_sexp_t keyparm);
/* The type used to query an ECC curve name. */
typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator,
unsigned int *r_nbits);
/* The type used to query ECC curve parameters by name. */
typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name);
/* Module specification structure for public key algorithms. */
typedef struct gcry_pk_spec
{
int algo;
struct {
unsigned int disabled:1;
unsigned int fips:1;
} flags;
int use;
const char *name;
const char **aliases;
const char *elements_pkey;
const char *elements_skey;
const char *elements_enc;
const char *elements_sig;
const char *elements_grip;
gcry_pk_generate_t generate;
gcry_pk_check_secret_key_t check_secret_key;
gcry_pk_encrypt_t encrypt;
gcry_pk_decrypt_t decrypt;
gcry_pk_sign_t sign;
gcry_pk_verify_t verify;
gcry_pk_get_nbits_t get_nbits;
selftest_func_t selftest;
pk_comp_keygrip_t comp_keygrip;
pk_get_curve_t get_curve;
pk_get_curve_param_t get_curve_param;
} gcry_pk_spec_t;
/*
*
* Symmetric cipher related definitions.
*
*/
/* Type for the cipher_setkey function. */
typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
const unsigned char *key,
unsigned keylen,
gcry_cipher_hd_t hd);
/* Type for the cipher_encrypt function. */
typedef unsigned int (*gcry_cipher_encrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf);
/* Type for the cipher_decrypt function. */
typedef unsigned int (*gcry_cipher_decrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf);
/* Type for the cipher_stencrypt function. */
typedef void (*gcry_cipher_stencrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf,
size_t n);
/* Type for the cipher_stdecrypt function. */
typedef void (*gcry_cipher_stdecrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf,
size_t n);
/* The type used to convey additional information to a cipher. */
typedef gpg_err_code_t (*cipher_set_extra_info_t)
(void *c, int what, const void *buffer, size_t buflen);
/* The type used to set an IV directly in the algorithm module. */
typedef void (*cipher_setiv_func_t)(void *c, const byte *iv, size_t ivlen);
/* A structure to map OIDs to encryption modes. */
typedef struct gcry_cipher_oid_spec
{
const char *oid;
int mode;
} gcry_cipher_oid_spec_t;
/* Module specification structure for ciphers. */
typedef struct gcry_cipher_spec
{
int algo;
struct {
unsigned int disabled:1;
unsigned int fips:1;
} flags;
const char *name;
const char **aliases;
gcry_cipher_oid_spec_t *oids;
size_t blocksize;
size_t keylen;
size_t contextsize;
gcry_cipher_setkey_t setkey;
gcry_cipher_encrypt_t encrypt;
gcry_cipher_decrypt_t decrypt;
gcry_cipher_stencrypt_t stencrypt;
gcry_cipher_stdecrypt_t stdecrypt;
selftest_func_t selftest;
cipher_set_extra_info_t set_extra_info;
cipher_setiv_func_t setiv;
} gcry_cipher_spec_t;
/*
*
* Message digest related definitions.
*
*/
/* Type for the md_init function. */
typedef void (*gcry_md_init_t) (void *c, unsigned int flags);
/* Type for the md_write function. */
typedef void (*gcry_md_write_t) (void *c, const void *buf, size_t nbytes);
/* Type for the md_final function. */
typedef void (*gcry_md_final_t) (void *c);
/* Type for the md_read function. */
typedef unsigned char *(*gcry_md_read_t) (void *c);
/* Type for the md_extract function. */
typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes);
/* Type for the md_hash_buffer function. */
typedef void (*gcry_md_hash_buffer_t) (void *outbuf, const void *buffer,
size_t length);
/* Type for the md_hash_buffers function. */
typedef void (*gcry_md_hash_buffers_t) (void *outbuf, const gcry_buffer_t *iov,
int iovcnt);
typedef struct gcry_md_oid_spec
{
const char *oidstring;
} gcry_md_oid_spec_t;
/* Module specification structure for message digests. */
typedef struct gcry_md_spec
{
int algo;
struct {
unsigned int disabled:1;
unsigned int fips:1;
} flags;
const char *name;
unsigned char *asnoid;
int asnlen;
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_buffer_t hash_buffer;
gcry_md_hash_buffers_t hash_buffers;
size_t contextsize; /* allocate this amount of context */
selftest_func_t selftest;
} gcry_md_spec_t;
/* The selftest functions. */
gcry_error_t _gcry_cipher_selftest (int algo, int extended,
selftest_report_func_t report);
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_random_selftest (selftest_report_func_t report);
#endif /*G10_CIPHER_PROTO_H*/
diff --git a/src/context.c b/src/context.c
index f77878bc..68b4ecc2 100644
--- a/src/context.c
+++ b/src/context.c
@@ -1,137 +1,137 @@
/* context.c - Context management
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "g10lib.h"
#include "mpi.h"
#include "context.h"
#define CTX_MAGIC "cTx"
#define CTX_MAGIC_LEN 3
/* The definition of the generic context object. The public typedef
gcry_ctx_t is used to access it. */
struct gcry_context
{
char magic[CTX_MAGIC_LEN]; /* Magic value to cross check that this
is really a context object. */
char type; /* The type of the context (CONTEXT_TYPE_foo). */
void (*deinit)(void*); /* Function used to free the private part. */
PROPERLY_ALIGNED_TYPE u;
};
/* Allocate a fresh generic context of contect TYPE and allocate
LENGTH extra bytes for private use of the type handler. DEINIT is a
function used called to deinitialize the private part; it may be
NULL if de-initialization is not required. Returns NULL and sets
ERRNO if memory allocation failed. */
gcry_ctx_t
_gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*))
{
gcry_ctx_t ctx;
switch (type)
{
case CONTEXT_TYPE_EC:
break;
default:
log_bug ("bad context type %d given to _gcry_ctx_alloc\n", type);
break;
}
if (length < sizeof (PROPERLY_ALIGNED_TYPE))
length = sizeof (PROPERLY_ALIGNED_TYPE);
ctx = xtrycalloc (1, sizeof *ctx - sizeof (PROPERLY_ALIGNED_TYPE) + length);
if (!ctx)
return NULL;
memcpy (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN);
ctx->type = type;
ctx->deinit = deinit;
return ctx;
}
/* Return a pointer to the private part of the context CTX. TYPE is
the requested context type. Using an explicit type allows to cross
check the type and eventually allows to store several private
contexts in one context object. The function does not return an
error but aborts if the provided CTX is not valid. */
void *
_gcry_ctx_get_pointer (gcry_ctx_t ctx, int type)
{
if (!ctx || memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
if (ctx->type != type)
log_fatal ("wrong context type %d request for context %p of type %d\n",
type, ctx, ctx->type);
return &ctx->u;
}
/* Return a pointer to the private part of the context CTX. TYPE is
the requested context type. Using an explicit type allows to cross
check the type and eventually allows to store several private
contexts in one context object. In contrast to
_gcry_ctx_get_pointer, this function returns NULL if no context for
the given type was found. If CTX is NULL the function does not
abort but returns NULL. */
void *
_gcry_ctx_find_pointer (gcry_ctx_t ctx, int type)
{
if (!ctx)
return NULL;
if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
if (ctx->type != type)
return NULL;
return &ctx->u;
}
/* Release the generic context CTX. */
void
_gcry_ctx_release (gcry_ctx_t ctx)
{
if (!ctx)
return;
if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
log_fatal ("bad pointer %p passed to gcry_ctx_relase\n", ctx);
switch (ctx->type)
{
case CONTEXT_TYPE_EC:
break;
default:
log_fatal ("bad context type %d detected in gcry_ctx_relase\n",
ctx->type);
break;
}
if (ctx->deinit)
ctx->deinit (&ctx->u);
xfree (ctx);
}
diff --git a/src/context.h b/src/context.h
index 875de243..84614179 100644
--- a/src/context.h
+++ b/src/context.h
@@ -1,32 +1,32 @@
/* context.h - Declarations for the context management
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_CONTEXT_H
#define GCRY_CONTEXT_H
/* Context types as used in struct gcry_context. */
#define CONTEXT_TYPE_EC 1 /* The context is used with EC 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);
void *_gcry_ctx_find_pointer (gcry_ctx_t ctx, int type);
#endif /*GCRY_CONTEXT_H*/
diff --git a/src/dumpsexp.c b/src/dumpsexp.c
index 5aeb77df..cedf0625 100644
--- a/src/dumpsexp.c
+++ b/src/dumpsexp.c
@@ -1,767 +1,767 @@
/* dumpsexp.c - Dump S-expressions.
* Copyright (C) 2007, 2010 Free Software Foundation, Inc.
*
* 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 <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <errno.h>
/* For a native WindowsCE binary we need to include gpg-error.h to
provide a replacement for strerror. */
#ifdef __MINGW32CE__
# include <gpg-error.h>
#endif
#define PGM "dumpsexp"
#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
static int verbose; /* Verbose mode. */
static int decimal; /* Print addresses in decimal. */
static int assume_hex; /* Assume input is hexencoded. */
static int advanced; /* Advanced format output. */
static void
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"
+ "<https://gnu.org/licenses/gpl.html>\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);
if (with_help)
fputs ("\n"
"Usage: " PGM " [OPTIONS] [file]\n"
"Debug tool for S-expressions\n"
"\n"
" --decimal Print offsets using decimal notation\n"
" --assume-hex Assume input is a hex dump\n"
" --advanced Print file in advanced format\n"
" --verbose Show what we are doing\n"
" --version Print version of the program and exit\n"
" --help Display this help and exit\n"
BUGREPORT_LINE, stdout );
exit (0);
}
static int
print_usage (void)
{
fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr);
fputs (" (use --help to display options)\n", stderr);
exit (1);
}
#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
#define digit_p(a) ((a) >= '0' && (a) <= '9')
#define octdigit_p(a) ((a) >= '0' && (a) <= '7')
#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \
|| ((a) >= 'a' && (a) <= 'z'))
#define hexdigit_p(a) (digit_p (a) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'a' && (a) <= 'f'))
#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \
(a) <= 'F'? ((a)-'A'+10):((a)-'a'+10))
/* Return true if P points to a byte containing a whitespace according
to the S-expressions definition. */
static inline int
whitespace_p (int c)
{
switch (c)
{
case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
default: return 0;
}
}
static void
logit (const char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format) ;
fputs (PGM ": ", stderr);
vfprintf (stderr, format, arg_ptr);
putc ('\n', stderr);
va_end (arg_ptr);
}
/* The raw data buffer and its current length */
static unsigned char databuffer[16];
static int databufferlen;
/* The number of bytes in databuffer which should be skipped at a flush. */
static int skipdatabufferlen;
/* The number of raw bytes printed on the last line. */
static int nbytesprinted;
/* The file offset of the current data buffer . */
static unsigned long databufferoffset;
static int
my_getc (FILE *fp)
{
int c1, c2;
if (!assume_hex)
return getc (fp);
while ( (c1=getc (fp)) != EOF && space_p (c1) )
;
if (c1 == EOF)
return EOF;
if (!hexdigit_p (c1))
{
logit ("non hex-digit encountered\n");
return EOF;
}
while ( (c2=getc (fp)) != EOF && space_p (c2) )
;
if (c2 == EOF)
{
logit ("error reading second hex nibble\n");
return EOF;
}
if (!hexdigit_p (c2))
{
logit ("second hex nibble is not a hex-digit\n");
return EOF;
}
return xtoi_1 (c1) * 16 + xtoi_1 (c2);
}
/* Flush the raw data buffer. */
static void
flushdatabuffer (void)
{
int i;
if (!databufferlen)
return;
nbytesprinted = 0;
if (decimal)
printf ("%08lu ", databufferoffset);
else
printf ("%08lx ", databufferoffset);
for (i=0; i < databufferlen; i++)
{
if (i == 8)
putchar (' ');
if (i < skipdatabufferlen)
fputs (" ", stdout);
else
{
printf (" %02x", databuffer[i]);
databufferoffset++;
}
nbytesprinted++;
}
for (; i < sizeof (databuffer); i++)
{
if (i == 8)
putchar (' ');
fputs (" ", stdout);
}
fputs (" |", stdout);
for (i=0; i < databufferlen; i++)
{
if (i < skipdatabufferlen)
putchar (' ');
else if (databuffer[i] >= ' ' && databuffer[i] <= '~'
&& databuffer[i] != '|')
putchar (databuffer[i]);
else
putchar ('.');
}
putchar ('|');
putchar ('\n');
databufferlen = 0;
skipdatabufferlen = 0;
}
/* Add C to the raw data buffer and flush as needed. */
static void
addrawdata (int c)
{
if ( databufferlen >= sizeof databuffer )
flushdatabuffer ();
databuffer[databufferlen++] = c;
}
static void
printcursor (int both)
{
int i;
flushdatabuffer ();
printf ("%8s ", "");
for (i=0; i < sizeof (databuffer); i++)
{
if (i == 8)
putchar (' ');
if (i+1 == nbytesprinted)
{
fputs (" ^ ", stdout);
if (!both)
break;
}
else
fputs (" ", stdout);
}
if (both)
{
fputs (" ", stdout);
for (i=0; i < nbytesprinted-1; i++)
putchar (' ');
putchar ('^');
}
databufferlen = skipdatabufferlen = nbytesprinted;
}
static void
printerr (const char *text)
{
printcursor (1);
printf ("\n Error: %s\n", text);
}
static void
printctl (const char *text)
{
if (verbose && !advanced)
{
printcursor (0);
printf ("%s\n", text);
}
}
static void
printchr (int c)
{
putchar (c);
}
/* static void */
/* printhex (int c) */
/* { */
/* printf ("\\x%02x", c); */
/* } */
#if 0
/****************
* Print SEXP to buffer using the MODE. Returns the length of the
* SEXP in buffer or 0 if the buffer is too short (We have at least an
* empty list consisting of 2 bytes). If a buffer of NULL is provided,
* the required length is returned.
*/
size_t
gcry_sexp_sprint (const gcry_sexp_t list,
void *buffer, size_t maxlength )
{
static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
const unsigned char *s;
char *d;
DATALEN n;
char numbuf[20];
int i, indent = 0;
s = list? list->d : empty;
d = buffer;
while ( *s != ST_STOP )
{
switch ( *s )
{
case ST_OPEN:
s++;
if (indent)
putchar ('\n');
for (i=0; i < indent; i++)
putchar (' ');
putchar ('(');
indent++;
break;
case ST_CLOSE:
s++;
putchar (')');
indent--;
if (*s != ST_OPEN && *s != ST_STOP)
{
putchar ('\n');
for (i=0; i < indent; i++)
putchar (' ');
}
break;
case ST_DATA:
s++;
memcpy (&n, s, sizeof n);
s += sizeof n;
{
int type;
size_t nn;
switch ( (type=suitable_encoding (s, n)))
{
case 1: nn = convert_to_string (s, n, NULL); break;
case 2: nn = convert_to_token (s, n, NULL); break;
default: nn = convert_to_hex (s, n, NULL); break;
}
switch (type)
{
case 1: convert_to_string (s, n, d); break;
case 2: convert_to_token (s, n, d); break;
default: convert_to_hex (s, n, d); break;
}
d += nn;
if (s[n] != ST_CLOSE)
putchar (' ');
}
else
{
snprintf (numbuf, sizeof numbuf, "%u:", (unsigned int)n );
d = stpcpy (d, numbuf);
memcpy (d, s, n);
d += n;
}
s += n;
break;
default:
BUG ();
}
}
putchar ('\n');
return len;
}
#endif
/* Prepare for saving a chunk of data. */
static void
init_data (void)
{
}
/* Push C on the current data chunk. */
static void
push_data (int c)
{
(void)c;
}
/* Flush and thus print the current data chunk. */
static void
flush_data (void)
{
}
/* Returns 0 on success. */
static int
parse_and_print (FILE *fp)
{
static const char tokenchars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789-./_:*+=";
int c;
int level = 0;
int tokenc = 0;
int hexcount = 0;
int disphint = 0;
unsigned long datalen = 0;
char quote_buf[10];
int quote_idx = 0;
enum
{
INIT_STATE = 0, IN_NUMBER, PRE_DATA, IN_DATA, IN_STRING,
IN_ESCAPE, IN_OCT_ESC, IN_HEX_ESC,
CR_ESC, LF_ESC, IN_HEXFMT, IN_BASE64
}
state = INIT_STATE;
while ((c = my_getc (fp)) != EOF )
{
addrawdata (c);
switch (state)
{
case INIT_STATE:
if (tokenc)
{
if (strchr (tokenchars, c))
{
printchr (c);
continue;
}
tokenc = 0;
}
parse_init_state:
if (c == '(')
{
if (disphint)
{
printerr ("unmatched display hint");
disphint = 0;
}
printctl ("open");
level++;
}
else if (c == ')')
{
if (disphint)
{
printerr ("unmatched display hint");
disphint = 0;
}
printctl ("close");
level--;
}
else if (c == '\"')
{
state = IN_STRING;
printctl ("beginstring");
init_data ();
}
else if (c == '#')
{
state = IN_HEXFMT;
hexcount = 0;
printctl ("beginhex");
init_data ();
}
else if (c == '|')
{
state = IN_BASE64;
printctl ("beginbase64");
init_data ();
}
else if (c == '[')
{
if (disphint)
printerr ("nested display hint");
disphint = c;
}
else if (c == ']')
{
if (!disphint)
printerr ("no open display hint");
disphint = 0;
}
else if (c >= '0' && c <= '9')
{
if (c == '0')
printerr ("zero prefixed length");
state = IN_NUMBER;
datalen = (c - '0');
}
else if (strchr (tokenchars, c))
{
printchr (c);
tokenc = c;
}
else if (whitespace_p (c))
;
else if (c == '{')
{
printerr ("rescanning is not supported");
}
else if (c == '&' || c == '\\')
{
printerr ("reserved punctuation detected");
}
else
{
printerr ("bad character detected");
}
break;
case IN_NUMBER:
if (digit_p (c))
{
unsigned long tmp = datalen * 10 + (c - '0');
if (tmp < datalen)
{
printerr ("overflow in data length");
state = INIT_STATE;
datalen = 0;
}
else
datalen = tmp;
}
else if (c == ':')
{
if (!datalen)
{
printerr ("no data length");
state = INIT_STATE;
}
else
state = PRE_DATA;
}
else if (c == '\"' || c == '#' || c == '|' )
{
/* We ignore the optional length and divert to the init
state parser code. */
goto parse_init_state;
}
else
printerr ("invalid length specification");
break;
case PRE_DATA:
state = IN_DATA;
printctl ("begindata");
init_data ();
/* fall through */
case IN_DATA:
if (datalen)
{
push_data (c);
datalen--;
}
if (!datalen)
{
state = INIT_STATE;
printctl ("enddata");
flush_data ();
}
break;
case IN_STRING:
if (c == '\"')
{
printctl ("endstring");
flush_data ();
state = INIT_STATE;
}
else if (c == '\\')
state = IN_ESCAPE;
else
push_data (c);
break;
case IN_ESCAPE:
switch (c)
{
case 'b': push_data ('\b'); state = IN_STRING; break;
case 't': push_data ('\t'); state = IN_STRING; break;
case 'v': push_data ('\v'); state = IN_STRING; break;
case 'n': push_data ('\n'); state = IN_STRING; break;
case 'f': push_data ('\f'); state = IN_STRING; break;
case 'r': push_data ('\r'); state = IN_STRING; break;
case '"': push_data ('"'); state = IN_STRING; break;
case '\'': push_data ('\''); state = IN_STRING; break;
case '\\': push_data ('\\'); state = IN_STRING; break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
state = IN_OCT_ESC;
quote_idx = 0;
quote_buf[quote_idx++] = c;
break;
case 'x':
state = IN_HEX_ESC;
quote_idx = 0;
break;
case '\r':
state = CR_ESC;
break;
case '\n':
state = LF_ESC;
break;
default:
printerr ("invalid escape sequence");
state = IN_STRING;
break;
}
break;
case IN_OCT_ESC:
if (quote_idx < 3 && strchr ("01234567", c))
{
quote_buf[quote_idx++] = c;
if (quote_idx == 3)
{
push_data ((unsigned int)quote_buf[0] * 8 * 8
+ (unsigned int)quote_buf[1] * 8
+ (unsigned int)quote_buf[2]);
state = IN_STRING;
}
}
else
state = IN_STRING;
break;
case IN_HEX_ESC:
if (quote_idx < 2 && strchr ("0123456789abcdefABCDEF", c))
{
quote_buf[quote_idx++] = c;
if (quote_idx == 2)
{
push_data (xtoi_1 (quote_buf[0]) * 16
+ xtoi_1 (quote_buf[1]));
state = IN_STRING;
}
}
else
state = IN_STRING;
break;
case CR_ESC:
state = IN_STRING;
break;
case LF_ESC:
state = IN_STRING;
break;
case IN_HEXFMT:
if (hexdigit_p (c))
{
push_data (c);
hexcount++;
}
else if (c == '#')
{
if ((hexcount & 1))
printerr ("odd number of hex digits");
printctl ("endhex");
flush_data ();
state = INIT_STATE;
}
else if (!whitespace_p (c))
printerr ("bad hex character");
break;
case IN_BASE64:
if (c == '|')
{
printctl ("endbase64");
flush_data ();
state = INIT_STATE;
}
else
push_data (c);
break;
default:
logit ("invalid state %d detected", state);
exit (1);
}
}
flushdatabuffer ();
if (ferror (fp))
{
logit ("error reading input: %s\n", strerror (errno));
return -1;
}
return 0;
}
int
main (int argc, char **argv)
{
int rc;
if (argc)
{
argc--; argv++;
}
while (argc && **argv == '-' && (*argv)[1] == '-')
{
if (!(*argv)[2])
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version"))
print_version (0);
else if (!strcmp (*argv, "--help"))
print_version (1);
else if (!strcmp (*argv, "--verbose"))
{
argc--; argv++;
verbose = 1;
}
else if (!strcmp (*argv, "--decimal"))
{
argc--; argv++;
decimal = 1;
}
else if (!strcmp (*argv, "--assume-hex"))
{
argc--; argv++;
assume_hex = 1;
}
else if (!strcmp (*argv, "--advanced"))
{
argc--; argv++;
advanced = 1;
}
else
print_usage ();
}
if (!argc)
{
rc = parse_and_print (stdin);
}
else
{
rc = 0;
for (; argc; argv++, argc--)
{
FILE *fp = fopen (*argv, "rb");
if (!fp)
{
logit ("can't open `%s': %s\n", *argv, strerror (errno));
rc = 1;
}
else
{
if (parse_and_print (fp))
rc = 1;
fclose (fp);
}
}
}
return !!rc;
}
diff --git a/src/ec-context.h b/src/ec-context.h
index e48ef6f1..d95086a3 100644
--- a/src/ec-context.h
+++ b/src/ec-context.h
@@ -1,104 +1,104 @@
/* ec-context.h - Private definitions for CONTEXT_TYPE_EC.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_EC_CONTEXT_H
#define GCRY_EC_CONTEXT_H
/* This context is used with all our EC functions. */
struct mpi_ec_ctx_s
{
enum gcry_mpi_ec_models model; /* The model describing this curve. */
enum ecc_dialects dialect; /* The ECC dialect used with the curve. */
int flags; /* Public key flags (not always used). */
unsigned int nbits; /* Number of bits. */
/* Domain parameters. Note that they may not all be set and if set
the MPIs may be flaged as constant. */
gcry_mpi_t p; /* Prime specifying the field GF(p). */
gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */
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. */
/* The actual key. May not be set. */
gcry_mpi_point_t Q; /* Public key. */
gcry_mpi_t d; /* Private key. */
/* This structure is private to mpi/ec.c! */
struct {
struct {
unsigned int a_is_pminus3:1;
unsigned int two_inv_p:1;
} valid; /* Flags to help setting the helper vars below. */
int a_is_pminus3; /* True if A = P - 3. */
gcry_mpi_t two_inv_p;
mpi_barrett_t p_barrett;
/* Scratch variables. */
gcry_mpi_t scratch[11];
/* Helper for fast reduction. */
/* int nist_nbits; /\* If this is a NIST curve, the # of bits. *\/ */
/* 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);
};
/*-- mpi/ec.c --*/
void _gcry_mpi_ec_get_reset (mpi_ec_t ec);
/*-- cipher/ecc-curves.c --*/
gcry_mpi_t _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy);
gcry_mpi_point_t _gcry_ecc_get_point (const char *name, mpi_ec_t ec);
gpg_err_code_t _gcry_ecc_set_mpi (const char *name,
gcry_mpi_t newvalue, mpi_ec_t ec);
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_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx,
mpi_point_t result);
/*-- cipher/ecc-eddsa.c --*/
gpg_err_code_t _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx,
mpi_point_t result,
unsigned char **r_encpk,
unsigned int *r_encpklen);
#endif /*GCRY_EC_CONTEXT_H*/
diff --git a/src/fips.c b/src/fips.c
index 1ac7f477..dde761f1 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -1,856 +1,856 @@
/* fips.c - FIPS mode management
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef ENABLE_HMAC_BINARY_CHECK
# include <dlfcn.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"
/* The states of the finite state machine used in fips mode. */
enum module_states
{
/* POWEROFF cannot be represented. */
STATE_POWERON = 0,
STATE_INIT,
STATE_SELFTEST,
STATE_OPERATIONAL,
STATE_ERROR,
STATE_FATALERROR,
STATE_SHUTDOWN
};
/* Flag telling whether we are in fips mode. It uses inverse logic so
that fips mode is the default unless changed by the initialization
code. To check whether fips mode is enabled, use the function
fips_mode()! */
int _gcry_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;
/* This is the lock we use to protect the FSM. */
GPGRT_LOCK_DEFINE (fsm_lock);
/* The current state of the FSM. The whole state machinery is only
used while in fips mode. Change this only while holding fsm_lock. */
static enum module_states current_state;
static void fips_new_state (enum module_states new_state);
/* Convert lowercase hex digits; assumes valid hex digits. */
#define loxtoi_1(p) (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10))
#define loxtoi_2(p) ((loxtoi_1(p) * 16) + loxtoi_1((p)+1))
/* Returns true if P points to a lowercase hex digit. */
#define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p))
/* 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;
}
/* For testing the system it is useful to override the system
provided detection of the FIPS mode and force FIPS mode using a
file. The filename is hardwired so that there won't be any
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 (!_gcry_no_fips_mode_required);
goto leave;
}
/* Checking based on /proc file properties. */
{
static const char procfname[] = "/proc/sys/crypto/fips_enabled";
FILE *fp;
int saved_errno;
fp = fopen (procfname, "r");
if (fp)
{
char line[256];
if (fgets (line, sizeof line, fp) && atoi (line))
{
/* System is in fips mode. */
fclose (fp);
gcry_assert (!_gcry_no_fips_mode_required);
goto leave;
}
fclose (fp);
}
else if ((saved_errno = errno) != ENOENT
&& saved_errno != EACCES
&& !access ("/proc/version", F_OK) )
{
/* Problem reading the fips file despite that we have the proc
file system. We better stop right away. */
log_info ("FATAL: error reading `%s' in libgcrypt: %s\n",
procfname, strerror (saved_errno));
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"reading `%s' failed: %s - abort",
procfname, strerror (saved_errno));
#endif /*HAVE_SYSLOG*/
abort ();
}
}
/* Fips not not requested, set flag. */
_gcry_no_fips_mode_required = 1;
leave:
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);
if (err)
{
/* If that fails we can't do anything but abort the
process. We need to use log_info so that the FSM won't
get involved. */
log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
gpg_strerror (err));
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"creating FSM lock failed: %s - abort",
gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
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;
}
static void
lock_fsm (void)
{
gpg_error_t err;
err = gpgrt_lock_lock (&fsm_lock);
if (err)
{
log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n",
gpg_strerror (err));
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"acquiring FSM lock failed: %s - abort",
gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
abort ();
}
}
static void
unlock_fsm (void)
{
gpg_error_t err;
err = gpgrt_lock_unlock (&fsm_lock);
if (err)
{
log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n",
gpg_strerror (err));
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"releasing FSM lock failed: %s - abort",
gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
abort ();
}
}
/* Return a flag telling whether we are in the enforced fips mode. */
int
_gcry_enforced_fips_mode (void)
{
if (!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 (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 (!fips_mode ())
return 0;
lock_fsm ();
flag = inactive_fips_mode;
unlock_fsm ();
return flag;
}
static const char *
state2str (enum module_states state)
{
const char *s;
switch (state)
{
case STATE_POWERON: s = "Power-On"; break;
case STATE_INIT: s = "Init"; break;
case STATE_SELFTEST: s = "Self-Test"; break;
case STATE_OPERATIONAL: s = "Operational"; break;
case STATE_ERROR: s = "Error"; break;
case STATE_FATALERROR: s = "Fatal-Error"; break;
case STATE_SHUTDOWN: s = "Shutdown"; break;
default: s = "?"; break;
}
return s;
}
/* Return true if the library is in the operational state. */
int
_gcry_fips_is_operational (void)
{
int result;
if (!fips_mode ())
result = 1;
else
{
lock_fsm ();
if (current_state == STATE_INIT)
{
/* If we are still in the INIT state, we need to run the
selftests so that the FSM can eventually get into
operational state. Given that we would need a 2-phase
initialization of libgcrypt, but that has traditionally
not been enforced, we use this on demand self-test
checking. Note that Proper applications would do the
application specific libgcrypt initialization between a
gcry_check_version() and gcry_control
(GCRYCTL_INITIALIZATION_FINISHED) where the latter will
run the selftests. The drawback of these on-demand
self-tests are a small chance that self-tests are
performed by several threads; that is no problem because
our FSM make sure that we won't oversee any error. */
unlock_fsm ();
_gcry_fips_run_selftests (0);
lock_fsm ();
}
result = (current_state == STATE_OPERATIONAL);
unlock_fsm ();
}
return result;
}
/* This is test on whether the library is in the operational state. In
contrast to _gcry_fips_is_operational this function won't do a
state transition on the fly. */
int
_gcry_fips_test_operational (void)
{
int result;
if (!fips_mode ())
result = 1;
else
{
lock_fsm ();
result = (current_state == STATE_OPERATIONAL);
unlock_fsm ();
}
return result;
}
/* This is a test on whether the library is in the error or
operational state. */
int
_gcry_fips_test_error_or_operational (void)
{
int result;
if (!fips_mode ())
result = 1;
else
{
lock_fsm ();
result = (current_state == STATE_OPERATIONAL
|| current_state == STATE_ERROR);
unlock_fsm ();
}
return result;
}
static void
reporter (const char *domain, int algo, const char *what, const char *errtxt)
{
if (!errtxt && !_gcry_log_verbosity (2))
return;
log_info ("libgcrypt selftest: %s %s%s (%d): %s%s%s%s\n",
!strcmp (domain, "hmac")? "digest":domain,
!strcmp (domain, "hmac")? "HMAC-":"",
!strcmp (domain, "cipher")? _gcry_cipher_algo_name (algo) :
!strcmp (domain, "digest")? _gcry_md_algo_name (algo) :
!strcmp (domain, "hmac")? _gcry_md_algo_name (algo) :
!strcmp (domain, "pubkey")? _gcry_pk_algo_name (algo) : "",
algo, errtxt? errtxt:"Okay",
what?" (":"", what? what:"", what?")":"");
}
/* Run self-tests for all required cipher algorithms. Return 0 on
success. */
static int
run_cipher_selftests (int extended)
{
static int algos[] =
{
GCRY_CIPHER_3DES,
GCRY_CIPHER_AES128,
GCRY_CIPHER_AES192,
GCRY_CIPHER_AES256,
0
};
int idx;
gpg_error_t err;
int anyerr = 0;
for (idx=0; algos[idx]; idx++)
{
err = _gcry_cipher_selftest (algos[idx], extended, reporter);
reporter ("cipher", algos[idx], NULL,
err? gpg_strerror (err):NULL);
if (err)
anyerr = 1;
}
return anyerr;
}
/* Run self-tests for all required hash algorithms. Return 0 on
success. */
static int
run_digest_selftests (int extended)
{
static int algos[] =
{
GCRY_MD_SHA1,
GCRY_MD_SHA224,
GCRY_MD_SHA256,
GCRY_MD_SHA384,
GCRY_MD_SHA512,
0
};
int idx;
gpg_error_t err;
int anyerr = 0;
for (idx=0; algos[idx]; idx++)
{
err = _gcry_md_selftest (algos[idx], extended, reporter);
reporter ("digest", algos[idx], NULL,
err? gpg_strerror (err):NULL);
if (err)
anyerr = 1;
}
return anyerr;
}
/* Run self-tests for all HMAC algorithms. Return 0 on success. */
static int
run_hmac_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,
0
};
int idx;
gpg_error_t err;
int anyerr = 0;
for (idx=0; algos[idx]; idx++)
{
err = _gcry_hmac_selftest (algos[idx], extended, reporter);
reporter ("hmac", 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. */
static int
run_pubkey_selftests (int extended)
{
static int algos[] =
{
GCRY_PK_RSA,
GCRY_PK_DSA,
GCRY_PK_ECC,
0
};
int idx;
gpg_error_t err;
int anyerr = 0;
for (idx=0; algos[idx]; idx++)
{
err = _gcry_pk_selftest (algos[idx], extended, reporter);
reporter ("pubkey", algos[idx], NULL,
err? gpg_strerror (err):NULL);
if (err)
anyerr = 1;
}
return anyerr;
}
/* Run self-tests for the random number generator. Returns 0 on
success. */
static int
run_random_selftests (void)
{
gpg_error_t err;
err = _gcry_random_selftest (reporter);
reporter ("random", 0, NULL, err? gpg_strerror (err):NULL);
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?";
if (!dladdr ("gcry_check_version", &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);
#ifdef HAVE_SYSLOG
if (err)
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"integrity check using `%s' failed: %s",
fname? fname:"[?]", gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
xfree (fname);
return !!err;
#else
return 0;
#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
_gcry_fips_run_selftests (int extended)
{
enum module_states result = STATE_ERROR;
gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
if (fips_mode ())
fips_new_state (STATE_SELFTEST);
if (run_cipher_selftests (extended))
goto leave;
if (run_digest_selftests (extended))
goto leave;
if (run_hmac_selftests (extended))
goto leave;
/* Run random tests before the pubkey tests because the latter
require random. */
if (run_random_selftests ())
goto leave;
if (run_pubkey_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;
}
/* All selftests passed. */
result = STATE_OPERATIONAL;
ec = 0;
leave:
if (fips_mode ())
fips_new_state (result);
return ec;
}
/* This function is used to tell the FSM about errors in the library.
The FSM will be put into an error state. This function should not
be called directly but by one of the macros
fips_signal_error (description)
fips_signal_fatal_error (description)
where DESCRIPTION is a string describing the error. */
void
_gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc,
int is_fatal, const char *description)
{
if (!fips_mode ())
return; /* Not required. */
/* Set new state before printing an error. */
fips_new_state (is_fatal? STATE_FATALERROR : STATE_ERROR);
/* Print error. */
log_info ("%serror in libgcrypt, file %s, line %d%s%s: %s\n",
is_fatal? "fatal ":"",
srcfile, srcline,
srcfunc? ", function ":"", srcfunc? srcfunc:"",
description? description : "no description available");
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
"%serror in file %s, line %d%s%s: %s",
is_fatal? "fatal ":"",
srcfile, srcline,
srcfunc? ", function ":"", srcfunc? srcfunc:"",
description? description : "no description available");
#endif /*HAVE_SYSLOG*/
}
/* Perform a state transition to NEW_STATE. If this is an invalid
transition, the module will go into a fatal error state. */
static void
fips_new_state (enum module_states new_state)
{
int ok = 0;
enum module_states last_state;
lock_fsm ();
last_state = current_state;
switch (current_state)
{
case STATE_POWERON:
if (new_state == STATE_INIT
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;
break;
case STATE_INIT:
if (new_state == STATE_SELFTEST
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;
break;
case STATE_SELFTEST:
if (new_state == STATE_OPERATIONAL
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;
break;
case STATE_OPERATIONAL:
if (new_state == STATE_SHUTDOWN
|| new_state == STATE_SELFTEST
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;
break;
case STATE_ERROR:
if (new_state == STATE_SHUTDOWN
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR
|| new_state == STATE_SELFTEST)
ok = 1;
break;
case STATE_FATALERROR:
if (new_state == STATE_SHUTDOWN )
ok = 1;
break;
case STATE_SHUTDOWN:
/* We won't see any transition *from* Shutdown because the only
allowed new state is Power-Off and that one can't be
represented. */
break;
}
if (ok)
{
current_state = new_state;
}
unlock_fsm ();
if (!ok || _gcry_log_verbosity (2))
log_info ("libgcrypt state transition %s => %s %s\n",
state2str (last_state), state2str (new_state),
ok? "granted":"denied");
if (!ok)
{
/* Invalid state transition. Halting library. */
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR,
"Libgcrypt error: invalid state transition %s => %s",
state2str (last_state), state2str (new_state));
#endif /*HAVE_SYSLOG*/
fips_noreturn ();
}
else if (new_state == STATE_ERROR || new_state == STATE_FATALERROR)
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING,
"Libgcrypt notice: state transition %s => %s",
state2str (last_state), state2str (new_state));
#endif /*HAVE_SYSLOG*/
}
}
/* This function should be called to ensure that the execution shall
not continue. */
void
_gcry_fips_noreturn (void)
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_ERR, "Libgcrypt terminated the application");
#endif /*HAVE_SYSLOG*/
fflush (NULL);
abort ();
/*NOTREACHED*/
}
diff --git a/src/g10lib.h b/src/g10lib.h
index 694c2d83..cad7ac30 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -1,480 +1,480 @@
/* g10lib.h - Internal definitions for libgcrypt
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
* 2007, 2011 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* This header is to be used inside of libgcrypt in place of gcrypt.h.
This way we can better distinguish between internal and external
usage of gcrypt.h. */
#ifndef G10LIB_H
#define G10LIB_H 1
#ifdef _GCRYPT_H
#error gcrypt.h already included
#endif
#ifndef _GCRYPT_IN_LIBGCRYPT
#error something is wrong with config.h
#endif
#include <stdio.h>
#include <stdarg.h>
#include "visibility.h"
#include "types.h"
/* Attribute handling macros. */
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
#define JNLIB_GCC_M_FUNCTION 1
#define JNLIB_GCC_A_NR __attribute__ ((noreturn))
#define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a)))
#define JNLIB_GCC_A_NR_PRINTF( f, a ) \
__attribute__ ((noreturn, format (printf,f,a)))
#define GCC_ATTR_NORETURN __attribute__ ((__noreturn__))
#else
#define JNLIB_GCC_A_NR
#define JNLIB_GCC_A_PRINTF( f, a )
#define JNLIB_GCC_A_NR_PRINTF( f, a )
#define GCC_ATTR_NORETURN
#endif
#if __GNUC__ >= 3
/* According to glibc this attribute is available since 2.8 however we
better play safe and use it only with gcc 3 or newer. */
#define GCC_ATTR_FORMAT_ARG(a) __attribute__ ((format_arg (a)))
#else
#define GCC_ATTR_FORMAT_ARG(a)
#endif
/* I am not sure since when the unused attribute is really supported.
In any case it it only needed for gcc versions which print a
warning. Thus let us require gcc >= 3.5. */
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 )
#define GCC_ATTR_UNUSED __attribute__ ((unused))
#else
#define GCC_ATTR_UNUSED
#endif
#if __GNUC__ >= 3
#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 CONSTANT_P(expr) (0)
#endif
/* Gettext macros. */
#define _(a) _gcry_gettext(a)
#define N_(a) (a)
/* Some handy macros */
#ifndef STR
#define STR(v) #v
#endif
#define STR2(v) STR(v)
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#define my_isascii(c) (!((c) & 0x80))
/*-- 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);
void _gcry_pre_syscall (void);
void _gcry_post_syscall (void);
int _gcry_get_debug_flag (unsigned int mask);
char *_gcry_get_config (int mode, const char *what);
/* Malloc functions and common wrapper macros. */
void *_gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_calloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_realloc (void *a, size_t n);
char *_gcry_strdup (const char *string) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_xmalloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_xcalloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_xmalloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_xcalloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_xrealloc (void *a, size_t n);
char *_gcry_xstrdup (const char * a) _GCRY_GCC_ATTR_MALLOC;
void _gcry_free (void *a);
int _gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
#define xtrymalloc(a) _gcry_malloc ((a))
#define xtrycalloc(a,b) _gcry_calloc ((a),(b))
#define xtrymalloc_secure(a) _gcry_malloc_secure ((a))
#define xtrycalloc_secure(a,b) _gcry_calloc_secure ((a),(b))
#define xtryrealloc(a,b) _gcry_realloc ((a),(b))
#define xtrystrdup(a) _gcry_strdup ((a))
#define xmalloc(a) _gcry_xmalloc ((a))
#define xcalloc(a,b) _gcry_xcalloc ((a),(b))
#define xmalloc_secure(a) _gcry_xmalloc_secure ((a))
#define xcalloc_secure(a,b) _gcry_xcalloc_secure ((a),(b))
#define xrealloc(a,b) _gcry_xrealloc ((a),(b))
#define xstrdup(a) _gcry_xstrdup ((a))
#define xfree(a) _gcry_free ((a))
/*-- src/misc.c --*/
#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L
void _gcry_bug (const char *file, int line,
const char *func) GCC_ATTR_NORETURN;
void _gcry_assert_failed (const char *expr, const char *file, int line,
const char *func) GCC_ATTR_NORETURN;
#else
void _gcry_bug (const char *file, int line);
void _gcry_assert_failed (const char *expr, const char *file, int line);
#endif
void _gcry_divide_by_zero (void) JNLIB_GCC_A_NR;
const char *_gcry_gettext (const char *key) GCC_ATTR_FORMAT_ARG(1);
void _gcry_fatal_error(int rc, const char *text ) JNLIB_GCC_A_NR;
void _gcry_logv (int level,
const char *fmt, va_list arg_ptr) JNLIB_GCC_A_PRINTF(2,0);
void _gcry_log( int level, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3);
void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void _gcry_log_printhex (const char *text, const void *buffer, size_t length);
void _gcry_log_printmpi (const char *text, gcry_mpi_t mpi);
void _gcry_log_printsxp (const char *text, gcry_sexp_t sexp);
void _gcry_set_log_verbosity( int level );
int _gcry_log_verbosity( int level );
#ifdef JNLIB_GCC_M_FUNCTION
#define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ )
#define gcry_assert(expr) (LIKELY(expr)? (void)0 \
: _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __FUNCTION__))
#elif __STDC_VERSION__ >= 199901L
#define BUG() _gcry_bug( __FILE__ , __LINE__, __func__ )
#define gcry_assert(expr) (LIKELY(expr)? (void)0 \
: _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __func__))
#else
#define BUG() _gcry_bug( __FILE__ , __LINE__ )
#define gcry_assert(expr) (LIKELY(expr)? (void)0 \
: _gcry_assert_failed (STR(expr), __FILE__, __LINE__))
#endif
#define log_bug _gcry_log_bug
#define log_fatal _gcry_log_fatal
#define log_error _gcry_log_error
#define log_info _gcry_log_info
#define log_debug _gcry_log_debug
#define log_printf _gcry_log_printf
#define log_printhex _gcry_log_printhex
#define log_printmpi _gcry_log_printmpi
#define log_printsxp _gcry_log_printsxp
/* Compatibility macro. */
#define log_mpidump _gcry_log_printmpi
/* Tokeninze STRING and return a malloced array. */
char **_gcry_strtokenize (const char *string, const char *delim);
/*-- src/hwfeatures.c --*/
#define HWF_PADLOCK_RNG (1 << 0)
#define HWF_PADLOCK_AES (1 << 1)
#define HWF_PADLOCK_SHA (1 << 2)
#define HWF_PADLOCK_MMUL (1 << 3)
#define HWF_INTEL_CPU (1 << 4)
#define HWF_INTEL_FAST_SHLD (1 << 5)
#define HWF_INTEL_BMI2 (1 << 6)
#define HWF_INTEL_SSSE3 (1 << 7)
#define HWF_INTEL_SSE4_1 (1 << 8)
#define HWF_INTEL_PCLMUL (1 << 9)
#define HWF_INTEL_AESNI (1 << 10)
#define HWF_INTEL_RDRAND (1 << 11)
#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_ARM_NEON (1 << 17)
#define HWF_ARM_AES (1 << 18)
#define HWF_ARM_SHA1 (1 << 19)
#define HWF_ARM_SHA2 (1 << 20)
#define HWF_ARM_PMULL (1 << 21)
gpg_err_code_t _gcry_disable_hw_feature (const char *name);
void _gcry_detect_hw_features (void);
unsigned int _gcry_get_hw_features (void);
const char *_gcry_enum_hw_features (int idx, unsigned int *r_feature);
/*-- mpi/mpiutil.c --*/
const char *_gcry_mpi_get_hw_config (void);
/*-- cipher/pubkey.c --*/
/* FIXME: shouldn't this go into mpi.h? */
#ifndef mpi_powm
#define mpi_powm(w,b,e,m) gcry_mpi_powm( (w), (b), (e), (m) )
#endif
/*-- primegen.c --*/
gcry_err_code_t _gcry_primegen_init (void);
gcry_mpi_t _gcry_generate_secret_prime (unsigned int nbits,
gcry_random_level_t random_level,
int (*extra_check)(void*, gcry_mpi_t),
void *extra_check_arg);
gcry_mpi_t _gcry_generate_public_prime (unsigned int nbits,
gcry_random_level_t random_level,
int (*extra_check)(void*, gcry_mpi_t),
void *extra_check_arg);
gcry_err_code_t _gcry_generate_elg_prime (int mode,
unsigned int pbits,
unsigned int qbits,
gcry_mpi_t g,
gcry_mpi_t *r_prime,
gcry_mpi_t **factors);
gcry_mpi_t _gcry_derive_x931_prime (const gcry_mpi_t xp,
const gcry_mpi_t xp1, const gcry_mpi_t xp2,
const gcry_mpi_t e,
gcry_mpi_t *r_p1, gcry_mpi_t *r_p2);
gpg_err_code_t _gcry_generate_fips186_2_prime
(unsigned int pbits, unsigned int qbits,
const void *seed, size_t seedlen,
gcry_mpi_t *r_q, gcry_mpi_t *r_p,
int *r_counter,
void **r_seed, size_t *r_seedlen);
gpg_err_code_t _gcry_generate_fips186_3_prime
(unsigned int pbits, unsigned int qbits,
const void *seed, size_t seedlen,
gcry_mpi_t *r_q, gcry_mpi_t *r_p,
int *r_counter,
void **r_seed, size_t *r_seedlen, int *r_hashalgo);
gpg_err_code_t _gcry_fips186_4_prime_check (const gcry_mpi_t x,
unsigned int bits);
/* Replacements of missing functions (missing-string.c). */
#ifndef HAVE_STPCPY
char *stpcpy (char *a, const char *b);
#endif
#ifndef HAVE_STRCASECMP
int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE;
#endif
#include "../compat/libcompat.h"
/* Macros used to rename missing functions. */
#ifndef HAVE_STRTOUL
#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c)))
#endif
#ifndef HAVE_MEMMOVE
#define memmove(d, s, n) bcopy((s), (d), (n))
#endif
#ifndef HAVE_STRICMP
#define stricmp(a,b) strcasecmp( (a), (b) )
#endif
#ifndef HAVE_ATEXIT
#define atexit(a) (on_exit((a),0))
#endif
#ifndef HAVE_RAISE
#define raise(a) kill(getpid(), (a))
#endif
/* Stack burning. */
#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
#define __gcry_burn_stack_dummy() asm volatile ("":::"memory")
#else
void __gcry_burn_stack_dummy (void);
#endif
void __gcry_burn_stack (unsigned int bytes);
#define _gcry_burn_stack(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. For small constant length buffers,
memory wiping is inlined. For non-constant or large length buffers,
memory is wiped with memset through _gcry_fast_wipememory. */
#define wipememory2(_ptr,_set,_len) do { \
if (!CONSTANT_P(_len) || _len > 64) { \
if (CONSTANT_P(_set) && (_set) == 0) \
_gcry_fast_wipememory((void *)_ptr, _len); \
else \
_gcry_fast_wipememory2((void *)_ptr, _set, _len); \
} else {\
volatile char *_vptr = (volatile char *)(_ptr); \
size_t _vlen = (_len); \
const 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)
void _gcry_fast_wipememory(void *ptr, size_t len);
void _gcry_fast_wipememory2(void *ptr, int set, size_t len);
#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
typedef struct fast_wipememory_s
{
u64 a;
} __attribute__((packed, aligned(1), may_alias)) fast_wipememory_t;
/* fast_wipememory may leave tail bytes unhandled, in which case tail bytes
are handled by wipememory. */
# define fast_wipememory2(_vptr,_vset,_vlen) do { \
fast_wipememory_t _vset_long; \
if (_vlen < sizeof(fast_wipememory_t)) \
break; \
_vset_long.a = (_vset); \
_vset_long.a *= U64_C(0x0101010101010101); \
do { \
volatile fast_wipememory_t *_vptr_long = \
(volatile void *)_vptr; \
_vptr_long->a = _vset_long.a; \
_vlen -= sizeof(fast_wipememory_t); \
_vptr += sizeof(fast_wipememory_t); \
} while (_vlen >= sizeof(fast_wipememory_t)); \
} while (0)
#else
# define fast_wipememory2(_vptr,_vset,_vlen)
#endif
/* Digit predicates. */
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
#define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \
|| (*(a) >= 'a' && *(a) <= 'z'))
#define hexdigitp(a) (digitp (a) \
|| (*(a) >= 'A' && *(a) <= 'F') \
|| (*(a) >= 'a' && *(a) <= 'f'))
/* Init functions. */
gcry_err_code_t _gcry_cipher_init (void);
gcry_err_code_t _gcry_md_init (void);
gcry_err_code_t _gcry_mac_init (void);
gcry_err_code_t _gcry_pk_init (void);
gcry_err_code_t _gcry_secmem_module_init (void);
gcry_err_code_t _gcry_mpi_init (void);
/* Memory management. */
#define GCRY_ALLOC_FLAG_SECURE (1 << 0)
#define GCRY_ALLOC_FLAG_XHINT (1 << 1) /* Called from xmalloc. */
/*-- sexp.c --*/
gcry_err_code_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, va_list arg_ptr);
char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number);
gpg_err_code_t _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
const char *list, va_list arg_ptr);
/*-- fips.c --*/
extern int _gcry_no_fips_mode_required;
void _gcry_initialize_fips_mode (int force);
/* 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.
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)
int _gcry_enforced_fips_mode (void);
void _gcry_set_enforced_fips_mode (void);
void _gcry_inactivate_fips_mode (const char *text);
int _gcry_is_fips_mode_inactive (void);
void _gcry_fips_signal_error (const char *srcfile,
int srcline,
const char *srcfunc,
int is_fatal,
const char *description);
#ifdef JNLIB_GCC_M_FUNCTION
# define fips_signal_error(a) \
_gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 0, (a))
# define fips_signal_fatal_error(a) \
_gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 1, (a))
#else
# define fips_signal_error(a) \
_gcry_fips_signal_error (__FILE__, __LINE__, NULL, 0, (a))
# define fips_signal_fatal_error(a) \
_gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a))
#endif
int _gcry_fips_is_operational (void);
/* 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);
int _gcry_fips_test_error_or_operational (void);
gpg_err_code_t _gcry_fips_run_selftests (int extended);
void _gcry_fips_noreturn (void);
#define fips_noreturn() (_gcry_fips_noreturn ())
#endif /* G10LIB_H */
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 7934f148..42d1c838 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -1,530 +1,530 @@
/* gcrypt-int.h - Internal version of gcrypt.h
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_GCRYPT_INT_H
#define GCRY_GCRYPT_INT_H
#ifdef _GCRYPT_H
#error gcrypt.h already included
#endif
#include "gcrypt.h"
#include "types.h"
/* These error codes are used but not defined in the required
* libgpg-error N.MM. Define them here. [None right now.] */
/* Context used with elliptic curve functions. */
struct mpi_ec_ctx_s;
typedef struct mpi_ec_ctx_s *mpi_ec_t;
/* Underscore prefixed internal versions of the public functions.
They return gpg_err_code_t and not gpg_error_t. Some macros also
need an underscore prefixed internal version.
Note that the memory allocation functions and macros (xmalloc etc.)
are not defined here but in g10lib.h because this file here is
included by some test programs which define theie own xmalloc
macros. */
gpg_err_code_t _gcry_cipher_open (gcry_cipher_hd_t *handle,
int algo, int mode, unsigned int flags);
void _gcry_cipher_close (gcry_cipher_hd_t h);
gpg_err_code_t _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
size_t buflen);
gpg_err_code_t _gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer,
size_t *nbytes);
gpg_err_code_t _gcry_cipher_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
const char *_gcry_cipher_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
int _gcry_cipher_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
int _gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE;
gpg_err_code_t _gcry_cipher_encrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen);
gpg_err_code_t _gcry_cipher_decrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen);
gcry_err_code_t _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);
gpg_err_code_t _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
size_t abuflen);
gpg_err_code_t _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag,
size_t taglen);
gpg_err_code_t _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag,
size_t taglen);
gpg_err_code_t _gcry_cipher_setctr (gcry_cipher_hd_t hd,
const void *ctr, size_t ctrlen);
gpg_err_code_t _gcry_cipher_getctr (gcry_cipher_hd_t hd,
void *ctr, size_t ctrlen);
size_t _gcry_cipher_get_algo_keylen (int algo);
size_t _gcry_cipher_get_algo_blklen (int algo);
#define _gcry_cipher_reset(h) _gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0)
gpg_err_code_t _gcry_pk_encrypt (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t pkey);
gpg_err_code_t _gcry_pk_decrypt (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t skey);
gpg_err_code_t _gcry_pk_sign (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t skey);
gpg_err_code_t _gcry_pk_verify (gcry_sexp_t sigval,
gcry_sexp_t data, gcry_sexp_t pkey);
gpg_err_code_t _gcry_pk_testkey (gcry_sexp_t key);
gpg_err_code_t _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms);
gpg_err_code_t _gcry_pk_ctl (int cmd, void *buffer, size_t buflen);
gpg_err_code_t _gcry_pk_algo_info (int algo, int what,
void *buffer, size_t *nbytes);
const char *_gcry_pk_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
int _gcry_pk_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
unsigned int _gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE;
unsigned char *_gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
const char *_gcry_pk_get_curve (gcry_sexp_t key, int iterator,
unsigned int *r_nbits);
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);
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);
gpg_err_code_t _gcry_md_enable (gcry_md_hd_t hd, int algo);
gpg_err_code_t _gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd);
void _gcry_md_reset (gcry_md_hd_t hd);
gpg_err_code_t _gcry_md_ctl (gcry_md_hd_t hd, int cmd,
void *buffer, size_t buflen);
void _gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
unsigned char *_gcry_md_read (gcry_md_hd_t hd, int algo);
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 (int algo, unsigned int flags,
void *digest,
const gcry_buffer_t *iov, int iovcnt);
int _gcry_md_get_algo (gcry_md_hd_t hd);
unsigned int _gcry_md_get_algo_dlen (int algo);
int _gcry_md_is_enabled (gcry_md_hd_t a, int algo);
int _gcry_md_is_secure (gcry_md_hd_t a);
gpg_err_code_t _gcry_md_info (gcry_md_hd_t h, int what, void *buffer,
size_t *nbytes);
gpg_err_code_t _gcry_md_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
const char *_gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
int _gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
gpg_err_code_t _gcry_md_setkey (gcry_md_hd_t hd,
const void *key, size_t keylen);
void _gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
#define _gcry_md_test_algo(a) \
_gcry_md_algo_info ((a), GCRYCTL_TEST_ALGO, NULL, NULL)
#define _gcry_md_final(a) \
_gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
#define _gcry_md_putc(h,c) \
do { \
gcry_md_hd_t h__ = (h); \
if( (h__)->bufpos == (h__)->bufsize ) \
_gcry_md_write( (h__), NULL, 0 ); \
(h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
} while(0)
gpg_err_code_t _gcry_mac_open (gcry_mac_hd_t *handle, int algo,
unsigned int flags, gcry_ctx_t ctx);
void _gcry_mac_close (gcry_mac_hd_t h);
gpg_err_code_t _gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer,
size_t buflen);
gpg_err_code_t _gcry_mac_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
gpg_err_code_t _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key,
size_t keylen);
gpg_err_code_t _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv,
size_t ivlen);
gpg_err_code_t _gcry_mac_write (gcry_mac_hd_t hd, const void *buffer,
size_t length);
gpg_err_code_t _gcry_mac_read (gcry_mac_hd_t hd, void *buffer, size_t *buflen);
gpg_err_code_t _gcry_mac_verify (gcry_mac_hd_t hd, const void *buffer,
size_t buflen);
int _gcry_mac_get_algo (gcry_mac_hd_t hd);
unsigned int _gcry_mac_get_algo_maclen (int algo);
unsigned int _gcry_mac_get_algo_keylen (int algo);
const char *_gcry_mac_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
int _gcry_mac_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
#define _gcry_mac_reset(h) _gcry_mac_ctl ((h), GCRYCTL_RESET, NULL, 0)
gpg_err_code_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);
gpg_err_code_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);
gpg_err_code_t _gcry_prime_group_generator (gcry_mpi_t *r_g,
gcry_mpi_t prime,
gcry_mpi_t *factors,
gcry_mpi_t start_g);
void _gcry_prime_release_factors (gcry_mpi_t *factors);
gpg_err_code_t _gcry_prime_check (gcry_mpi_t x, unsigned int flags);
void _gcry_randomize (void *buffer, size_t length,
enum gcry_random_level level);
gpg_err_code_t _gcry_random_add_bytes (const void *buffer, size_t length,
int quality);
void *_gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
_GCRY_GCC_ATTR_MALLOC;
void *_gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
_GCRY_GCC_ATTR_MALLOC;
void _gcry_mpi_randomize (gcry_mpi_t w,
unsigned int nbits, enum gcry_random_level level);
void _gcry_create_nonce (void *buffer, size_t length);
void _gcry_ctx_release (gcry_ctx_t ctx);
const char *_gcry_check_version (const char *req_version);
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);
void _gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque);
void _gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque);
void _gcry_set_log_handler (gcry_handler_log_t f, void *opaque);
void _gcry_set_gettext_handler (const char *(*f)(const char*));
void _gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
/* Return a pointer to a string containing a description of the error
code in the error value ERR. */
static inline const char *
_gcry_strerror (gcry_error_t err)
{
return gpg_strerror (err);
}
/* Return a pointer to a string containing a description of the error
source in the error value ERR. */
static inline const char *
_gcry_strsource (gcry_error_t err)
{
return gpg_strsource (err);
}
/* Retrieve the error code for the system error ERR. This returns
GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
this). */
static inline gcry_err_code_t
_gcry_err_code_from_errno (int err)
{
return gpg_err_code_from_errno (err);
}
/* Retrieve the system error for the error code CODE. This returns 0
if CODE is not a system error code. */
static inline int
_gcry_err_code_to_errno (gcry_err_code_t code)
{
return gpg_err_code_from_errno (code);
}
/* Return an error value with the error source SOURCE and the system
error ERR. */
static inline gcry_error_t
_gcry_err_make_from_errno (gpg_err_source_t source, int err)
{
return gpg_err_make_from_errno (source, err);
}
/* Return an error value with the system error ERR. */
static inline gcry_error_t
_gcry_error_from_errno (int err)
{
return gpg_error (gpg_err_code_from_errno (err));
}
gpg_err_code_t _gcry_sexp_new (gcry_sexp_t *retsexp,
const void *buffer, size_t length,
int autodetect);
gpg_err_code_t _gcry_sexp_create (gcry_sexp_t *retsexp,
void *buffer, size_t length,
int autodetect, void (*freefnc) (void *));
gpg_err_code_t _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length);
gpg_err_code_t _gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, ...);
gpg_err_code_t _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, void **arg_list);
void _gcry_sexp_release (gcry_sexp_t sexp);
size_t _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
size_t *erroff, gcry_err_code_t *errcode);
size_t _gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
size_t maxlength);
void _gcry_sexp_dump (const gcry_sexp_t a);
gcry_sexp_t _gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b);
gcry_sexp_t _gcry_sexp_alist (const gcry_sexp_t *array);
gcry_sexp_t _gcry_sexp_vlist (const gcry_sexp_t a, ...);
gcry_sexp_t _gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n);
gcry_sexp_t _gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n);
gcry_sexp_t _gcry_sexp_find_token (gcry_sexp_t list,
const char *tok, size_t toklen);
int _gcry_sexp_length (const gcry_sexp_t list);
gcry_sexp_t _gcry_sexp_nth (const gcry_sexp_t list, int number);
gcry_sexp_t _gcry_sexp_car (const gcry_sexp_t list);
gcry_sexp_t _gcry_sexp_cdr (const gcry_sexp_t list);
gcry_sexp_t _gcry_sexp_cadr (const gcry_sexp_t list);
const char *_gcry_sexp_nth_data (const gcry_sexp_t list, int number,
size_t *datalen);
void *_gcry_sexp_nth_buffer (const gcry_sexp_t list, int number,
size_t *rlength);
char *_gcry_sexp_nth_string (gcry_sexp_t list, int number);
gcry_mpi_t _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
gpg_err_code_t _gcry_sexp_extract_param (gcry_sexp_t sexp,
const char *path,
const char *list,
...) _GCRY_GCC_ATTR_SENTINEL(0);
#define sexp_new(a, b, c, d) _gcry_sexp_new ((a), (b), (c), (d))
#define sexp_create(a, b, c, d, e) _gcry_sexp_create ((a), (b), (c), (d), (e))
#define sexp_sscan(a, b, c, d) _gcry_sexp_sscan ((a), (b), (c), (d))
#define sexp_build _gcry_sexp_build
#define sexp_build_array(a, b, c, d) _gcry_sexp_build_array ((a), (b), (c), (d))
#define sexp_release(a) _gcry_sexp_release ((a))
#define sexp_canon_len(a, b, c, d) _gcry_sexp_canon_len ((a), (b), (c), (d))
#define sexp_sprint(a, b, c, d) _gcry_sexp_sprint ((a), (b), (c), (d))
#define sexp_dump(a) _gcry_sexp_dump ((a))
#define sexp_cons(a, b) _gcry_sexp_cons ((a), (b))
#define sexp_alist(a) _gcry_sexp_alist ((a))
#define sexp_vlist _gcry_sexp_vlist
#define sexp_append(a, b) _gcry_sexp_append ((a), (b))
#define sexp_prepend(a, b) _gcry_sexp_prepend ((a), (b))
#define sexp_find_token(a, b, c) _gcry_sexp_find_token ((a), (b), (c))
#define sexp_length(a) _gcry_sexp_length ((a))
#define sexp_nth(a, b) _gcry_sexp_nth ((a), (b))
#define sexp_car(a) _gcry_sexp_car ((a))
#define sexp_cdr(a) _gcry_sexp_cdr ((a))
#define sexp_cadr(a) _gcry_sexp_cadr ((a))
#define sexp_nth_data(a, b, c) _gcry_sexp_nth_data ((a), (b), (c))
#define sexp_nth_buffer(a, b, c) _gcry_sexp_nth_buffer ((a), (b), (c))
#define sexp_nth_string(a, b) _gcry_sexp_nth_string ((a), (b))
#define sexp_nth_mpi(a, b, c) _gcry_sexp_nth_mpi ((a), (b), (c))
#define sexp_extract_param _gcry_sexp_extract_param
gcry_mpi_t _gcry_mpi_new (unsigned int nbits);
gcry_mpi_t _gcry_mpi_snew (unsigned int nbits);
void _gcry_mpi_release (gcry_mpi_t a);
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 (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);
void _gcry_mpi_abs (gcry_mpi_t w);
int _gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v);
int _gcry_mpi_cmpabs (const gcry_mpi_t u, const gcry_mpi_t v);
int _gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v);
gpg_err_code_t _gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
const void *buffer, size_t buflen,
size_t *nscanned);
gpg_err_code_t _gcry_mpi_print (enum gcry_mpi_format format,
unsigned char *buffer, size_t buflen,
size_t *nwritten,
const gcry_mpi_t a);
gpg_err_code_t _gcry_mpi_aprint (enum gcry_mpi_format format,
unsigned char **buffer, size_t *nwritten,
const gcry_mpi_t a);
void _gcry_mpi_dump (const gcry_mpi_t a);
void _gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
void _gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v);
void _gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
void _gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
void _gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
void _gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
void _gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
void _gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
void _gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
void _gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt);
void _gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
void _gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor);
void _gcry_mpi_powm (gcry_mpi_t w,
const gcry_mpi_t b, const gcry_mpi_t e,
const gcry_mpi_t m);
int _gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b);
int _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m);
gcry_mpi_point_t _gcry_mpi_point_new (unsigned int nbits);
void _gcry_mpi_point_release (gcry_mpi_point_t point);
gcry_mpi_point_t _gcry_mpi_point_copy (gcry_mpi_point_t point);
void _gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
gcry_mpi_point_t point);
void _gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
gcry_mpi_point_t point);
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);
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);
gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy);
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_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);
void _gcry_mpi_ec_sub (gcry_mpi_point_t w,
gcry_mpi_point_t u, gcry_mpi_point_t v, mpi_ec_t ctx);
void _gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u,
mpi_ec_t ctx);
int _gcry_mpi_ec_curve_point (gcry_mpi_point_t w, mpi_ec_t ctx);
unsigned int _gcry_mpi_get_nbits (gcry_mpi_t a);
int _gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n);
void _gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n);
void _gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n);
void _gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n);
void _gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n);
void _gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
void _gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
gcry_mpi_t _gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits);
gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a,
const void *p, unsigned int nbits);
void *_gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits);
void _gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
void _gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
/* Private function - do not use. */
/* gcry_mpi_t _gcry_mpi_get_const (int no); */
/* We need our internal versions of the macros. */
#ifndef GCRYPT_NO_MPI_MACROS
# error GCRYPT_NO_MPI_MACROS is not defined
#endif
#define mpi_new(n) _gcry_mpi_new ((n))
#define mpi_secure_new( n ) _gcry_mpi_snew ((n))
#define mpi_snew(n) _gcry_mpi_snew ((n))
#define mpi_release(a) \
do \
{ \
_gcry_mpi_release ((a));\
(a) = NULL; \
} \
while (0)
#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_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) )
#define mpi_cmp( u, v ) _gcry_mpi_cmp( (u), (v) )
#define mpi_cmpabs( u, v ) _gcry_mpi_cmpabs( (u), (v) )
#define mpi_cmp_ui( u, v ) _gcry_mpi_cmp_ui( (u), (v) )
#define mpi_is_neg( a ) _gcry_mpi_is_neg ((a))
#define mpi_add_ui(w,u,v) _gcry_mpi_add_ui((w),(u),(v))
#define mpi_add(w,u,v) _gcry_mpi_add ((w),(u),(v))
#define mpi_addm(w,u,v,m) _gcry_mpi_addm ((w),(u),(v),(m))
#define mpi_sub_ui(w,u,v) _gcry_mpi_sub_ui ((w),(u),(v))
#define mpi_sub(w,u,v) _gcry_mpi_sub ((w),(u),(v))
#define mpi_subm(w,u,v,m) _gcry_mpi_subm ((w),(u),(v),(m))
#define mpi_mul_ui(w,u,v) _gcry_mpi_mul_ui ((w),(u),(v))
#define mpi_mul_2exp(w,u,v) _gcry_mpi_mul_2exp ((w),(u),(v))
#define mpi_mul(w,u,v) _gcry_mpi_mul ((w),(u),(v))
#define mpi_mulm(w,u,v,m) _gcry_mpi_mulm ((w),(u),(v),(m))
#define mpi_powm(w,b,e,m) _gcry_mpi_powm ( (w), (b), (e), (m) )
#define mpi_tdiv(q,r,a,m) _gcry_mpi_div ( (q), (r), (a), (m), 0)
#define mpi_fdiv(q,r,a,m) _gcry_mpi_div ( (q), (r), (a), (m), -1)
#define mpi_mod(r,a,m) _gcry_mpi_mod ((r), (a), (m))
#define mpi_gcd(g,a,b) _gcry_mpi_gcd ( (g), (a), (b) )
#define mpi_invm(g,a,b) _gcry_mpi_invm ( (g), (a), (b) )
#define mpi_point_new(n) _gcry_mpi_point_new((n))
#define mpi_point_release(p) \
do \
{ \
_gcry_mpi_point_release ((p)); \
(p) = NULL; \
} \
while (0)
#define mpi_point_copy(p) _gcry_mpi_point_copy((p))
#define mpi_point_get(x,y,z,p) _gcry_mpi_point_get((x),(y),(z),(p))
#define mpi_point_snatch_get(x,y,z,p) _gcry_mpi_point_snatch_get((x),(y), \
(z),(p))
#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_get_nbits(a) _gcry_mpi_get_nbits ((a))
#define mpi_test_bit(a,b) _gcry_mpi_test_bit ((a),(b))
#define mpi_set_bit(a,b) _gcry_mpi_set_bit ((a),(b))
#define mpi_set_highbit(a,b) _gcry_mpi_set_highbit ((a),(b))
#define mpi_clear_bit(a,b) _gcry_mpi_clear_bit ((a),(b))
#define mpi_clear_highbit(a,b) _gcry_mpi_clear_highbit ((a),(b))
#define mpi_rshift(a,b,c) _gcry_mpi_rshift ((a),(b),(c))
#define mpi_lshift(a,b,c) _gcry_mpi_lshift ((a),(b),(c))
#define mpi_set_opaque(a,b,c) _gcry_mpi_set_opaque ((a), (b), (c))
#define mpi_get_opaque(a,b) _gcry_mpi_get_opaque ((a), (b))
#define mpi_set_flag(a,f) _gcry_mpi_set_flag ((a), (f))
#define mpi_set_flag(a,f) _gcry_mpi_set_flag ((a), (f))
#define mpi_clear_flag(a,f) _gcry_mpi_clear_flag ((a), (f))
#define mpi_get_flag(a,f) _gcry_mpi_get_flag ((a), (f))
#endif /*GCRY_GCRYPT_INT_H*/
diff --git a/src/gcrypt-testapi.h b/src/gcrypt-testapi.h
index 0417754f..78b88351 100644
--- a/src/gcrypt-testapi.h
+++ b/src/gcrypt-testapi.h
@@ -1,69 +1,69 @@
/* gcrypt-testapi.h - Definitiona for the Regression test API
* Copyright (C) 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* WARNING: This is a private API to be used by regression tests. In
* particular this API does not constitute a well defined ABI. The
* header may only be used with its matching Libgcrypt version.
*/
#ifndef GCRY_GCRYPT_TESTAPI_H
#define GCRY_GCRYPT_TESTAPI_H
/* For use with gcry_control: */
#define PRIV_CTL_INIT_EXTRNG_TEST 58
#define PRIV_CTL_RUN_EXTRNG_TEST 59
#define PRIV_CTL_DEINIT_EXTRNG_TEST 60
#define PRIV_CTL_EXTERNAL_LOCK_TEST 61
#define PRIV_CTL_DUMP_SECMEM_STATS 62
#define EXTERNAL_LOCK_TEST_INIT 30111
#define EXTERNAL_LOCK_TEST_LOCK 30112
#define EXTERNAL_LOCK_TEST_UNLOCK 30113
#define EXTERNAL_LOCK_TEST_DESTROY 30114
/* For use with gcry_cipher_ctl: */
#define PRIV_CIPHERCTL_DISABLE_WEAK_KEY 61
#define PRIV_CIPHERCTL_GET_INPUT_VECTOR 62
/* Private interfaces for testing of random-drbg.c. */
struct gcry_drbg_test_vector
{
const char *flagstr;
unsigned char *entropy;
size_t entropylen;
unsigned char *entpra;
unsigned char *entprb;
size_t entprlen;
unsigned char *addtla;
unsigned char *addtlb;
size_t addtllen;
unsigned char *pers;
size_t perslen;
unsigned char *expected;
size_t expectedlen;
unsigned char *entropyreseed;
size_t entropyreseed_len;
unsigned char *addtl_reseed;
size_t addtl_reseed_len;
};
#endif /*GCRY_GCRYPT_TESTAPI_H*/
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 8346ce15..be8d88f3 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1,1819 +1,1819 @@
/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*-
* Copyright (C) 1998-2018 Free Software Foundation, Inc.
* Copyright (C) 2012-2018 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*
* File: @configure_input@
*/
#ifndef _GCRYPT_H
#define _GCRYPT_H
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <gpg-error.h>
#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@
/* This is required for error code compatibility. */
#define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
#ifdef __cplusplus
extern "C" {
#if 0 /* (Keep Emacsens' auto-indent happy.) */
}
#endif
#endif
/* The version of this header should match the one of the library. It
should not be used by a program because gcry_check_version() should
return the same version. The purpose of this macro is to let
autoconf (using the AM_PATH_GCRYPT macro) check that this header
matches the installed library. */
#define GCRYPT_VERSION "@VERSION@"
/* The version number of this header. It may be used to handle minor
API incompatibilities. */
#define GCRYPT_VERSION_NUMBER @VERSION_NUMBER@
/* Internal: We can't use the convenience macros for the multi
precision integer functions when building this library. */
#ifdef _GCRYPT_IN_LIBGCRYPT
#ifndef GCRYPT_NO_MPI_MACROS
#define GCRYPT_NO_MPI_MACROS 1
#endif
#endif
/* We want to use gcc attributes when possible. Warning: Don't use
these macros in your programs: As indicated by the leading
underscore they are subject to change without notice. */
#ifdef __GNUC__
#define _GCRY_GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if _GCRY_GCC_VERSION >= 30100
#define _GCRY_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
#endif
#if _GCRY_GCC_VERSION >= 29600
#define _GCRY_GCC_ATTR_PURE __attribute__ ((__pure__))
#endif
#if _GCRY_GCC_VERSION >= 30200
#define _GCRY_GCC_ATTR_MALLOC __attribute__ ((__malloc__))
#endif
#define _GCRY_GCC_ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a)))
#if _GCRY_GCC_VERSION >= 40000
#define _GCRY_GCC_ATTR_SENTINEL(a) __attribute__ ((sentinel(a)))
#endif
#endif /*__GNUC__*/
#ifndef _GCRY_GCC_ATTR_DEPRECATED
#define _GCRY_GCC_ATTR_DEPRECATED
#endif
#ifndef _GCRY_GCC_ATTR_PURE
#define _GCRY_GCC_ATTR_PURE
#endif
#ifndef _GCRY_GCC_ATTR_MALLOC
#define _GCRY_GCC_ATTR_MALLOC
#endif
#ifndef _GCRY_GCC_ATTR_PRINTF
#define _GCRY_GCC_ATTR_PRINTF(f,a)
#endif
#ifndef _GCRY_GCC_ATTR_SENTINEL
#define _GCRY_GCC_ATTR_SENTINEL(a)
#endif
/* Make up an attribute to mark functions and types as deprecated but
allow internal use by Libgcrypt. */
#ifdef _GCRYPT_IN_LIBGCRYPT
#define _GCRY_ATTR_INTERNAL
#else
#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED
#endif
/* Wrappers for the libgpg-error library. */
typedef gpg_error_t gcry_error_t;
typedef gpg_err_code_t gcry_err_code_t;
typedef gpg_err_source_t gcry_err_source_t;
static GPG_ERR_INLINE gcry_error_t
gcry_err_make (gcry_err_source_t source, gcry_err_code_t code)
{
return gpg_err_make (source, code);
}
/* The user can define GPG_ERR_SOURCE_DEFAULT before including this
file to specify a default source for gpg_error. */
#ifndef GCRY_ERR_SOURCE_DEFAULT
#define GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
#endif
static GPG_ERR_INLINE gcry_error_t
gcry_error (gcry_err_code_t code)
{
return gcry_err_make (GCRY_ERR_SOURCE_DEFAULT, code);
}
static GPG_ERR_INLINE gcry_err_code_t
gcry_err_code (gcry_error_t err)
{
return gpg_err_code (err);
}
static GPG_ERR_INLINE gcry_err_source_t
gcry_err_source (gcry_error_t err)
{
return gpg_err_source (err);
}
/* Return a pointer to a string containing a description of the error
code in the error value ERR. */
const char *gcry_strerror (gcry_error_t err);
/* Return a pointer to a string containing a description of the error
source in the error value ERR. */
const char *gcry_strsource (gcry_error_t err);
/* Retrieve the error code for the system error ERR. This returns
GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
this). */
gcry_err_code_t gcry_err_code_from_errno (int err);
/* Retrieve the system error for the error code CODE. This returns 0
if CODE is not a system error code. */
int gcry_err_code_to_errno (gcry_err_code_t code);
/* Return an error value with the error source SOURCE and the system
error ERR. */
gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err);
/* Return an error value with the system error ERR. */
gcry_error_t gcry_error_from_errno (int err);
/* NOTE: Since Libgcrypt 1.6 the thread callbacks are not anymore
used. However we keep it to allow for some source code
compatibility if used in the standard way. */
/* Constants defining the thread model to use. Used with the OPTION
field of the struct gcry_thread_cbs. */
#define GCRY_THREAD_OPTION_DEFAULT 0
#define GCRY_THREAD_OPTION_USER 1
#define GCRY_THREAD_OPTION_PTH 2
#define GCRY_THREAD_OPTION_PTHREAD 3
/* The version number encoded in the OPTION field of the struct
gcry_thread_cbs. */
#define GCRY_THREAD_OPTION_VERSION 1
/* Wrapper for struct ath_ops. */
struct gcry_thread_cbs
{
/* The OPTION field encodes the thread model and the version number
of this structure.
Bits 7 - 0 are used for the thread model
Bits 15 - 8 are used for the version number. */
unsigned int option;
} _GCRY_ATTR_INTERNAL;
#define GCRY_THREAD_OPTION_PTH_IMPL \
static struct gcry_thread_cbs gcry_threads_pth = { \
(GCRY_THREAD_OPTION_PTH | (GCRY_THREAD_OPTION_VERSION << 8))}
#define GCRY_THREAD_OPTION_PTHREAD_IMPL \
static struct gcry_thread_cbs gcry_threads_pthread = { \
(GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8))}
/* A generic context object as used by some functions. */
struct gcry_context;
typedef struct gcry_context *gcry_ctx_t;
/* The data objects used to hold multi precision integers. */
struct gcry_mpi;
typedef struct gcry_mpi *gcry_mpi_t;
struct gcry_mpi_point;
typedef struct gcry_mpi_point *gcry_mpi_point_t;
#ifndef GCRYPT_NO_DEPRECATED
typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED;
typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED;
#endif
/* A structure used for scatter gather hashing. */
typedef struct
{
size_t size; /* The allocated size of the buffer or 0. */
size_t off; /* Offset into the buffer. */
size_t len; /* The used length of the buffer. */
void *data; /* The buffer. */
} gcry_buffer_t;
/* Check that the library fulfills the version requirement. */
const char *gcry_check_version (const char *req_version);
/* Codes for function dispatchers. */
/* Codes used with the gcry_control function. */
enum gcry_ctl_cmds
{
/* Note: 1 .. 2 are not anymore used. */
GCRYCTL_CFB_SYNC = 3,
GCRYCTL_RESET = 4, /* e.g. for MDs */
GCRYCTL_FINALIZE = 5,
GCRYCTL_GET_KEYLEN = 6,
GCRYCTL_GET_BLKLEN = 7,
GCRYCTL_TEST_ALGO = 8,
GCRYCTL_IS_SECURE = 9,
GCRYCTL_GET_ASNOID = 10,
GCRYCTL_ENABLE_ALGO = 11,
GCRYCTL_DISABLE_ALGO = 12,
GCRYCTL_DUMP_RANDOM_STATS = 13,
GCRYCTL_DUMP_SECMEM_STATS = 14,
GCRYCTL_GET_ALGO_NPKEY = 15,
GCRYCTL_GET_ALGO_NSKEY = 16,
GCRYCTL_GET_ALGO_NSIGN = 17,
GCRYCTL_GET_ALGO_NENCR = 18,
GCRYCTL_SET_VERBOSITY = 19,
GCRYCTL_SET_DEBUG_FLAGS = 20,
GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
GCRYCTL_USE_SECURE_RNDPOOL= 22,
GCRYCTL_DUMP_MEMORY_STATS = 23,
GCRYCTL_INIT_SECMEM = 24,
GCRYCTL_TERM_SECMEM = 25,
GCRYCTL_DISABLE_SECMEM_WARN = 27,
GCRYCTL_SUSPEND_SECMEM_WARN = 28,
GCRYCTL_RESUME_SECMEM_WARN = 29,
GCRYCTL_DROP_PRIVS = 30,
GCRYCTL_ENABLE_M_GUARD = 31,
GCRYCTL_START_DUMP = 32,
GCRYCTL_STOP_DUMP = 33,
GCRYCTL_GET_ALGO_USAGE = 34,
GCRYCTL_IS_ALGO_ENABLED = 35,
GCRYCTL_DISABLE_INTERNAL_LOCKING = 36,
GCRYCTL_DISABLE_SECMEM = 37,
GCRYCTL_INITIALIZATION_FINISHED = 38,
GCRYCTL_INITIALIZATION_FINISHED_P = 39,
GCRYCTL_ANY_INITIALIZATION_P = 40,
GCRYCTL_SET_CBC_CTS = 41,
GCRYCTL_SET_CBC_MAC = 42,
/* Note: 43 is not anymore used. */
GCRYCTL_ENABLE_QUICK_RANDOM = 44,
GCRYCTL_SET_RANDOM_SEED_FILE = 45,
GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46,
GCRYCTL_SET_THREAD_CBS = 47,
GCRYCTL_FAST_POLL = 48,
GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49,
GCRYCTL_USE_RANDOM_DAEMON = 50,
GCRYCTL_FAKED_RANDOM_P = 51,
GCRYCTL_SET_RNDEGD_SOCKET = 52,
GCRYCTL_PRINT_CONFIG = 53,
GCRYCTL_OPERATIONAL_P = 54,
GCRYCTL_FIPS_MODE_P = 55,
GCRYCTL_FORCE_FIPS_MODE = 56,
GCRYCTL_SELFTEST = 57,
/* Note: 58 .. 62 are used internally. */
GCRYCTL_DISABLE_HWF = 63,
GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64,
GCRYCTL_SET_PREFERRED_RNG_TYPE = 65,
GCRYCTL_GET_CURRENT_RNG_TYPE = 66,
GCRYCTL_DISABLE_LOCKED_SECMEM = 67,
GCRYCTL_DISABLE_PRIV_DROP = 68,
GCRYCTL_SET_CCM_LENGTHS = 69,
GCRYCTL_CLOSE_RANDOM_DEVICE = 70,
GCRYCTL_INACTIVATE_FIPS_FLAG = 71,
GCRYCTL_REACTIVATE_FIPS_FLAG = 72,
GCRYCTL_SET_SBOX = 73,
GCRYCTL_DRBG_REINIT = 74,
GCRYCTL_SET_TAGLEN = 75,
GCRYCTL_GET_TAGLEN = 76,
GCRYCTL_REINIT_SYSCALL_CLAMP = 77,
GCRYCTL_AUTO_EXPAND_SECMEM = 78
};
/* Perform various operations defined by CMD. */
gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...);
/* S-expression management. */
/* The object to represent an S-expression as used with the public key
functions. */
struct gcry_sexp;
typedef struct gcry_sexp *gcry_sexp_t;
#ifndef GCRYPT_NO_DEPRECATED
typedef struct gcry_sexp *GCRY_SEXP _GCRY_GCC_ATTR_DEPRECATED;
typedef struct gcry_sexp *GcrySexp _GCRY_GCC_ATTR_DEPRECATED;
#endif
/* The possible values for the S-expression format. */
enum gcry_sexp_format
{
GCRYSEXP_FMT_DEFAULT = 0,
GCRYSEXP_FMT_CANON = 1,
GCRYSEXP_FMT_BASE64 = 2,
GCRYSEXP_FMT_ADVANCED = 3
};
/* Create an new S-expression object from BUFFER of size LENGTH and
return it in RETSEXP. With AUTODETECT set to 0 the data in BUFFER
is expected to be in canonized format. */
gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp,
const void *buffer, size_t length,
int autodetect);
/* Same as gcry_sexp_new but allows to pass a FREEFNC which has the
effect to transfer ownership of BUFFER to the created object. */
gcry_error_t gcry_sexp_create (gcry_sexp_t *retsexp,
void *buffer, size_t length,
int autodetect, void (*freefnc) (void *));
/* Scan BUFFER and return a new S-expression object in RETSEXP. This
function expects a printf like string in BUFFER. */
gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length);
/* Same as gcry_sexp_sscan but expects a string in FORMAT and can thus
only be used for certain encodings. */
gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, ...);
/* 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);
/* Release the S-expression object SEXP */
void gcry_sexp_release (gcry_sexp_t sexp);
/* Calculate the length of an canonized S-expression in BUFFER and
check for a valid encoding. */
size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
size_t *erroff, gcry_error_t *errcode);
/* Copies the S-expression object SEXP into BUFFER using the format
specified in MODE. */
size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer,
size_t maxlength);
/* Dumps the S-expression object A in a format suitable for debugging
to Libgcrypt's logging stream. */
void gcry_sexp_dump (const gcry_sexp_t a);
gcry_sexp_t gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b);
gcry_sexp_t gcry_sexp_alist (const gcry_sexp_t *array);
gcry_sexp_t gcry_sexp_vlist (const gcry_sexp_t a, ...);
gcry_sexp_t gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n);
gcry_sexp_t gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n);
/* 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. */
gcry_sexp_t gcry_sexp_find_token (gcry_sexp_t list,
const char *tok, size_t toklen);
/* Return the length of the LIST. For a valid S-expression this
should be at least 1. */
int gcry_sexp_length (const gcry_sexp_t list);
/* 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. */
gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t list, int number);
/* Create and return a new S-expression from the first element in
LIST; this called the "type" and should always exist and be a
string. `NULL' is returned in case of a problem. */
gcry_sexp_t gcry_sexp_car (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. */
gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t list);
gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list);
/* 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.
*Note:* The returned pointer is valid as long as LIST is not
modified or released. */
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 malloced buffer to the
data with index NUMBER is returned and the length of this
data will be stored to RLENGTH. If there is no data at the given
index or the index represents another list, `NULL' is returned. */
void *gcry_sexp_nth_buffer (const gcry_sexp_t list, int number,
size_t *rlength);
/* 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 the 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. */
char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
/* 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. */
gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
/* Extract MPIs from an s-expression using a list of parameters. The
* 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.
*
* In general parameter names are single letters. To use a string for
* a parameter name, enclose the name in single quotes.
*
* Unless in gcry_buffer_t mode for each parameter name a pointer to
* an MPI variable is expected that must be set to NULL prior to
* invoking this function, and finally a NULL is expected. Example:
*
* _gcry_sexp_extract_param (key, NULL, "n/x+ed",
* &mpi_n, &mpi_x, &mpi_e, NULL)
*
* This stores the parameter "N" from KEY as an unsigned MPI into
* MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
* parameter "E" again as an unsigned MPI into MPI_E.
*
* If in buffer descriptor mode a pointer to gcry_buffer_t descriptor
* is expected instead of a pointer to an MPI. The caller may use two
* different operation modes: If the DATA field of the provided buffer
* descriptor is NULL, the function allocates a new buffer and stores
* it at DATA; the other fields are set accordingly with OFF being 0.
* If DATA is not NULL, the function assumes that DATA, SIZE, and OFF
* describe a buffer where to but the data; on return the LEN field
* receives the number of bytes copied to that buffer; if the buffer
* is too small, the function immediately returns with an error code
* (and LEN set to 0).
*
* 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.
*
* 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.
*/
gpg_error_t gcry_sexp_extract_param (gcry_sexp_t sexp,
const char *path,
const char *list,
...) _GCRY_GCC_ATTR_SENTINEL(0);
/*******************************************
* *
* Multi Precision Integer Functions *
* *
*******************************************/
/* Different formats of external big integer representation. */
enum gcry_mpi_format
{
GCRYMPI_FMT_NONE= 0,
GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */
GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */
GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */
GCRYMPI_FMT_HEX = 4, /* Hex format. */
GCRYMPI_FMT_USG = 5, /* Like STD but unsigned. */
GCRYMPI_FMT_OPAQUE = 8 /* Opaque format (some functions only). */
};
/* Flags used for creating big integers. */
enum gcry_mpi_flag
{
GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */
GCRYMPI_FLAG_OPAQUE = 2, /* The number is not a real one but just
a way to store some bytes. This is
useful for encrypted big integers. */
GCRYMPI_FLAG_IMMUTABLE = 4, /* Mark the MPI as immutable. */
GCRYMPI_FLAG_CONST = 8, /* Mark the MPI as a constant. */
GCRYMPI_FLAG_USER1 = 0x0100,/* User flag 1. */
GCRYMPI_FLAG_USER2 = 0x0200,/* User flag 2. */
GCRYMPI_FLAG_USER3 = 0x0400,/* User flag 3. */
GCRYMPI_FLAG_USER4 = 0x0800 /* User flag 4. */
};
/* Macros to return pre-defined MPI constants. */
#define GCRYMPI_CONST_ONE (_gcry_mpi_get_const (1))
#define GCRYMPI_CONST_TWO (_gcry_mpi_get_const (2))
#define GCRYMPI_CONST_THREE (_gcry_mpi_get_const (3))
#define GCRYMPI_CONST_FOUR (_gcry_mpi_get_const (4))
#define GCRYMPI_CONST_EIGHT (_gcry_mpi_get_const (8))
/* Allocate a new big integer object, initialize it with 0 and
initially allocate memory for a number of at least NBITS. */
gcry_mpi_t gcry_mpi_new (unsigned int nbits);
/* Same as gcry_mpi_new() but allocate in "secure" memory. */
gcry_mpi_t gcry_mpi_snew (unsigned int nbits);
/* Release the number A and free all associated resources. */
void gcry_mpi_release (gcry_mpi_t a);
/* Create a new number with the same value as A. */
gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t a);
/* Store the big integer value U in W and release U. */
void gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u);
/* Store the big integer value U in W. */
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);
/* Return 1 if A is negative; 0 if zero or positive. */
int gcry_mpi_is_neg (gcry_mpi_t a);
/* W = - U */
void gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
/* W = [W] */
void gcry_mpi_abs (gcry_mpi_t w);
/* Compare the big integer number U and V returning 0 for equality, a
positive value for U > V and a negative for U < V. */
int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v);
/* Compare the big integer number U with the unsigned integer V
returning 0 for equality, a positive value for U > V and a negative
for U < V. */
int gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v);
/* Convert the external representation of an integer stored in BUFFER
with a length of BUFLEN into a newly create MPI returned in
RET_MPI. If NSCANNED is not NULL, it will receive the number of
bytes actually scanned after a successful operation. */
gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
const void *buffer, size_t buflen,
size_t *nscanned);
/* Convert the big integer A into the external representation
described by FORMAT and store it in the provided BUFFER which has
been allocated by the user with a size of BUFLEN bytes. NWRITTEN
receives the actual length of the external representation unless it
has been passed as NULL. */
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 big integer A into the external representation described
by FORMAT and store it in a newly allocated buffer which address
will be put into BUFFER. NWRITTEN receives the actual lengths of the
external representation. */
gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format format,
unsigned char **buffer, size_t *nwritten,
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. */
void gcry_mpi_dump (const gcry_mpi_t a);
/* W = U + V. */
void gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
/* W = U + V. V is an unsigned integer. */
void gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v);
/* W = U + V mod M. */
void gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
/* W = U - V. */
void gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
/* W = U - V. V is an unsigned integer. */
void gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
/* W = U - V mod M */
void gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
/* W = U * V. */
void gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v);
/* W = U * V. V is an unsigned integer. */
void gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v );
/* W = U * V mod M. */
void gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m);
/* W = U * (2 ^ CNT). */
void gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt);
/* Q = DIVIDEND / DIVISOR, R = DIVIDEND % DIVISOR,
Q or R may be passed as NULL. ROUND should be negative or 0. */
void gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
gcry_mpi_t dividend, gcry_mpi_t divisor, int round);
/* R = DIVIDEND % DIVISOR */
void gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor);
/* W = B ^ E mod M. */
void gcry_mpi_powm (gcry_mpi_t w,
const gcry_mpi_t b, const gcry_mpi_t e,
const gcry_mpi_t m);
/* Set G to the greatest common divisor of A and B.
Return true if the G is 1. */
int gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b);
/* Set X to the multiplicative inverse of A mod M.
Return true if the value exists. */
int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m);
/* Create a new point object. NBITS is usually 0. */
gcry_mpi_point_t gcry_mpi_point_new (unsigned int nbits);
/* Release the object POINT. POINT may be NULL. */
void gcry_mpi_point_release (gcry_mpi_point_t point);
/* Return a copy of POINT. */
gcry_mpi_point_t gcry_mpi_point_copy (gcry_mpi_point_t point);
/* Store the projective coordinates from POINT into X, Y, and Z. */
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 X, Y, and Z and
release POINT. */
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 X, Y, and Z into POINT. */
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 X, Y, and Z into POINT and release
X, Y, and Z. */
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);
/* Allocate a new context for elliptic curve operations based on the
parameters given by KEYPARAM or using CURVENAME. */
gpg_error_t gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
gcry_sexp_t keyparam, const char *curvename);
/* Get a named MPI from an elliptic curve context. */
gcry_mpi_t gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy);
/* Get a named point from an elliptic curve context. */
gcry_mpi_point_t gcry_mpi_ec_get_point (const char *name,
gcry_ctx_t ctx, int copy);
/* Store a named MPI into an elliptic curve context. */
gpg_error_t gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
gcry_ctx_t ctx);
/* Store a named point into an elliptic curve context. */
gpg_error_t gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
gcry_ctx_t ctx);
/* Decode and store VALUE into RESULT. */
gpg_error_t gcry_mpi_ec_decode_point (gcry_mpi_point_t result,
gcry_mpi_t value, gcry_ctx_t ctx);
/* Store the affine coordinates of POINT into X and Y. */
int gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
gcry_ctx_t ctx);
/* W = 2 * U. */
void gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx);
/* W = U + V. */
void gcry_mpi_ec_add (gcry_mpi_point_t w,
gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx);
/* W = U - V. */
void gcry_mpi_ec_sub (gcry_mpi_point_t w,
gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx);
/* W = N * U. */
void gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u,
gcry_ctx_t ctx);
/* Return true if POINT is on the curve described by CTX. */
int gcry_mpi_ec_curve_point (gcry_mpi_point_t w, gcry_ctx_t ctx);
/* Return the number of bits required to represent A. */
unsigned int gcry_mpi_get_nbits (gcry_mpi_t a);
/* Return true when bit number N (counting from 0) is set in A. */
int gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n);
/* Set bit number N in A. */
void gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n);
/* Clear bit number N in A. */
void gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n);
/* Set bit number N in A and clear all bits greater than N. */
void gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n);
/* Clear bit number N in A and all bits greater than N. */
void gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n);
/* Shift the value of A by N bits to the right and store the result in X. */
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 left and store the result in X. */
void gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n);
/* Store NBITS of the value P points to in A and mark A as an opaque
value. On success A received the the ownership of the value P.
WARNING: Never use an opaque MPI for anything thing else than
gcry_mpi_release, gcry_mpi_get_opaque. */
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. The function takes a copy of the provided value P.
WARNING: Never use an opaque MPI for anything thing else than
gcry_mpi_release, gcry_mpi_get_opaque. */
gcry_mpi_t gcry_mpi_set_opaque_copy (gcry_mpi_t a,
const void *p, 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. */
void *gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits);
/* Set the FLAG for the big integer A. Currently only the flag
GCRYMPI_FLAG_SECURE is allowed to convert A into an big intger
stored in "secure" memory. */
void gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
/* Clear FLAG for the big integer A. Note that this function is
currently useless as no flags are allowed. */
void gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
/* Return true if the FLAG is set for A. */
int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
/* Private function - do not use. */
gcry_mpi_t _gcry_mpi_get_const (int no);
/* Unless the GCRYPT_NO_MPI_MACROS is used, provide a couple of
convenience macros for the big integer functions. */
#ifndef GCRYPT_NO_MPI_MACROS
#define mpi_new(n) gcry_mpi_new( (n) )
#define mpi_secure_new( n ) gcry_mpi_snew( (n) )
#define mpi_release(a) \
do \
{ \
gcry_mpi_release ((a)); \
(a) = NULL; \
} \
while (0)
#define mpi_copy( a ) gcry_mpi_copy( (a) )
#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) )
#define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) )
#define mpi_is_neg( a ) gcry_mpi_is_neg ((a))
#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v))
#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v))
#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m))
#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v))
#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v))
#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m))
#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v))
#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v))
#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v))
#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m))
#define mpi_powm(w,b,e,m) gcry_mpi_powm ( (w), (b), (e), (m) )
#define mpi_tdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), 0)
#define mpi_fdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), -1)
#define mpi_mod(r,a,m) gcry_mpi_mod ((r), (a), (m))
#define mpi_gcd(g,a,b) gcry_mpi_gcd ( (g), (a), (b) )
#define mpi_invm(g,a,b) gcry_mpi_invm ( (g), (a), (b) )
#define mpi_point_new(n) gcry_mpi_point_new((n))
#define mpi_point_release(p) \
do \
{ \
gcry_mpi_point_release ((p)); \
(p) = NULL; \
} \
while (0)
#define mpi_point_copy(p) gcry_mpi_point_copy((p))
#define mpi_point_get(x,y,z,p) gcry_mpi_point_get((x),(y),(z),(p))
#define mpi_point_snatch_get(x,y,z,p) gcry_mpi_point_snatch_get((x),(y),(z),(p))
#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_get_nbits(a) gcry_mpi_get_nbits ((a))
#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b))
#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b))
#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b))
#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b))
#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b))
#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c))
#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c))
#define mpi_set_opaque(a,b,c) gcry_mpi_set_opaque( (a), (b), (c) )
#define mpi_get_opaque(a,b) gcry_mpi_get_opaque( (a), (b) )
#endif /* GCRYPT_NO_MPI_MACROS */
/************************************
* *
* Symmetric Cipher Functions *
* *
************************************/
/* The data object used to hold a handle to an encryption object. */
struct gcry_cipher_handle;
typedef struct gcry_cipher_handle *gcry_cipher_hd_t;
#ifndef GCRYPT_NO_DEPRECATED
typedef struct gcry_cipher_handle *GCRY_CIPHER_HD _GCRY_GCC_ATTR_DEPRECATED;
typedef struct gcry_cipher_handle *GcryCipherHd _GCRY_GCC_ATTR_DEPRECATED;
#endif
/* All symmetric encryption algorithms are identified by their IDs.
More IDs may be registered at runtime. */
enum gcry_cipher_algos
{
GCRY_CIPHER_NONE = 0,
GCRY_CIPHER_IDEA = 1,
GCRY_CIPHER_3DES = 2,
GCRY_CIPHER_CAST5 = 3,
GCRY_CIPHER_BLOWFISH = 4,
GCRY_CIPHER_SAFER_SK128 = 5,
GCRY_CIPHER_DES_SK = 6,
GCRY_CIPHER_AES = 7,
GCRY_CIPHER_AES192 = 8,
GCRY_CIPHER_AES256 = 9,
GCRY_CIPHER_TWOFISH = 10,
/* Other cipher numbers are above 300 for OpenPGP reasons. */
GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */
GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */
GCRY_CIPHER_TWOFISH128 = 303,
GCRY_CIPHER_SERPENT128 = 304,
GCRY_CIPHER_SERPENT192 = 305,
GCRY_CIPHER_SERPENT256 = 306,
GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */
GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */
GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */
GCRY_CIPHER_CAMELLIA128 = 310,
GCRY_CIPHER_CAMELLIA192 = 311,
GCRY_CIPHER_CAMELLIA256 = 312,
GCRY_CIPHER_SALSA20 = 313,
GCRY_CIPHER_SALSA20R12 = 314,
GCRY_CIPHER_GOST28147 = 315,
GCRY_CIPHER_CHACHA20 = 316
};
/* The Rijndael algorithm is basically AES, so provide some macros. */
#define GCRY_CIPHER_AES128 GCRY_CIPHER_AES
#define GCRY_CIPHER_RIJNDAEL GCRY_CIPHER_AES
#define GCRY_CIPHER_RIJNDAEL128 GCRY_CIPHER_AES128
#define GCRY_CIPHER_RIJNDAEL192 GCRY_CIPHER_AES192
#define GCRY_CIPHER_RIJNDAEL256 GCRY_CIPHER_AES256
/* The supported encryption modes. Note that not all of them are
supported for each algorithm. */
enum gcry_cipher_modes
{
GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
GCRY_CIPHER_MODE_CTR = 6, /* Counter. */
GCRY_CIPHER_MODE_AESWRAP = 7, /* AES-WRAP algorithm. */
GCRY_CIPHER_MODE_CCM = 8, /* Counter with CBC-MAC. */
GCRY_CIPHER_MODE_GCM = 9, /* Galois Counter Mode. */
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_EAX = 14 /* EAX mode. */
};
/* Flags used with the open function. */
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). */
};
/* GCM works only with blocks of 128 bits */
#define GCRY_GCM_BLOCK_LEN (128 / 8)
/* CCM works only with blocks of 128 bits. */
#define GCRY_CCM_BLOCK_LEN (128 / 8)
/* OCB works only with blocks of 128 bits. */
#define GCRY_OCB_BLOCK_LEN (128 / 8)
/* XTS works only with blocks of 128 bits. */
#define GCRY_XTS_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,
int algo, int mode, unsigned int flags);
/* Close the cipher handle H and release all resource. */
void gcry_cipher_close (gcry_cipher_hd_t h);
/* Perform various operations on the cipher object H. */
gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer,
size_t buflen);
/* Retrieve various information about the cipher object H. */
gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer,
size_t *nbytes);
/* Retrieve various information about the cipher algorithm ALGO. */
gcry_error_t gcry_cipher_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
/* Map the cipher algorithm whose ID is contained in ALGORITHM to a
string representation of the algorithm name. For unknown algorithm
IDs this function returns "?". */
const char *gcry_cipher_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
/* Map the algorithm name NAME to an cipher algorithm ID. Return 0 if
the algorithm name is not known. */
int gcry_cipher_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
/* Given an ASN.1 object identifier in standard IETF dotted decimal
format in STRING, return the encryption mode associated with that
OID or 0 if not known or applicable. */
int gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE;
/* Encrypt the plaintext of size INLEN in IN using the cipher handle H
into the buffer OUT which has an allocated length of OUTSIZE. For
most algorithms it is possible to pass NULL for in and 0 for INLEN
and do a in-place decryption of the data provided in OUT. */
gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen);
/* The counterpart to gcry_cipher_encrypt. */
gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen);
/* Set KEY of length KEYLEN bytes for the cipher handle HD. */
gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd,
const void *key, size_t keylen);
/* Set initialization vector IV of length IVLEN for the cipher handle HD. */
gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd,
const void *iv, size_t ivlen);
/* Provide additional authentication data for AEAD modes/ciphers. */
gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
size_t abuflen);
/* Get authentication tag for AEAD modes/ciphers. */
gcry_error_t gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag,
size_t taglen);
/* Check authentication tag for AEAD modes/ciphers. */
gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag,
size_t taglen);
/* Reset the handle to the state after open. */
#define gcry_cipher_reset(h) gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0)
/* Perform the OpenPGP sync operation if this is enabled for the
cipher handle H. */
#define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, NULL, 0)
/* Enable or disable CTS in future calls to gcry_encrypt(). CBC mode only. */
#define gcry_cipher_cts(h,on) gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \
NULL, on )
#define gcry_cipher_set_sbox(h,oid) gcry_cipher_ctl( (h), GCRYCTL_SET_SBOX, \
(void *) oid, 0);
/* Indicate to the encrypt and decrypt functions that the next call
provides the final data. Only used with some modes. */
#define gcry_cipher_final(a) \
gcry_cipher_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
/* 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. */
gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd,
const void *ctr, size_t ctrlen);
/* Retrieve the key length in bytes used with algorithm A. */
size_t gcry_cipher_get_algo_keylen (int algo);
/* Retrieve the block length in bytes used with algorithm A. */
size_t gcry_cipher_get_algo_blklen (int algo);
/* Return 0 if the algorithm A is available for use. */
#define gcry_cipher_test_algo(a) \
gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/************************************
* *
* Asymmetric Cipher Functions *
* *
************************************/
/* The algorithms and their IDs we support. */
enum gcry_pk_algos
{
GCRY_PK_RSA = 1, /* RSA */
GCRY_PK_RSA_E = 2, /* (deprecated: use 1). */
GCRY_PK_RSA_S = 3, /* (deprecated: use 1). */
GCRY_PK_ELG_E = 16, /* (deprecated: use 20). */
GCRY_PK_DSA = 17, /* Digital Signature Algorithm. */
GCRY_PK_ECC = 18, /* Generic ECC. */
GCRY_PK_ELG = 20, /* Elgamal */
GCRY_PK_ECDSA = 301, /* (only for external use). */
GCRY_PK_ECDH = 302, /* (only for external use). */
GCRY_PK_EDDSA = 303 /* (only for external use). */
};
/* Flags describing usage capabilities of a PK algorithm. */
#define GCRY_PK_USAGE_SIGN 1 /* Good for signatures. */
#define GCRY_PK_USAGE_ENCR 2 /* Good for encryption. */
#define GCRY_PK_USAGE_CERT 4 /* Good to certify other keys. */
#define GCRY_PK_USAGE_AUTH 8 /* Good for authentication. */
#define GCRY_PK_USAGE_UNKN 128 /* Unknown usage flag. */
/* Modes used with gcry_pubkey_get_sexp. */
#define GCRY_PK_GET_PUBKEY 1
#define GCRY_PK_GET_SECKEY 2
/* Encrypt the DATA using the public key PKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t pkey);
/* Decrypt the DATA using the private key SKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_decrypt (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t skey);
/* Sign the DATA using the private key SKEY and store the result as
a newly created S-expression at RESULT. */
gcry_error_t gcry_pk_sign (gcry_sexp_t *result,
gcry_sexp_t data, gcry_sexp_t skey);
/* Check the signature SIGVAL on DATA using the public key PKEY. */
gcry_error_t gcry_pk_verify (gcry_sexp_t sigval,
gcry_sexp_t data, gcry_sexp_t pkey);
/* Check that private KEY is sane. */
gcry_error_t gcry_pk_testkey (gcry_sexp_t key);
/* Generate a new key pair according to the parameters given in
S_PARMS. The new key pair is returned in as an S-expression in
R_KEY. */
gcry_error_t gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms);
/* Catch all function for miscellaneous operations. */
gcry_error_t gcry_pk_ctl (int cmd, void *buffer, size_t buflen);
/* Retrieve information about the public key algorithm ALGO. */
gcry_error_t gcry_pk_algo_info (int algo, int what,
void *buffer, size_t *nbytes);
/* Map the public key algorithm whose ID is contained in ALGORITHM to
a string representation of the algorithm name. For unknown
algorithm IDs this functions returns "?". */
const char *gcry_pk_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
/* Map the algorithm NAME to a public key algorithm Id. Return 0 if
the algorithm name is not known. */
int gcry_pk_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
/* Return what is commonly referred as the key length for the given
public or private KEY. */
unsigned int gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE;
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
key parameters expressed in a way depending on the algorithm. */
unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array);
/* Return the name of the curve matching KEY. */
const char *gcry_pk_get_curve (gcry_sexp_t key, int iterator,
unsigned int *r_nbits);
/* Return an S-expression with the parameters of the named ECC curve
NAME. ALGO must be set to an ECC algorithm. */
gcry_sexp_t gcry_pk_get_param (int algo, const char *name);
/* Return 0 if the public key algorithm A is available for use. */
#define gcry_pk_test_algo(a) \
gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/* 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);
/************************************
* *
* Cryptograhic Hash Functions *
* *
************************************/
/* Algorithm IDs for the hash functions we know about. Not all of them
are implemented. */
enum gcry_md_algos
{
GCRY_MD_NONE = 0,
GCRY_MD_MD5 = 1,
GCRY_MD_SHA1 = 2,
GCRY_MD_RMD160 = 3,
GCRY_MD_MD2 = 5,
GCRY_MD_TIGER = 6, /* TIGER/192 as used by gpg <= 1.3.2. */
GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
GCRY_MD_SHA256 = 8,
GCRY_MD_SHA384 = 9,
GCRY_MD_SHA512 = 10,
GCRY_MD_SHA224 = 11,
GCRY_MD_MD4 = 301,
GCRY_MD_CRC32 = 302,
GCRY_MD_CRC32_RFC1510 = 303,
GCRY_MD_CRC24_RFC2440 = 304,
GCRY_MD_WHIRLPOOL = 305,
GCRY_MD_TIGER1 = 306, /* TIGER fixed. */
GCRY_MD_TIGER2 = 307, /* TIGER2 variant. */
GCRY_MD_GOSTR3411_94 = 308, /* GOST R 34.11-94. */
GCRY_MD_STRIBOG256 = 309, /* GOST R 34.11-2012, 256 bit. */
GCRY_MD_STRIBOG512 = 310, /* GOST R 34.11-2012, 512 bit. */
GCRY_MD_GOSTR3411_CP = 311, /* GOST R 34.11-94 with CryptoPro-A S-Box. */
GCRY_MD_SHA3_224 = 312,
GCRY_MD_SHA3_256 = 313,
GCRY_MD_SHA3_384 = 314,
GCRY_MD_SHA3_512 = 315,
GCRY_MD_SHAKE128 = 316,
GCRY_MD_SHAKE256 = 317,
GCRY_MD_BLAKE2B_512 = 318,
GCRY_MD_BLAKE2B_384 = 319,
GCRY_MD_BLAKE2B_256 = 320,
GCRY_MD_BLAKE2B_160 = 321,
GCRY_MD_BLAKE2S_256 = 322,
GCRY_MD_BLAKE2S_224 = 323,
GCRY_MD_BLAKE2S_160 = 324,
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. */
enum gcry_md_flags
{
GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */
GCRY_MD_FLAG_HMAC = 2, /* Make an HMAC out of this algorithm. */
GCRY_MD_FLAG_BUGEMU1 = 0x0100
};
/* (Forward declaration.) */
struct gcry_md_context;
/* This object is used to hold a handle to a message digest object.
This structure is private - only to be used by the public gcry_md_*
macros. */
typedef struct gcry_md_handle
{
/* Actual context. */
struct gcry_md_context *ctx;
/* Buffer management. */
int bufpos;
int bufsize;
unsigned char buf[1];
} *gcry_md_hd_t;
/* Compatibility types, do not use them. */
#ifndef GCRYPT_NO_DEPRECATED
typedef struct gcry_md_handle *GCRY_MD_HD _GCRY_GCC_ATTR_DEPRECATED;
typedef struct gcry_md_handle *GcryMDHd _GCRY_GCC_ATTR_DEPRECATED;
#endif
/* Create a message digest object for algorithm ALGO. FLAGS may be
given as an bitwise OR of the gcry_md_flags values. ALGO may be
given as 0 if the algorithms to be used are later set using
gcry_md_enable. */
gcry_error_t gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags);
/* Release the message digest object HD. */
void gcry_md_close (gcry_md_hd_t hd);
/* Add the message digest algorithm ALGO to the digest object HD. */
gcry_error_t gcry_md_enable (gcry_md_hd_t hd, int algo);
/* Create a new digest object as an exact copy of the object HD. */
gcry_error_t gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd);
/* Reset the digest object HD to its initial state. */
void gcry_md_reset (gcry_md_hd_t hd);
/* Perform various operations on the digest object HD. */
gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd,
void *buffer, size_t buflen);
/* Pass LENGTH bytes of data in BUFFER to the digest object HD so that
it can update the digest values. This is the actual hash
function. */
void gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
/* Read out the final digest from HD return the digest value for
algorithm ALGO. */
unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo);
/* Read more output from algorithm ALGO to BUFFER of size LENGTH from
* digest object HD. Algorithm needs to be 'expendable-output function'. */
gpg_error_t gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer,
size_t length);
/* Convenience function to calculate the hash from the data in BUFFER
of size LENGTH using the algorithm ALGO avoiding the creation of a
hash object. The hash is returned in the caller provided buffer
DIGEST which must be large enough to hold the digest of the given
algorithm. */
void gcry_md_hash_buffer (int algo, void *digest,
const void *buffer, size_t length);
/* Convenience function to hash multiple buffers. */
gpg_error_t gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
const gcry_buffer_t *iov, int iovcnt);
/* Retrieve the algorithm used with HD. This does not work reliable
if more than one algorithm is enabled in HD. */
int gcry_md_get_algo (gcry_md_hd_t hd);
/* Retrieve the length in bytes of the digest yielded by algorithm
ALGO. */
unsigned int gcry_md_get_algo_dlen (int algo);
/* Return true if the the algorithm ALGO is enabled in the digest
object A. */
int gcry_md_is_enabled (gcry_md_hd_t a, int algo);
/* Return true if the digest object A is allocated in "secure" memory. */
int gcry_md_is_secure (gcry_md_hd_t a);
/* Deprecated: Use gcry_md_is_enabled or gcry_md_is_secure. */
gcry_error_t gcry_md_info (gcry_md_hd_t h, int what, void *buffer,
size_t *nbytes) _GCRY_ATTR_INTERNAL;
/* Retrieve various information about the algorithm ALGO. */
gcry_error_t gcry_md_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
/* Map the digest algorithm id ALGO to a string representation of the
algorithm name. For unknown algorithms this function returns
"?". */
const char *gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
/* Map the algorithm NAME to a digest algorithm Id. Return 0 if
the algorithm name is not known. */
int gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
/* For use with the HMAC feature, the set MAC key to the KEY of
KEYLEN bytes. */
gcry_error_t gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen);
/* Start or stop debugging for digest handle HD; i.e. create a file
named dbgmd-<n>.<suffix> while hashing. If SUFFIX is NULL,
debugging stops and the file will be closed. */
void gcry_md_debug (gcry_md_hd_t hd, const char *suffix);
/* Update the hash(s) of H with the character C. This is a buffered
version of the gcry_md_write function. */
#define gcry_md_putc(h,c) \
do { \
gcry_md_hd_t h__ = (h); \
if( (h__)->bufpos == (h__)->bufsize ) \
gcry_md_write( (h__), NULL, 0 ); \
(h__)->buf[(h__)->bufpos++] = (c) & 0xff; \
} while(0)
/* Finalize the digest calculation. This is not really needed because
gcry_md_read() does this implicitly. */
#define gcry_md_final(a) \
gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0)
/* Return 0 if the algorithm A is available for use. */
#define gcry_md_test_algo(a) \
gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/* Return an DER encoded ASN.1 OID for the algorithm A in buffer B. N
must point to size_t variable with the available size of buffer B.
After return it will receive the actual size of the returned
OID. */
#define gcry_md_get_asnoid(a,b,n) \
gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n))
/**********************************************
* *
* Message Authentication Code Functions *
* *
**********************************************/
/* The data object used to hold a handle to an encryption object. */
struct gcry_mac_handle;
typedef struct gcry_mac_handle *gcry_mac_hd_t;
/* Algorithm IDs for the hash functions we know about. Not all of them
are implemented. */
enum gcry_mac_algos
{
GCRY_MAC_NONE = 0,
GCRY_MAC_HMAC_SHA256 = 101,
GCRY_MAC_HMAC_SHA224 = 102,
GCRY_MAC_HMAC_SHA512 = 103,
GCRY_MAC_HMAC_SHA384 = 104,
GCRY_MAC_HMAC_SHA1 = 105,
GCRY_MAC_HMAC_MD5 = 106,
GCRY_MAC_HMAC_MD4 = 107,
GCRY_MAC_HMAC_RMD160 = 108,
GCRY_MAC_HMAC_TIGER1 = 109, /* The fixed TIGER variant */
GCRY_MAC_HMAC_WHIRLPOOL = 110,
GCRY_MAC_HMAC_GOSTR3411_94 = 111,
GCRY_MAC_HMAC_STRIBOG256 = 112,
GCRY_MAC_HMAC_STRIBOG512 = 113,
GCRY_MAC_HMAC_MD2 = 114,
GCRY_MAC_HMAC_SHA3_224 = 115,
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,
GCRY_MAC_CMAC_CAMELLIA = 203,
GCRY_MAC_CMAC_CAST5 = 204,
GCRY_MAC_CMAC_BLOWFISH = 205,
GCRY_MAC_CMAC_TWOFISH = 206,
GCRY_MAC_CMAC_SERPENT = 207,
GCRY_MAC_CMAC_SEED = 208,
GCRY_MAC_CMAC_RFC2268 = 209,
GCRY_MAC_CMAC_IDEA = 210,
GCRY_MAC_CMAC_GOST28147 = 211,
GCRY_MAC_GMAC_AES = 401,
GCRY_MAC_GMAC_CAMELLIA = 402,
GCRY_MAC_GMAC_TWOFISH = 403,
GCRY_MAC_GMAC_SERPENT = 404,
GCRY_MAC_GMAC_SEED = 405,
GCRY_MAC_POLY1305 = 501,
GCRY_MAC_POLY1305_AES = 502,
GCRY_MAC_POLY1305_CAMELLIA = 503,
GCRY_MAC_POLY1305_TWOFISH = 504,
GCRY_MAC_POLY1305_SERPENT = 505,
GCRY_MAC_POLY1305_SEED = 506
};
/* Flags used with the open function. */
enum gcry_mac_flags
{
GCRY_MAC_FLAG_SECURE = 1 /* Allocate all buffers in "secure" memory. */
};
/* Create a MAC handle for algorithm ALGO. FLAGS may be given as an bitwise OR
of the gcry_mac_flags values. CTX maybe NULL or gcry_ctx_t object to be
associated with HANDLE. */
gcry_error_t gcry_mac_open (gcry_mac_hd_t *handle, int algo,
unsigned int flags, gcry_ctx_t ctx);
/* Close the MAC handle H and release all resource. */
void gcry_mac_close (gcry_mac_hd_t h);
/* Perform various operations on the MAC object H. */
gcry_error_t gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer,
size_t buflen);
/* Retrieve various information about the MAC algorithm ALGO. */
gcry_error_t gcry_mac_algo_info (int algo, int what, void *buffer,
size_t *nbytes);
/* Set KEY of length KEYLEN bytes for the MAC handle HD. */
gcry_error_t gcry_mac_setkey (gcry_mac_hd_t hd, const void *key,
size_t keylen);
/* Set initialization vector IV of length IVLEN for the MAC handle HD. */
gcry_error_t gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv,
size_t ivlen);
/* Pass LENGTH bytes of data in BUFFER to the MAC object HD so that
it can update the MAC values. */
gcry_error_t gcry_mac_write (gcry_mac_hd_t hd, const void *buffer,
size_t length);
/* Read out the final authentication code from the MAC object HD to BUFFER. */
gcry_error_t gcry_mac_read (gcry_mac_hd_t hd, void *buffer, size_t *buflen);
/* Verify the final authentication code from the MAC object HD with BUFFER. */
gcry_error_t gcry_mac_verify (gcry_mac_hd_t hd, const void *buffer,
size_t buflen);
/* Retrieve the algorithm used with MAC. */
int gcry_mac_get_algo (gcry_mac_hd_t hd);
/* Retrieve the length in bytes of the MAC yielded by algorithm ALGO. */
unsigned int gcry_mac_get_algo_maclen (int algo);
/* Retrieve the default key length in bytes used with algorithm A. */
unsigned int gcry_mac_get_algo_keylen (int algo);
/* Map the MAC algorithm whose ID is contained in ALGORITHM to a
string representation of the algorithm name. For unknown algorithm
IDs this function returns "?". */
const char *gcry_mac_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE;
/* Map the algorithm name NAME to an MAC algorithm ID. Return 0 if
the algorithm name is not known. */
int gcry_mac_map_name (const char *name) _GCRY_GCC_ATTR_PURE;
/* Reset the handle to the state after open/setkey. */
#define gcry_mac_reset(h) gcry_mac_ctl ((h), GCRYCTL_RESET, NULL, 0)
/* Return 0 if the algorithm A is available for use. */
#define gcry_mac_test_algo(a) \
gcry_mac_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
/******************************
* *
* Key Derivation Functions *
* *
******************************/
/* Algorithm IDs for the KDFs. */
enum gcry_kdf_algos
{
GCRY_KDF_NONE = 0,
GCRY_KDF_SIMPLE_S2K = 16,
GCRY_KDF_SALTED_S2K = 17,
GCRY_KDF_ITERSALTED_S2K = 19,
GCRY_KDF_PBKDF1 = 33,
GCRY_KDF_PBKDF2 = 34,
GCRY_KDF_SCRYPT = 48
};
/* Derive a key from a passphrase. */
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);
/************************************
* *
* Random Generating Functions *
* *
************************************/
/* The type of the random number generator. */
enum gcry_rng_types
{
GCRY_RNG_TYPE_STANDARD = 1, /* The default CSPRNG generator. */
GCRY_RNG_TYPE_FIPS = 2, /* The FIPS X9.31 AES generator. */
GCRY_RNG_TYPE_SYSTEM = 3 /* The system's native generator. */
};
/* The possible values for the random quality. The rule of thumb is
to use STRONG for session keys and VERY_STRONG for key material.
WEAK is usually an alias for STRONG and should not be used anymore
(except with gcry_mpi_randomize); use gcry_create_nonce instead. */
typedef enum gcry_random_level
{
GCRY_WEAK_RANDOM = 0,
GCRY_STRONG_RANDOM = 1,
GCRY_VERY_STRONG_RANDOM = 2
}
gcry_random_level_t;
/* Fill BUFFER with LENGTH bytes of random, using random numbers of
quality LEVEL. */
void gcry_randomize (void *buffer, size_t length,
enum gcry_random_level level);
/* Add the external random from BUFFER with LENGTH bytes into the
pool. QUALITY should either be -1 for unknown or in the range of 0
to 100 */
gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length,
int quality);
/* If random numbers are used in an application, this macro should be
called from time to time so that new stuff gets added to the
internal pool of the RNG. */
#define gcry_fast_random_poll() gcry_control (GCRYCTL_FAST_POLL, NULL)
/* Return NBYTES of allocated random using a random numbers of quality
LEVEL. */
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. */
void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
_GCRY_GCC_ATTR_MALLOC;
/* Set the big integer W to a random value of NBITS using a random
generator with quality LEVEL. Note that by using a level of
GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */
void gcry_mpi_randomize (gcry_mpi_t w,
unsigned int nbits, enum gcry_random_level level);
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
void gcry_create_nonce (void *buffer, size_t length);
/*******************************/
/* */
/* Prime Number Functions */
/* */
/*******************************/
/* Mode values passed to a gcry_prime_check_func_t. */
#define GCRY_PRIME_CHECK_AT_FINISH 0
#define GCRY_PRIME_CHECK_AT_GOT_PRIME 1
#define GCRY_PRIME_CHECK_AT_MAYBE_PRIME 2
/* The function should return 1 if the operation shall continue, 0 to
reject the prime candidate. */
typedef int (*gcry_prime_check_func_t) (void *arg, int mode,
gcry_mpi_t candidate);
/* Flags for gcry_prime_generate(): */
/* Allocate prime numbers and factors in secure memory. */
#define GCRY_PRIME_FLAG_SECRET (1 << 0)
/* Make sure that at least one prime factor is of size
`FACTOR_BITS'. */
#define GCRY_PRIME_FLAG_SPECIAL_FACTOR (1 << 1)
/* 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. */
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);
/* 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. */
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);
/* Convenience function to release the FACTORS array. */
void gcry_prime_release_factors (gcry_mpi_t *factors);
/* Check whether the number X is prime. */
gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags);
/************************************
* *
* Miscellaneous Stuff *
* *
************************************/
/* Release the context object CTX. */
void gcry_ctx_release (gcry_ctx_t ctx);
/* Log data using Libgcrypt's own log interface. */
void gcry_log_debug (const char *fmt, ...) _GCRY_GCC_ATTR_PRINTF(1,2);
void gcry_log_debughex (const char *text, const void *buffer, size_t length);
void gcry_log_debugmpi (const char *text, gcry_mpi_t mpi);
void gcry_log_debugpnt (const char *text,
gcry_mpi_point_t point, gcry_ctx_t ctx);
void gcry_log_debugsxp (const char *text, gcry_sexp_t sexp);
char *gcry_get_config (int mode, const char *what);
/* Log levels used by the internal logging facility. */
enum gcry_log_levels
{
GCRY_LOG_CONT = 0, /* (Continue the last log line.) */
GCRY_LOG_INFO = 10,
GCRY_LOG_WARN = 20,
GCRY_LOG_ERROR = 30,
GCRY_LOG_FATAL = 40,
GCRY_LOG_BUG = 50,
GCRY_LOG_DEBUG = 100
};
/* Type for progress handlers. */
typedef void (*gcry_handler_progress_t) (void *, const char *, int, int, int);
/* Type for memory allocation handlers. */
typedef void *(*gcry_handler_alloc_t) (size_t n);
/* Type for secure memory check handlers. */
typedef int (*gcry_handler_secure_check_t) (const void *);
/* Type for memory reallocation handlers. */
typedef void *(*gcry_handler_realloc_t) (void *p, size_t n);
/* Type for memory free handlers. */
typedef void (*gcry_handler_free_t) (void *);
/* Type for out-of-memory handlers. */
typedef int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int);
/* Type for fatal error handlers. */
typedef void (*gcry_handler_error_t) (void *, int, const char *);
/* Type for logging handlers. */
typedef void (*gcry_handler_log_t) (void *, int, const char *, va_list);
/* Certain operations can provide progress information. This function
is used to register a handler for retrieving these information. */
void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
/* Register a custom memory allocation functions. */
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);
/* Register a function used instead of the internal out of memory
handler. */
void gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque);
/* Register a function used instead of the internal fatal error
handler. */
void gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque);
/* Register a function used instead of the internal logging
facility. */
void gcry_set_log_handler (gcry_handler_log_t f, void *opaque);
/* Reserved for future use. */
void gcry_set_gettext_handler (const char *(*f)(const char*));
/* Libgcrypt uses its own memory allocation. It is important to use
gcry_free () to release memory allocated by libgcrypt. */
void *gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *gcry_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *gcry_calloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *gcry_realloc (void *a, size_t n);
char *gcry_strdup (const char *string) _GCRY_GCC_ATTR_MALLOC;
void *gcry_xmalloc (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *gcry_xcalloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *gcry_xmalloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC;
void *gcry_xcalloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC;
void *gcry_xrealloc (void *a, size_t n);
char *gcry_xstrdup (const char * a) _GCRY_GCC_ATTR_MALLOC;
void gcry_free (void *a);
/* Return true if A is allocated in "secure" memory. */
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)
#if 0 /* (Keep Emacsens' auto-indent happy.) */
{
#endif
#ifdef __cplusplus
}
#endif
#endif /* _GCRYPT_H */
/*
@emacs_local_vars_begin@
@emacs_local_vars_read_only@
@emacs_local_vars_end@
*/
diff --git a/src/gcryptrnd.c b/src/gcryptrnd.c
index b13931b6..fded8f34 100644
--- a/src/gcryptrnd.c
+++ b/src/gcryptrnd.c
@@ -1,680 +1,680 @@
/* gcryptrnd.c - Libgcrypt Random Number Daemon
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Gcryptend 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.
*
* Gcryptrnd is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/* We require vsyslog pth
We need to test for: setrlimit
We should also prioritize requests. This is best done by putting
the requests into queues and have a main thread processing these
queues.
*/
#include <config.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#include <pth.h>
#include <gcrypt.h>
#define PGM "gcryptrnd"
#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
/* Pth wrapper function definitions. */
GCRY_THREAD_OPTION_PTH_IMPL;
/* Flag set to true if we have been daemonized. */
static int running_detached;
/* Flag indicating that a shutdown has been requested. */
static int shutdown_pending;
/* Counter for active connections. */
static int active_connections;
/* Local prototypes. */
static void serve (int listen_fd);
/* 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); \
while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
} while(0)
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
/* Error printing utility. PRIORITY should be one of syslog's
priority levels. This functions prints to the stderr or syslog
depending on whether we are already daemonized. */
static void
logit (int priority, const char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format) ;
if (running_detached)
{
vsyslog (priority, format, arg_ptr);
}
else
{
fputs (PGM ": ", stderr);
vfprintf (stderr, format, arg_ptr);
putc ('\n', stderr);
}
va_end (arg_ptr);
}
/* Callback used by libgcrypt for logging. */
static void
my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr)
{
(void)dummy;
/* Map the log levels. */
switch (level)
{
case GCRY_LOG_CONT: level = LOG_INFO /* FIXME */; break;
case GCRY_LOG_INFO: level = LOG_INFO; break;
case GCRY_LOG_WARN: level = LOG_WARNING; break;
case GCRY_LOG_ERROR:level = LOG_ERR; break;
case GCRY_LOG_FATAL:level = LOG_CRIT; break;
case GCRY_LOG_BUG: level = LOG_CRIT; break;
case GCRY_LOG_DEBUG:level = LOG_DEBUG; break;
default: level = LOG_ERR; break;
}
if (running_detached)
{
vsyslog (level, format, arg_ptr);
}
else
{
fputs (PGM ": ", stderr);
vfprintf (stderr, format, arg_ptr);
if (!*format || format[strlen (format)-1] != '\n')
putc ('\n', stderr);
}
}
/* The cleanup handler - used to wipe out the secure memory. */
static void
cleanup (void)
{
gcry_control (GCRYCTL_TERM_SECMEM );
}
/* Make us a daemon and open the syslog. */
static void
daemonize (void)
{
int i;
pid_t pid;
fflush (NULL);
pid = fork ();
if (pid == (pid_t)-1)
{
logit (LOG_CRIT, "fork failed: %s", strerror (errno));
exit (1);
}
if (pid)
exit (0);
if (setsid() == -1)
{
logit (LOG_CRIT, "setsid() failed: %s", strerror(errno));
exit (1);
}
signal (SIGHUP, SIG_IGN);
pid = fork ();
if (pid == (pid_t)-1)
{
logit (LOG_CRIT, PGM ": second fork failed: %s", strerror (errno));
exit (1);
}
if (pid)
exit (0); /* First child exits. */
running_detached = 1;
if (chdir("/"))
{
logit (LOG_CRIT, "chdir(\"/\") failed: %s", strerror (errno));
exit (1);
}
umask (0);
for (i=0; i <= 2; i++)
close (i);
openlog (PGM, LOG_PID, LOG_DAEMON);
}
static void
disable_core_dumps (void)
{
#ifdef HAVE_SETRLIMIT
struct rlimit limit;
if (getrlimit (RLIMIT_CORE, &limit))
limit.rlim_max = 0;
limit.rlim_cur = 0;
if( !setrlimit (RLIMIT_CORE, &limit) )
return 0;
if (errno != EINVAL && errno != ENOSYS)
logit (LOG_ERR, "can't disable core dumps: %s\n", strerror (errno));
#endif /* HAVE_SETRLIMIT */
}
static void
print_version (int with_help)
{
fputs (MYVERSION_LINE "\n"
"Copyright (C) 2006 Free Software Foundation, Inc.\n"
"License GPLv2+: GNU GPL version 2 or later "
- "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
+ "<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\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);
if (with_help)
fputs ("\n"
"Usage: " PGM " [OPTIONS] [SOCKETNAME]\n"
"Start Libgcrypt's random number daemon listening"
" on socket SOCKETNAME\n"
"SOCKETNAME defaults to XXX\n"
"\n"
" --no-detach do not deatach from the console\n"
" --version print version of the program and exit\n"
" --help display this help and exit\n"
BUGREPORT_LINE, stdout );
exit (0);
}
static int
print_usage (void)
{
fputs ("usage: " PGM " [OPTIONS] [SOCKETNAME]\n", stderr);
fputs (" (use --help to display options)\n", stderr);
exit (1);
}
int
main (int argc, char **argv)
{
int no_detach = 0;
gpg_error_t err;
struct sockaddr_un *srvr_addr;
socklen_t addrlen;
int fd;
int rc;
const char *socketname = "/var/run/libgcrypt/S.gcryptrnd";
if (argc)
{
argc--; argv++;
}
while (argc && **argv == '-' && (*argv)[1] == '-')
{
if (!(*argv)[2])
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version"))
print_version (0);
else if (!strcmp (*argv, "--help"))
print_version (1);
else if (!strcmp (*argv, "--no-detach"))
{
no_detach = 1;
argc--; argv++;
}
else
print_usage ();
}
if (argc == 1)
socketname = argv[0];
else if (argc > 1)
print_usage ();
if (!no_detach)
daemonize ();
signal (SIGPIPE, SIG_IGN);
logit (LOG_NOTICE, "started version " VERSION );
/* Libgcrypt requires us to register the threading model before we
do anything else with it. Note that this also calls pth_init. We
do the initialization while already running as a daemon to avoid
overhead with double initialization of Libgcrypt. */
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
if (err)
{
logit (LOG_CRIT, "can't register GNU Pth with Libgcrypt: %s",
gpg_strerror (err));
exit (1);
}
/* Check that the libgcrypt version is sufficient. */
if (!gcry_check_version (VERSION) )
{
logit (LOG_CRIT, "libgcrypt is too old (need %s, have %s)",
VERSION, gcry_check_version (NULL) );
exit (1);
}
/* Register the logging callback and tell Libcgrypt to put the
random pool into secure memory. */
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
/* Obviously we don't want to allow any core dumps. */
disable_core_dumps ();
/* Initialize the secure memory stuff which will also drop any extra
privileges we have. */
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
/* Register a cleanup handler. */
atexit (cleanup);
/* Create and listen on the socket. */
fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
{
logit (LOG_CRIT, "can't create socket: %s", strerror (errno));
exit (1);
}
srvr_addr = gcry_xmalloc (sizeof *srvr_addr);
memset (srvr_addr, 0, sizeof *srvr_addr);
srvr_addr->sun_family = AF_UNIX;
if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
{
logit (LOG_CRIT, "socket name `%s' too long", socketname);
exit (1);
}
strcpy (srvr_addr->sun_path, socketname);
addrlen = (offsetof (struct sockaddr_un, sun_path)
+ strlen (srvr_addr->sun_path) + 1);
rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen);
if (rc == -1 && errno == EADDRINUSE)
{
remove (socketname);
rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen);
}
if (rc == -1)
{
logit (LOG_CRIT, "error binding socket to `%s': %s",
srvr_addr->sun_path, strerror (errno));
close (fd);
exit (1);
}
if (listen (fd, 5 ) == -1)
{
logit (LOG_CRIT, "listen() failed: %s", strerror (errno));
close (fd);
exit (1);
}
logit (LOG_INFO, "listening on socket `%s', fd=%d",
srvr_addr->sun_path, fd);
serve (fd);
close (fd);
logit (LOG_NOTICE, "stopped version " VERSION );
return 0;
}
/* 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)
{
while (length)
{
ssize_t n = pth_write (fd, buffer, length);
if (n < 0)
{
logit (LOG_ERR, "connection %d: write error: %s",
fd, strerror (errno));
return -1; /* write error */
}
length -= n;
buffer = (const char*)buffer + n;
}
return 0; /* Okay */
}
/* Send an error response back. Returns 0 on success. */
static int
send_error (int fd, int errcode)
{
unsigned char buf[2];
buf[0] = errcode;
buf[1] = 0;
return writen (fd, buf, 2 );
}
/* Send a pong response back. Returns 0 on success or another value
on write error. */
static int
send_pong (int fd)
{
return writen (fd, "\x00\x04pong", 6);
}
/* Send a nonce of size LENGTH back. Return 0 on success. */
static int
send_nonce (int fd, int length)
{
unsigned char buf[2+255];
int rc;
assert (length >= 0 && length <= 255);
buf[0] = 0;
buf[1] = length;
gcry_create_nonce (buf+2, length);
rc = writen (fd, buf, 2+length );
wipememory (buf+2, length);
return rc;
}
/* Send a random of size LENGTH with quality LEVEL back. Return 0 on
success. */
static int
send_random (int fd, int length, int level)
{
unsigned char buf[2+255];
int rc;
assert (length >= 0 && length <= 255);
assert (level == GCRY_STRONG_RANDOM || level == GCRY_VERY_STRONG_RANDOM);
buf[0] = 0;
buf[1] = length;
/* Note that we don't bother putting the random stuff into secure
memory because this daemon is anyway intended to be run under
root and it is questionable whether the kernel buffers etc. are
equally well protected. */
gcry_randomize (buf+2, length, level);
rc = writen (fd, buf, 2+length );
wipememory (buf+2, length);
return rc;
}
/* Main processing loop for a connection.
A request is made up of:
1 byte Total length of request; must be 3
1 byte Command
0 = Ping
10 = GetNonce
11 = GetStrongRandom
12 = GetVeryStrongRandom
(all other values are reserved)
1 byte Number of requested bytes.
This is ignored for command Ping.
A response is made up of:
1 byte Error Code
0 = Everything is fine
1 = Bad Command
0xff = Other error.
(For a bad request the connection will simply be closed)
1 byte Length of data
n byte data
The requests are read as long as the connection is open.
*/
static void
connection_loop (int fd)
{
unsigned char request[3];
unsigned char *p;
int nleft, n;
int rc;
for (;;)
{
for (nleft=3, p=request; nleft > 0; )
{
n = pth_read (fd, p, nleft);
if (!n && p == request)
return; /* Client terminated connection. */
if (n <= 0)
{
logit (LOG_ERR, "connection %d: read error: %s",
fd, n? strerror (errno) : "Unexpected EOF");
return;
}
p += n;
nleft -= n;
}
if (request[0] != 3)
{
logit (LOG_ERR, "connection %d: invalid length (%d) of request",
fd, request[0]);
return;
}
switch (request[1])
{
case 0: /* Ping */
rc = send_pong (fd);
break;
case 10: /* GetNonce */
rc = send_nonce (fd, request[2]);
break;
case 11: /* GetStrongRandom */
rc = send_random (fd, request[2], GCRY_STRONG_RANDOM);
break;
case 12: /* GetVeryStrongRandom */
rc = send_random (fd, request[2], GCRY_VERY_STRONG_RANDOM);
break;
default: /* Invalid command */
rc = send_error (fd, 1);
break;
}
if (rc)
break; /* A write error occurred while sending the response. */
}
}
/* Entry point for a connection's thread. */
static void *
connection_thread (void *arg)
{
int fd = (int)arg;
active_connections++;
logit (LOG_INFO, "connection handler for fd %d started", fd);
connection_loop (fd);
close (fd);
logit (LOG_INFO, "connection handler for fd %d terminated", fd);
active_connections--;
return NULL;
}
/* This signal handler is called from the main loop between acepting
connections. It is called on the regular stack, thus no special
caution needs to be taken. It returns true to indicate that the
process should terminate. */
static int
handle_signal (int signo)
{
switch (signo)
{
case SIGHUP:
logit (LOG_NOTICE, "SIGHUP received - re-reading configuration");
break;
case SIGUSR1:
logit (LOG_NOTICE, "SIGUSR1 received - no action defined");
break;
case SIGUSR2:
logit (LOG_NOTICE, "SIGUSR2 received - no action defined");
break;
case SIGTERM:
if (!shutdown_pending)
logit (LOG_NOTICE, "SIGTERM received - shutting down ...");
else
logit (LOG_NOTICE, "SIGTERM received - still %d active connections",
active_connections);
shutdown_pending++;
if (shutdown_pending > 2)
{
logit (LOG_NOTICE, "shutdown forced");
return 1;
}
break;
case SIGINT:
logit (LOG_NOTICE, "SIGINT received - immediate shutdown");
return 1;
default:
logit (LOG_NOTICE, "signal %d received - no action defined\n", signo);
}
return 0;
}
/* Main server loop. This is called with the FD of the listening
socket. */
static void
serve (int listen_fd)
{
pth_attr_t tattr;
pth_event_t ev;
sigset_t sigs;
int signo;
struct sockaddr_un paddr;
socklen_t plen = sizeof (paddr);
int fd;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "connection");
sigemptyset (&sigs);
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
for (;;)
{
if (shutdown_pending)
{
if (!active_connections)
break; /* Ready. */
/* Do not accept anymore connections but wait for existing
connections to terminate. */
signo = 0;
pth_wait (ev);
if (pth_event_occurred (ev) && signo)
if (handle_signal (signo))
break; /* Stop the loop. */
continue;
}
gcry_fast_random_poll ();
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
if (fd == -1)
{
if (pth_event_occurred (ev))
{
if (handle_signal (signo))
break; /* Stop the loop. */
continue;
}
logit (LOG_WARNING, "accept failed: %s - waiting 1s\n",
strerror (errno));
gcry_fast_random_poll ();
pth_sleep (1);
continue;
}
if (!pth_spawn (tattr, connection_thread, (void*)fd))
{
logit (LOG_ERR, "error spawning connection handler: %s\n",
strerror (errno) );
close (fd);
}
}
pth_event_free (ev, PTH_FREE_ALL);
}
diff --git a/src/getrandom.c b/src/getrandom.c
index f9bb5c0c..588766ac 100644
--- a/src/getrandom.c
+++ b/src/getrandom.c
@@ -1,326 +1,326 @@
/* getrandom.c - Libgcrypt Random Number client
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Getrandom 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.
*
* Getrandom is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <config.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <errno.h>
#define PGM "getrandom"
#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
static void
logit (const char *format, ...)
{
va_list arg_ptr;
va_start (arg_ptr, format) ;
fputs (PGM ": ", stderr);
vfprintf (stderr, format, arg_ptr);
putc ('\n', stderr);
va_end (arg_ptr);
}
/* 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)
{
while (length)
{
ssize_t n;
do
n = write (fd, buffer, length);
while (n < 0 && errno == EINTR);
if (n < 0)
{
logit ("write error: %s", strerror (errno));
return -1; /* write error */
}
length -= n;
buffer = (const char *)buffer + n;
}
return 0; /* Okay */
}
static void
print_version (int with_help)
{
fputs (MYVERSION_LINE "\n"
"Copyright (C) 2006 Free Software Foundation, Inc.\n"
"License GPLv2+: GNU GPL version 2 or later "
- "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n"
+ "<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\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);
if (with_help)
fputs ("\n"
"Usage: " PGM " [OPTIONS] NBYTES\n"
"Connect to libgcrypt's random number daemon and "
"return random numbers"
"\n"
" --nonce Return weak random suitable for a nonce\n"
" --very-strong Return very strong random\n"
" --ping Send a ping\n"
" --socket NAME Name of sockket to connect to\n"
" --hex Return result as a hex dump\n"
" --verbose Show what we are doing\n"
" --version Print version of the program and exit\n"
" --help Display this help and exit\n"
BUGREPORT_LINE, stdout );
exit (0);
}
static int
print_usage (void)
{
fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr);
fputs (" (use --help to display options)\n", stderr);
exit (1);
}
int
main (int argc, char **argv)
{
struct sockaddr_un *srvr_addr;
socklen_t addrlen;
int fd;
int rc;
unsigned char buffer[300];
int nleft, nread;
const char *socketname = "/var/run/libgcrypt/S.gcryptrnd";
int do_ping = 0;
int get_nonce = 0;
int get_very_strong = 0;
int req_nbytes, nbytes, n;
int verbose = 0;
int fail = 0;
int do_hex = 0;
if (argc)
{
argc--; argv++;
}
while (argc && **argv == '-' && (*argv)[1] == '-')
{
if (!(*argv)[2])
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version"))
print_version (0);
else if (!strcmp (*argv, "--help"))
print_version (1);
else if (!strcmp (*argv, "--socket") && argc > 1 )
{
argc--; argv++;
socketname = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--nonce"))
{
argc--; argv++;
get_nonce = 1;
}
else if (!strcmp (*argv, "--very-strong"))
{
argc--; argv++;
get_very_strong = 1;
}
else if (!strcmp (*argv, "--ping"))
{
argc--; argv++;
do_ping = 1;
}
else if (!strcmp (*argv, "--hex"))
{
argc--; argv++;
do_hex = 1;
}
else if (!strcmp (*argv, "--verbose"))
{
argc--; argv++;
verbose = 1;
}
else
print_usage ();
}
if (!argc && do_ping)
; /* This is allowed. */
else if (argc != 1)
print_usage ();
req_nbytes = argc? atoi (*argv) : 0;
if (req_nbytes < 0)
print_usage ();
/* Create a socket. */
fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
{
logit ("can't create socket: %s", strerror (errno));
exit (1);
}
srvr_addr = malloc (sizeof *srvr_addr);
if (!srvr_addr)
{
logit ("malloc failed: %s", strerror (errno));
exit (1);
}
memset (srvr_addr, 0, sizeof *srvr_addr);
srvr_addr->sun_family = AF_UNIX;
if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
{
logit ("socket name `%s' too long", socketname);
exit (1);
}
strcpy (srvr_addr->sun_path, socketname);
addrlen = (offsetof (struct sockaddr_un, sun_path)
+ strlen (srvr_addr->sun_path) + 1);
rc = connect (fd, (struct sockaddr*) srvr_addr, addrlen);
if (rc == -1)
{
logit ("error connecting socket `%s': %s",
srvr_addr->sun_path, strerror (errno));
close (fd);
exit (1);
}
do
{
nbytes = req_nbytes > 255? 255 : req_nbytes;
req_nbytes -= nbytes;
buffer[0] = 3;
if (do_ping)
buffer[1] = 0;
else if (get_nonce)
buffer[1] = 10;
else if (get_very_strong)
buffer[1] = 12;
else
buffer[1] = 11;
buffer[2] = nbytes;
if (writen (fd, buffer, 3))
fail = 1;
else
{
for (nleft=2, nread=0; nleft > 0; )
{
do
n = read (fd, buffer+nread, nleft);
while (n < 0 && errno == EINTR);
if (n < 0)
{
logit ("read error: %s", strerror (errno));
exit (1);
}
nleft -= n;
nread += n;
if (nread && buffer[0])
{
logit ("server returned error code %d", buffer[0]);
exit (1);
}
}
if (verbose)
logit ("received response with %d bytes of data", buffer[1]);
if (buffer[1] < nbytes)
{
logit ("warning: server returned less bytes than requested");
fail = 1;
}
else if (buffer[1] > nbytes && !do_ping)
{
logit ("warning: server returned more bytes than requested");
fail = 1;
}
nbytes = buffer[1];
if (nbytes > sizeof buffer)
{
logit ("buffer too short to receive data");
exit (1);
}
for (nleft=nbytes, nread=0; nleft > 0; )
{
do
n = read (fd, buffer+nread, nleft);
while (n < 0 && errno == EINTR);
if (n < 0)
{
logit ("read error: %s", strerror (errno));
exit (1);
}
nleft -= n;
nread += n;
}
if (do_hex)
{
for (n=0; n < nbytes; n++)
{
if (!n)
;
else if (!(n % 16))
putchar ('\n');
else
putchar (' ');
printf ("%02X", buffer[n]);
}
if (nbytes)
putchar ('\n');
}
else
{
if (fwrite (buffer, nbytes, 1, stdout) != 1)
{
logit ("error writing to stdout: %s", strerror (errno));
fail = 1;
}
}
}
}
while (!fail && req_nbytes);
close (fd);
free (srvr_addr);
return fail? 1 : 0;
}
diff --git a/src/global.c b/src/global.c
index d82c680a..3f6fe08b 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,1344 +1,1344 @@
/* global.c - global control functions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
* 2004, 2005, 2006, 2008, 2011,
* 2012 Free Software Foundation, Inc.
* Copyright (C) 2013, 2014, 2017 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /*HAVE_SYSLOG*/
#include "g10lib.h"
#include "gcrypt-testapi.h"
#include "cipher.h"
#include "stdmem.h" /* our own memory allocator */
#include "secmem.h" /* our own secmem allocator */
/****************
* flag bits: 0 : general cipher debug
* 1 : general MPI debug
*/
static unsigned int debug_flags;
/* gcry_control (GCRYCTL_SET_FIPS_MODE), sets this flag so that the
initialization code switched fips mode on. */
static int force_fips_mode;
/* Controlled by global_init(). */
int _gcry_global_any_init_done;
/*
* Functions called before and after blocking syscalls.
* Initialized by global_init and used via
* _gcry_pre_syscall and _gcry_post_syscall.
*/
static void (*pre_syscall_func)(void);
static void (*post_syscall_func)(void);
/* Memory management. */
static gcry_handler_alloc_t alloc_func;
static gcry_handler_alloc_t alloc_secure_func;
static gcry_handler_secure_check_t is_secure_func;
static gcry_handler_realloc_t realloc_func;
static gcry_handler_free_t free_func;
static gcry_handler_no_mem_t outofcore_handler;
static void *outofcore_handler_value;
static int no_secure_memory;
/* Prototypes. */
static gpg_err_code_t external_lock_test (int cmd);
/* This is our handmade constructor. It gets called by any function
likely to be called at startup. The suggested way for an
application to make sure that this has been called is by using
gcry_check_version. */
static void
global_init (void)
{
gcry_error_t err = 0;
if (_gcry_global_any_init_done)
return;
_gcry_global_any_init_done = 1;
/* Tell the random module that we have seen an init call. */
_gcry_set_preferred_rng_type (0);
/* Get the system call clamp functions. */
if (!pre_syscall_func)
gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
/* See whether the system is in FIPS mode. This needs to come as
early as possible but after ATH has been initialized. */
_gcry_initialize_fips_mode (force_fips_mode);
/* Before we do any other initialization we need to test available
hardware features. */
_gcry_detect_hw_features ();
/* Initialize the modules - this is mainly allocating some memory and
creating mutexes. */
err = _gcry_cipher_init ();
if (err)
goto fail;
err = _gcry_md_init ();
if (err)
goto fail;
err = _gcry_mac_init ();
if (err)
goto fail;
err = _gcry_pk_init ();
if (err)
goto fail;
err = _gcry_primegen_init ();
if (err)
goto fail;
err = _gcry_secmem_module_init ();
if (err)
goto fail;
err = _gcry_mpi_init ();
if (err)
goto fail;
return;
fail:
BUG ();
}
/* This function is called by the macro fips_is_operational and makes
sure that the minimal initialization has been done. This is far
from a perfect solution and hides problems with an improper
initialization but at least in single-threaded mode it should work
reliable.
The reason we need this is that a lot of applications don't use
Libgcrypt properly by not running any initialization code at all.
They just call a Libgcrypt function and that is all what they want.
Now with the FIPS mode, that has the side effect of entering FIPS
mode (for security reasons, FIPS mode is the default if no
initialization has been done) and bailing out immediately because
the FSM is in the wrong state. If we always run the init code,
Libgcrypt can test for FIPS mode and at least if not in FIPS mode,
it will behave as before. Note that this on-the-fly initialization
is only done for the cryptographic functions subject to FIPS mode
and thus not all API calls will do such an initialization. */
int
_gcry_global_is_operational (void)
{
if (!_gcry_global_any_init_done)
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
"missing initialization - please fix the application");
#endif /*HAVE_SYSLOG*/
global_init ();
}
return _gcry_fips_is_operational ();
}
/* Version number parsing. */
/* This function parses the first portion of the version number S and
stores it in *NUMBER. On success, this function returns a pointer
into S starting with the first character, which is not part of the
initial number portion; on failure, NULL is returned. */
static const char*
parse_version_number( const char *s, int *number )
{
int val = 0;
if( *s == '0' && isdigit(s[1]) )
return NULL; /* leading zeros are not allowed */
for ( ; isdigit(*s); s++ ) {
val *= 10;
val += *s - '0';
}
*number = val;
return val < 0? NULL : s;
}
/* This function breaks up the complete string-representation of the
version number S, which is of the following struture: <major
number>.<minor number>.<micro number><patch level>. The major,
minor and micro number components will be stored in *MAJOR, *MINOR
and *MICRO.
On success, the last component, the patch level, will be returned;
in failure, NULL will be returned. */
static const char *
parse_version_string( const char *s, int *major, int *minor, int *micro )
{
s = parse_version_number( s, major );
if( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number( s, minor );
if( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number( s, micro );
if( !s )
return NULL;
return s; /* patchlevel */
}
/* If REQ_VERSION is non-NULL, check that the version of the library
is at minimum the requested one. Returns the string representation
of the library version if the condition is satisfied; return NULL
if the requested version is newer than that of the library.
If a NULL is passed to this function, no check is done, but the
string representation of the library is simply returned. */
const char *
_gcry_check_version (const char *req_version)
{
const char *ver = VERSION;
int my_major, my_minor, my_micro;
int rq_major, rq_minor, rq_micro;
const char *my_plvl;
if (req_version && req_version[0] == 1 && req_version[1] == 1)
return _gcry_compat_identification ();
/* Initialize library. */
global_init ();
if ( !req_version )
/* Caller wants our version number. */
return ver;
/* Parse own version number. */
my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro );
if ( !my_plvl )
/* very strange our own version is bogus. Shouldn't we use
assert() here and bail out in case this happens? -mo. */
return NULL;
/* Parse requested version number. */
if (!parse_version_string (req_version, &rq_major, &rq_minor, &rq_micro))
return NULL; /* req version string is invalid, this can happen. */
/* 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))
{
return ver;
}
return NULL;
}
static void
print_config (const char *what, gpgrt_stream_t fp)
{
int i;
const char *s;
if (!what || !strcmp (what, "version"))
{
gpgrt_fprintf (fp, "version:%s:%x:%s:%x:\n",
VERSION, GCRYPT_VERSION_NUMBER,
GPGRT_VERSION, GPGRT_VERSION_NUMBER);
}
if (!what || !strcmp (what, "cc"))
{
gpgrt_fprintf (fp, "cc:%d:%s:\n",
#if GPGRT_VERSION_NUMBER >= 0x011b00 /* 1.27 */
GPGRT_GCC_VERSION
#else
_GPG_ERR_GCC_VERSION /* Due to a bug in gpg-error.h. */
#endif
,
#ifdef __clang__
"clang:" __VERSION__
#elif __GNUC__
"gcc:" __VERSION__
#else
":"
#endif
);
}
if (!what || !strcmp (what, "ciphers"))
gpgrt_fprintf (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS);
if (!what || !strcmp (what, "pubkeys"))
gpgrt_fprintf (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS);
if (!what || !strcmp (what, "digests"))
gpgrt_fprintf (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS);
if (!what || !strcmp (what, "rnd-mod"))
{
gpgrt_fprintf (fp, "rnd-mod:"
#if USE_RNDEGD
"egd:"
#endif
#if USE_RNDLINUX
"linux:"
#endif
#if USE_RNDUNIX
"unix:"
#endif
#if USE_RNDW32
"w32:"
#endif
"\n");
}
if (!what || !strcmp (what, "cpu-arch"))
{
gpgrt_fprintf (fp, "cpu-arch:"
#if defined(HAVE_CPU_ARCH_X86)
"x86"
#elif defined(HAVE_CPU_ARCH_ALPHA)
"alpha"
#elif defined(HAVE_CPU_ARCH_SPARC)
"sparc"
#elif defined(HAVE_CPU_ARCH_MIPS)
"mips"
#elif defined(HAVE_CPU_ARCH_M68K)
"m68k"
#elif defined(HAVE_CPU_ARCH_PPC)
"ppc"
#elif defined(HAVE_CPU_ARCH_ARM)
"arm"
#endif
":\n");
}
if (!what || !strcmp (what, "mpi-asm"))
gpgrt_fprintf (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ());
if (!what || !strcmp (what, "hwflist"))
{
unsigned int hwfeatures, afeature;
hwfeatures = _gcry_get_hw_features ();
gpgrt_fprintf (fp, "hwflist:");
for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++)
if ((hwfeatures & afeature))
gpgrt_fprintf (fp, "%s:", s);
gpgrt_fprintf (fp, "\n");
}
if (!what || !strcmp (what, "fips-mode"))
{
/* 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",
fips_mode ()? 'y':'n',
_gcry_enforced_fips_mode ()? 'y':'n' );
}
if (!what || !strcmp (what, "rng-type"))
{
/* The currently used RNG type. */
unsigned int jver;
int active;
i = _gcry_get_rng_type (0);
switch (i)
{
case GCRY_RNG_TYPE_STANDARD: s = "standard"; break;
case GCRY_RNG_TYPE_FIPS: s = "fips"; break;
case GCRY_RNG_TYPE_SYSTEM: s = "system"; break;
default: BUG ();
}
jver = _gcry_rndjent_get_version (&active);
gpgrt_fprintf (fp, "rng-type:%s:%d:%u:%d:\n", s, i, jver, active);
}
}
/* With a MODE of 0 return a malloced string with configured features.
* In that case a WHAT of NULL returns everything in the same way
* GCRYCTL_PRINT_CONFIG would do. With a specific WHAT string only
* the requested feature is returned (w/o the trailing LF. On error
* NULL is returned. */
char *
_gcry_get_config (int mode, const char *what)
{
gpgrt_stream_t fp;
int save_errno;
void *data;
char *p;
if (mode)
{
gpg_err_set_errno (EINVAL);
return NULL;
}
fp = gpgrt_fopenmem (0, "w+b,samethread");
if (!fp)
return NULL;
print_config (what, fp);
if (gpgrt_ferror (fp))
{
save_errno = errno;
gpgrt_fclose (fp);
gpg_err_set_errno (save_errno);
return NULL;
}
gpgrt_rewind (fp);
if (gpgrt_fclose_snatch (fp, &data, NULL))
{
save_errno = errno;
gpgrt_fclose (fp);
gpg_err_set_errno (save_errno);
return NULL;
}
if (!data)
{
/* Nothing was printed (unknown value for WHAT). This is okay,
* so clear ERRNO to indicate this. */
gpg_err_set_errno (0);
return NULL;
}
/* Strip trailing LF. */
if (what && (p = strchr (data, '\n')))
*p = 0;
return data;
}
/* Command dispatcher function, acting as general control
function. */
gcry_err_code_t
_gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
{
static int init_finished = 0;
gcry_err_code_t rc = 0;
switch (cmd)
{
case GCRYCTL_ENABLE_M_GUARD:
_gcry_private_enable_m_guard ();
break;
case GCRYCTL_ENABLE_QUICK_RANDOM:
_gcry_set_preferred_rng_type (0);
_gcry_enable_quick_random_gen ();
break;
case GCRYCTL_FAKED_RANDOM_P:
/* Return an error if the RNG is faked one (e.g. enabled by
ENABLE_QUICK_RANDOM. */
if (_gcry_random_is_faked ())
rc = GPG_ERR_GENERAL; /* Use as TRUE value. */
break;
case GCRYCTL_DUMP_RANDOM_STATS:
_gcry_random_dump_stats ();
break;
case GCRYCTL_DUMP_MEMORY_STATS:
/*m_print_stats("[fixme: prefix]");*/
break;
case GCRYCTL_DUMP_SECMEM_STATS:
_gcry_secmem_dump_stats (0);
break;
case GCRYCTL_DROP_PRIVS:
global_init ();
_gcry_secmem_init (0);
break;
case GCRYCTL_DISABLE_SECMEM:
global_init ();
no_secure_memory = 1;
break;
case GCRYCTL_INIT_SECMEM:
global_init ();
_gcry_secmem_init (va_arg (arg_ptr, unsigned int));
if ((_gcry_secmem_get_flags () & GCRY_SECMEM_FLAG_NOT_LOCKED))
rc = GPG_ERR_GENERAL;
break;
case GCRYCTL_TERM_SECMEM:
global_init ();
_gcry_secmem_term ();
break;
case GCRYCTL_DISABLE_SECMEM_WARN:
_gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_NO_WARNING));
break;
case GCRYCTL_SUSPEND_SECMEM_WARN:
_gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_SUSPEND_WARNING));
break;
case GCRYCTL_RESUME_SECMEM_WARN:
_gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
& ~GCRY_SECMEM_FLAG_SUSPEND_WARNING));
break;
case GCRYCTL_AUTO_EXPAND_SECMEM:
_gcry_secmem_set_auto_expand (va_arg (arg_ptr, unsigned int));
break;
case GCRYCTL_USE_SECURE_RNDPOOL:
global_init ();
_gcry_secure_random_alloc (); /* Put random number into secure memory. */
break;
case GCRYCTL_SET_RANDOM_SEED_FILE:
_gcry_set_preferred_rng_type (0);
_gcry_set_random_seed_file (va_arg (arg_ptr, const char *));
break;
case GCRYCTL_UPDATE_RANDOM_SEED_FILE:
_gcry_set_preferred_rng_type (0);
if ( fips_is_operational () )
_gcry_update_random_seed_file ();
break;
case GCRYCTL_SET_VERBOSITY:
_gcry_set_preferred_rng_type (0);
_gcry_set_log_verbosity (va_arg (arg_ptr, int));
break;
case GCRYCTL_SET_DEBUG_FLAGS:
debug_flags |= va_arg (arg_ptr, unsigned int);
break;
case GCRYCTL_CLEAR_DEBUG_FLAGS:
debug_flags &= ~va_arg (arg_ptr, unsigned int);
break;
case GCRYCTL_DISABLE_INTERNAL_LOCKING:
/* Not used anymore. */
global_init ();
break;
case GCRYCTL_ANY_INITIALIZATION_P:
if (_gcry_global_any_init_done)
rc = GPG_ERR_GENERAL;
break;
case GCRYCTL_INITIALIZATION_FINISHED_P:
if (init_finished)
rc = GPG_ERR_GENERAL; /* Yes. */
break;
case GCRYCTL_INITIALIZATION_FINISHED:
/* This is a hook which should be used by an application after
all initialization has been done and right before any threads
are started. It is not really needed but the only way to be
really sure that all initialization for thread-safety has
been done. */
if (! init_finished)
{
global_init ();
/* Do only a basic random initialization, i.e. init the
mutexes. */
_gcry_random_initialize (0);
init_finished = 1;
/* Force us into operational state if in FIPS mode. */
(void)fips_is_operational ();
}
break;
case GCRYCTL_SET_THREAD_CBS:
/* This is now a dummy call. We used to install our own thread
library here. */
_gcry_set_preferred_rng_type (0);
global_init ();
break;
case GCRYCTL_FAST_POLL:
_gcry_set_preferred_rng_type (0);
/* We need to do make sure that the random pool is really
initialized so that the poll function is not a NOP. */
_gcry_random_initialize (1);
if ( fips_is_operational () )
_gcry_fast_random_poll ();
break;
case GCRYCTL_SET_RNDEGD_SOCKET:
#if USE_RNDEGD
_gcry_set_preferred_rng_type (0);
rc = _gcry_rndegd_set_socket_name (va_arg (arg_ptr, const char *));
#else
rc = GPG_ERR_NOT_SUPPORTED;
#endif
break;
case GCRYCTL_SET_RANDOM_DAEMON_SOCKET:
_gcry_set_preferred_rng_type (0);
_gcry_set_random_daemon_socket (va_arg (arg_ptr, const char *));
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));
break;
case GCRYCTL_CLOSE_RANDOM_DEVICE:
_gcry_random_close_fds ();
break;
/* This command dumps information pertaining to the
configuration of libgcrypt to the given stream. It may be
used before the initialization has been finished but not
before a gcry_version_check. See also gcry_get_config. */
case GCRYCTL_PRINT_CONFIG:
{
FILE *fp = va_arg (arg_ptr, FILE *);
char *tmpstr;
_gcry_set_preferred_rng_type (0);
tmpstr = _gcry_get_config (0, NULL);
if (tmpstr)
{
if (fp)
fputs (tmpstr, fp);
else
log_info ("%s", tmpstr);
xfree (tmpstr);
}
}
break;
case GCRYCTL_OPERATIONAL_P:
/* Returns true if the library is in an operational state. This
is always true for non-fips mode. */
_gcry_set_preferred_rng_type (0);
if (_gcry_fips_test_operational ())
rc = GPG_ERR_GENERAL; /* Used as TRUE value */
break;
case GCRYCTL_FIPS_MODE_P:
if (fips_mode ()
&& !_gcry_is_fips_mode_inactive ()
&& !no_secure_memory)
rc = GPG_ERR_GENERAL; /* Used as TRUE value */
break;
case GCRYCTL_FORCE_FIPS_MODE:
/* Performing this command puts the library into fips mode. If
the library has already been initialized into fips mode, a
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 (!_gcry_global_any_init_done)
{
/* Not yet initialized at all. Set a flag so that we are put
into fips mode during initialization. */
force_fips_mode = 1;
}
else
{
/* Already initialized. If we are already operational we
run a selftest. If not we use the is_operational call to
force us into operational state if possible. */
if (_gcry_fips_test_error_or_operational ())
_gcry_fips_run_selftests (1);
if (_gcry_fips_is_operational ())
rc = GPG_ERR_GENERAL; /* Used as TRUE value */
}
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
extended version of the selftests. Returns 0 on success or an
error code. */
global_init ();
rc = _gcry_fips_run_selftests (1);
break;
#if _GCRY_GCC_VERSION >= 40200
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wswitch"
#endif
case PRIV_CTL_INIT_EXTRNG_TEST: /* Init external random test. */
rc = GPG_ERR_NOT_SUPPORTED;
break;
case PRIV_CTL_RUN_EXTRNG_TEST: /* Run external DRBG test. */
{
struct gcry_drbg_test_vector *test =
va_arg (arg_ptr, struct gcry_drbg_test_vector *);
unsigned char *buf = va_arg (arg_ptr, unsigned char *);
if (buf)
rc = _gcry_rngdrbg_cavs_test (test, buf);
else
rc = _gcry_rngdrbg_healthcheck_one (test);
}
break;
case PRIV_CTL_DEINIT_EXTRNG_TEST: /* Deinit external random test. */
rc = GPG_ERR_NOT_SUPPORTED;
break;
case PRIV_CTL_EXTERNAL_LOCK_TEST: /* Run external lock test */
rc = external_lock_test (va_arg (arg_ptr, int));
break;
case PRIV_CTL_DUMP_SECMEM_STATS:
_gcry_secmem_dump_stats (1);
break;
#if _GCRY_GCC_VERSION >= 40200
# pragma GCC diagnostic pop
#endif
case GCRYCTL_DISABLE_HWF:
{
const char *name = va_arg (arg_ptr, const char *);
rc = _gcry_disable_hw_feature (name);
}
break;
case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
if (!_gcry_global_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;
break;
case GCRYCTL_SET_PREFERRED_RNG_TYPE:
/* This may be called before gcry_check_version. */
{
int i = va_arg (arg_ptr, int);
/* Note that we may not pass 0 to _gcry_set_preferred_rng_type. */
if (i > 0)
_gcry_set_preferred_rng_type (i);
}
break;
case GCRYCTL_GET_CURRENT_RNG_TYPE:
{
int *ip = va_arg (arg_ptr, int*);
if (ip)
*ip = _gcry_get_rng_type (!_gcry_global_any_init_done);
}
break;
case GCRYCTL_DISABLE_LOCKED_SECMEM:
_gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_NO_MLOCK));
break;
case GCRYCTL_DISABLE_PRIV_DROP:
_gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_NO_PRIV_DROP));
break;
case GCRYCTL_INACTIVATE_FIPS_FLAG:
case GCRYCTL_REACTIVATE_FIPS_FLAG:
rc = GPG_ERR_NOT_IMPLEMENTED;
break;
case GCRYCTL_DRBG_REINIT:
{
const char *flagstr = va_arg (arg_ptr, const char *);
gcry_buffer_t *pers = va_arg (arg_ptr, gcry_buffer_t *);
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 (!_gcry_global_any_init_done)
!= GCRY_RNG_TYPE_FIPS)
rc = GPG_ERR_NOT_SUPPORTED;
else
rc = _gcry_rngdrbg_reinit (flagstr, pers, npers);
}
break;
case GCRYCTL_REINIT_SYSCALL_CLAMP:
if (!pre_syscall_func)
gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
break;
default:
_gcry_set_preferred_rng_type (0);
rc = GPG_ERR_INV_OP;
}
return rc;
}
/* Set custom allocation handlers. This is in general not useful
* because the libgcrypt allocation functions are guaranteed to
* provide proper allocation handlers which zeroize memory if needed.
* NOTE: All 5 functions should be set. */
void
_gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func,
gcry_handler_alloc_t new_alloc_secure_func,
gcry_handler_secure_check_t new_is_secure_func,
gcry_handler_realloc_t new_realloc_func,
gcry_handler_free_t new_free_func)
{
global_init ();
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");
}
alloc_func = new_alloc_func;
alloc_secure_func = new_alloc_secure_func;
is_secure_func = new_is_secure_func;
realloc_func = new_realloc_func;
free_func = new_free_func;
}
/****************
* Set an optional handler which is called in case the xmalloc functions
* ran out of memory. This handler may do one of these things:
* o free some memory and return true, so that the xmalloc function
* tries again.
* o Do whatever it like and return false, so that the xmalloc functions
* use the default fatal error handler.
* o Terminate the program and don't return.
*
* The handler function is called with 3 arguments: The opaque value set with
* this function, the requested memory size, and a flag with these bits
* currently defined:
* bit 0 set = secure memory has been requested.
*/
void
_gcry_set_outofcore_handler (int (*f)(void*, size_t, unsigned int), void *value)
{
global_init ();
if (fips_mode () )
{
log_info ("out of core handler ignored in FIPS mode\n");
return;
}
outofcore_handler = f;
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)
{
gcry_err_code_t err = 0;
void *m;
if ((flags & GCRY_ALLOC_FLAG_SECURE) && !get_no_secure_memory ())
{
if (alloc_secure_func)
m = (*alloc_secure_func) (n);
else
m = _gcry_private_malloc_secure (n, !!(flags & GCRY_ALLOC_FLAG_XHINT));
}
else
{
if (alloc_func)
m = (*alloc_func) (n);
else
m = _gcry_private_malloc (n);
}
if (!m)
{
/* Make sure that ERRNO has been set in case a user supplied
memory handler didn't it correctly. */
if (!errno)
gpg_err_set_errno (ENOMEM);
err = gpg_err_code_from_errno (errno);
}
else
*mem = m;
return err;
}
void *
_gcry_malloc (size_t n)
{
void *mem = NULL;
do_malloc (n, 0, &mem);
return mem;
}
static void *
_gcry_malloc_secure_core (size_t n, int xhint)
{
void *mem = NULL;
do_malloc (n, (GCRY_ALLOC_FLAG_SECURE | (xhint? GCRY_ALLOC_FLAG_XHINT:0)),
&mem);
return mem;
}
void *
_gcry_malloc_secure (size_t n)
{
return _gcry_malloc_secure_core (n, 0);
}
int
_gcry_is_secure (const void *a)
{
if (get_no_secure_memory ())
return 0;
if (is_secure_func)
return is_secure_func (a) ;
return _gcry_private_is_secure (a);
}
void
_gcry_check_heap( const void *a )
{
(void)a;
/* FIXME: implement this*/
#if 0
if( some_handler )
some_handler(a)
else
_gcry_private_check_heap(a)
#endif
}
static void *
_gcry_realloc_core (void *a, size_t n, int xhint)
{
void *p;
/* To avoid problems with non-standard realloc implementations and
our own secmem_realloc, we divert to malloc and free here. */
if (!a)
return _gcry_malloc (n);
if (!n)
{
xfree (a);
return NULL;
}
if (realloc_func)
p = realloc_func (a, n);
else
p = _gcry_private_realloc (a, n, xhint);
if (!p && !errno)
gpg_err_set_errno (ENOMEM);
return p;
}
void *
_gcry_realloc (void *a, size_t n)
{
return _gcry_realloc_core (a, n, 0);
}
void
_gcry_free (void *p)
{
int save_errno;
if (!p)
return;
/* In case ERRNO is set we better save it so that the free machinery
may not accidentally change ERRNO. We restore it only if it was
already set to comply with the usual C semantic for ERRNO. */
save_errno = errno;
if (free_func)
free_func (p);
else
_gcry_private_free (p);
if (save_errno)
gpg_err_set_errno (save_errno);
}
void *
_gcry_calloc (size_t n, size_t m)
{
size_t bytes;
void *p;
bytes = n * m; /* size_t is unsigned so the behavior on overflow is
defined. */
if (m && bytes / m != n)
{
gpg_err_set_errno (ENOMEM);
return NULL;
}
p = _gcry_malloc (bytes);
if (p)
memset (p, 0, bytes);
return p;
}
void *
_gcry_calloc_secure (size_t n, size_t m)
{
size_t bytes;
void *p;
bytes = n * m; /* size_t is unsigned so the behavior on overflow is
defined. */
if (m && bytes / m != n)
{
gpg_err_set_errno (ENOMEM);
return NULL;
}
p = _gcry_malloc_secure (bytes);
if (p)
memset (p, 0, bytes);
return p;
}
static char *
_gcry_strdup_core (const char *string, int xhint)
{
char *string_cp = NULL;
size_t string_n = 0;
string_n = strlen (string);
if (_gcry_is_secure (string))
string_cp = _gcry_malloc_secure_core (string_n + 1, xhint);
else
string_cp = _gcry_malloc (string_n + 1);
if (string_cp)
strcpy (string_cp, string);
return string_cp;
}
/* Create and return a copy of the null-terminated string STRING. If
* it is contained in secure memory, the copy will be contained in
* secure memory as well. In an out-of-memory condition, NULL is
* returned. */
char *
_gcry_strdup (const char *string)
{
return _gcry_strdup_core (string, 0);
}
void *
_gcry_xmalloc( size_t n )
{
void *p;
while ( !(p = _gcry_malloc( n )) )
{
if ( fips_mode ()
|| !outofcore_handler
|| !outofcore_handler (outofcore_handler_value, n, 0) )
{
_gcry_fatal_error (gpg_err_code_from_errno (errno), NULL);
}
}
return p;
}
void *
_gcry_xrealloc( void *a, size_t n )
{
void *p;
while (!(p = _gcry_realloc_core (a, n, 1)))
{
if ( fips_mode ()
|| !outofcore_handler
|| !outofcore_handler (outofcore_handler_value, n,
_gcry_is_secure(a)? 3:2))
{
_gcry_fatal_error (gpg_err_code_from_errno (errno), NULL );
}
}
return p;
}
void *
_gcry_xmalloc_secure( size_t n )
{
void *p;
while (!(p = _gcry_malloc_secure_core (n, 1)))
{
if ( fips_mode ()
|| !outofcore_handler
|| !outofcore_handler (outofcore_handler_value, n, 1) )
{
_gcry_fatal_error (gpg_err_code_from_errno (errno),
_("out of core in secure memory"));
}
}
return p;
}
void *
_gcry_xcalloc( size_t n, size_t m )
{
size_t nbytes;
void *p;
nbytes = n * m;
if (m && nbytes / m != n)
{
gpg_err_set_errno (ENOMEM);
_gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
}
p = _gcry_xmalloc ( nbytes );
memset ( p, 0, nbytes );
return p;
}
void *
_gcry_xcalloc_secure( size_t n, size_t m )
{
size_t nbytes;
void *p;
nbytes = n * m;
if (m && nbytes / m != n)
{
gpg_err_set_errno (ENOMEM);
_gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
}
p = _gcry_xmalloc_secure ( nbytes );
memset ( p, 0, nbytes );
return p;
}
char *
_gcry_xstrdup (const char *string)
{
char *p;
while ( !(p = _gcry_strdup_core (string, 1)) )
{
size_t n = strlen (string);
int is_sec = !!_gcry_is_secure (string);
if (fips_mode ()
|| !outofcore_handler
|| !outofcore_handler (outofcore_handler_value, n, is_sec) )
{
_gcry_fatal_error (gpg_err_code_from_errno (errno),
is_sec? _("out of core in secure memory"):NULL);
}
}
return p;
}
/* Used before blocking system calls. */
void
_gcry_pre_syscall (void)
{
if (pre_syscall_func)
pre_syscall_func ();
}
/* Used after blocking system calls. */
void
_gcry_post_syscall (void)
{
if (post_syscall_func)
post_syscall_func ();
}
int
_gcry_get_debug_flag (unsigned int mask)
{
if ( fips_mode () )
return 0;
return (debug_flags & mask);
}
/* It is often useful to get some feedback of long running operations.
This function may be used to register a handler for this.
The callback function CB is used as:
void cb (void *opaque, const char *what, int printchar,
int current, int total);
Where WHAT is a string identifying the the type of the progress
output, PRINTCHAR the character usually printed, CURRENT the amount
of progress currently done and TOTAL the expected amount of
progress. A value of 0 for TOTAL indicates that there is no
estimation available.
Defined values for WHAT:
"need_entropy" X 0 number-of-bytes-required
When running low on entropy
"primegen" '\n' 0 0
Prime generated
'!'
Need to refresh the prime pool
'<','>'
Number of bits adjusted
'^'
Looking for a generator
'.'
Fermat tests on 10 candidates failed
':'
Restart with a new random value
'+'
Rabin Miller test passed
"pk_elg" '+','-','.','\n' 0 0
Only used in debugging mode.
"pk_dsa"
Only used in debugging mode.
*/
void
_gcry_set_progress_handler (void (*cb)(void *,const char*,int, int, int),
void *cb_data)
{
#if USE_DSA
_gcry_register_pk_dsa_progress (cb, cb_data);
#endif
#if USE_ELGAMAL
_gcry_register_pk_elg_progress (cb, cb_data);
#endif
_gcry_register_primegen_progress (cb, cb_data);
_gcry_register_random_progress (cb, cb_data);
}
/* This is a helper for the regression test suite to test Libgcrypt's locks.
It works using a one test lock with CMD controlling what to do:
30111 - Allocate and init lock
30112 - Take lock
30113 - Release lock
30114 - Destroy lock.
This function is used by tests/t-lock.c - it is not part of the
public API!
*/
static gpg_err_code_t
external_lock_test (int cmd)
{
GPGRT_LOCK_DEFINE (testlock);
gpg_err_code_t rc = 0;
switch (cmd)
{
case 30111: /* Init Lock. */
rc = gpgrt_lock_init (&testlock);
break;
case 30112: /* Take Lock. */
rc = gpgrt_lock_lock (&testlock);
break;
case 30113: /* Release Lock. */
rc = gpgrt_lock_unlock (&testlock);
break;
case 30114: /* Destroy Lock. */
rc = gpgrt_lock_destroy (&testlock);
break;
default:
rc = GPG_ERR_INV_OP;
break;
}
return rc;
}
diff --git a/src/hmac256.c b/src/hmac256.c
index 2d66079c..d6f3e0b4 100644
--- a/src/hmac256.c
+++ b/src/hmac256.c
@@ -1,800 +1,800 @@
/* hmac256.c - Standalone HMAC implementation
* Copyright (C) 2003, 2006, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
This is a standalone HMAC-SHA-256 implementation based on the code
from ../cipher/sha256.c. It is a second implementation to allow
comparing against the standard implementations 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.
This module may be used standalone.
Types:
u32 - unsigned 32 bit type.
Constants:
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.
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.
STANDALONE Compile a test driver similar to the
sha1sum tool. This driver uses a self-test
identically to the one used by Libcgrypt
for testing this included module.
*/
#ifdef STANDALONE
#include <stdint.h>
#define HAVE_U32_TYPEDEF 1
typedef uint32_t u32;
#define VERSION "standalone"
/* For GCC, we can detect endianness. If not GCC, please define manually. */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define WORDS_BIGENDIAN 1
#endif
#else
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#if defined(__WIN32) && defined(STANDALONE)
# include <fcntl.h> /* We need setmode(). */
#endif
#ifdef STANDALONE
#define xtrymalloc(a) malloc((a))
#define gpg_err_set_errno(a) (errno = (a))
#else
#include "g10lib.h"
#endif
#include "hmac256.h"
#ifndef HAVE_U32_TYPEDEF
# undef u32 /* Undef a possible macro with that name. */
# if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int u32;
# elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long u32;
# else
# error no typedef for u32
# endif
# define HAVE_U32_TYPEDEF
#endif
/* The context used by this module. */
struct hmac256_context
{
u32 h0, h1, h2, h3, h4, h5, h6, h7;
u32 nblocks;
int count;
int finalized:1;
int use_hmac:1;
unsigned char buf[64];
unsigned char opad[64];
};
/* Rotate a 32 bit word. */
static inline u32 ror(u32 x, int n)
{
return ( ((x) >> (n)) | ((x) << (32-(n))) );
}
#define my_wipememory2(_ptr,_set,_len) do { \
volatile char *_vptr=(volatile char *)(_ptr); \
size_t _vlen=(_len); \
while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
} while(0)
#define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len)
/*
The SHA-256 core: Transform the message X which consists of 16
32-bit-words. See FIPS 180-2 for details.
*/
static void
transform (hmac256_context_t hd, const void *data_arg)
{
const unsigned char *data = data_arg;
#define Cho(x,y,z) (z ^ (x & (y ^ z))) /* (4.2) same as SHA-1's F1 */
#define Maj(x,y,z) ((x & y) | (z & (x|y))) /* (4.3) same as SHA-1's F3 */
#define Sum0(x) (ror ((x), 2) ^ ror ((x), 13) ^ ror ((x), 22)) /* (4.4) */
#define Sum1(x) (ror ((x), 6) ^ ror ((x), 11) ^ ror ((x), 25)) /* (4.5) */
#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */
#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */
#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)); \
h = g; \
g = f; \
f = e; \
e = d + t1; \
d = c; \
c = b; \
b = a; \
a = t1 + t2; \
} while (0)
static const u32 K[64] =
{
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
};
u32 a, b, c, d, e, f, g, h, t1, t2;
u32 x[16];
u32 w[64];
int i;
a = hd->h0;
b = hd->h1;
c = hd->h2;
d = hd->h3;
e = hd->h4;
f = hd->h5;
g = hd->h6;
h = hd->h7;
#ifdef WORDS_BIGENDIAN
memcpy (x, data, 64);
#else /*!WORDS_BIGENDIAN*/
{
unsigned char *p2;
for (i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 )
{
p2[3] = *data++;
p2[2] = *data++;
p2[1] = *data++;
p2[0] = *data++;
}
}
#endif /*!WORDS_BIGENDIAN*/
for (i=0; i < 16; i++)
w[i] = x[i];
for (; i < 64; i++)
w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];
for (i=0; i < 64; i++)
R(a,b,c,d,e,f,g,h,K[i],w[i]);
hd->h0 += a;
hd->h1 += b;
hd->h2 += c;
hd->h3 += d;
hd->h4 += e;
hd->h5 += f;
hd->h6 += g;
hd->h7 += h;
}
#undef Cho
#undef Maj
#undef Sum0
#undef Sum1
#undef S0
#undef S1
#undef R
/* Finalize the current SHA256 calculation. */
static void
finalize (hmac256_context_t hd)
{
u32 t, msb, lsb;
unsigned char *p;
if (hd->finalized)
return; /* Silently ignore a finalized context. */
_gcry_hmac256_update (hd, NULL, 0); /* Flush. */
t = hd->nblocks;
/* Multiply by 64 to make a byte count. */
lsb = t << 6;
msb = t >> 26;
/* Add the count. */
t = lsb;
if ((lsb += hd->count) < t)
msb++;
/* Multiply by 8 to make a bit count. */
t = lsb;
lsb <<= 3;
msb <<= 3;
msb |= t >> 29;
if (hd->count < 56)
{ /* Enough room. */
hd->buf[hd->count++] = 0x80; /* pad */
while (hd->count < 56)
hd->buf[hd->count++] = 0; /* pad */
}
else
{ /* Need one extra block. */
hd->buf[hd->count++] = 0x80; /* pad character */
while (hd->count < 64)
hd->buf[hd->count++] = 0;
_gcry_hmac256_update (hd, NULL, 0); /* Flush. */;
memset (hd->buf, 0, 56 ); /* Zero out next next block. */
}
/* Append the 64 bit count. */
hd->buf[56] = msb >> 24;
hd->buf[57] = msb >> 16;
hd->buf[58] = msb >> 8;
hd->buf[59] = msb;
hd->buf[60] = lsb >> 24;
hd->buf[61] = lsb >> 16;
hd->buf[62] = lsb >> 8;
hd->buf[63] = lsb;
transform (hd, hd->buf);
/* Store the digest into hd->buf. */
p = hd->buf;
#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
*p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
X(0);
X(1);
X(2);
X(3);
X(4);
X(5);
X(6);
X(7);
#undef X
hd->finalized = 1;
}
/* Create a new context. On error NULL is returned and errno is set
appropriately. If KEY is given the function computes HMAC using
this key; with KEY given as NULL, a plain SHA-256 digest is
computed. */
hmac256_context_t
_gcry_hmac256_new (const void *key, size_t keylen)
{
hmac256_context_t hd;
hd = xtrymalloc (sizeof *hd);
if (!hd)
return NULL;
hd->h0 = 0x6a09e667;
hd->h1 = 0xbb67ae85;
hd->h2 = 0x3c6ef372;
hd->h3 = 0xa54ff53a;
hd->h4 = 0x510e527f;
hd->h5 = 0x9b05688c;
hd->h6 = 0x1f83d9ab;
hd->h7 = 0x5be0cd19;
hd->nblocks = 0;
hd->count = 0;
hd->finalized = 0;
hd->use_hmac = 0;
if (key)
{
int i;
unsigned char ipad[64];
memset (ipad, 0, 64);
memset (hd->opad, 0, 64);
if (keylen <= 64)
{
memcpy (ipad, key, keylen);
memcpy (hd->opad, key, keylen);
}
else
{
hmac256_context_t tmphd;
tmphd = _gcry_hmac256_new (NULL, 0);
if (!tmphd)
{
free (hd);
return NULL;
}
_gcry_hmac256_update (tmphd, key, keylen);
finalize (tmphd);
memcpy (ipad, tmphd->buf, 32);
memcpy (hd->opad, tmphd->buf, 32);
_gcry_hmac256_release (tmphd);
}
for (i=0; i < 64; i++)
{
ipad[i] ^= 0x36;
hd->opad[i] ^= 0x5c;
}
hd->use_hmac = 1;
_gcry_hmac256_update (hd, ipad, 64);
my_wipememory (ipad, 64);
}
return hd;
}
/* Release a context created by _gcry_hmac256_new. CTX may be NULL
in which case the function does nothing. */
void
_gcry_hmac256_release (hmac256_context_t ctx)
{
if (ctx)
{
/* Note: We need to take care not to modify errno. */
if (ctx->use_hmac)
my_wipememory (ctx->opad, 64);
free (ctx);
}
}
/* Update the message digest with the contents of BUFFER containing
LENGTH bytes. */
void
_gcry_hmac256_update (hmac256_context_t hd,
const void *buffer, size_t length)
{
const unsigned char *inbuf = buffer;
if (hd->finalized)
return; /* Silently ignore a finalized context. */
if (hd->count == 64)
{
/* Flush the buffer. */
transform (hd, hd->buf);
hd->count = 0;
hd->nblocks++;
}
if (!inbuf)
return; /* Only flushing was requested. */
if (hd->count)
{
for (; length && hd->count < 64; length--)
hd->buf[hd->count++] = *inbuf++;
_gcry_hmac256_update (hd, NULL, 0); /* Flush. */
if (!length)
return;
}
while (length >= 64)
{
transform (hd, inbuf);
hd->count = 0;
hd->nblocks++;
length -= 64;
inbuf += 64;
}
for (; length && hd->count < 64; length--)
hd->buf[hd->count++] = *inbuf++;
}
/* Finalize an operation and return the digest. If R_DLEN is not NULL
the length of the digest will be stored at that address. The
returned value is valid as long as the context exists. On error
NULL is returned. */
const void *
_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen)
{
finalize (hd);
if (hd->use_hmac)
{
hmac256_context_t tmphd;
tmphd = _gcry_hmac256_new (NULL, 0);
if (!tmphd)
return NULL;
_gcry_hmac256_update (tmphd, hd->opad, 64);
_gcry_hmac256_update (tmphd, hd->buf, 32);
finalize (tmphd);
memcpy (hd->buf, tmphd->buf, 32);
_gcry_hmac256_release (tmphd);
}
if (r_dlen)
*r_dlen = 32;
return (void*)hd->buf;
}
/* Convenience function to compute the HMAC-SHA256 of one file. The
user needs to provide a buffer RESULT of at least 32 bytes, he
needs to put the size of the buffer into RESULTSIZE and the
FILENAME. KEY and KEYLEN are as described for _gcry_hmac256_new.
On success the function returns the valid length of the result
buffer (which will be 32) or -1 on error. On error ERRNO is set
appropriate. */
int
_gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
const void *key, size_t keylen)
{
FILE *fp;
hmac256_context_t hd;
size_t buffer_size, nread, digestlen;
char *buffer;
const unsigned char *digest;
fp = fopen (filename, "rb");
if (!fp)
return -1;
hd = _gcry_hmac256_new (key, keylen);
if (!hd)
{
fclose (fp);
return -1;
}
buffer_size = 32768;
buffer = xtrymalloc (buffer_size);
if (!buffer)
{
fclose (fp);
_gcry_hmac256_release (hd);
return -1;
}
while ( (nread = fread (buffer, 1, buffer_size, fp)))
_gcry_hmac256_update (hd, buffer, nread);
free (buffer);
if (ferror (fp))
{
fclose (fp);
_gcry_hmac256_release (hd);
return -1;
}
fclose (fp);
digest = _gcry_hmac256_finalize (hd, &digestlen);
if (!digest)
{
_gcry_hmac256_release (hd);
return -1;
}
if (digestlen > resultsize)
{
_gcry_hmac256_release (hd);
gpg_err_set_errno (EINVAL);
return -1;
}
memcpy (result, digest, digestlen);
_gcry_hmac256_release (hd);
return digestlen;
}
#ifdef STANDALONE
static int
selftest (void)
{
static struct
{
const char * const desc;
const char * const data;
const char * const key;
const unsigned 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 }
};
int tvidx;
for (tvidx=0; tv[tvidx].desc; tvidx++)
{
hmac256_context_t hmachd;
const unsigned char *digest;
size_t dlen;
hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
if (!hmachd)
return -1;
_gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
digest = _gcry_hmac256_finalize (hmachd, &dlen);
if (!digest)
{
_gcry_hmac256_release (hmachd);
return -1;
}
if (dlen != sizeof (tv[tvidx].expect)
|| memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect)))
{
_gcry_hmac256_release (hmachd);
return -1;
}
_gcry_hmac256_release (hmachd);
}
return 0; /* Succeeded. */
}
int
main (int argc, char **argv)
{
const char *pgm;
int last_argc = -1;
const char *key;
size_t keylen;
FILE *fp;
hmac256_context_t hd;
const unsigned char *digest;
char buffer[4096];
size_t n, dlen, idx;
int use_stdin = 0;
int use_binary = 0;
int use_stdkey = 0;
assert (sizeof (u32) == 4);
#ifdef __WIN32
setmode (fileno (stdin), O_BINARY);
#endif
if (argc)
{
pgm = strrchr (*argv, '/');
if (pgm)
pgm++;
else
pgm = *argv;
argc--; argv++;
}
else
pgm = "?";
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version"))
{
fputs ("hmac256 (Libgcrypt) " VERSION "\n"
"Copyright (C) 2008 Free Software Foundation, Inc.\n"
"License LGPLv2.1+: GNU LGPL version 2.1 or later "
- "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
+ "<https://gnu.org/licenses/old-licenses/lgpl-2.1.html>\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);
exit (0);
}
else if (!strcmp (*argv, "--binary"))
{
argc--; argv++;
use_binary = 1;
}
else if (!strcmp (*argv, "--stdkey"))
{
argc--; argv++;
use_stdkey = 1;
}
}
if (argc < 1)
{
fprintf (stderr, "usage: %s [--binary] [--stdkey] key [filename]\n", pgm);
exit (1);
}
#ifdef __WIN32
if (use_binary)
setmode (fileno (stdout), O_BINARY);
#endif
key = use_stdkey? "What am I, a doctor or a moonshuttle conductor?" : *argv;
argc--, argv++;
keylen = strlen (key);
use_stdin = !argc;
if (selftest ())
{
fprintf (stderr, "%s: fatal error: self-test failed\n", pgm);
exit (2);
}
for (; argc || use_stdin; argv++, argc--)
{
const char *fname = use_stdin? "-" : *argv;
fp = use_stdin? stdin : fopen (fname, "rb");
if (!fp)
{
fprintf (stderr, "%s: can't open `%s': %s\n",
pgm, fname, strerror (errno));
exit (1);
}
hd = _gcry_hmac256_new (key, keylen);
if (!hd)
{
fprintf (stderr, "%s: can't allocate context: %s\n",
pgm, strerror (errno));
exit (1);
}
while ( (n = fread (buffer, 1, sizeof buffer, fp)))
_gcry_hmac256_update (hd, buffer, n);
if (ferror (fp))
{
fprintf (stderr, "%s: error reading `%s': %s\n",
pgm, fname, strerror (errno));
exit (1);
}
if (!use_stdin)
fclose (fp);
digest = _gcry_hmac256_finalize (hd, &dlen);
if (!digest)
{
fprintf (stderr, "%s: error computing HMAC: %s\n",
pgm, strerror (errno));
exit (1);
}
if (use_binary)
{
if (fwrite (digest, dlen, 1, stdout) != 1)
{
fprintf (stderr, "%s: error writing output: %s\n",
pgm, strerror (errno));
exit (1);
}
if (use_stdin)
break;
}
else
{
for (idx=0; idx < dlen; idx++)
printf ("%02x", digest[idx]);
_gcry_hmac256_release (hd);
if (use_stdin)
{
putchar ('\n');
break;
}
printf (" %s\n", fname);
}
}
return 0;
}
#endif /*STANDALONE*/
/*
Local Variables:
compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c"
End:
*/
diff --git a/src/hmac256.h b/src/hmac256.h
index df28e727..525e0258 100644
--- a/src/hmac256.h
+++ b/src/hmac256.h
@@ -1,36 +1,36 @@
/* hmac256.h - Declarations for _gcry_hmac256
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HMAC256_H
#define HMAC256_H
struct hmac256_context;
typedef struct hmac256_context *hmac256_context_t;
hmac256_context_t _gcry_hmac256_new (const void *key, size_t keylen);
void _gcry_hmac256_update (hmac256_context_t hd, const void *buf, size_t len);
const void *_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen);
void _gcry_hmac256_release (hmac256_context_t hd);
int _gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
const void *key, size_t keylen);
#endif /*HMAC256_H*/
diff --git a/src/hwf-arm.c b/src/hwf-arm.c
index 1d19ea86..2bb3632d 100644
--- a/src/hwf-arm.c
+++ b/src/hwf-arm.c
@@ -1,393 +1,393 @@
/* hwf-arm.c - Detect hardware features - ARM part
* Copyright (C) 2013,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/>.
+ * License along with this program; if not, see <https://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 (__arm__) && !defined (__aarch64__)
# 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;
const char *feature_match;
unsigned int hwf_flag;
};
#ifdef __arm__
/* 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 HWCAP_NEON
# define HWCAP_NEON 4096
#endif
#ifndef HWCAP2_AES
# define HWCAP2_AES 1
#endif
#ifndef HWCAP2_PMULL
# define HWCAP2_PMULL 2
#endif
#ifndef HWCAP2_SHA1
# define HWCAP2_SHA1 3
#endif
#ifndef HWCAP2_SHA2
# define HWCAP2_SHA2 4
#endif
static const struct feature_map_s arm_features[] =
{
#ifdef ENABLE_NEON_SUPPORT
{ HWCAP_NEON, 0, " neon", HWF_ARM_NEON },
#endif
#ifdef ENABLE_ARM_CRYPTO_SUPPORT
{ 0, HWCAP2_AES, " aes", HWF_ARM_AES },
{ 0, HWCAP2_SHA1," sha1", HWF_ARM_SHA1 },
{ 0, HWCAP2_SHA2, " sha2", HWF_ARM_SHA2 },
{ 0, HWCAP2_PMULL, " pmull", HWF_ARM_PMULL },
#endif
};
#elif defined(__aarch64__)
/* 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
#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[] =
{
#ifdef ENABLE_NEON_SUPPORT
{ HWCAP_ASIMD, 0, " asimd", HWF_ARM_NEON },
#endif
#ifdef ENABLE_ARM_CRYPTO_SUPPORT
{ HWCAP_AES, 0, " aes", HWF_ARM_AES },
{ HWCAP_SHA1, 0, " sha1", HWF_ARM_SHA1 },
{ HWCAP_SHA2, 0, " sha2", HWF_ARM_SHA2 },
{ HWCAP_PMULL, 0, " pmull", HWF_ARM_PMULL },
#endif
};
#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 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_arm_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(arm_features); i++)
{
if (hwcap & arm_features[i].hwcap_flag)
features |= arm_features[i].hwf_flag;
if (hwcap2 & arm_features[i].hwcap2_flag)
features |= arm_features[i].hwf_flag;
}
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)
{
char buf[1024]; /* large enough */
char *str_features, *str_feat;
int cpu_implementer, cpu_arch, cpu_variant, cpu_part, cpu_revision;
FILE *f;
int readlen, i;
size_t mlen;
static int cpuinfo_initialized = 0;
static unsigned int stored_cpuinfo_features;
static unsigned int stored_broken_hwfs;
struct {
const char *name;
int *value;
} cpu_entries[5] = {
{ "CPU implementer", &cpu_implementer },
{ "CPU architecture", &cpu_arch },
{ "CPU variant", &cpu_variant },
{ "CPU part", &cpu_part },
{ "CPU revision", &cpu_revision },
};
if (cpuinfo_initialized)
{
*broken_hwfs |= stored_broken_hwfs;
return stored_cpuinfo_features;
}
f = fopen("/proc/cpuinfo", "r");
if (!f)
return 0;
memset (buf, 0, sizeof(buf));
readlen = fread (buf, 1, sizeof(buf), f);
fclose (f);
if (readlen <= 0 || readlen > sizeof(buf))
return 0;
buf[sizeof(buf) - 1] = '\0';
cpuinfo_initialized = 1;
stored_cpuinfo_features = 0;
stored_broken_hwfs = 0;
/* Find features line. */
str_features = strstr(buf, "Features");
if (!str_features)
return stored_cpuinfo_features;
/* Find CPU version information. */
for (i = 0; i < DIM(cpu_entries); i++)
{
char *str;
*cpu_entries[i].value = -1;
str = strstr(buf, cpu_entries[i].name);
if (!str)
continue;
str = strstr(str, ": ");
if (!str)
continue;
str += 2;
if (strcmp(cpu_entries[i].name, "CPU architecture") == 0
&& strcmp(str, "AArch64") == 0)
*cpu_entries[i].value = 8;
else
*cpu_entries[i].value = strtoul(str, NULL, 0);
}
/* Lines to strings. */
for (i = 0; i < sizeof(buf); i++)
if (buf[i] == '\n')
buf[i] = '\0';
/* Check features. */
for (i = 0; i < DIM(arm_features); i++)
{
str_feat = strstr(str_features, arm_features[i].feature_match);
if (str_feat)
{
mlen = strlen(arm_features[i].feature_match);
if (str_feat[mlen] == ' ' || str_feat[mlen] == '\0')
{
stored_cpuinfo_features |= arm_features[i].hwf_flag;
}
}
}
/* Check for CPUs with broken NEON implementation. See
* https://code.google.com/p/chromium/issues/detail?id=341598
*/
if (cpu_implementer == 0x51
&& cpu_arch == 7
&& cpu_variant == 1
&& cpu_part == 0x4d
&& cpu_revision == 0)
{
stored_broken_hwfs = HWF_ARM_NEON;
}
*broken_hwfs |= stored_broken_hwfs;
return stored_cpuinfo_features;
}
#endif /* __linux__ */
unsigned int
_gcry_hwf_detect_arm (void)
{
unsigned int ret = 0;
unsigned int broken_hwfs = 0;
#if defined (HAS_SYS_AT_HWCAP)
ret |= detect_arm_at_hwcap ();
#endif
#if defined (HAS_PROC_CPUINFO)
ret |= detect_arm_proc_cpuinfo (&broken_hwfs);
#endif
#if defined(__ARM_NEON) && defined(ENABLE_NEON_SUPPORT)
ret |= HWF_ARM_NEON;
#endif
ret &= ~broken_hwfs;
return ret;
}
diff --git a/src/hwf-common.h b/src/hwf-common.h
index 8f156b56..f68d9b4d 100644
--- a/src/hwf-common.h
+++ b/src/hwf-common.h
@@ -1,27 +1,27 @@
/* hwf-common.h - Declarations for hwf-CPU.c modules
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HWF_COMMON_H
#define HWF_COMMON_H
unsigned int _gcry_hwf_detect_x86 (void);
unsigned int _gcry_hwf_detect_arm (void);
#endif /*HWF_COMMON_H*/
diff --git a/src/hwf-x86.c b/src/hwf-x86.c
index 796e874f..386e9db6 100644
--- a/src/hwf-x86.c
+++ b/src/hwf-x86.c
@@ -1,386 +1,386 @@
/* hwf-x86.c - Detect hardware features - x86 part
* Copyright (C) 2007, 2011, 2012 Free Software Foundation, Inc.
* Copyright (C) 2012 Jussi Kivilinna
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "g10lib.h"
#include "hwf-common.h"
#if !defined (__i386__) && !defined (__x86_64__)
# error Module build for wrong CPU.
#endif
/* We use the next macro to decide whether we can test for certain
features. */
#undef HAS_X86_CPUID
#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
# define HAS_X86_CPUID 1
#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;
/* Detect the CPUID feature by testing some undefined behaviour (16
vs 32 bit pushf/popf). */
asm volatile
("pushf\n\t" /* Copy flags to EAX. */
"popl %%eax\n\t"
"movl %%eax, %%ecx\n\t" /* Save flags into ECX. */
"xorl $0x200000, %%eax\n\t" /* Toggle ID bit and copy it to the flags. */
"pushl %%eax\n\t"
"popf\n\t"
"pushf\n\t" /* Copy changed flags again to EAX. */
"popl %%eax\n\t"
"pushl %%ecx\n\t" /* Restore flags from ECX. */
"popf\n\t"
"xorl %%eax, %%ecx\n\t" /* Compare flags against saved flags. */
"jz .Lno_cpuid%=\n\t" /* Toggling did not work, thus no CPUID. */
"movl $1, %0\n" /* Worked. true -> HAS_CPUID. */
".Lno_cpuid%=:\n\t"
: "+r" (has_cpuid)
:
: "%eax", "%ecx", "cc", "memory"
);
return has_cpuid;
}
static void
get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
unsigned int regs[4];
asm volatile
("movl %%ebx, %%edi\n\t" /* Save GOT register. */
"xorl %%ebx, %%ebx\n\t"
"cpuid\n\t"
"movl %%ebx, %1\n\t"
"movl %%edi, %%ebx\n\t" /* Restore GOT register. */
: "=a" (regs[0]), "=g" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
: "0" (in), "2" (0), "3" (0)
: "cc", "edi"
);
if (eax)
*eax = regs[0];
if (ebx)
*ebx = regs[1];
if (ecx)
*ecx = regs[2];
if (edx)
*edx = regs[3];
}
#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT)
static unsigned int
get_xgetbv(void)
{
unsigned int t_eax, t_edx;
asm volatile
("xgetbv\n\t"
: "=a" (t_eax), "=d" (t_edx)
: "c" (0)
);
return t_eax;
}
#endif /* ENABLE_AVX_SUPPORT || ENABLE_AVX2_SUPPORT */
#endif /* i386 && GNUC */
#if defined (__x86_64__) && defined (__GNUC__)
# define HAS_X86_CPUID 1
static int
is_cpuid_available(void)
{
return 1;
}
static void
get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
unsigned int regs[4];
asm volatile
("cpuid\n\t"
: "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
: "0" (in), "1" (0), "2" (0), "3" (0)
: "cc"
);
if (eax)
*eax = regs[0];
if (ebx)
*ebx = regs[1];
if (ecx)
*ecx = regs[2];
if (edx)
*edx = regs[3];
}
#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT)
static unsigned int
get_xgetbv(void)
{
unsigned int t_eax, t_edx;
asm volatile
("xgetbv\n\t"
: "=a" (t_eax), "=d" (t_edx)
: "c" (0)
);
return t_eax;
}
#endif /* ENABLE_AVX_SUPPORT || ENABLE_AVX2_SUPPORT */
#endif /* x86-64 && GNUC */
#ifdef HAS_X86_CPUID
static unsigned int
detect_x86_gnuc (void)
{
union
{
char c[12+1];
unsigned int ui[3];
} vendor_id;
unsigned int features, features2;
unsigned int os_supports_avx_avx2_registers = 0;
unsigned int max_cpuid_level;
unsigned int fms, family, model;
unsigned int result = 0;
unsigned int avoid_vpgather = 0;
(void)os_supports_avx_avx2_registers;
if (!is_cpuid_available())
return 0;
get_cpuid(0, &max_cpuid_level, &vendor_id.ui[0], &vendor_id.ui[2],
&vendor_id.ui[1]);
vendor_id.c[12] = 0;
if (0)
; /* Just to make "else if" and ifdef macros look pretty. */
#ifdef ENABLE_PADLOCK_SUPPORT
else if (!strcmp (vendor_id.c, "CentaurHauls"))
{
/* This is a VIA CPU. Check what PadLock features we have. */
/* Check for extended centaur (EAX). */
get_cpuid(0xC0000000, &features, NULL, NULL, NULL);
/* Has extended centaur features? */
if (features > 0xC0000000)
{
/* Ask for the extended feature flags (EDX). */
get_cpuid(0xC0000001, NULL, NULL, NULL, &features);
/* Test bits 2 and 3 to see whether the RNG exists and is enabled. */
if ((features & 0x0C) == 0x0C)
result |= HWF_PADLOCK_RNG;
/* Test bits 6 and 7 to see whether the ACE exists and is enabled. */
if ((features & 0xC0) == 0xC0)
result |= HWF_PADLOCK_AES;
/* Test bits 10 and 11 to see whether the PHE exists and is
enabled. */
if ((features & 0xC00) == 0xC00)
result |= HWF_PADLOCK_SHA;
/* Test bits 12 and 13 to see whether the MONTMUL exists and is
enabled. */
if ((features & 0x3000) == 0x3000)
result |= HWF_PADLOCK_MMUL;
}
}
#endif /*ENABLE_PADLOCK_SUPPORT*/
else if (!strcmp (vendor_id.c, "GenuineIntel"))
{
/* This is an Intel CPU. */
result |= HWF_INTEL_CPU;
}
else if (!strcmp (vendor_id.c, "AuthenticAMD"))
{
/* This is an AMD CPU. */
}
/* Detect Intel features, that might also be supported by other
vendors. */
/* Get CPU family/model/stepping (EAX) and Intel feature flags (ECX, EDX). */
get_cpuid(1, &fms, NULL, &features, &features2);
family = ((fms & 0xf00) >> 8) + ((fms & 0xff00000) >> 20);
model = ((fms & 0xf0) >> 4) + ((fms & 0xf0000) >> 12);
if ((result & HWF_INTEL_CPU) && family == 6)
{
/* These Intel Core processor models have SHLD/SHRD instruction that
* can do integer rotation faster actual ROL/ROR instructions. */
switch (model)
{
case 0x2A:
case 0x2D:
case 0x3A:
case 0x3C:
case 0x3F:
case 0x45:
case 0x46:
case 0x3D:
case 0x4F:
case 0x56:
case 0x47:
case 0x4E:
case 0x5E:
case 0x8E:
case 0x9E:
case 0x55:
case 0x66:
result |= HWF_INTEL_FAST_SHLD;
break;
}
/* These Intel Core processors that have AVX2 have slow VPGATHER and
* should be avoided for table-lookup use. */
switch (model)
{
case 0x3C:
case 0x3F:
case 0x45:
case 0x46:
/* Haswell */
avoid_vpgather |= 1;
break;
}
}
else
{
/* Avoid VPGATHER for non-Intel CPUs as testing is needed to
* make sure it is fast enough. */
avoid_vpgather |= 1;
}
#ifdef ENABLE_PCLMUL_SUPPORT
/* Test bit 1 for PCLMUL. */
if (features & 0x00000002)
result |= HWF_INTEL_PCLMUL;
#endif
/* Test bit 9 for SSSE3. */
if (features & 0x00000200)
result |= HWF_INTEL_SSSE3;
/* Test bit 19 for SSE4.1. */
if (features & 0x00080000)
result |= HWF_INTEL_SSE4_1;
#ifdef ENABLE_AESNI_SUPPORT
/* Test bit 25 for AES-NI. */
if (features & 0x02000000)
result |= HWF_INTEL_AESNI;
#endif /*ENABLE_AESNI_SUPPORT*/
#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT)
/* Test bit 27 for OSXSAVE (required for AVX/AVX2). */
if (features & 0x08000000)
{
/* Check that OS has enabled both XMM and YMM state support. */
if ((get_xgetbv() & 0x6) == 0x6)
os_supports_avx_avx2_registers = 1;
}
#endif
#ifdef ENABLE_AVX_SUPPORT
/* Test bit 28 for AVX. */
if (features & 0x10000000)
if (os_supports_avx_avx2_registers)
result |= HWF_INTEL_AVX;
#endif /*ENABLE_AVX_SUPPORT*/
#ifdef ENABLE_DRNG_SUPPORT
/* Test bit 30 for RDRAND. */
if (features & 0x40000000)
result |= HWF_INTEL_RDRAND;
#endif /*ENABLE_DRNG_SUPPORT*/
/* Test bit 4 of EDX for TSC. */
if (features2 & 0x00000010)
result |= HWF_INTEL_RDTSC;
/* Check additional Intel feature flags. Early Intel P5 processors report
* too high max_cpuid_level, so don't check level 7 if processor does not
* support SSE3 (as cpuid:7 contains only features for newer processors).
* Source: http://www.sandpile.org/x86/cpuid.htm */
if (max_cpuid_level >= 7 && (features & 0x00000001))
{
/* Get CPUID:7 contains further Intel feature flags. */
get_cpuid(7, NULL, &features, NULL, NULL);
/* Test bit 8 for BMI2. */
if (features & 0x00000100)
result |= HWF_INTEL_BMI2;
#ifdef ENABLE_AVX2_SUPPORT
/* Test bit 5 for AVX2. */
if (features & 0x00000020)
if (os_supports_avx_avx2_registers)
result |= HWF_INTEL_AVX2;
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;
}
return result;
}
#endif /* HAS_X86_CPUID */
unsigned int
_gcry_hwf_detect_x86 (void)
{
#if defined (HAS_X86_CPUID)
return detect_x86_gnuc ();
#else
return 0;
#endif
}
diff --git a/src/hwfeatures.c b/src/hwfeatures.c
index e0816694..6edb22f0 100644
--- a/src/hwfeatures.c
+++ b/src/hwfeatures.c
@@ -1,219 +1,219 @@
/* hwfeatures.c - Detect hardware features.
* Copyright (C) 2007, 2011 Free Software Foundation, Inc.
* Copyright (C) 2012 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /*HAVE_SYSLOG*/
#include "g10lib.h"
#include "hwf-common.h"
/* 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. */
static struct
{
unsigned int flag;
const char *desc;
} hwflist[] =
{
{ HWF_PADLOCK_RNG, "padlock-rng" },
{ HWF_PADLOCK_AES, "padlock-aes" },
{ HWF_PADLOCK_SHA, "padlock-sha" },
{ HWF_PADLOCK_MMUL, "padlock-mmul"},
{ HWF_INTEL_CPU, "intel-cpu" },
{ HWF_INTEL_FAST_SHLD, "intel-fast-shld" },
{ HWF_INTEL_BMI2, "intel-bmi2" },
{ HWF_INTEL_SSSE3, "intel-ssse3" },
{ HWF_INTEL_SSE4_1, "intel-sse4.1" },
{ HWF_INTEL_PCLMUL, "intel-pclmul" },
{ HWF_INTEL_AESNI, "intel-aesni" },
{ HWF_INTEL_RDRAND, "intel-rdrand" },
{ HWF_INTEL_AVX, "intel-avx" },
{ HWF_INTEL_AVX2, "intel-avx2" },
{ HWF_INTEL_FAST_VPGATHER, "intel-fast-vpgather" },
{ HWF_INTEL_RDTSC, "intel-rdtsc" },
{ HWF_INTEL_SHAEXT, "intel-shaext" },
{ 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" }
};
/* A bit vector with the hardware features which shall not be used.
This variable must be set prior to any initialization. */
static unsigned int disabled_hw_features;
/* A bit vector describing the hardware features currently
available. */
static unsigned int hw_features;
/* Disable a feature by name. This function must be called *before*
_gcry_detect_hw_features is called. */
gpg_err_code_t
_gcry_disable_hw_feature (const char *name)
{
int i;
size_t n1, n2;
while (name && *name)
{
n1 = strcspn (name, ":,");
if (!n1)
;
else if (n1 == 3 && !strncmp (name, "all", 3))
disabled_hw_features = ~0;
else
{
for (i=0; i < DIM (hwflist); i++)
{
n2 = strlen (hwflist[i].desc);
if (n1 == n2 && !strncmp (hwflist[i].desc, name, n2))
{
disabled_hw_features |= hwflist[i].flag;
break;
}
}
if (!(i < DIM (hwflist)))
return GPG_ERR_INV_NAME;
}
name += n1;
if (*name)
name++; /* Skip delimiter ':' or ','. */
}
return 0;
}
/* Return a bit vector describing the available hardware features.
The HWF_ constants are used to test for them. */
unsigned int
_gcry_get_hw_features (void)
{
return hw_features;
}
/* Enumerate all features. The caller is expected to start with an
IDX of 0 and then increment IDX until NULL is returned. */
const char *
_gcry_enum_hw_features (int idx, unsigned int *r_feature)
{
if (idx < 0 || idx >= DIM (hwflist))
return NULL;
if (r_feature)
*r_feature = hwflist[idx].flag;
return hwflist[idx].desc;
}
/* Read a file with features which shall not be used. The file is a
simple text file where empty lines and lines with the first non
white-space character being '#' are ignored. */
static void
parse_hwf_deny_file (void)
{
const char *fname = HWF_DENY_FILE;
FILE *fp;
char buffer[256];
char *p, *pend;
int lnr = 0;
fp = fopen (fname, "r");
if (!fp)
return;
for (;;)
{
if (!fgets (buffer, sizeof buffer, fp))
{
if (!feof (fp))
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING,
"Libgcrypt warning: error reading '%s', line %d",
fname, lnr);
#endif /*HAVE_SYSLOG*/
}
fclose (fp);
return;
}
lnr++;
for (p=buffer; my_isascii (*p) && isspace (*p); p++)
;
pend = strchr (p, '\n');
if (pend)
*pend = 0;
pend = p + (*p? (strlen (p)-1):0);
for ( ;pend > p; pend--)
if (my_isascii (*pend) && isspace (*pend))
*pend = 0;
if (!*p || *p == '#')
continue;
if (_gcry_disable_hw_feature (p) == GPG_ERR_INV_NAME)
{
#ifdef HAVE_SYSLOG
syslog (LOG_USER|LOG_WARNING,
"Libgcrypt warning: unknown feature in '%s', line %d",
fname, lnr);
#endif /*HAVE_SYSLOG*/
}
}
}
/* Detect the available hardware features. This function is called
once right at startup and we assume that no other threads are
running. */
void
_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)
{
hw_features = _gcry_hwf_detect_arm ();
}
#endif /* HAVE_CPU_ARCH_ARM */
hw_features &= ~disabled_hw_features;
}
diff --git a/src/misc.c b/src/misc.c
index 283e3a72..a94a921b 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,579 +1,579 @@
/* misc.c
* Copyright (C) 1999, 2001, 2002, 2003, 2007,
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "g10lib.h"
#include "secmem.h"
#include "mpi.h"
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;
static void *log_handler_value = 0;
static const char *(*user_gettext_handler)( const char * ) = NULL;
void
_gcry_set_gettext_handler (const char *(*f)(const char*))
{
user_gettext_handler = f;
}
const char *
_gcry_gettext( const char *key )
{
if( user_gettext_handler )
return user_gettext_handler( key );
/* FIXME: switch the domain to gnupg and restore later */
return key;
}
void
_gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value)
{
fatal_error_handler_value = value;
fatal_error_handler = fnc;
}
static void
write2stderr( const char *s )
{
/* Dummy variable to silence gcc warning. */
int res = write( 2, s, strlen(s) );
(void) res;
}
/*
* This function is called for fatal errors. A caller might want to
* set his own handler because this function simply calls abort().
*/
void
_gcry_fatal_error (int rc, const char *text)
{
if ( !text ) /* get a default text */
text = gpg_strerror (rc);
if (fatal_error_handler && !fips_mode () )
fatal_error_handler (fatal_error_handler_value, rc, text);
fips_signal_fatal_error (text);
write2stderr("\nFatal error: ");
write2stderr(text);
write2stderr("\n");
_gcry_secmem_term ();
abort ();
}
void
_gcry_set_log_handler (void (*f)(void*,int, const char*, va_list), void *opaque)
{
log_handler = f;
log_handler_value = opaque;
}
void
_gcry_set_log_verbosity( int level )
{
verbosity_level = level;
}
int
_gcry_log_verbosity( int level )
{
return verbosity_level >= level;
}
/****************
* This is our log function which prints all log messages to stderr or
* using the function defined with gcry_set_log_handler().
*/
void
_gcry_logv( int level, const char *fmt, va_list arg_ptr )
{
if (log_handler)
log_handler (log_handler_value, level, fmt, arg_ptr);
else
{
switch (level)
{
case GCRY_LOG_CONT: break;
case GCRY_LOG_INFO: break;
case GCRY_LOG_WARN: break;
case GCRY_LOG_ERROR: break;
case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break;
case GCRY_LOG_BUG: fputs("Ohhhh jeeee: ", stderr); break;
case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break;
default: fprintf(stderr,"[Unknown log level %d]: ", level ); break;
}
vfprintf(stderr,fmt,arg_ptr) ;
}
if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG )
{
fips_signal_fatal_error ("internal error (fatal or bug)");
_gcry_secmem_term ();
abort ();
}
}
void
_gcry_log( int level, const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( level, fmt, arg_ptr );
va_end(arg_ptr);
}
#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L
void
_gcry_bug( const char *file, int line, const char *func )
{
_gcry_log( GCRY_LOG_BUG,
("... this is a bug (%s:%d:%s)\n"), file, line, func );
abort(); /* never called, but it makes the compiler happy */
}
void
_gcry_assert_failed (const char *expr, const char *file, int line,
const char *func)
{
_gcry_log (GCRY_LOG_BUG,
("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func );
abort(); /* Never called, but it makes the compiler happy. */
}
#else
void
_gcry_bug( const char *file, int line )
{
_gcry_log( GCRY_LOG_BUG,
_("you found a bug ... (%s:%d)\n"), file, line);
abort(); /* never called, but it makes the compiler happy */
}
void
_gcry_assert_failed (const char *expr, const char *file, int line)
{
_gcry_log (GCRY_LOG_BUG,
("Assertion `%s' failed (%s:%d)\n"), expr, file, line);
abort(); /* Never called, but it makes the compiler happy. */
}
#endif
void
_gcry_log_info( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr );
va_end(arg_ptr);
}
void
_gcry_log_error( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr );
va_end(arg_ptr);
}
void
_gcry_log_fatal( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
_gcry_log_bug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
_gcry_log_debug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr );
va_end(arg_ptr);
}
void
_gcry_log_printf (const char *fmt, ...)
{
va_list arg_ptr;
if (fmt)
{
va_start( arg_ptr, fmt ) ;
_gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr);
va_end(arg_ptr);
}
}
/* Helper for _gcry_log_printhex and _gcry_log_printmpi. */
static void
do_printhex (const char *text, const char *text2,
const void *buffer, size_t length)
{
int wrap = 0;
int cnt = 0;
if (text && *text)
{
wrap = 1;
log_debug ("%s:%s", text, text2);
if (text2[1] == '[' && length && buffer)
{
/* Start with a new line so that we get nice output for
opaque MPIS:
"value: [31 bit]"
" 01020300" */
log_printf ("\n");
text2 = " ";
log_debug ("%*s ", (int)strlen(text), "");
}
}
if (length && buffer)
{
const unsigned char *p = buffer;
for (; length--; p++)
{
log_printf ("%02x", *p);
if (wrap && ++cnt == 32 && length)
{
cnt = 0;
log_printf (" \\\n");
log_debug ("%*s %*s",
(int)strlen(text), "", (int)strlen(text2), "");
}
}
}
if (text)
log_printf ("\n");
}
/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw
dump without any wrappping, with TEXT an empty string, print a
trailing linefeed, otherwise print an entire debug line. */
void
_gcry_log_printhex (const char *text, const void *buffer, size_t length)
{
do_printhex (text, " ", buffer, length);
}
/* Print MPI in hex notation. To make clear that the output is an MPI
a sign is always printed. With TEXT of NULL print just the raw dump
without any wrapping, with TEXT an empty string, print a trailing
linefeed, otherwise print an entire debug line. */
void
_gcry_log_printmpi (const char *text, gcry_mpi_t mpi)
{
unsigned char *rawmpi;
unsigned int rawmpilen;
int sign;
if (!mpi)
do_printhex (text? text:" ", " (null)", NULL, 0);
else if (mpi_is_opaque (mpi))
{
unsigned int nbits;
const unsigned char *p;
char prefix[30];
p = mpi_get_opaque (mpi, &nbits);
snprintf (prefix, sizeof prefix, " [%u bit]", nbits);
do_printhex (text? text:" ", prefix, p, (nbits+7)/8);
}
else
{
rawmpi = _gcry_mpi_get_buffer (mpi, 0, &rawmpilen, &sign);
if (!rawmpi)
do_printhex (text? text:" ", " [out of core]", NULL, 0);
else
{
if (!rawmpilen)
do_printhex (text, sign? "-":"+", "", 1);
else
do_printhex (text, sign? "-":"+", rawmpi, rawmpilen);
xfree (rawmpi);
}
}
}
static int
count_closing_parens (const char *p)
{
int count = 0;
for (; *p; p++)
if (*p == ')')
count++;
else if (!strchr ("\n \t", *p))
return 0;
return count;
}
/* Print SEXP in human readabale format. With TEXT of NULL print just the raw
dump without any wrappping, with TEXT an empty string, print a
trailing linefeed, otherwise print the full debug output. */
void
_gcry_log_printsxp (const char *text, gcry_sexp_t sexp)
{
int with_lf = 0;
if (text && *text)
{
if ((with_lf = !!strchr (text, '\n')))
log_debug ("%s", text);
else
log_debug ("%s: ", text);
}
if (sexp)
{
int any = 0;
int n_closing;
char *buf, *pend;
const char *p;
size_t size;
size = sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
p = buf = xmalloc (size);
sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buf, size);
do
{
if (any && !with_lf)
log_debug ("%*s ", text?(int)strlen(text):0, "");
else
any = 1;
pend = strchr (p, '\n');
size = pend? (pend - p) : strlen (p);
if (with_lf)
log_debug ("%.*s", (int)size, p);
else
log_printf ("%.*s", (int)size, p);
if (pend)
p = pend + 1;
else
p += size;
n_closing = count_closing_parens (p);
if (n_closing)
{
while (n_closing--)
log_printf (")");
p = "";
}
log_printf ("\n");
}
while (*p);
xfree (buf);
}
else if (text)
log_printf ("\n");
}
/*
* Tokenize STRING using the set of delimiters in DELIM. Leading
* white spaces are removed from all tokens. The caller must xfree
* the result.
*
* Returns: A malloced and NULL delimited array with the tokens. On
* memory error NULL is returned and ERRNO is set.
*/
char **
_gcry_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;
char const ws[] = " \t\v\f\r\n";
if (!delim)
delim = ws;
/* 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)
{
gpg_err_set_errno (ENOMEM);
return NULL;
}
n = strlen (string) + 1;
bytes += n;
if (bytes < n)
{
gpg_err_set_errno (ENOMEM);
return NULL;
}
result = xtrymalloc (bytes);
if (!result)
return NULL;
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 (strchr (ws, *(byte*)p))
p++;
for (px = pend - 1; px >= p && strchr (ws, *(byte*)px); px--)
*px = 0;
result[n++] = p;
}
while (*p && strchr (ws, *(byte*)p))
p++;
for (px = p + strlen (p) - 1; px >= p && strchr (ws, *(byte*)px); px--)
*px = 0;
/* Traling spaces may result in an empty field. We do not want to
store that. */
result[n++] = *p? p : NULL;
result[n] = NULL;
gcry_assert ((char*)(result + n + 1) == buffer);
return result;
}
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
__gcry_burn_stack (unsigned int bytes)
{
#ifdef HAVE_VLA
/* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
char buf[buflen];
_gcry_fast_wipememory (buf, buflen);
#else
volatile char buf[64];
_gcry_fast_wipememory (buf, sizeof buf);
if (bytes > sizeof buf)
_gcry_burn_stack (bytes - sizeof buf);
#endif
}
#ifndef HAVE_GCC_ASM_VOLATILE_MEMORY
void
__gcry_burn_stack_dummy (void)
{
}
#endif
void
_gcry_divide_by_zero (void)
{
gpg_err_set_errno (EDOM);
_gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero");
}
diff --git a/src/mpicalc.c b/src/mpicalc.c
index 11246f38..e8a8f432 100644
--- a/src/mpicalc.c
+++ b/src/mpicalc.c
@@ -1,627 +1,627 @@
/* mpicalc.c - Simple RPN calculator using gcry_mpi functions
* Copyright (C) 1997, 1998, 1999, 2004, 2006, 2013 Werner Koch
*
* This program 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 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 Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
This program is a simple RPN calculator which was originally used
to develop the mpi functions of GnuPG. Values must be given in
hex. Operation is like dc(1) except that the input/output radix is
always 16 and you can use a '-' to prefix a negative number.
Addition operators: ++ and --. All operators must be delimited by
a blank.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# undef _GCRYPT_IN_LIBGCRYPT
# include "gcrypt.h"
#else
# include <gcrypt.h>
#endif
#define MPICALC_VERSION "2.0"
#define NEED_LIBGCRYPT_VERSION "1.6.0"
#define STACKSIZE 500
static gcry_mpi_t stack[STACKSIZE];
static int stackidx;
static int
scan_mpi (gcry_mpi_t retval, const char *string)
{
gpg_error_t err;
gcry_mpi_t val;
err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (err)
{
fprintf (stderr, "scanning input failed: %s\n", gpg_strerror (err));
return -1;
}
mpi_set (retval, val);
mpi_release (val);
return 0;
}
static void
print_mpi (gcry_mpi_t a)
{
gpg_error_t err;
char *buf;
void *bufaddr = &buf;
err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
if (err)
fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (err));
else
{
fputs (buf, stdout);
gcry_free (buf);
}
}
static void
do_add (void)
{
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_add (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
stackidx--;
}
static void
do_sub (void)
{
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_sub (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
stackidx--;
}
static void
do_inc (void)
{
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_add_ui (stack[stackidx - 1], stack[stackidx - 1], 1);
}
static void
do_dec (void)
{
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
/* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
}
static void
do_mul (void)
{
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_mul (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
stackidx--;
}
static void
do_mulm (void)
{
if (stackidx < 3)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_mulm (stack[stackidx - 3], stack[stackidx - 3],
stack[stackidx - 2], stack[stackidx - 1]);
stackidx -= 2;
}
static void
do_div (void)
{
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_fdiv (stack[stackidx - 2], NULL,
stack[stackidx - 2], stack[stackidx - 1]);
stackidx--;
}
static void
do_rem (void)
{
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_mod (stack[stackidx - 2],
stack[stackidx - 2], stack[stackidx - 1]);
stackidx--;
}
static void
do_powm (void)
{
gcry_mpi_t a;
if (stackidx < 3)
{
fputs ("stack underflow\n", stderr);
return;
}
a = mpi_new (0);
mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]);
mpi_release (stack[stackidx - 3]);
stack[stackidx - 3] = a;
stackidx -= 2;
}
static void
do_inv (void)
{
gcry_mpi_t a;
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
a = mpi_new (0);
mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]);
mpi_set (stack[stackidx - 2], a);
mpi_release (a);
stackidx--;
}
static void
do_gcd (void)
{
gcry_mpi_t a;
if (stackidx < 2)
{
fputs ("stack underflow\n", stderr);
return;
}
a = mpi_new (0);
mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]);
mpi_set (stack[stackidx - 2], a);
mpi_release (a);
stackidx--;
}
static void
do_lshift (void)
{
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_lshift (stack[stackidx - 1], stack[stackidx - 1], 1);
}
static void
do_rshift (void)
{
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
mpi_rshift (stack[stackidx - 1], stack[stackidx - 1], 1);
}
static void
do_nbits (void)
{
unsigned int n;
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
n = mpi_get_nbits (stack[stackidx - 1]);
mpi_set_ui (stack[stackidx - 1], n);
}
static void
do_primecheck (void)
{
gpg_error_t err;
if (stackidx < 1)
{
fputs ("stack underflow\n", stderr);
return;
}
err = gcry_prime_check (stack[stackidx - 1], 0);
mpi_set_ui (stack[stackidx - 1], !err);
if (err && gpg_err_code (err) != GPG_ERR_NO_PRIME)
fprintf (stderr, "checking prime failed: %s\n", gpg_strerror (err));
}
static int
my_getc (void)
{
static int shown;
int c;
for (;;)
{
if ((c = getc (stdin)) == EOF)
return EOF;
if (!(c & 0x80))
return c;
if (!shown)
{
shown = 1;
fputs ("note: Non ASCII characters are ignored\n", stderr);
}
}
}
static void
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"
"% modulo [0] := [1] % [0] {-1}\n"
"< left shift [0] := [0] << 1 {0}\n"
"> right shift [0] := [0] >> 1 {0}\n"
"++ increment [0] := [0]++ {0}\n"
"-- decrement [0] := [0]-- {0}\n"
"m multiply mod [0] := [2] * [1] mod [0] {-2}\n"
"^ power mod [0] := [2] ^ [1] mod [0] {-2}\n"
"I inverse mod [0] := [1]^-1 mod [0] {-1}\n"
"G gcd [0] := gcd([1],[0]) {-1}\n"
"i remove item [0] := [1] {-1}\n"
"d dup item [-1] := [0] {+1}\n"
"r reverse [0] := [1], [1] := [0] {0}\n"
"b # of bits [0] := nbits([0]) {0}\n"
"P prime check [0] := is_prime([0])?1:0 {0}\n"
"c clear stack\n"
"p print top item\n"
"f print the stack\n"
"# ignore until end of line\n"
"? print this help\n"
, stdout);
}
int
main (int argc, char **argv)
{
const char *pgm;
int last_argc = -1;
int print_config = 0;
int i, c;
int state = 0;
char strbuf[4096];
int stridx = 0;
if (argc)
{
pgm = strrchr (*argv, '/');
if (pgm)
pgm++;
else
pgm = *argv;
argc--; argv++;
}
else
pgm = "?";
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version")
|| !strcmp (*argv, "--help"))
{
printf ("%s " MPICALC_VERSION "\n"
"libgcrypt %s\n"
"Copyright (C) 1997, 2013 Werner Koch\n"
"License LGPLv2.1+: GNU LGPL version 2.1 or later "
- "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
+ "<https://gnu.org/licenses/old-licenses/lgpl-2.1.html>\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"
"\n"
"Syntax: mpicalc [options]\n"
"Simple interactive big integer RPN calculator\n"
"\n"
"Options:\n"
" --version print version information\n"
" --print-config print the Libgcrypt config\n"
" --disable-hwf NAME disable feature NAME\n",
pgm, gcry_check_version (NULL));
exit (0);
}
else if (!strcmp (*argv, "--print-config"))
{
argc--; argv++;
print_config = 1;
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--; argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr, "%s: unknown hardware feature `%s'"
" - option ignored\n", pgm, *argv);
argc--; argv++;
}
}
}
if (argc)
{
fprintf (stderr, "usage: %s [options] (--help for help)\n", pgm);
exit (1);
}
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
{
fprintf (stderr, "%s: Libgcrypt is too old (need %s, have %s)\n",
pgm, NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
exit (1);
}
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (print_config)
{
gcry_control (GCRYCTL_PRINT_CONFIG, stdout);
exit (0);
}
for (i = 0; i < STACKSIZE; i++)
stack[i] = NULL;
stackidx = 0;
while ((c = my_getc ()) != EOF)
{
if (!state) /* waiting */
{
if (isdigit (c))
{
state = 1;
ungetc (c, stdin);
strbuf[0] = '0';
strbuf[1] = 'x';
stridx = 2;
}
else if (isspace (c))
;
else
{
switch (c)
{
case '#':
state = 2;
break;
case '+':
if ((c = my_getc ()) == '+')
do_inc ();
else
{
ungetc (c, stdin);
do_add ();
}
break;
case '-':
if ((c = my_getc ()) == '-')
do_dec ();
else if (isdigit (c)
|| (c >= 'A' && c <= 'F')
|| (c >= 'a' && c <= 'f'))
{
state = 1;
ungetc (c, stdin);
strbuf[0] = '-';
strbuf[1] = '0';
strbuf[2] = 'x';
stridx = 3;
}
else
{
ungetc (c, stdin);
do_sub ();
}
break;
case '*':
do_mul ();
break;
case 'm':
do_mulm ();
break;
case '/':
do_div ();
break;
case '%':
do_rem ();
break;
case '^':
do_powm ();
break;
case '<':
do_lshift ();
break;
case '>':
do_rshift ();
break;
case 'I':
do_inv ();
break;
case 'G':
do_gcd ();
break;
case 'i': /* dummy */
if (!stackidx)
fputs ("stack underflow\n", stderr);
else
{
mpi_release (stack[stackidx - 1]);
stackidx--;
}
break;
case 'd': /* duplicate the tos */
if (!stackidx)
fputs ("stack underflow\n", stderr);
else if (stackidx < STACKSIZE)
{
mpi_release (stack[stackidx]);
stack[stackidx] = mpi_copy (stack[stackidx - 1]);
stackidx++;
}
else
fputs ("stack overflow\n", stderr);
break;
case 'r': /* swap top elements */
if (stackidx < 2)
fputs ("stack underflow\n", stderr);
else if (stackidx < STACKSIZE)
{
gcry_mpi_t tmp = stack[stackidx-1];
stack[stackidx-1] = stack[stackidx - 2];
stack[stackidx-2] = tmp;
}
break;
case 'b':
do_nbits ();
break;
case 'P':
do_primecheck ();
break;
case 'c':
for (i = 0; i < stackidx; i++)
{
mpi_release (stack[i]); stack[i] = NULL;
}
stackidx = 0;
break;
case 'p': /* print the tos */
if (!stackidx)
puts ("stack is empty");
else
{
print_mpi (stack[stackidx - 1]);
putchar ('\n');
}
break;
case 'f': /* print the stack */
for (i = stackidx - 1; i >= 0; i--)
{
printf ("[%2d]: ", i);
print_mpi (stack[i]);
putchar ('\n');
}
break;
case '?':
print_help ();
break;
default:
fputs ("invalid operator\n", stderr);
}
}
}
else if (state == 1) /* In a number. */
{
if (!isxdigit (c))
{
/* Store the number */
state = 0;
ungetc (c, stdin);
if (stridx < sizeof strbuf)
strbuf[stridx] = 0;
if (stackidx < STACKSIZE)
{
if (!stack[stackidx])
stack[stackidx] = mpi_new (0);
if (scan_mpi (stack[stackidx], strbuf))
fputs ("invalid number\n", stderr);
else
stackidx++;
}
else
fputs ("stack overflow\n", stderr);
}
else
{ /* Store a digit. */
if (stridx < sizeof strbuf - 1)
strbuf[stridx++] = c;
else if (stridx == sizeof strbuf - 1)
{
strbuf[stridx] = 0;
fputs ("input too large - truncated\n", stderr);
stridx++;
}
}
}
else if (state == 2) /* In a comment. */
{
if (c == '\n')
state = 0;
}
}
for (i = 0; i < stackidx; i++)
mpi_release (stack[i]);
return 0;
}
diff --git a/src/secmem.c b/src/secmem.c
index b36c44f6..9e3e5cf3 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -1,952 +1,952 @@
/* secmem.c - memory allocation from a secure heap
* Copyright (C) 1998, 1999, 2000, 2001, 2002,
* 2003, 2007 Free Software Foundation, Inc.
* Copyright (C) 2013, 2016 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <stddef.h>
#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef USE_CAPABILITIES
#include <sys/capability.h>
#endif
#endif
#include "g10lib.h"
#include "secmem.h"
#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
#define MINIMUM_POOL_SIZE 16384
#define STANDARD_POOL_SIZE 32768
#define DEFAULT_PAGE_SIZE 4096
typedef struct memblock
{
unsigned size; /* Size of the memory available to the
user. */
int flags; /* See below. */
PROPERLY_ALIGNED_TYPE aligned;
} memblock_t;
/* This flag specifies that the memory block is in use. */
#define MB_FLAG_ACTIVE (1 << 0)
/* An object describing a memory pool. */
typedef struct pooldesc_s
{
/* A link to the next pool. This is used to connect the overflow
* pools. */
struct pooldesc_s * volatile next;
/* A memory buffer used as allocation pool. */
void *mem;
/* The allocated size of MEM. */
size_t size;
/* Flag indicating that this memory pool is ready for use. May be
* checked in an atexit function. */
volatile int okay;
/* Flag indicating whether MEM is mmapped. */
volatile int is_mmapped;
/* The number of allocated bytes and the number of used blocks in
* this pool. */
unsigned int cur_alloced, cur_blocks;
} pooldesc_t;
/* The pool of secure memory. This is the head of a linked list with
* the first element being the standard mlock-ed pool and the
* following elements being the overflow pools. */
static pooldesc_t mainpool;
/* A couple of flags with some being set early. */
static int disable_secmem;
static int show_warning;
static int not_locked;
static int no_warning;
static int suspend_warning;
static int no_mlock;
static int no_priv_drop;
static unsigned int auto_expand;
/* Lock protecting accesses to the memory pools. */
GPGRT_LOCK_DEFINE (secmem_lock);
/* Convenient macros. */
#define SECMEM_LOCK gpgrt_lock_lock (&secmem_lock)
#define SECMEM_UNLOCK gpgrt_lock_unlock (&secmem_lock)
/* The size of the memblock structure; this does not include the
memory that is available to the user. */
#define BLOCK_HEAD_SIZE \
offsetof (memblock_t, aligned)
/* Convert an address into the according memory block structure. */
#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)
{
/* We need to convert pointers to addresses. This is required by
C-99 6.5.8 to avoid undefined behaviour. See also
- http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
+ https://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
*/
uintptr_t p_addr = (uintptr_t)p;
uintptr_t pool_addr = (uintptr_t)pool->mem;
return p_addr >= pool_addr && p_addr < pool_addr + pool->size;
}
/* Update the stats. */
static void
stats_update (pooldesc_t *pool, size_t add, size_t sub)
{
if (add)
{
pool->cur_alloced += add;
pool->cur_blocks++;
}
if (sub)
{
pool->cur_alloced -= sub;
pool->cur_blocks--;
}
}
/* Return the block following MB or NULL, if MB is the last block. */
static memblock_t *
mb_get_next (pooldesc_t *pool, memblock_t *mb)
{
memblock_t *mb_next;
mb_next = (memblock_t *) (void *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
if (! ptr_into_pool_p (pool, mb_next))
mb_next = NULL;
return mb_next;
}
/* Return the block preceding MB or NULL, if MB is the first
block. */
static memblock_t *
mb_get_prev (pooldesc_t *pool, memblock_t *mb)
{
memblock_t *mb_prev, *mb_next;
if (mb == pool->mem)
mb_prev = NULL;
else
{
mb_prev = (memblock_t *) pool->mem;
while (1)
{
mb_next = mb_get_next (pool, mb_prev);
if (mb_next == mb)
break;
else
mb_prev = mb_next;
}
}
return mb_prev;
}
/* If the preceding block of MB and/or the following block of MB
exist and are not active, merge them to form a bigger block. */
static void
mb_merge (pooldesc_t *pool, memblock_t *mb)
{
memblock_t *mb_prev, *mb_next;
mb_prev = mb_get_prev (pool, mb);
mb_next = mb_get_next (pool, mb);
if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
{
mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
mb = mb_prev;
}
if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
mb->size += BLOCK_HEAD_SIZE + mb_next->size;
}
/* Return a new block, which can hold SIZE bytes. */
static memblock_t *
mb_get_new (pooldesc_t *pool, memblock_t *block, size_t size)
{
memblock_t *mb, *mb_split;
for (mb = block; ptr_into_pool_p (pool, mb); mb = mb_get_next (pool, mb))
if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
{
/* Found a free block. */
mb->flags |= MB_FLAG_ACTIVE;
if (mb->size - size > BLOCK_HEAD_SIZE)
{
/* Split block. */
mb_split = (memblock_t *) (void *) (((char *) mb) + BLOCK_HEAD_SIZE
+ size);
mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
mb_split->flags = 0;
mb->size = size;
mb_merge (pool, mb_split);
}
break;
}
if (! ptr_into_pool_p (pool, mb))
{
gpg_err_set_errno (ENOMEM);
mb = NULL;
}
return mb;
}
/* Print a warning message. */
static void
print_warn (void)
{
if (!no_warning)
log_info (_("Warning: using insecure memory!\n"));
}
/* Lock the memory pages of pool P of size N into core and drop
* privileges. */
static void
lock_pool_pages (void *p, size_t n)
{
#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
int err;
{
cap_t cap;
if (!no_priv_drop)
{
cap = cap_from_text ("cap_ipc_lock+ep");
cap_set_proc (cap);
cap_free (cap);
}
err = no_mlock? 0 : mlock (p, n);
if (err && errno)
err = errno;
if (!no_priv_drop)
{
cap = cap_from_text ("cap_ipc_lock+p");
cap_set_proc (cap);
cap_free(cap);
}
}
if (err)
{
if (err != EPERM
#ifdef EAGAIN /* BSD and also Linux may return EAGAIN */
&& err != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
&& err != ENOSYS
#endif
#ifdef ENOMEM /* Linux might return this. */
&& err != ENOMEM
#endif
)
log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
not_locked = 1;
}
#elif defined(HAVE_MLOCK)
uid_t uid;
int err;
uid = getuid ();
#ifdef HAVE_BROKEN_MLOCK
/* Under HP/UX mlock segfaults if called by non-root. Note, we have
noch checked whether mlock does really work under AIX where we
also detected a broken nlock. Note further, that using plock ()
is not a good idea under AIX. */
if (uid)
{
errno = EPERM;
err = errno;
}
else
{
err = no_mlock? 0 : mlock (p, n);
if (err && errno)
err = errno;
}
#else /* !HAVE_BROKEN_MLOCK */
err = no_mlock? 0 : mlock (p, n);
if (err && errno)
err = errno;
#endif /* !HAVE_BROKEN_MLOCK */
/* Test whether we are running setuid(0). */
if (uid && ! geteuid ())
{
/* Yes, we are. */
if (!no_priv_drop)
{
/* Check that we really dropped the privs.
* Note: setuid(0) should always fail */
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
log_fatal ("failed to reset uid: %s\n", strerror (errno));
}
}
if (err)
{
if (err != EPERM
#ifdef EAGAIN /* BSD and also Linux may return this. */
&& err != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented). */
&& err != ENOSYS
#endif
#ifdef ENOMEM /* Linux might return this. */
&& err != ENOMEM
#endif
)
log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
not_locked = 1;
}
#elif defined ( __QNX__ )
/* QNX does not page at all, so the whole secure memory stuff does
* not make much sense. However it is still of use because it
* wipes out the memory on a free().
* Therefore it is sufficient to suppress the warning. */
(void)p;
(void)n;
#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
/* It does not make sense to print such a warning, given the fact that
* this whole Windows !@#$% and their user base are inherently insecure. */
(void)p;
(void)n;
#elif defined (__riscos__)
/* No virtual memory on RISC OS, so no pages are swapped to disc,
* besides we don't have mmap, so we don't use it! ;-)
* But don't complain, as explained above. */
(void)p;
(void)n;
#else
(void)p;
(void)n;
if (!no_mlock)
log_info ("Please note that you don't have secure memory on this system\n");
#endif
}
/* Initialize POOL. */
static void
init_pool (pooldesc_t *pool, size_t n)
{
memblock_t *mb;
pool->size = n;
if (disable_secmem)
log_bug ("secure memory is disabled");
#if HAVE_MMAP
{
size_t pgsize;
long int pgsize_val;
# if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
pgsize_val = sysconf (_SC_PAGESIZE);
# elif defined(HAVE_GETPAGESIZE)
pgsize_val = getpagesize ();
# else
pgsize_val = -1;
# endif
pgsize = (pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE;
pool->size = (pool->size + pgsize - 1) & ~(pgsize - 1);
# ifdef MAP_ANONYMOUS
pool->mem = mmap (0, pool->size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
# else /* map /dev/zero instead */
{
int fd;
fd = open ("/dev/zero", O_RDWR);
if (fd == -1)
{
log_error ("can't open /dev/zero: %s\n", strerror (errno));
pool->mem = (void *) -1;
}
else
{
pool->mem = mmap (0, pool->size,
(PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
close (fd);
}
}
# endif
if (pool->mem == (void *) -1)
log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
(unsigned) pool->size, strerror (errno));
else
{
pool->is_mmapped = 1;
pool->okay = 1;
}
}
#endif /*HAVE_MMAP*/
if (!pool->okay)
{
pool->mem = malloc (pool->size);
if (!pool->mem)
log_fatal ("can't allocate memory pool of %u bytes\n",
(unsigned) pool->size);
else
pool->okay = 1;
}
/* Initialize first memory block. */
mb = (memblock_t *) pool->mem;
mb->size = pool->size - BLOCK_HEAD_SIZE;
mb->flags = 0;
}
/* Enable overflow pool allocation in all cases. CHUNKSIZE is a hint
* on how large to allocate overflow pools. */
void
_gcry_secmem_set_auto_expand (unsigned int chunksize)
{
/* Round up to a multiple of the STANDARD_POOL_SIZE. */
chunksize = ((chunksize + (2*STANDARD_POOL_SIZE) - 1)
/ STANDARD_POOL_SIZE ) * STANDARD_POOL_SIZE;
if (chunksize < STANDARD_POOL_SIZE) /* In case of overflow. */
chunksize = STANDARD_POOL_SIZE;
SECMEM_LOCK;
auto_expand = chunksize;
SECMEM_UNLOCK;
}
void
_gcry_secmem_set_flags (unsigned flags)
{
int was_susp;
SECMEM_LOCK;
was_susp = suspend_warning;
no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
no_mlock = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
/* and now issue the warning if it is not longer suspended */
if (was_susp && !suspend_warning && show_warning)
{
show_warning = 0;
print_warn ();
}
SECMEM_UNLOCK;
}
unsigned int
_gcry_secmem_get_flags (void)
{
unsigned flags;
SECMEM_LOCK;
flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
SECMEM_UNLOCK;
return flags;
}
/* 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)
{
pooldesc_t *pool;
pool = &mainpool;
if (!n)
{
#ifdef USE_CAPABILITIES
/* drop all capabilities */
if (!no_priv_drop)
{
cap_t cap;
cap = cap_from_text ("all-eip");
cap_set_proc (cap);
cap_free (cap);
}
#elif !defined(HAVE_DOSISH_SYSTEM)
uid_t uid;
disable_secmem = 1;
uid = getuid ();
if (uid != geteuid ())
{
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
log_fatal ("failed to drop setuid\n");
}
#endif
}
else
{
if (n < MINIMUM_POOL_SIZE)
n = MINIMUM_POOL_SIZE;
if (! pool->okay)
{
init_pool (pool, n);
lock_pool_pages (pool->mem, n);
}
else
log_error ("Oops, secure memory pool already initialized\n");
}
}
/* Initialize the secure memory system. If running with the necessary
privileges, the secure memory pool will be locked into the core in
order to prevent page-outs of the data. Furthermore allocated
secure memory will be wiped out when released. */
void
_gcry_secmem_init (size_t n)
{
SECMEM_LOCK;
_gcry_secmem_init_internal (n);
SECMEM_UNLOCK;
}
gcry_err_code_t
_gcry_secmem_module_init ()
{
/* Not anymore needed. */
return 0;
}
static void *
_gcry_secmem_malloc_internal (size_t size, int xhint)
{
pooldesc_t *pool;
memblock_t *mb;
pool = &mainpool;
if (!pool->okay)
{
/* Try to initialize the pool if the user forgot about it. */
_gcry_secmem_init_internal (STANDARD_POOL_SIZE);
if (!pool->okay)
{
log_info (_("operation is not possible without "
"initialized secure memory\n"));
gpg_err_set_errno (ENOMEM);
return NULL;
}
}
if (not_locked && fips_mode ())
{
log_info (_("secure memory pool is not locked while in FIPS mode\n"));
gpg_err_set_errno (ENOMEM);
return NULL;
}
if (show_warning && !suspend_warning)
{
show_warning = 0;
print_warn ();
}
/* Blocks are always a multiple of 32. */
size = ((size + 31) / 32) * 32;
mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
if (mb)
{
stats_update (pool, mb->size, 0);
return &mb->aligned.c;
}
/* 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. 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);
if (mb)
{
stats_update (pool, mb->size, 0);
return &mb->aligned.c;
}
}
/* Allocate a new overflow pool. We put a new pool right after
* the mainpool so that the next allocation will happen in that
* pool and not in one of the older pools. When this new pool
* gets full we will try to find space in the older pools. */
pool = calloc (1, sizeof *pool);
if (!pool)
return NULL; /* Not enough memory for a new pool descriptor. */
pool->size = auto_expand? auto_expand : STANDARD_POOL_SIZE;
pool->mem = malloc (pool->size);
if (!pool->mem)
{
free (pool);
return NULL; /* Not enough memory available for a new pool. */
}
/* Initialize first memory block. */
mb = (memblock_t *) pool->mem;
mb->size = pool->size - BLOCK_HEAD_SIZE;
mb->flags = 0;
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. 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
* warning. */
if (!pool->next)
print_warn ();
/* Allocate. */
mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
if (mb)
{
stats_update (pool, mb->size, 0);
return &mb->aligned.c;
}
}
return NULL;
}
/* Allocate a block from the secmem of SIZE. With XHINT set assume
* that the caller is a xmalloc style function. */
void *
_gcry_secmem_malloc (size_t size, int xhint)
{
void *p;
SECMEM_LOCK;
p = _gcry_secmem_malloc_internal (size, xhint);
SECMEM_UNLOCK;
return p;
}
static int
_gcry_secmem_free_internal (void *a)
{
pooldesc_t *pool;
memblock_t *mb;
int size;
for (pool = &mainpool; pool; pool = pool->next)
if (pool->okay && ptr_into_pool_p (pool, a))
break;
if (!pool)
return 0; /* A does not belong to use. */
mb = ADDR_TO_BLOCK (a);
size = mb->size;
/* This does not make much sense: probably this memory is held in the
* cache. We do it anyway: */
#define MB_WIPE_OUT(byte) \
wipememory2 (((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
MB_WIPE_OUT (0xff);
MB_WIPE_OUT (0xaa);
MB_WIPE_OUT (0x55);
MB_WIPE_OUT (0x00);
/* Update stats. */
stats_update (pool, 0, size);
mb->flags &= ~MB_FLAG_ACTIVE;
mb_merge (pool, mb);
return 1; /* Freed. */
}
/* Wipe out and release memory. Returns true if this function
* actually released A. */
int
_gcry_secmem_free (void *a)
{
int mine;
if (!a)
return 1; /* Tell caller that we handled it. */
SECMEM_LOCK;
mine = _gcry_secmem_free_internal (a);
SECMEM_UNLOCK;
return mine;
}
static void *
_gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
{
memblock_t *mb;
size_t size;
void *a;
mb = (memblock_t *) (void *) ((char *) p
- ((size_t) &((memblock_t *) 0)->aligned.c));
size = mb->size;
if (newsize < size)
{
/* It is easier to not shrink the memory. */
a = p;
}
else
{
a = _gcry_secmem_malloc_internal (newsize, xhint);
if (a)
{
memcpy (a, p, size);
memset ((char *) a + size, 0, newsize - size);
_gcry_secmem_free_internal (p);
}
}
return a;
}
/* Realloc memory. With XHINT set assume that the caller is a xmalloc
* style function. */
void *
_gcry_secmem_realloc (void *p, size_t newsize, int xhint)
{
void *a;
SECMEM_LOCK;
a = _gcry_secmem_realloc_internal (p, newsize, xhint);
SECMEM_UNLOCK;
return a;
}
/* Return true if P points into the secure memory areas. */
int
_gcry_private_is_secure (const void *p)
{
pooldesc_t *pool;
/* 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;
return 0;
}
/****************
* Warning: This code might be called by an interrupt handler
* and frankly, there should really be such a handler,
* to make sure that the memory is wiped out.
* We hope that the OS wipes out mlocked memory after
* receiving a SIGKILL - it really should do so, otherwise
* there is no chance to get the secure memory cleaned.
*/
void
_gcry_secmem_term ()
{
pooldesc_t *pool, *next;
for (pool = &mainpool; pool; pool = next)
{
next = pool->next;
if (!pool->okay)
continue;
wipememory2 (pool->mem, 0xff, pool->size);
wipememory2 (pool->mem, 0xaa, pool->size);
wipememory2 (pool->mem, 0x55, pool->size);
wipememory2 (pool->mem, 0x00, pool->size);
if (0)
;
#if HAVE_MMAP
else if (pool->is_mmapped)
munmap (pool->mem, pool->size);
#endif
else
free (pool->mem);
pool->mem = NULL;
pool->okay = 0;
pool->size = 0;
if (pool != &mainpool)
free (pool);
}
mainpool.next = NULL;
not_locked = 0;
}
/* Print stats of the secmem allocator. With EXTENDED passwed as true
* a detiled listing is returned (used for testing). */
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;
for (pool = &mainpool, poolno = 0; pool; pool = pool->next, poolno++)
{
if (!extended)
{
if (pool->okay)
log_info ("%-13s %u/%lu bytes in %u blocks\n",
pool == &mainpool? "secmem usage:":"",
pool->cur_alloced, (unsigned long)pool->size,
pool->cur_blocks);
}
else
{
for (i = 0, mb = (memblock_t *) pool->mem;
ptr_into_pool_p (pool, mb);
mb = mb_get_next (pool, mb), i++)
log_info ("SECMEM: pool %d %s block %i size %i\n",
poolno,
(mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
i,
mb->size);
}
}
}
diff --git a/src/stdmem.c b/src/stdmem.c
index 04ce64fb..3632d95c 100644
--- a/src/stdmem.c
+++ b/src/stdmem.c
@@ -1,246 +1,246 @@
/* stdmem.c - private memory allocator
* Copyright (C) 1998, 2000, 2002, 2005, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/*
* Description of the layered memory management in Libgcrypt:
*
* [User]
* |
* |
* \ /
* global.c: [MM entrance points] -----> [user callbacks]
* | |
* | |
* \ / \ /
*
* stdmem.c: [non-secure handlers] [secure handlers]
*
* | |
* | |
* \ / \ /
*
* stdmem.c: [ memory guard ]
*
* | |
* | |
* \ / \ /
*
* libc: [ MM functions ] secmem.c: [ secure MM functions]
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include "g10lib.h"
#include "stdmem.h"
#include "secmem.h"
#define MAGIC_NOR_BYTE 0x55
#define MAGIC_SEC_BYTE 0xcc
#define MAGIC_END_BYTE 0xaa
#if SIZEOF_UNSIGNED_LONG == 8
#define EXTRA_ALIGN 4
#else
#define EXTRA_ALIGN 0
#endif
static int use_m_guard = 0;
/****************
* Warning: Never use this function after any of the functions
* here have been used.
*/
void
_gcry_private_enable_m_guard (void)
{
use_m_guard = 1;
}
/*
* Allocate memory of size n.
* Return NULL if we are out of memory.
*/
void *
_gcry_private_malloc (size_t n)
{
if (!n)
{
gpg_err_set_errno (EINVAL);
return NULL; /* Allocating 0 bytes is undefined - we better return
an error to detect such coding errors. */
}
if (use_m_guard)
{
char *p;
if ( !(p = malloc (n + EXTRA_ALIGN+5)) )
return NULL;
((byte*)p)[EXTRA_ALIGN+0] = n;
((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
}
else
{
return malloc( n );
}
}
/*
* Allocate memory of size N from the secure memory pool. Return NULL
* if we are out of memory. XHINT tells the allocator that the caller
* used an xmalloc style call.
*/
void *
_gcry_private_malloc_secure (size_t n, int xhint)
{
if (!n)
{
gpg_err_set_errno (EINVAL);
return NULL; /* Allocating 0 bytes is undefined - better return an
error to detect such coding errors. */
}
if (use_m_guard)
{
char *p;
if (!(p = _gcry_secmem_malloc (n + EXTRA_ALIGN + 5, xhint)))
return NULL;
((byte*)p)[EXTRA_ALIGN+0] = n;
((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
}
else
{
return _gcry_secmem_malloc (n, xhint);
}
}
/*
* Realloc and clear the old space. XHINT tells the allocator that
* the caller used an xmalloc style call. Returns NULL if there is
* not enough memory.
*/
void *
_gcry_private_realloc (void *a, size_t n, int xhint)
{
if (use_m_guard)
{
unsigned char *p = a;
char *b;
size_t len;
if (!a)
return _gcry_private_malloc(n);
_gcry_private_check_heap(p);
len = p[-4];
len |= p[-3] << 8;
len |= p[-2] << 16;
if( len >= n ) /* We don't shrink for now. */
return a;
if (p[-1] == MAGIC_SEC_BYTE)
b = _gcry_private_malloc_secure (n, xhint);
else
b = _gcry_private_malloc(n);
if (!b)
return NULL;
memcpy (b, a, len);
memset (b+len, 0, n-len);
_gcry_private_free (p);
return b;
}
else if ( _gcry_private_is_secure(a) )
{
return _gcry_secmem_realloc (a, n, xhint);
}
else
{
return realloc( a, n );
}
}
void
_gcry_private_check_heap (const void *a)
{
if (use_m_guard)
{
const byte *p = a;
size_t len;
if (!p)
return;
if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
_gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
len = p[-4];
len |= p[-3] << 8;
len |= p[-2] << 16;
if ( p[len] != MAGIC_END_BYTE )
_gcry_log_fatal ("memory at %p corrupted (overflow=%02x)\n", p, p[-1]);
}
}
/*
* Free a memory block allocated by this or the secmem module
*/
void
_gcry_private_free (void *a)
{
unsigned char *p = a;
unsigned char *freep;
if (!p)
return;
if (use_m_guard)
{
_gcry_private_check_heap (p);
freep = p - EXTRA_ALIGN - 4;
}
else
{
freep = p;
}
if (!_gcry_private_is_secure (freep) ||
!_gcry_secmem_free (freep))
{
free (freep);
}
}
diff --git a/src/visibility.c b/src/visibility.c
index 44972a18..1959709e 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1,1573 +1,1573 @@
/* visibility.c - Wrapper for all public functions.
* Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdarg.h>
#define _GCRY_INCLUDED_BY_VISIBILITY_C
#include "g10lib.h"
#include "cipher-proto.h"
#include "context.h"
#include "mpi.h"
const char *
gcry_strerror (gcry_error_t err)
{
return _gcry_strerror (err);
}
const char *
gcry_strsource (gcry_error_t err)
{
return _gcry_strsource (err);
}
gcry_err_code_t
gcry_err_code_from_errno (int err)
{
return _gcry_err_code_from_errno (err);
}
int
gcry_err_code_to_errno (gcry_err_code_t code)
{
return _gcry_err_code_to_errno (code);
}
gcry_error_t
gcry_err_make_from_errno (gcry_err_source_t source, int err)
{
return _gcry_err_make_from_errno (source, err);
}
gcry_error_t
gcry_error_from_errno (int err)
{
return _gcry_error_from_errno (err);
}
const char *
gcry_check_version (const char *req_version)
{
return _gcry_check_version (req_version);
}
gcry_error_t
gcry_control (enum gcry_ctl_cmds cmd, ...)
{
gcry_error_t err;
va_list arg_ptr;
va_start (arg_ptr, cmd);
err = gpg_error (_gcry_vcontrol (cmd, arg_ptr));
va_end(arg_ptr);
return err;
}
gcry_error_t
gcry_sexp_new (gcry_sexp_t *retsexp,
const void *buffer, size_t length,
int autodetect)
{
return gpg_error (_gcry_sexp_new (retsexp, buffer, length, autodetect));
}
gcry_error_t
gcry_sexp_create (gcry_sexp_t *retsexp,
void *buffer, size_t length,
int autodetect, void (*freefnc) (void *))
{
return gpg_error (_gcry_sexp_create (retsexp, buffer, length,
autodetect, freefnc));
}
gcry_error_t
gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length)
{
return gpg_error (_gcry_sexp_sscan (retsexp, erroff, buffer, length));
}
gcry_error_t
gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, ...)
{
gcry_err_code_t rc;
va_list arg_ptr;
va_start (arg_ptr, format);
rc = _gcry_sexp_vbuild (retsexp, erroff, format, arg_ptr);
va_end (arg_ptr);
return gpg_error (rc);
}
gcry_error_t
gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, void **arg_list)
{
return gpg_error (_gcry_sexp_build_array (retsexp, erroff, format, arg_list));
}
void
gcry_sexp_release (gcry_sexp_t sexp)
{
_gcry_sexp_release (sexp);
}
size_t
gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
size_t *erroff, gcry_error_t *errcode)
{
size_t n;
gpg_err_code_t rc;
n = _gcry_sexp_canon_len (buffer, length, erroff, &rc);
if (errcode)
*errcode = gpg_error (rc);
return n;
}
size_t
gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer, size_t maxlength)
{
return _gcry_sexp_sprint (sexp, mode, buffer, maxlength);
}
void
gcry_sexp_dump (const gcry_sexp_t a)
{
_gcry_sexp_dump (a);
}
gcry_sexp_t
gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b)
{
return _gcry_sexp_cons (a, b);
}
gcry_sexp_t
gcry_sexp_alist (const gcry_sexp_t *array)
{
return _gcry_sexp_alist (array);
}
gcry_sexp_t
gcry_sexp_vlist (const gcry_sexp_t a, ...)
{
/* This is not yet implemented in sexp.c. */
(void)a;
BUG ();
return NULL;
}
gcry_sexp_t
gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n)
{
return _gcry_sexp_append (a, n);
}
gcry_sexp_t
gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n)
{
return _gcry_sexp_prepend (a, n);
}
gcry_sexp_t
gcry_sexp_find_token (gcry_sexp_t list, const char *tok, size_t toklen)
{
return _gcry_sexp_find_token (list, tok, toklen);
}
int
gcry_sexp_length (const gcry_sexp_t list)
{
return _gcry_sexp_length (list);
}
gcry_sexp_t
gcry_sexp_nth (const gcry_sexp_t list, int number)
{
return _gcry_sexp_nth (list, number);
}
gcry_sexp_t
gcry_sexp_car (const gcry_sexp_t list)
{
return _gcry_sexp_car (list);
}
gcry_sexp_t
gcry_sexp_cdr (const gcry_sexp_t list)
{
return _gcry_sexp_cdr (list);
}
gcry_sexp_t
gcry_sexp_cadr (const gcry_sexp_t list)
{
return _gcry_sexp_cadr (list);
}
const char *
gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
{
return _gcry_sexp_nth_data (list, number, datalen);
}
void *
gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
{
return _gcry_sexp_nth_buffer (list, number, rlength);
}
char *
gcry_sexp_nth_string (gcry_sexp_t list, int number)
{
return _gcry_sexp_nth_string (list, number);
}
gcry_mpi_t
gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
{
return _gcry_sexp_nth_mpi (list, number, mpifmt);
}
gpg_error_t
gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path,
const char *list, ...)
{
gcry_err_code_t rc;
va_list arg_ptr;
va_start (arg_ptr, list);
rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
va_end (arg_ptr);
return gpg_error (rc);
}
gcry_mpi_t
gcry_mpi_new (unsigned int nbits)
{
return _gcry_mpi_new (nbits);
}
gcry_mpi_t
gcry_mpi_snew (unsigned int nbits)
{
return _gcry_mpi_snew (nbits);
}
void
gcry_mpi_release (gcry_mpi_t a)
{
_gcry_mpi_release (a);
}
gcry_mpi_t
gcry_mpi_copy (const gcry_mpi_t a)
{
return _gcry_mpi_copy (a);
}
void
gcry_mpi_snatch (gcry_mpi_t w, const gcry_mpi_t u)
{
_gcry_mpi_snatch (w, u);
}
gcry_mpi_t
gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u)
{
return _gcry_mpi_set (w, u);
}
gcry_mpi_t
gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
{
return _gcry_mpi_set_ui (w, u);
}
gcry_error_t
gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
{
return gpg_error (_gcry_mpi_get_ui (w, u));
}
void
gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
{
_gcry_mpi_swap (a, b);
}
int
gcry_mpi_is_neg (gcry_mpi_t a)
{
return _gcry_mpi_is_neg (a);
}
void
gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u)
{
_gcry_mpi_neg (w, u);
}
void
gcry_mpi_abs (gcry_mpi_t w)
{
_gcry_mpi_abs (w);
}
int
gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v)
{
return _gcry_mpi_cmp (u, v);
}
int
gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v)
{
return _gcry_mpi_cmp_ui (u, v);
}
gcry_error_t
gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format,
const void *buffer, size_t buflen,
size_t *nscanned)
{
return gpg_error (_gcry_mpi_scan (ret_mpi, format, buffer, buflen, nscanned));
}
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)
{
return gpg_error (_gcry_mpi_print (format, buffer, buflen, nwritten, a));
}
gcry_error_t
gcry_mpi_aprint (enum gcry_mpi_format format,
unsigned char **buffer, size_t *nwritten,
const gcry_mpi_t a)
{
return gpg_error (_gcry_mpi_aprint (format, buffer, nwritten, a));
}
void
gcry_mpi_dump (const gcry_mpi_t a)
{
_gcry_log_printmpi (NULL, a);
}
void
gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
{
_gcry_mpi_add (w, u, v);
}
void
gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v)
{
_gcry_mpi_add_ui (w, u, v);
}
void
gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
{
_gcry_mpi_addm (w, u, v, m);
}
void
gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
{
_gcry_mpi_sub (w, u, v);
}
void
gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
{
_gcry_mpi_sub_ui (w, u, v);
}
void
gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
{
_gcry_mpi_subm (w, u, v, m);
}
void
gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
{
_gcry_mpi_mul (w, u, v);
}
void
gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
{
_gcry_mpi_mul_ui (w, u, v);
}
void
gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
{
_gcry_mpi_mulm (w, u, v, m);
}
void
gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt)
{
_gcry_mpi_mul_2exp (w, u, cnt);
}
void
gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r,
gcry_mpi_t dividend, gcry_mpi_t divisor, int round)
{
_gcry_mpi_div (q, r, dividend, divisor, round);
}
void
gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor)
{
_gcry_mpi_mod (r, dividend, divisor);
}
void
gcry_mpi_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e,
const gcry_mpi_t m)
{
_gcry_mpi_powm (w, b, e, m);
}
int
gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b)
{
return _gcry_mpi_gcd (g, a, b);
}
int
gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m)
{
return _gcry_mpi_invm (x, a, m);
}
gcry_mpi_point_t
gcry_mpi_point_new (unsigned int nbits)
{
return _gcry_mpi_point_new (nbits);
}
void
gcry_mpi_point_release (gcry_mpi_point_t point)
{
_gcry_mpi_point_release (point);
}
gcry_mpi_point_t
gcry_mpi_point_copy (gcry_mpi_point_t point)
{
return _gcry_mpi_point_copy (point);
}
void
gcry_mpi_point_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
gcry_mpi_point_t point)
{
_gcry_mpi_point_get (x, y, z, point);
}
void
gcry_mpi_point_snatch_get (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
gcry_mpi_point_t point)
{
_gcry_mpi_point_snatch_get (x, y, z, point);
}
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)
{
return _gcry_mpi_point_set (point, x, y, z);
}
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)
{
return _gcry_mpi_point_snatch_set (point, x, y, z);
}
gpg_error_t
gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
gcry_sexp_t keyparam, const char *curvename)
{
return gpg_error (_gcry_mpi_ec_new (r_ctx, keyparam, curvename));
}
gcry_mpi_t
gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
{
return _gcry_mpi_ec_get_mpi (name, ctx, copy);
}
gcry_mpi_point_t
gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
{
return _gcry_mpi_ec_get_point (name, ctx, copy);
}
gpg_error_t
gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue, gcry_ctx_t ctx)
{
return gpg_error (_gcry_mpi_ec_set_mpi (name, newvalue, ctx));
}
gpg_error_t
gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
gcry_ctx_t ctx)
{
return gpg_error (_gcry_mpi_ec_set_point (name, newvalue, ctx));
}
gpg_error_t
gcry_mpi_ec_decode_point (gcry_mpi_point_t result, gcry_mpi_t value,
gcry_ctx_t ctx)
{
return gpg_error (_gcry_mpi_ec_decode_point
(result, value,
ctx? _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC) : NULL));
}
int
gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
gcry_ctx_t ctx)
{
return _gcry_mpi_ec_get_affine (x, y, point,
_gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
}
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));
}
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));
}
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));
}
void
gcry_mpi_ec_mul (gcry_mpi_point_t w, gcry_mpi_t n, gcry_mpi_point_t u,
gcry_ctx_t ctx)
{
_gcry_mpi_ec_mul_point (w, n, u,
_gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
}
int
gcry_mpi_ec_curve_point (gcry_mpi_point_t point, gcry_ctx_t ctx)
{
return _gcry_mpi_ec_curve_point
(point, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
}
unsigned int
gcry_mpi_get_nbits (gcry_mpi_t a)
{
return _gcry_mpi_get_nbits (a);
}
int
gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n)
{
return _gcry_mpi_test_bit (a, n);
}
void
gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_set_bit (a, n);
}
void
gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_clear_bit (a, n);
}
void
gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_set_highbit (a, n);
}
void
gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_clear_highbit (a, n);
}
void
gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_rshift (x, a, n);
}
void
gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n)
{
_gcry_mpi_lshift (x, a, n);
}
gcry_mpi_t
gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits)
{
return _gcry_mpi_set_opaque (a, p, nbits);
}
gcry_mpi_t
gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits)
{
return _gcry_mpi_set_opaque_copy (a, p, nbits);
}
void *
gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits)
{
return _gcry_mpi_get_opaque (a, nbits);
}
void
gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
_gcry_mpi_set_flag (a, flag);
}
void
gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
_gcry_mpi_clear_flag (a, flag);
}
int
gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
{
return _gcry_mpi_get_flag (a, flag);
}
gcry_mpi_t
_gcry_mpi_get_const (int no)
{
switch (no)
{
case 1: return _gcry_mpi_const (MPI_C_ONE);
case 2: return _gcry_mpi_const (MPI_C_TWO);
case 3: return _gcry_mpi_const (MPI_C_THREE);
case 4: return _gcry_mpi_const (MPI_C_FOUR);
case 8: return _gcry_mpi_const (MPI_C_EIGHT);
default: log_bug("unsupported GCRYMPI_CONST_ macro used\n");
}
}
gcry_error_t
gcry_cipher_open (gcry_cipher_hd_t *handle,
int algo, int mode, unsigned int flags)
{
if (!fips_is_operational ())
{
*handle = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_cipher_open (handle, algo, mode, flags));
}
void
gcry_cipher_close (gcry_cipher_hd_t h)
{
_gcry_cipher_close (h);
}
gcry_error_t
gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gcry_error (_gcry_cipher_setkey (hd, key, keylen));
}
gcry_error_t
gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gcry_error (_gcry_cipher_setiv (hd, iv, ivlen));
}
gpg_error_t
gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gcry_error (_gcry_cipher_setctr (hd, ctr, ctrlen));
}
gcry_error_t
gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, size_t abuflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_authenticate (hd, abuf, abuflen));
}
gcry_error_t
gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_gettag (hd, outtag, taglen));
}
gcry_error_t
gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_checktag (hd, intag, taglen));
}
gcry_error_t
gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_ctl (h, cmd, buffer, buflen));
}
gcry_error_t
gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer, size_t *nbytes)
{
return gpg_error (_gcry_cipher_info (h, what, buffer, nbytes));
}
gcry_error_t
gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_algo_info (algo, what, buffer, nbytes));
}
const char *
gcry_cipher_algo_name (int algorithm)
{
return _gcry_cipher_algo_name (algorithm);
}
int
gcry_cipher_map_name (const char *name)
{
return _gcry_cipher_map_name (name);
}
int
gcry_cipher_mode_from_oid (const char *string)
{
return _gcry_cipher_mode_from_oid (string);
}
gcry_error_t
gcry_cipher_encrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen)
{
if (!fips_is_operational ())
{
/* Make sure that the plaintext will never make it to OUT. */
if (out)
memset (out, 0x42, outsize);
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_cipher_encrypt (h, out, outsize, in, inlen));
}
gcry_error_t
gcry_cipher_decrypt (gcry_cipher_hd_t h,
void *out, size_t outsize,
const void *in, size_t inlen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_cipher_decrypt (h, out, outsize, in, inlen));
}
size_t
gcry_cipher_get_algo_keylen (int algo)
{
return _gcry_cipher_get_algo_keylen (algo);
}
size_t
gcry_cipher_get_algo_blklen (int algo)
{
return _gcry_cipher_get_algo_blklen (algo);
}
gcry_error_t
gcry_mac_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_algo_info (algo, what, buffer, nbytes));
}
const char *
gcry_mac_algo_name (int algorithm)
{
return _gcry_mac_algo_name (algorithm);
}
int
gcry_mac_map_name (const char *string)
{
return _gcry_mac_map_name (string);
}
int
gcry_mac_get_algo (gcry_mac_hd_t hd)
{
return _gcry_mac_get_algo (hd);
}
unsigned int
gcry_mac_get_algo_maclen (int algo)
{
return _gcry_mac_get_algo_maclen (algo);
}
unsigned int
gcry_mac_get_algo_keylen (int algo)
{
return _gcry_mac_get_algo_keylen (algo);
}
gcry_error_t
gcry_mac_open (gcry_mac_hd_t *handle, int algo, unsigned int flags,
gcry_ctx_t ctx)
{
if (!fips_is_operational ())
{
*handle = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_mac_open (handle, algo, flags, ctx));
}
void
gcry_mac_close (gcry_mac_hd_t hd)
{
_gcry_mac_close (hd);
}
gcry_error_t
gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_setkey (hd, key, keylen));
}
gcry_error_t
gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_setiv (hd, iv, ivlen));
}
gcry_error_t
gcry_mac_write (gcry_mac_hd_t hd, const void *buf, size_t buflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_write (hd, buf, buflen));
}
gcry_error_t
gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t *outlen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_read (hd, outbuf, outlen));
}
gcry_error_t
gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_verify (hd, buf, buflen));
}
gcry_error_t
gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer, size_t buflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_mac_ctl (h, cmd, buffer, buflen));
}
gcry_error_t
gcry_pk_encrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t pkey)
{
if (!fips_is_operational ())
{
*result = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_pk_encrypt (result, data, pkey));
}
gcry_error_t
gcry_pk_decrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t skey)
{
if (!fips_is_operational ())
{
*result = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_pk_decrypt (result, data, skey));
}
gcry_error_t
gcry_pk_sign (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t skey)
{
if (!fips_is_operational ())
{
*result = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_pk_sign (result, data, skey));
}
gcry_error_t
gcry_pk_verify (gcry_sexp_t sigval, gcry_sexp_t data, gcry_sexp_t pkey)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_pk_verify (sigval, data, pkey));
}
gcry_error_t
gcry_pk_testkey (gcry_sexp_t key)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_pk_testkey (key));
}
gcry_error_t
gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
{
if (!fips_is_operational ())
{
*r_key = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_pk_genkey (r_key, s_parms));
}
gcry_error_t
gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
{
return gpg_error (_gcry_pk_ctl (cmd, buffer, buflen));
}
gcry_error_t
gcry_pk_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_pk_algo_info (algo, what, buffer, nbytes));
}
const char *
gcry_pk_algo_name (int algorithm)
{
return _gcry_pk_algo_name (algorithm);
}
int
gcry_pk_map_name (const char *name)
{
return _gcry_pk_map_name (name);
}
unsigned int
gcry_pk_get_nbits (gcry_sexp_t key)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return 0;
}
return _gcry_pk_get_nbits (key);
}
unsigned char *
gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return NULL;
}
return _gcry_pk_get_keygrip (key, array);
}
const char *
gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return NULL;
}
return _gcry_pk_get_curve (key, iterator, r_nbits);
}
gcry_sexp_t
gcry_pk_get_param (int algo, const char *name)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return NULL;
}
return _gcry_pk_get_param (algo, name);
}
gcry_error_t
gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
{
if (!fips_is_operational ())
{
*r_sexp = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_pubkey_get_sexp (r_sexp, mode, ctx));
}
gcry_error_t
gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
{
if (!fips_is_operational ())
{
*h = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_md_open (h, algo, flags));
}
void
gcry_md_close (gcry_md_hd_t hd)
{
_gcry_md_close (hd);
}
gcry_error_t
gcry_md_enable (gcry_md_hd_t hd, int algo)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_md_enable (hd, algo));
}
gcry_error_t
gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd)
{
if (!fips_is_operational ())
{
*bhd = NULL;
return gpg_error (fips_not_operational ());
}
return gpg_error (_gcry_md_copy (bhd, ahd));
}
void
gcry_md_reset (gcry_md_hd_t hd)
{
_gcry_md_reset (hd);
}
gcry_error_t
gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_md_ctl (hd, cmd, buffer, buflen));
}
void
gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return;
}
_gcry_md_write (hd, buffer, length);
}
unsigned char *
gcry_md_read (gcry_md_hd_t hd, int algo)
{
return _gcry_md_read (hd, algo);
}
gcry_error_t
gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer, size_t length)
{
return gpg_error (_gcry_md_extract(hd, algo, buffer, length));
}
void
gcry_md_hash_buffer (int algo, void *digest,
const void *buffer, size_t length)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_error ("called in non-operational state");
}
_gcry_md_hash_buffer (algo, digest, buffer, length);
}
gpg_error_t
gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
const gcry_buffer_t *iov, int iovcnt)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_error ("called in non-operational state");
}
return gpg_error (_gcry_md_hash_buffers (algo, flags, digest, iov, iovcnt));
}
int
gcry_md_get_algo (gcry_md_hd_t hd)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_error ("used in non-operational state");
return 0;
}
return _gcry_md_get_algo (hd);
}
unsigned int
gcry_md_get_algo_dlen (int algo)
{
return _gcry_md_get_algo_dlen (algo);
}
int
gcry_md_is_enabled (gcry_md_hd_t a, int algo)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
return 0;
}
return _gcry_md_is_enabled (a, algo);
}
int
gcry_md_is_secure (gcry_md_hd_t a)
{
return _gcry_md_is_secure (a);
}
gcry_error_t
gcry_md_info (gcry_md_hd_t h, int what, void *buffer, size_t *nbytes)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_md_info (h, what, buffer, nbytes));
}
gcry_error_t
gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
{
return gpg_error (_gcry_md_algo_info (algo, what, buffer, nbytes));
}
const char *
gcry_md_algo_name (int algo)
{
return _gcry_md_algo_name (algo);
}
int
gcry_md_map_name (const char* name)
{
return _gcry_md_map_name (name);
}
gcry_error_t
gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_md_setkey (hd, key, keylen));
}
void
gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
{
_gcry_md_debug (hd, suffix);
}
gpg_error_t
gcry_kdf_derive (const void *passphrase, size_t passphraselen,
int algo, int hashalgo,
const void *salt, size_t saltlen,
unsigned long iterations,
size_t keysize, void *keybuffer)
{
return gpg_error (_gcry_kdf_derive (passphrase, passphraselen, algo, hashalgo,
salt, saltlen, iterations,
keysize, keybuffer));
}
void
gcry_randomize (void *buffer, size_t length, 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_randomize (buffer, length, level);
}
gcry_error_t
gcry_random_add_bytes (const void *buffer, size_t length, int quality)
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
return gpg_error (_gcry_random_add_bytes (buffer, length, quality));
}
void *
gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_fatal_error ("called in non-operational state");
fips_noreturn ();
}
return _gcry_random_bytes (nbytes,level);
}
void *
gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_fatal_error ("called in non-operational state");
fips_noreturn ();
}
return _gcry_random_bytes_secure (nbytes, level);
}
void
gcry_mpi_randomize (gcry_mpi_t w,
unsigned int nbits, enum gcry_random_level level)
{
_gcry_mpi_randomize (w, nbits, level);
}
void
gcry_create_nonce (void *buffer, size_t length)
{
if (!fips_is_operational ())
{
(void)fips_not_operational ();
fips_signal_fatal_error ("called in non-operational state");
fips_noreturn ();
}
_gcry_create_nonce (buffer, length);
}
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)
{
return gpg_error (_gcry_prime_generate (prime, prime_bits, factor_bits,
factors, cb_func, cb_arg,
random_level, flags));
}
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)
{
return gpg_error (_gcry_prime_group_generator (r_g, prime, factors, start_g));
}
void
gcry_prime_release_factors (gcry_mpi_t *factors)
{
_gcry_prime_release_factors (factors);
}
gcry_error_t
gcry_prime_check (gcry_mpi_t x, unsigned int flags)
{
return gpg_error (_gcry_prime_check (x, flags));
}
void
gcry_ctx_release (gcry_ctx_t ctx)
{
_gcry_ctx_release (ctx);
}
void
gcry_log_debug (const char *fmt, ...)
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
_gcry_logv (GCRY_LOG_DEBUG, fmt, arg_ptr);
va_end (arg_ptr);
}
void
gcry_log_debughex (const char *text, const void *buffer, size_t length)
{
_gcry_log_printhex (text, buffer, length);
}
void
gcry_log_debugmpi (const char *text, gcry_mpi_t mpi)
{
_gcry_log_printmpi (text, mpi);
}
void
gcry_log_debugpnt (const char *text, mpi_point_t point, gcry_ctx_t ctx)
{
mpi_ec_t ec = ctx? _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC) : NULL;
_gcry_mpi_point_log (text, point, ec);
}
void
gcry_log_debugsxp (const char *text, gcry_sexp_t sexp)
{
_gcry_log_printsxp (text, sexp);
}
char *
gcry_get_config (int mode, const char *what)
{
return _gcry_get_config (mode, what);
}
void
gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data)
{
_gcry_set_progress_handler (cb, cb_data);
}
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)
{
_gcry_set_allocation_handler (func_alloc, func_alloc_secure,
func_secure_check, func_realloc, func_free);
}
void
gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque)
{
_gcry_set_outofcore_handler (h, opaque);
}
void
gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque)
{
_gcry_set_fatalerror_handler (fnc, opaque);
}
void
gcry_set_log_handler (gcry_handler_log_t f, void *opaque)
{
_gcry_set_log_handler (f, opaque);
}
void
gcry_set_gettext_handler (const char *(*f)(const char*))
{
_gcry_set_gettext_handler (f);
}
void *
gcry_malloc (size_t n)
{
return _gcry_malloc (n);
}
void *
gcry_calloc (size_t n, size_t m)
{
return _gcry_calloc (n, m);
}
void *
gcry_malloc_secure (size_t n)
{
return _gcry_malloc_secure (n);
}
void *
gcry_calloc_secure (size_t n, size_t m)
{
return _gcry_calloc_secure (n,m);
}
void *
gcry_realloc (void *a, size_t n)
{
return _gcry_realloc (a, n);
}
char *
gcry_strdup (const char *string)
{
return _gcry_strdup (string);
}
void *
gcry_xmalloc (size_t n)
{
return _gcry_xmalloc (n);
}
void *
gcry_xcalloc (size_t n, size_t m)
{
return _gcry_xcalloc (n, m);
}
void *
gcry_xmalloc_secure (size_t n)
{
return _gcry_xmalloc_secure (n);
}
void *
gcry_xcalloc_secure (size_t n, size_t m)
{
return _gcry_xcalloc_secure (n, m);
}
void *
gcry_xrealloc (void *a, size_t n)
{
return _gcry_xrealloc (a, n);
}
char *
gcry_xstrdup (const char *a)
{
return _gcry_xstrdup (a);
}
void
gcry_free (void *a)
{
_gcry_free (a);
}
int
gcry_is_secure (const void *a)
{
return _gcry_is_secure (a);
}
diff --git a/src/visibility.h b/src/visibility.h
index 9c9fa877..cee2b460 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -1,517 +1,517 @@
/* visibility.h - Set visibility attribute
* Copyright (C) 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 Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifndef GCRY_VISIBILITY_H
#define GCRY_VISIBILITY_H
/* Redefine all public symbols with an underscore unless we already
use the underscore prefixed version internally. */
/* Include the main header here so that public symbols are mapped to
the internal underscored ones. */
#ifdef _GCRY_INCLUDED_BY_VISIBILITY_C
/* We need to redeclare the deprecated functions without the
deprecated attribute. */
# define GCRYPT_NO_DEPRECATED
# include "gcrypt-int.h"
/* None in this version. */
#else
# include "gcrypt-int.h"
#endif
/* Prototypes of functions exported but not ready for use. */
gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo,
unsigned char *buffer, int buflen);
/* Our use of the ELF visibility feature works by passing
-fvisibiliy=hidden on the command line and by explicitly marking
all exported functions as visible.
NOTE: When adding new functions, please make sure to add them to
libgcrypt.vers and libgcrypt.def as well. */
#ifdef _GCRY_INCLUDED_BY_VISIBILITY_C
/* A macro to flag a function as visible. */
#ifdef GCRY_USE_VISIBILITY
# define MARK_VISIBLEX(name) \
extern __typeof__ (name) name __attribute__ ((visibility("default")));
#else
# define MARK_VISIBLEX(name) /* */
#endif
/* Now mark all symbols. */
MARK_VISIBLEX (gcry_check_version)
MARK_VISIBLEX (gcry_control)
MARK_VISIBLEX (gcry_set_allocation_handler)
MARK_VISIBLEX (gcry_set_fatalerror_handler)
MARK_VISIBLEX (gcry_set_gettext_handler)
MARK_VISIBLEX (gcry_set_log_handler)
MARK_VISIBLEX (gcry_set_outofcore_handler)
MARK_VISIBLEX (gcry_set_progress_handler)
MARK_VISIBLEX (gcry_err_code_from_errno)
MARK_VISIBLEX (gcry_err_code_to_errno)
MARK_VISIBLEX (gcry_err_make_from_errno)
MARK_VISIBLEX (gcry_error_from_errno)
MARK_VISIBLEX (gcry_strerror)
MARK_VISIBLEX (gcry_strsource)
MARK_VISIBLEX (gcry_malloc)
MARK_VISIBLEX (gcry_malloc_secure)
MARK_VISIBLEX (gcry_calloc)
MARK_VISIBLEX (gcry_calloc_secure)
MARK_VISIBLEX (gcry_realloc)
MARK_VISIBLEX (gcry_strdup)
MARK_VISIBLEX (gcry_is_secure)
MARK_VISIBLEX (gcry_xcalloc)
MARK_VISIBLEX (gcry_xcalloc_secure)
MARK_VISIBLEX (gcry_xmalloc)
MARK_VISIBLEX (gcry_xmalloc_secure)
MARK_VISIBLEX (gcry_xrealloc)
MARK_VISIBLEX (gcry_xstrdup)
MARK_VISIBLEX (gcry_free)
MARK_VISIBLEX (gcry_md_algo_info)
MARK_VISIBLEX (gcry_md_algo_name)
MARK_VISIBLEX (gcry_md_close)
MARK_VISIBLEX (gcry_md_copy)
MARK_VISIBLEX (gcry_md_ctl)
MARK_VISIBLEX (gcry_md_enable)
MARK_VISIBLEX (gcry_md_get)
MARK_VISIBLEX (gcry_md_get_algo)
MARK_VISIBLEX (gcry_md_get_algo_dlen)
MARK_VISIBLEX (gcry_md_hash_buffer)
MARK_VISIBLEX (gcry_md_hash_buffers)
MARK_VISIBLEX (gcry_md_info)
MARK_VISIBLEX (gcry_md_is_enabled)
MARK_VISIBLEX (gcry_md_is_secure)
MARK_VISIBLEX (gcry_md_map_name)
MARK_VISIBLEX (gcry_md_open)
MARK_VISIBLEX (gcry_md_read)
MARK_VISIBLEX (gcry_md_extract)
MARK_VISIBLEX (gcry_md_reset)
MARK_VISIBLEX (gcry_md_setkey)
MARK_VISIBLEX (gcry_md_write)
MARK_VISIBLEX (gcry_md_debug)
MARK_VISIBLEX (gcry_cipher_algo_info)
MARK_VISIBLEX (gcry_cipher_algo_name)
MARK_VISIBLEX (gcry_cipher_close)
MARK_VISIBLEX (gcry_cipher_setkey)
MARK_VISIBLEX (gcry_cipher_setiv)
MARK_VISIBLEX (gcry_cipher_setctr)
MARK_VISIBLEX (gcry_cipher_authenticate)
MARK_VISIBLEX (gcry_cipher_checktag)
MARK_VISIBLEX (gcry_cipher_gettag)
MARK_VISIBLEX (gcry_cipher_ctl)
MARK_VISIBLEX (gcry_cipher_decrypt)
MARK_VISIBLEX (gcry_cipher_encrypt)
MARK_VISIBLEX (gcry_cipher_get_algo_blklen)
MARK_VISIBLEX (gcry_cipher_get_algo_keylen)
MARK_VISIBLEX (gcry_cipher_info)
MARK_VISIBLEX (gcry_cipher_map_name)
MARK_VISIBLEX (gcry_cipher_mode_from_oid)
MARK_VISIBLEX (gcry_cipher_open)
MARK_VISIBLEX (gcry_mac_algo_info)
MARK_VISIBLEX (gcry_mac_algo_name)
MARK_VISIBLEX (gcry_mac_map_name)
MARK_VISIBLEX (gcry_mac_get_algo)
MARK_VISIBLEX (gcry_mac_get_algo_maclen)
MARK_VISIBLEX (gcry_mac_get_algo_keylen)
MARK_VISIBLEX (gcry_mac_open)
MARK_VISIBLEX (gcry_mac_close)
MARK_VISIBLEX (gcry_mac_setkey)
MARK_VISIBLEX (gcry_mac_setiv)
MARK_VISIBLEX (gcry_mac_write)
MARK_VISIBLEX (gcry_mac_read)
MARK_VISIBLEX (gcry_mac_verify)
MARK_VISIBLEX (gcry_mac_ctl)
MARK_VISIBLEX (gcry_pk_algo_info)
MARK_VISIBLEX (gcry_pk_algo_name)
MARK_VISIBLEX (gcry_pk_ctl)
MARK_VISIBLEX (gcry_pk_decrypt)
MARK_VISIBLEX (gcry_pk_encrypt)
MARK_VISIBLEX (gcry_pk_genkey)
MARK_VISIBLEX (gcry_pk_get_keygrip)
MARK_VISIBLEX (gcry_pk_get_curve)
MARK_VISIBLEX (gcry_pk_get_param)
MARK_VISIBLEX (gcry_pk_get_nbits)
MARK_VISIBLEX (gcry_pk_map_name)
MARK_VISIBLEX (gcry_pk_sign)
MARK_VISIBLEX (gcry_pk_testkey)
MARK_VISIBLEX (gcry_pk_verify)
MARK_VISIBLEX (gcry_pubkey_get_sexp)
MARK_VISIBLEX (gcry_kdf_derive)
MARK_VISIBLEX (gcry_prime_check)
MARK_VISIBLEX (gcry_prime_generate)
MARK_VISIBLEX (gcry_prime_group_generator)
MARK_VISIBLEX (gcry_prime_release_factors)
MARK_VISIBLEX (gcry_random_add_bytes)
MARK_VISIBLEX (gcry_random_bytes)
MARK_VISIBLEX (gcry_random_bytes_secure)
MARK_VISIBLEX (gcry_randomize)
MARK_VISIBLEX (gcry_create_nonce)
MARK_VISIBLEX (gcry_sexp_alist)
MARK_VISIBLEX (gcry_sexp_append)
MARK_VISIBLEX (gcry_sexp_build)
MARK_VISIBLEX (gcry_sexp_build_array)
MARK_VISIBLEX (gcry_sexp_cadr)
MARK_VISIBLEX (gcry_sexp_canon_len)
MARK_VISIBLEX (gcry_sexp_car)
MARK_VISIBLEX (gcry_sexp_cdr)
MARK_VISIBLEX (gcry_sexp_cons)
MARK_VISIBLEX (gcry_sexp_create)
MARK_VISIBLEX (gcry_sexp_dump)
MARK_VISIBLEX (gcry_sexp_find_token)
MARK_VISIBLEX (gcry_sexp_length)
MARK_VISIBLEX (gcry_sexp_new)
MARK_VISIBLEX (gcry_sexp_nth)
MARK_VISIBLEX (gcry_sexp_nth_buffer)
MARK_VISIBLEX (gcry_sexp_nth_data)
MARK_VISIBLEX (gcry_sexp_nth_mpi)
MARK_VISIBLEX (gcry_sexp_nth_string)
MARK_VISIBLEX (gcry_sexp_prepend)
MARK_VISIBLEX (gcry_sexp_release)
MARK_VISIBLEX (gcry_sexp_sprint)
MARK_VISIBLEX (gcry_sexp_sscan)
MARK_VISIBLEX (gcry_sexp_vlist)
MARK_VISIBLEX (gcry_sexp_extract_param)
MARK_VISIBLEX (gcry_mpi_abs)
MARK_VISIBLEX (gcry_mpi_add)
MARK_VISIBLEX (gcry_mpi_add_ui)
MARK_VISIBLEX (gcry_mpi_addm)
MARK_VISIBLEX (gcry_mpi_aprint)
MARK_VISIBLEX (gcry_mpi_clear_bit)
MARK_VISIBLEX (gcry_mpi_clear_flag)
MARK_VISIBLEX (gcry_mpi_clear_highbit)
MARK_VISIBLEX (gcry_mpi_cmp)
MARK_VISIBLEX (gcry_mpi_cmp_ui)
MARK_VISIBLEX (gcry_mpi_copy)
MARK_VISIBLEX (gcry_mpi_div)
MARK_VISIBLEX (gcry_mpi_dump)
MARK_VISIBLEX (gcry_mpi_ec_add)
MARK_VISIBLEX (gcry_mpi_ec_sub)
MARK_VISIBLEX (gcry_mpi_ec_curve_point)
MARK_VISIBLEX (gcry_mpi_ec_dup)
MARK_VISIBLEX (gcry_mpi_ec_decode_point)
MARK_VISIBLEX (gcry_mpi_ec_get_affine)
MARK_VISIBLEX (gcry_mpi_ec_mul)
MARK_VISIBLEX (gcry_mpi_ec_new)
MARK_VISIBLEX (gcry_mpi_ec_get_mpi)
MARK_VISIBLEX (gcry_mpi_ec_get_point)
MARK_VISIBLEX (gcry_mpi_ec_set_mpi)
MARK_VISIBLEX (gcry_mpi_ec_set_point)
MARK_VISIBLEX (gcry_mpi_gcd)
MARK_VISIBLEX (gcry_mpi_get_flag)
MARK_VISIBLEX (gcry_mpi_get_nbits)
MARK_VISIBLEX (gcry_mpi_get_opaque)
MARK_VISIBLEX (gcry_mpi_is_neg)
MARK_VISIBLEX (gcry_mpi_invm)
MARK_VISIBLEX (gcry_mpi_mod)
MARK_VISIBLEX (gcry_mpi_mul)
MARK_VISIBLEX (gcry_mpi_mul_2exp)
MARK_VISIBLEX (gcry_mpi_mul_ui)
MARK_VISIBLEX (gcry_mpi_mulm)
MARK_VISIBLEX (gcry_mpi_neg)
MARK_VISIBLEX (gcry_mpi_new)
MARK_VISIBLEX (gcry_mpi_point_get)
MARK_VISIBLEX (gcry_mpi_point_new)
MARK_VISIBLEX (gcry_mpi_point_release)
MARK_VISIBLEX (gcry_mpi_point_copy)
MARK_VISIBLEX (gcry_mpi_point_set)
MARK_VISIBLEX (gcry_mpi_point_snatch_get)
MARK_VISIBLEX (gcry_mpi_point_snatch_set)
MARK_VISIBLEX (gcry_mpi_powm)
MARK_VISIBLEX (gcry_mpi_print)
MARK_VISIBLEX (gcry_mpi_randomize)
MARK_VISIBLEX (gcry_mpi_release)
MARK_VISIBLEX (gcry_mpi_rshift)
MARK_VISIBLEX (gcry_mpi_lshift)
MARK_VISIBLEX (gcry_mpi_scan)
MARK_VISIBLEX (gcry_mpi_snatch)
MARK_VISIBLEX (gcry_mpi_set)
MARK_VISIBLEX (gcry_mpi_set_bit)
MARK_VISIBLEX (gcry_mpi_set_flag)
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)
MARK_VISIBLEX (gcry_mpi_subm)
MARK_VISIBLEX (gcry_mpi_swap)
MARK_VISIBLEX (gcry_mpi_test_bit)
MARK_VISIBLEX (gcry_ctx_release)
MARK_VISIBLEX (gcry_log_debug)
MARK_VISIBLEX (gcry_log_debughex)
MARK_VISIBLEX (gcry_log_debugmpi)
MARK_VISIBLEX (gcry_log_debugpnt)
MARK_VISIBLEX (gcry_log_debugsxp)
MARK_VISIBLEX (gcry_get_config)
/* Functions used to implement macros. */
MARK_VISIBLEX (_gcry_mpi_get_const)
#undef MARK_VISIBLEX
#else /*!_GCRY_INCLUDED_BY_VISIBILITY_C*/
/* To avoid accidental use of the public functions inside Libgcrypt,
we redefine them to catch such errors. The usual difference
between a public and an internal version is that the internal
version use gpg_err_code_t and the public version gpg_error_t. */
#define gcry_check_version _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_control _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_allocation_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_fatalerror_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_gettext_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_log_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_outofcore_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_set_progress_handler _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_err_code_from_errno _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_err_code_to_errno _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_err_make_from_errno _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_error_from_errno _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_strerror _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_strsource _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_malloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_malloc_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_calloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_calloc_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_realloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_strdup _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xcalloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xcalloc_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xmalloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xmalloc_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xrealloc _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_xstrdup _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_free _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_is_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_open _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_close _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_setkey _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_setiv _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_setctr _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_algo_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_authenticate _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_checktag _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_gettag _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_ctl _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_decrypt _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_encrypt _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_get_algo_blklen _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_get_algo_keylen _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_map_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_cipher_mode_from_oid _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_algo_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_ctl _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_decrypt _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_encrypt _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_genkey _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_get_keygrip _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_get_curve _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_get_param _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_get_nbits _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_map_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_pk_sign _gcry_USE_THE_UNDERSCORED_FUNCTION
#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_md_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_algo_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_close _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_copy _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_ctl _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_enable _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_get _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_get_algo _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_get_algo_dlen _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_hash_buffer _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_hash_buffers _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_is_enabled _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_is_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_map_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_open _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_read _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_extract _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_reset _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_setkey _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_write _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_debug _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_algo_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_map_name _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_get_algo _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_get_algo_maclen _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_get_algo_keylen _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_open _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_close _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_setkey _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_setiv _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_write _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_read _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_verify _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mac_ctl _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_kdf_derive _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_prime_check _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_prime_generate _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_prime_group_generator _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_prime_release_factors _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_random_add_bytes _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_random_bytes _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_random_bytes_secure _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_randomize _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_create_nonce _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_ctx_release _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_alist _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_append _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_build _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_build_array _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_cadr _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_canon_len _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_car _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_cdr _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_cons _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_create _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_dump _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_find_token _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_length _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_new _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_nth _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_nth_buffer _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_nth_data _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_nth_mpi _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_nth_string _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_prepend _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_release _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_sprint _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_sscan _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_vlist _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_sexp_extract_param _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_add _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_add_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_addm _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_aprint _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_clear_bit _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_clear_flag _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_clear_highbit _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_cmp _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_cmp_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_copy _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_div _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_dump _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_gcd _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_get_flag _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_get_nbits _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_get_opaque _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_invm _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_mod _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_mul _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_mul_2exp _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_mul_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_mulm _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_new _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_get _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_new _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_release _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_copy _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_set _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_snatch_get _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_point_snatch_set _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_powm _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_print _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_randomize _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_release _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_rshift _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_lshift _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_scan _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set_bit _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set_flag _gcry_USE_THE_UNDERSCORED_FUNCTION
#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
#define gcry_mpi_sub_ui _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_subm _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_swap _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_test_bit _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_abs _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_add _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_sub _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_curve_point _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_dup _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_decode_point _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_get_affine _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_get_mpi _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_get_point _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_mul _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_new _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_set_mpi _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_ec_set_point _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_is_neg _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_neg _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_mpi_set_opaque_copy _gcry_USE_THE_UNDERSCORED_FUNCTION
#endif /*!_GCRY_INCLUDED_BY_VISIBILITY_C*/
#endif /*GCRY_VISIBILITY_H*/
diff --git a/tests/basic.c b/tests/basic.c
index b0c292a0..c4d56df7 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -1,12635 +1,12635 @@
/* basic.c - basic regression tests
* Copyright (C) 2001, 2002, 2003, 2005, 2008,
* 2009 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://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 <assert.h>
#include "../src/gcrypt-int.h"
#define PGM "basic"
#include "t-common.h"
typedef struct test_spec_pubkey_key
{
const char *secret;
const char *public;
const char *grip;
}
test_spec_pubkey_key_t;
typedef struct test_spec_pubkey
{
int id;
int flags;
test_spec_pubkey_key_t key;
}
test_spec_pubkey_t;
#define FLAG_CRYPT (1 << 0)
#define FLAG_SIGN (1 << 1)
#define FLAG_GRIP (1 << 2)
static int in_fips_mode;
#define MAX_DATA_LEN 128
static void
mismatch (const void *expected, size_t expectedlen,
const void *computed, size_t computedlen)
{
const unsigned char *p;
fprintf (stderr, "expected:");
for (p = expected; expectedlen; p++, expectedlen--)
fprintf (stderr, " %02x", *p);
fprintf (stderr, "\ncomputed:");
for (p = computed; computedlen; p++, computedlen--)
fprintf (stderr, " %02x", *p);
fprintf (stderr, "\n");
}
/* 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 terminates 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))
die ("invalid hex digits in \"%s\"\n", string);
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, 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);
}
static void
show_md_not_available (int algo)
{
static int list[100];
static int listlen;
int i;
if (!verbose && algo == GCRY_MD_MD2)
return; /* Do not print the diagnostic for that one. */
for (i=0; i < listlen; i++)
if (algo == list[i])
return; /* Note already printed. */
if (listlen < DIM (list))
list[listlen++] = algo;
show_note ("hash algorithm %d not available - skipping tests", algo);
}
static void
show_old_hmac_not_available (int algo)
{
static int list[100];
static int listlen;
int i;
if (!verbose && algo == GCRY_MD_MD2)
return; /* Do not print the diagnostic for that one. */
for (i=0; i < listlen; i++)
if (algo == list[i])
return; /* Note already printed. */
if (listlen < DIM (list))
list[listlen++] = algo;
show_note ("hash algorithm %d for old HMAC API not available "
"- skipping tests", algo);
}
static void
show_mac_not_available (int algo)
{
static int list[100];
static int listlen;
int i;
if (!verbose && algo == GCRY_MD_MD2)
return; /* Do not print the diagnostic for that one. */
for (i=0; i < listlen; i++)
if (algo == list[i])
return; /* Note already printed. */
if (listlen < DIM (list))
list[listlen++] = algo;
show_note ("MAC algorithm %d not available - skipping tests", algo);
}
void
progress_handler (void *cb_data, const char *what, int printchar,
int current, int total)
{
(void)cb_data;
(void)what;
(void)current;
(void)total;
if (printchar == '\n')
fputs ( "<LF>", stdout);
else
putchar (printchar);
fflush (stdout);
}
static void
check_cbc_mac_cipher (void)
{
static const struct tv
{
int algo;
char key[MAX_DATA_LEN];
unsigned char plaintext[MAX_DATA_LEN];
size_t plaintextlen;
char mac[MAX_DATA_LEN];
}
tv[] =
{
{ GCRY_CIPHER_AES,
"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" },
{ GCRY_CIPHER_3DES,
"abcdefghABCDEFGH01234567",
"This is a sample plaintext for CBC MAC of sixtyfour bytes.......",
0, "\x5c\x11\xf0\x01\x47\xbd\x3d\x3a" },
{ GCRY_CIPHER_DES,
"abcdefgh",
"This is a sample plaintext for CBC MAC of sixtyfour bytes.......",
0, "\xfa\x4b\xdf\x9d\xfa\xab\x01\x70" }
};
gcry_cipher_hd_t hd;
unsigned char out[MAX_DATA_LEN];
int i, blklen, keylen;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting CBC MAC checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
err = gcry_cipher_open (&hd,
tv[i].algo,
GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC);
if (!hd)
{
fail ("cbc-mac algo %d, gcry_cipher_open failed: %s\n",
tv[i].algo, gpg_strerror (err));
return;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("cbc-mac algo %d, gcry_cipher_get_algo_blklen failed\n",
tv[i].algo);
gcry_cipher_close (hd);
return;
}
keylen = gcry_cipher_get_algo_keylen (tv[i].algo);
if (!keylen)
{
fail ("cbc-mac algo %d, gcry_cipher_get_algo_keylen failed\n",
tv[i].algo);
return;
}
err = gcry_cipher_setkey (hd, tv[i].key, keylen);
if (err)
{
fail ("cbc-mac algo %d, gcry_cipher_setkey failed: %s\n",
tv[i].algo, gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
err = gcry_cipher_setiv (hd, NULL, 0);
if (err)
{
fail ("cbc-mac algo %d, gcry_cipher_setiv failed: %s\n",
tv[i].algo, gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
if (verbose)
fprintf (stderr, " checking CBC MAC for %s [%i]\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo);
err = gcry_cipher_encrypt (hd,
out, blklen,
tv[i].plaintext,
tv[i].plaintextlen ?
tv[i].plaintextlen :
strlen ((char*)tv[i].plaintext));
if (err)
{
fail ("cbc-mac algo %d, gcry_cipher_encrypt failed: %s\n",
tv[i].algo, gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
#if 0
{
int j;
for (j = 0; j < gcry_cipher_get_algo_blklen (tv[i].algo); j++)
printf ("\\x%02x", out[j] & 0xFF);
printf ("\n");
}
#endif
if (memcmp (tv[i].mac, out, blklen))
fail ("cbc-mac algo %d, encrypt mismatch entry %d\n", tv[i].algo, i);
gcry_cipher_close (hd);
}
if (verbose)
fprintf (stderr, " Completed CBC MAC checks.\n");
}
static void
check_aes128_cbc_cts_cipher (void)
{
static const char key[128 / 8] = "chicken teriyaki";
static const unsigned char plaintext[] =
"I would like the General Gau's Chicken, please, and wonton soup.";
static const struct tv
{
unsigned char out[MAX_DATA_LEN];
int inlen;
} tv[] =
{
{ "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
"\x97",
17 },
{ "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5",
31 },
{ "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
32 },
{ "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
"\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5",
47 },
{ "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
48 },
{ "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
"\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
64 },
};
gcry_cipher_hd_t hd;
unsigned char out[MAX_DATA_LEN];
int i;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting AES128 CBC CTS checks.\n");
err = gcry_cipher_open (&hd,
GCRY_CIPHER_AES,
GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hd, key, 128 / 8);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
err = gcry_cipher_setiv (hd, NULL, 0);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
if (verbose)
fprintf (stderr, " checking encryption for length %i\n", tv[i].inlen);
err = gcry_cipher_encrypt (hd, out, MAX_DATA_LEN,
plaintext, tv[i].inlen);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
if (memcmp (tv[i].out, out, tv[i].inlen))
fail ("aes-cbc-cts, encrypt mismatch entry %d\n", i);
err = gcry_cipher_setiv (hd, NULL, 0);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
if (verbose)
fprintf (stderr, " checking decryption for length %i\n", tv[i].inlen);
err = gcry_cipher_decrypt (hd, out, tv[i].inlen, NULL, 0);
if (err)
{
fail ("aes-cbc-cts, gcry_cipher_decrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
return;
}
if (memcmp (plaintext, out, tv[i].inlen))
fail ("aes-cbc-cts, decrypt mismatch entry %d\n", i);
}
gcry_cipher_close (hd);
if (verbose)
fprintf (stderr, " Completed AES128 CBC CTS checks.\n");
}
static void
check_ecb_cipher (void)
{
/* ECB cipher check. Mainly for testing underlying block cipher. */
static const struct tv
{
int algo;
const char *key;
struct
{
const char *plaintext;
int keylen;
int inlen;
const char *out;
} data[MAX_DATA_LEN];
} tv[] =
{
/* 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",
{ { "\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",
{ { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
56,
8,
"\xc0\x45\x04\x01\x2e\x4e\x1f\x53" },
{ }
}
},
};
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 (gcry_cipher_test_algo (algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\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;
}
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)
err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
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;
char key[MAX_DATA_LEN];
char ctr[MAX_DATA_LEN];
struct data
{
unsigned char plaintext[MAX_DATA_LEN];
int inlen;
char out[MAX_DATA_LEN];
} data[8];
} tv[] =
{
- /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
+ /* https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
{ GCRY_CIPHER_AES,
"\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",
16,
"\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd\xff" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x1e\x03\x1d\xda\x2f\xbe\x03\xd1\x79\x21\x70\xa0\xf3\x00\x9c\xee" },
{ "", 0, "" }
}
},
{ GCRY_CIPHER_AES192,
"\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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\x1a\xbc\x93\x24\x17\x52\x1c\xa2\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x09\x03\x39\xec\x0a\xa6\xfa\xef\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70\xd1\xbd\x1d\x66\x56\x20\xab\xf7" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x4f\x78\xa7\xf6\xd2\x98\x09\x58\x5a\x97\xda\xec\x58\xc6\xb0\x50" },
{ "", 0, "" }
}
},
{ GCRY_CIPHER_AES256,
"\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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\x60\x1e\xc3\x13\x77\x57\x89\xa5\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\xf4\x43\xe3\xca\x4d\x62\xb5\x9a\xca\x84\xe9\x90\xca\xca\xf5\xc5" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x2b\x09\x30\xda\xa2\x3d\xe9\x4c\xe8\x70\x17\xba\x2d\x84\x98\x8d" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6\x13\xc2\xdd\x08\x45\x79\x41\xa6" },
{ "", 0, "" }
}
},
/* Some truncation tests. With a truncated second block and
also with a single truncated block. */
{ GCRY_CIPHER_AES,
"\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",
16,
"\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
{"\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e",
15,
"\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd" },
{"", 0, "" }
}
},
{ GCRY_CIPHER_AES,
"\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",
16,
"\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
{"\xae",
1,
"\x98" },
{"", 0, "" }
}
},
{ GCRY_CIPHER_AES,
"\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",
15,
"\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6" },
{"", 0, "" }
}
},
{ GCRY_CIPHER_AES,
"\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",
1,
"\x87" },
{"", 0, "" }
}
},
/* Tests to see whether it works correctly as a stream cipher. */
{ GCRY_CIPHER_AES,
"\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",
16,
"\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
{"\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e",
15,
"\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd" },
{"\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
17,
"\xff\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" },
{"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x1e\x03\x1d\xda\x2f\xbe\x03\xd1\x79\x21\x70\xa0\xf3\x00\x9c\xee" },
{ "", 0, "" }
}
},
{ GCRY_CIPHER_AES,
"\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",
1,
"\x87" },
{"\xc1\xbe",
2,
"\x4d\x61" },
{"\xe2\x2e\x40",
3,
"\x91\xb6\x20" },
{"\x9f",
1,
"\xe3" },
{"\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
9,
"\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
{"\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e",
15,
"\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd" },
{"\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
9,
"\xff\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e" },
{ "", 0, "" }
}
},
#if USE_CAST5
/* A selfmade test vector using an 64 bit block cipher. */
{ GCRY_CIPHER_CAST5,
"\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",
16,
"\xe8\xa7\xac\x68\xca\xca\xa0\x20\x10\xcb\x1b\xcc\x79\x2c\xc4\x48" },
{"\xae\x2d\x8a\x57\x1e\x03\xac\x9c",
8,
"\x16\xe8\x72\x77\xb0\x98\x29\x68" },
{"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
8,
"\x9a\xb3\xa8\x03\x3b\xb4\x14\xba" },
{"\xae\x2d\x8a\x57\x1e\x03\xac\x9c\xa1\x00",
10,
"\x31\x5e\xd3\xfb\x1b\x8d\xd1\xf9\xb0\x83" },
{ "", 0, "" }
}
},
#endif /*USE_CAST5*/
{ 0,
"",
"",
{
{"", 0, "" }
}
}
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
int i, j, keylen, blklen;
gcry_error_t err = 0;
size_t taglen2;
if (verbose)
fprintf (stderr, " Starting CTR cipher checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (!tv[i].algo)
continue;
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
if (err)
{
fail ("aes-ctr, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("aes-ctr, 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-ctr, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("aes-ctr, gcry_cipher_get_algo_blklen failed\n");
return;
}
err = gcry_cipher_setctr (hde, tv[i].ctr, blklen);
if (!err)
err = gcry_cipher_setctr (hdd, tv[i].ctr, blklen);
if (err)
{
fail ("aes-ctr, gcry_cipher_setctr 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 (gpg_err_code (err) != GPG_ERR_INV_CIPHER_MODE)
{
fail ("aes-ctr, gcryctl_get_taglen failed to fail (tv %d): %s\n",
i, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (verbose)
fprintf (stderr, " checking CTR mode for %s [%i]\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo);
for (j = 0; tv[i].data[j].inlen; j++)
{
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
tv[i].data[j].plaintext,
tv[i].data[j].inlen == -1 ?
strlen ((char*)tv[i].data[j].plaintext) :
tv[i].data[j].inlen);
if (err)
{
fail ("aes-ctr, gcry_cipher_encrypt (%d, %d) failed: %s\n",
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 ("aes-ctr, encrypt mismatch entry %d:%d\n", i, j);
mismatch (tv[i].data[j].out, tv[i].data[j].inlen,
out, tv[i].data[j].inlen);
}
err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
if (err)
{
fail ("aes-ctr, gcry_cipher_decrypt (%d, %d) failed: %s\n",
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 ("aes-ctr, decrypt mismatch entry %d:%d\n", i, j);
mismatch (tv[i].data[j].plaintext, tv[i].data[j].inlen,
out, tv[i].data[j].inlen);
}
}
/* Now check that we get valid return codes back for good and
bad inputs. */
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
"1234567890123456", 16);
if (err)
fail ("aes-ctr, encryption failed for valid input");
err = gcry_cipher_encrypt (hde, out, 15,
"1234567890123456", 16);
if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
fail ("aes-ctr, too short output buffer returned wrong error: %s\n",
gpg_strerror (err));
err = gcry_cipher_encrypt (hde, out, 0,
"1234567890123456", 16);
if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
fail ("aes-ctr, 0 length output buffer returned wrong error: %s\n",
gpg_strerror (err));
err = gcry_cipher_encrypt (hde, out, 16,
"1234567890123456", 16);
if (err)
fail ("aes-ctr, correct length output buffer returned error: %s\n",
gpg_strerror (err));
/* Again, now for decryption. */
err = gcry_cipher_decrypt (hde, out, MAX_DATA_LEN,
"1234567890123456", 16);
if (err)
fail ("aes-ctr, decryption failed for valid input");
err = gcry_cipher_decrypt (hde, out, 15,
"1234567890123456", 16);
if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
fail ("aes-ctr, too short output buffer returned wrong error: %s\n",
gpg_strerror (err));
err = gcry_cipher_decrypt (hde, out, 0,
"1234567890123456", 16);
if (gpg_err_code (err) != GPG_ERR_BUFFER_TOO_SHORT)
fail ("aes-ctr, 0 length output buffer returned wrong error: %s\n",
gpg_strerror (err));
err = gcry_cipher_decrypt (hde, out, 16,
"1234567890123456", 16);
if (err)
fail ("aes-ctr, correct length output buffer returned error: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
if (verbose)
fprintf (stderr, " Completed CTR cipher checks.\n");
}
static void
check_cfb_cipher (void)
{
static const struct tv
{
int algo;
int cfb8;
char key[MAX_DATA_LEN];
char iv[MAX_DATA_LEN];
struct data
{
unsigned char plaintext[MAX_DATA_LEN];
int inlen;
char out[MAX_DATA_LEN];
}
data[MAX_DATA_LEN];
} tv[] =
{
- /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
+ /* https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
{ 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",
16,
"\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\xc8\xa6\x45\x37\xa0\xb3\xa9\x3f\xcd\xe3\xcd\xad\x9f\x1c\xe5\x8b"},
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x26\x75\x1f\x67\xa3\xcb\xb1\x40\xb1\x80\x8c\xf1\x87\xa4\xf4\xdf" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\xc0\x4b\x05\x35\x7c\x5d\x1c\x0e\xea\xc4\xc6\x6f\x9f\xf7\xf2\xe6" },
}
},
{ 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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab\x34\xc2\x59\x09\xc9\x9a\x41\x74" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x67\xce\x7f\x7f\x81\x17\x36\x21\x96\x1a\x2b\x70\x17\x1d\x3d\x7a" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x2e\x1e\x8a\x1d\xd5\x9b\x88\xb1\xc8\xe6\x0f\xed\x1e\xfa\xc4\xc9" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\xc0\x5f\x9f\x9c\xa9\x83\x4f\xa0\x42\xae\x8f\xba\x58\x4b\x09\xff" },
}
},
{ 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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\xdc\x7e\x84\xbf\xda\x79\x16\x4b\x7e\xcd\x84\x86\x98\x5d\x38\x60" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x39\xff\xed\x14\x3b\x28\xb1\xc8\x32\x11\x3c\x63\x31\xe5\x40\x7b" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\xdf\x10\x13\x24\x15\xe5\x4b\x92\xa1\x3e\xd0\xa8\x26\x7a\xe2\xf9" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x75\xa3\x85\x74\x1a\xb9\xce\xf8\x20\x31\x62\x3d\x55\xb1\xe4\x71" }
}
},
{ GCRY_CIPHER_AES, 1,
"\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",
1,
"\x3b"},
{ "\xc1",
1,
"\x79"},
{ "\xbe",
1,
"\x42"},
{ "\xe2",
1,
"\x4c"},
}
},
{ GCRY_CIPHER_AES192, 1,
"\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",
{ { "\x6b",
1,
"\xcd"},
{ "\xc1",
1,
"\xa2"},
{ "\xbe",
1,
"\x52"},
{ "\xe2",
1,
"\x1e"},
}
},
{ GCRY_CIPHER_AES256, 1,
"\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",
{ { "\x6b",
1,
"\xdc"},
{ "\xc1",
1,
"\x1f"},
{ "\xbe",
1,
"\x1a"},
{ "\xe2",
1,
"\x85"},
}
},
{ GCRY_CIPHER_AES, 1,
"\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",
10,
"\x8e\x9c\x50\x42\x56\x14\xd5\x40\xce\x11"},
}
},
{ GCRY_CIPHER_AES192, 1,
"\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",
{ { "\xd3\xd8\xb9\xb9\x84\xad\xc2\x42\x37\xee",
10,
"\x38\x79\xfe\xa7\x2a\xc9\x99\x29\xe5\x3a"},
}
},
{ GCRY_CIPHER_AES256, 1,
"\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",
{ { "\xb0\xfe\x25\xac\x8d\x3d\x28\xa2\xf4\x71",
10,
"\x63\x8c\x68\x23\xe7\x25\x6f\xb5\x62\x6e"},
}
},
{ GCRY_CIPHER_3DES, 1,
"\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",
{ { "\xdb\xe9\x15\xfc\xb3\x3b\xca\x18\xef\x14",
10,
"\xf4\x80\x1a\x8d\x03\x9d\xb4\xca\x8f\xf6"},
}
},
{ GCRY_CIPHER_3DES, 1,
"\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",
{ { "\x2e\xa9\x56\xd4\xa2\x11\xdb\x68\x59\xb7",
10,
"\xf2\x0e\x53\x66\x74\xa6\x6f\xa7\x38\x05"},
}
},
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
int i, j, keylen, blklen, mode;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting CFB checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
mode = tv[i].cfb8? GCRY_CIPHER_MODE_CFB8 : GCRY_CIPHER_MODE_CFB;
if (verbose)
fprintf (stderr, " checking CFB mode for %s [%i]\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo);
err = gcry_cipher_open (&hde, tv[i].algo, mode, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, mode, 0);
if (err)
{
fail ("aes-cfb, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("aes-cfb, 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-cfb, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("aes-cfb, gcry_cipher_get_algo_blklen failed\n");
return;
}
err = gcry_cipher_setiv (hde, tv[i].iv, blklen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, blklen);
if (err)
{
fail ("aes-cfb, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
for (j = 0; tv[i].data[j].inlen; j++)
{
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
tv[i].data[j].plaintext,
tv[i].data[j].inlen);
if (err)
{
fail ("aes-cfb, gcry_cipher_encrypt (%d, %d) failed: %s\n",
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 ("aes-cfb, encrypt mismatch entry %d:%d\n", i, j);
}
err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
if (err)
{
fail ("aes-cfb, gcry_cipher_decrypt (%d, %d) failed: %s\n",
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 ("aes-cfb, decrypt mismatch entry %d:%d\n", i, j);
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
if (verbose)
fprintf (stderr, " Completed CFB checks.\n");
}
static void
check_ofb_cipher (void)
{
static const struct tv
{
int algo;
char key[MAX_DATA_LEN];
char iv[MAX_DATA_LEN];
struct data
{
unsigned char plaintext[MAX_DATA_LEN];
unsigned int inlen;
char out[MAX_DATA_LEN];
}
data[MAX_DATA_LEN];
} tv[] =
{
- /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
+ /* https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
{ GCRY_CIPHER_AES,
"\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",
16,
"\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20\x33\x34\x49\xf8\xe8\x3c\xfb\x4a" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x77\x89\x50\x8d\x16\x91\x8f\x03\xf5\x3c\x52\xda\xc5\x4e\xd8\x25"},
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x97\x40\x05\x1e\x9c\x5f\xec\xf6\x43\x44\xf7\xa8\x22\x60\xed\xcc" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x30\x4c\x65\x28\xf6\x59\xc7\x78\x66\xa5\x10\xd9\xc1\xd6\xae\x5e" },
}
},
{ GCRY_CIPHER_AES192,
"\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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\xcd\xc8\x0d\x6f\xdd\xf1\x8c\xab\x34\xc2\x59\x09\xc9\x9a\x41\x74" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\xfc\xc2\x8b\x8d\x4c\x63\x83\x7c\x09\xe8\x17\x00\xc1\x10\x04\x01" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x8d\x9a\x9a\xea\xc0\xf6\x59\x6f\x55\x9c\x6d\x4d\xaf\x59\xa5\xf2" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x6d\x9f\x20\x08\x57\xca\x6c\x3e\x9c\xac\x52\x4b\xd9\xac\xc9\x2a" },
}
},
{ GCRY_CIPHER_AES256,
"\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",
{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
16,
"\xdc\x7e\x84\xbf\xda\x79\x16\x4b\x7e\xcd\x84\x86\x98\x5d\x38\x60" },
{ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
16,
"\x4f\xeb\xdc\x67\x40\xd2\x0b\x3a\xc8\x8f\x6a\xd8\x2a\x4f\xb0\x8d" },
{ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
16,
"\x71\xab\x47\xa0\x86\xe8\x6e\xed\xf3\x9d\x1c\x5b\xba\x97\xc4\x08" },
{ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
16,
"\x01\x26\x14\x1d\x67\xf3\x7b\xe8\x53\x8f\x5a\x8b\xe7\x40\xe4\x84" }
}
}
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
int i, j, keylen, blklen;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting OFB checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
if (verbose)
fprintf (stderr, " checking OFB 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_OFB, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_OFB, 0);
if (err)
{
fail ("aes-ofb, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("aes-ofb, 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-ofb, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("aes-ofb, gcry_cipher_get_algo_blklen failed\n");
return;
}
err = gcry_cipher_setiv (hde, tv[i].iv, blklen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, blklen);
if (err)
{
fail ("aes-ofb, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
for (j = 0; tv[i].data[j].inlen; j++)
{
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
tv[i].data[j].plaintext,
tv[i].data[j].inlen);
if (err)
{
fail ("aes-ofb, gcry_cipher_encrypt (%d, %d) failed: %s\n",
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 ("aes-ofb, encrypt mismatch entry %d:%d\n", i, j);
err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
if (err)
{
fail ("aes-ofb, gcry_cipher_decrypt (%d, %d) failed: %s\n",
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 ("aes-ofb, decrypt mismatch entry %d:%d\n", i, j);
}
err = gcry_cipher_reset(hde);
if (!err)
err = gcry_cipher_reset(hdd);
if (err)
{
fail ("aes-ofb, gcry_cipher_reset (%d, %d) failed: %s\n",
i, j, 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].iv, blklen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, blklen);
if (err)
{
fail ("aes-ofb, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
/* this time we encrypt and decrypt one byte at a time */
for (j = 0; tv[i].data[j].inlen; j++)
{
int byteNum;
for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum)
{
err = gcry_cipher_encrypt (hde, out+byteNum, 1,
(tv[i].data[j].plaintext) + byteNum,
1);
if (err)
{
fail ("aes-ofb, gcry_cipher_encrypt (%d, %d) failed: %s\n",
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 ("aes-ofb, encrypt mismatch entry %d:%d\n", i, j);
for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum)
{
err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0);
if (err)
{
fail ("aes-ofb, gcry_cipher_decrypt (%d, %d) failed: %s\n",
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 ("aes-ofb, decrypt mismatch entry %d:%d\n", i, j);
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
if (verbose)
fprintf (stderr, " Completed OFB checks.\n");
}
static void
_check_gcm_cipher (unsigned int step)
{
#define MAX_GCM_DATA_LEN (256 + 32)
static const struct tv
{
int algo;
char key[MAX_DATA_LEN];
char iv[MAX_DATA_LEN];
int ivlen;
unsigned char aad[MAX_DATA_LEN];
int aadlen;
unsigned char plaintext[MAX_GCM_DATA_LEN];
int inlen;
char out[MAX_GCM_DATA_LEN];
char tag[MAX_DATA_LEN];
int taglen;
int should_fail;
} tv[] =
{
- /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */
+ /* https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45\x5a" },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45",
15 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7",
14 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4",
13 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57",
12 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d",
11, 1 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61",
8 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58\xe2\xfc\xce",
4 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"",
0,
"",
"\x58",
1, 1 },
{ GCRY_CIPHER_AES,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
16,
"\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78",
"\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf" },
{ GCRY_CIPHER_AES,
"\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,
"", 0,
"\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\x1a\xaf\xd2\x55",
64,
"\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
"\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85",
"\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4" },
{ GCRY_CIPHER_AES,
"\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,
"\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
"\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
"\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85",
"\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47" },
{ GCRY_CIPHER_AES,
"\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08",
"\xca\xfe\xba\xbe\xfa\xce\xdb\xad", 8,
"\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,
"\x61\x35\x3b\x4c\x28\x06\x93\x4a\x77\x7f\xf5\x1f\xa2\x2a\x47\x55"
"\x69\x9b\x2a\x71\x4f\xcd\xc6\xf8\x37\x66\xe5\xf9\x7b\x6c\x74\x23"
"\x73\x80\x69\x00\xe4\x9f\x24\xb2\x2b\x09\x75\x44\xd4\x89\x6b\x42"
"\x49\x89\xb5\xe1\xeb\xac\x0f\x07\xc2\x3f\x45\x98",
"\x36\x12\xd2\xe7\x9e\x3b\x07\x85\x56\x1b\xe1\x4a\xac\xa2\xfc\xcb" },
{ GCRY_CIPHER_AES,
"\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08",
"\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa"
"\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28"
"\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54"
"\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60,
"\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,
"\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94"
"\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7"
"\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f"
"\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5",
"\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50" },
{ GCRY_CIPHER_AES192,
"\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
"\xfe\xff\xe9\x92\x86\x65\x73\x1c",
"\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa"
"\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28"
"\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54"
"\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60,
"\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,
"\xd2\x7e\x88\x68\x1c\xe3\x24\x3c\x48\x30\x16\x5a\x8f\xdc\xf9\xff"
"\x1d\xe9\xa1\xd8\xe6\xb4\x47\xef\x6e\xf7\xb7\x98\x28\x66\x6e\x45"
"\x81\xe7\x90\x12\xaf\x34\xdd\xd9\xe2\xf0\x37\x58\x9b\x29\x2d\xb3"
"\xe6\x7c\x03\x67\x45\xfa\x22\xe7\xe9\xb7\x37\x3b",
"\xdc\xf5\x66\xff\x29\x1c\x25\xbb\xb8\x56\x8f\xc3\xd3\x76\xa6\xd9" },
{ 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",
"\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa"
"\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28"
"\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54"
"\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60,
"\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,
"\x5a\x8d\xef\x2f\x0c\x9e\x53\xf1\xf7\x5d\x78\x53\x65\x9e\x2a\x20"
"\xee\xb2\xb2\x2a\xaf\xde\x64\x19\xa0\x58\xab\x4f\x6f\x74\x6b\xf4"
"\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" },
/* Test vectors for overflowing CTR. */
/* After setiv, ctr_low: 0xffffffff */
{ 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\x86\xdd\x40\xe7",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x7d\x6e\x38\xfd\xd0\x04\x9d\x28\xdf\x4a\x10\x3f\xa3\x9e\xf8\xf8"
"\x6c\x2c\x10\xa7\x91\xab\xc0\x86\xd4\x6d\x69\xea\x58\xc4\xf9\xc0"
"\xd4\xee\xc2\xb0\x9d\x36\xae\xe7\xc9\xa9\x1f\x71\xa8\xee\xa2\x1d"
"\x20\xfd\x79\xc7\xd9\xc4\x90\x51\x38\x97\xb6\x9f\x55\xea\xf3\xf0"
"\x78\xb4\xd3\x8c\xa9\x9b\x32\x7d\x19\x36\x96\xbc\x8e\xab\x80\x9f"
"\x61\x56\xcc\xbd\x3a\x80\xc6\x69\x37\x0a\x89\x89\x21\x82\xb7\x79"
"\x6d\xe9\xb4\x34\xc4\x31\xe0\xbe\x71\xad\xf3\x50\x05\xb2\x61\xab"
"\xb3\x1a\x80\x57\xcf\xe1\x11\x26\xcb\xa9\xd1\xf6\x58\x46\xf1\x69"
"\xa2\xb8\x42\x3c\xe8\x28\x13\xca\x58\xd9\x28\x99\xf8\xc8\x17\x32"
"\x4a\xf9\xb3\x4c\x7a\x47\xad\xe4\x77\x64\xec\x70\xa1\x01\x0b\x88"
"\xe7\x30\x0b\xbd\x66\x25\x39\x1e\x51\x67\xee\xec\xdf\xb8\x24\x5d"
"\x7f\xcb\xee\x7a\x4e\xa9\x93\xf0\xa1\x84\x7b\xfe\x5a\xe3\x86\xb2"
"\xfb\xcd\x39\xe7\x1e\x5e\x48\x65\x4b\x50\x2b\x4a\x99\x46\x3f\x6f"
"\xdb\xd9\x97\xdb\xe5\x6d\xa4\xdd\x6c\x18\x64\x5e\xae\x7e\x2c\xd3"
"\xb4\xf3\x57\x5c\xb5\xf8\x7f\xe5\x87\xb5\x35\xdb\x80\x38\x6e\x2c"
"\x5c\xdd\xeb\x7c\x63\xac\xe4\xb5\x5a\x6a\x40\x6d\x72\x69\x9a\xa9"
"\x8f\x5e\x93\x91\x4d\xce\xeb\x87\xf5\x25\xed\x75\x6b\x3b\x1a\xf2"
"\x0c\xd2\xa4\x10\x45\xd2\x87\xae\x29\x6d\xeb\xea\x66\x5f\xa0\xc2",
"\x8c\x22\xe3\xda\x9d\x94\x8a\xbe\x8a\xbc\x55\x2c\x94\x63\x44\x40" },
/* After setiv, ctr_low: 0xfffffffe */
{ 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\x8d\xd1\xc1\xdf",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\xac\x6a\x10\x3f\xe2\x8d\xed\x27\x55\x14\xca\x1f\x03\x67\x0a\xa8"
"\xa1\x07\xbf\x00\x73\x5b\x64\xef\xac\x30\x83\x81\x48\x4c\xaa\xd5"
"\xff\xca\xef\x2f\x77\xbe\xfe\x1b\x20\x5c\x86\x19\xc7\xf9\x11\x99"
"\x27\xc5\x57\xa7\x0a\xc2\xa8\x05\xd9\x07\x2b\xb9\x38\xa4\xef\x58"
"\x92\x74\xcf\x89\xc7\xba\xfc\xb9\x70\xac\x86\xe2\x31\xba\x7c\xf9"
"\xc4\xe2\xe0\x4c\x1b\xe4\x3f\x75\x83\x5c\x40\x0e\xa4\x13\x8b\x04"
"\x60\x78\x57\x29\xbb\xe6\x61\x93\xe3\x16\xf9\x58\x07\x75\xd0\x96"
"\xfb\x8f\x6d\x1e\x49\x0f\xd5\x31\x9e\xee\x31\xe6\x0a\x85\x93\x49"
"\x22\xcf\xd6\x1b\x40\x44\x63\x9c\x95\xaf\xf0\x44\x23\x51\x37\x92"
"\x0d\xa0\x22\x37\xb9\x6d\x13\xf9\x78\xba\x27\x27\xed\x08\x7e\x35"
"\xe4\xe2\x28\xeb\x0e\xbe\x3d\xce\x89\x93\x35\x84\x0f\xa0\xf9\x8d"
"\x94\xe9\x5a\xec\xd4\x0d\x1f\x5c\xbe\x6f\x8e\x6a\x4d\x10\x65\xbb"
"\xc7\x0b\xa0\xd5\x5c\x20\x80\x0b\x4a\x43\xa6\xe1\xb0\xe0\x56\x6a"
"\xde\x90\xe0\x6a\x45\xe7\xc2\xd2\x69\x9b\xc6\x62\x11\xe3\x2b\xa5"
"\x45\x98\xb0\x80\xd3\x57\x4d\x1f\x09\x83\x58\xd4\x4d\xa6\xc5\x95"
"\x87\x59\xb0\x58\x6c\x81\x49\xc5\x95\x18\x23\x1b\x6f\x10\x86\xa2"
"\xd9\x56\x19\x30\xec\xd3\x4a\x4b\xe8\x1c\x11\x37\xfb\x31\x60\x4d"
"\x4f\x9b\xc4\x95\xba\xda\x49\x43\x6c\xc7\x3d\x5b\x13\xf9\x91\xf8",
"\xcd\x2b\x83\xd5\x5b\x5a\x8e\x0b\x2e\x77\x0d\x97\xbf\xf7\xaa\xab" },
/* After setiv, ctr_low: 0xfffffffd */
{ 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\x76\x8c\x18\x92",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x3d\x6f\x4e\xf6\xd2\x6f\x4e\xce\xa6\xb4\x4a\x9e\xcb\x57\x13\x90"
"\x51\x3b\xf6\xb2\x40\x55\x0c\x2c\xa2\x85\x44\x72\xf2\x90\xaf\x6b"
"\x86\x8c\x75\x2a\x9c\xd6\x52\x50\xee\xc6\x5f\x59\xbc\x8d\x18\xd7"
"\x87\xa5\x7f\xa0\x13\xd1\x5d\x54\x77\x30\xe2\x5d\x1b\x4f\x87\x9f"
"\x3a\x41\xcb\x6a\xdf\x44\x4f\xa2\x1a\xbc\xfb\x4b\x16\x67\xed\x59"
"\x65\xf0\x77\x48\xca\xfd\xf0\xb6\x90\x65\xca\x23\x09\xca\x83\x43"
"\x8f\xf0\x78\xb4\x5f\x96\x2a\xfd\x29\xae\xda\x62\x85\xc5\x87\x4b"
"\x2a\x3f\xba\xbe\x15\x5e\xb0\x4e\x8e\xe7\x66\xae\xb4\x80\x66\x90"
"\x10\x9d\x81\xb9\x64\xd3\x36\x00\xb2\x95\xa8\x7d\xaf\x54\xf8\xbd"
"\x8f\x7a\xb1\xa1\xde\x09\x0d\x10\xc8\x8e\x1e\x18\x2c\x1e\x73\x71"
"\x2f\x1e\xfd\x16\x6e\xbe\xe1\x3e\xe5\xb4\xb5\xbf\x03\x63\xf4\x5a"
"\x0d\xeb\xff\xe0\x61\x80\x67\x51\xb4\xa3\x1f\x18\xa5\xa9\xf1\x9a"
"\xeb\x2a\x7f\x56\xb6\x01\x88\x82\x78\xdb\xec\xb7\x92\xfd\xef\x56"
"\x55\xd3\x72\x35\xcd\xa4\x0d\x19\x6a\xb6\x79\x91\xd5\xcb\x0e\x3b"
"\xfb\xea\xa3\x55\x9f\x77\xfb\x75\xc2\x3e\x09\x02\x73\x7a\xff\x0e"
"\xa5\xf0\x83\x11\xeb\xe7\xff\x3b\xd0\xfd\x7a\x07\x53\x63\x43\x89"
"\xf5\x7b\xc4\x7d\x3b\x2c\x9b\xca\x1c\xf6\xb2\xab\x13\xf5\xc4\x2a"
"\xbf\x46\x77\x3b\x09\xdd\xd1\x80\xef\x55\x11\x3e\xd8\xe4\x42\x22",
"\xa3\x86\xa1\x5f\xe3\x4f\x3b\xed\x12\x23\xeb\x5c\xb8\x0c\xad\x4a" },
/* After setiv, ctr_low: 0xfffffffc */
{ 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\x9b\xc8\xc3\xaf",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x33\x5f\xdc\x8d\x5d\x77\x7b\x78\xc1\x5b\x7b\xb3\xd9\x08\x9a\x0c"
"\xce\x63\x4e\xef\x19\xf8\x8c\x7a\xcb\x31\x39\x93\x69\x7a\x2c\x97"
"\x3a\xb4\x52\x45\x9e\x7b\x78\xbc\xa9\xad\x54\x7f\x88\xa6\xae\xd5"
"\xc0\x8b\x7a\xe4\x23\x6b\xb2\x29\x98\xea\x25\x7a\xae\x11\x0c\xc9"
"\xf3\x77\xa1\x74\x82\xde\x0c\xec\x68\xce\x94\xfd\xb0\xa0\xc5\x32"
"\xd6\xbb\xc3\xe7\xed\x3c\x6f\x0b\x53\x9d\xf3\xc8\xeb\x4e\xee\x99"
"\x19\xc7\x16\xd1\xa5\x59\x1d\xa9\xd3\xe6\x43\x52\x74\x61\x28\xe6"
"\xac\xd8\x47\x63\xc2\xb7\x53\x39\xc1\x9a\xb0\xa3\xa4\x26\x14\xd0"
"\x88\xa9\x8c\xc5\x6d\xe9\x21\x7c\xb9\xa5\xab\x67\xe3\x8d\xe9\x1d"
"\xe3\x1c\x7b\xcd\xa4\x12\x0c\xd7\xa6\x5d\x41\xcf\xdd\x3d\xfc\xbc"
"\x2a\xbb\xa2\x7a\x9c\x4b\x3a\x42\x6c\x98\x1d\x50\x99\x9c\xfb\xda"
"\x21\x09\x2a\x31\xff\x05\xeb\xa5\xf1\xba\x65\x78\xbe\x15\x8e\x84"
"\x35\xdd\x45\x29\xcc\xcd\x32\x2d\x27\xe9\xa8\x94\x4b\x16\x16\xcc"
"\xab\xf2\xec\xfb\xa0\xb5\x9d\x39\x81\x3e\xec\x5e\x3d\x13\xd1\x83"
"\x04\x79\x2d\xbb\x2c\x76\x76\x93\x28\x77\x27\x13\xdd\x1d\x3e\x89"
"\x3e\x37\x46\x4c\xb8\x34\xbe\xbf\x9f\x4f\x9f\x37\xff\x0c\xe6\x14"
"\x14\x66\x52\x41\x18\xa9\x39\x2b\x0c\xe5\x44\x04\xb0\x93\x06\x64"
"\x67\xf7\xa0\x19\xa7\x61\xcf\x03\x7b\xcb\xc8\xb3\x88\x28\xe4\xe7",
"\xe6\xe8\x0a\xe3\x72\xfc\xe0\x07\x69\x09\xf2\xeb\xbc\xc8\x6a\xf0" },
/* After setiv, ctr_low: 0xfffffffb */
{ 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\x60\x95\x1a\xe2",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\xd8\x32\x5a\xe3\x55\x8e\xb3\xc2\x51\x84\x2b\x09\x01\x5e\x6c\xfb"
"\x4a\xc4\x88\xa0\x33\xe7\x3e\xbf\xe5\x7c\xd2\x00\x4c\x1a\x85\x32"
"\x34\xec\x38\x9d\x18\x5f\xf1\x50\x61\x82\xee\xf3\x84\x5a\x84\x4e"
"\xeb\x29\x08\x4c\x7b\xb5\x27\xec\x7d\x79\x77\xd7\xa1\x68\x91\x32"
"\x2d\xf3\x38\xa9\xd6\x27\x16\xfb\x7d\x8b\x09\x5e\xcf\x1b\x74\x6d"
"\xcf\x51\x91\x91\xa1\xe7\x40\x19\x43\x7b\x0d\xa5\xa9\xa5\xf4\x2e"
"\x7f\x1c\xc7\xba\xa2\xea\x00\xdd\x24\x01\xa8\x66\x1e\x88\xf1\xf6"
"\x0c\x9a\xd6\x2b\xda\x3f\x3e\xb2\x98\xea\x89\xc7\xc6\x63\x27\xb7"
"\x6a\x48\x9a\xee\x1e\x70\xa0\xc8\xec\x3d\xc3\x3e\xb5\xf0\xc2\xb1"
"\xb9\x71\x1a\x69\x9d\xdd\x72\x1e\xfe\x72\xa0\x21\xb8\x9f\x18\x96"
"\x26\xcf\x89\x2e\x92\xf1\x02\x65\xa5\xb4\x2e\xb7\x4e\x12\xbd\xa0"
"\x48\xbe\xf6\x5c\xef\x7e\xf3\x0a\xcf\x9d\x1f\x1e\x14\x70\x3e\xa0"
"\x01\x0f\x14\xbf\x38\x10\x3a\x3f\x3f\xc2\x76\xe0\xb0\xe0\x7c\xc6"
"\x77\x6d\x7f\x69\x8e\xa0\x4b\x00\xc3\x9d\xf9\x0b\x7f\x8a\x8e\xd3"
"\x17\x58\x40\xfe\xaf\xf4\x16\x3a\x65\xff\xce\x85\xbb\x80\xfa\xb8"
"\x34\xc9\xef\x3a\xdd\x04\x46\xca\x8f\x70\x48\xbc\x1c\x71\x4d\x6a"
"\x17\x30\x32\x87\x2e\x2e\x54\x9e\x3f\x15\xed\x17\xd7\xa1\xcf\x6c"
"\x5d\x0f\x3c\xee\xf5\x96\xf1\x8f\x68\x1c\xbc\x27\xdc\x10\x3c\x3c",
"\x8c\x31\x06\xbb\xf8\x18\x2d\x9d\xd1\x0d\x03\x56\x2b\x28\x25\x9b" },
/* After setiv, ctr_low: 0xfffffffa */
{ 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\x6b\x99\x9b\xda",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x7a\x74\x57\xe7\xc1\xb8\x7e\xcf\x91\x98\xf4\x1a\xa4\xdb\x4d\x2c"
"\x6e\xdc\x05\x0b\xd1\x16\xdf\x25\xa8\x1e\x42\xa6\xf9\x09\x36\xfb"
"\x02\x8a\x10\x7d\xa1\x07\x88\x40\xb7\x41\xfd\x64\xf6\xe3\x92\x20"
"\xfd\xc9\xde\xbd\x88\x46\xd3\x1f\x20\x14\x73\x86\x09\xb6\x68\x61"
"\x64\x90\xda\x24\xa8\x0f\x6a\x10\xc5\x01\xbf\x52\x8a\xee\x23\x44"
"\xd5\xb0\xd8\x68\x5e\x77\xc3\x62\xed\xcb\x3c\x1b\x0c\x1f\x13\x92"
"\x2c\x74\x6d\xee\x40\x1b\x6b\xfe\xbe\x3c\xb8\x02\xdd\x24\x9d\xd3"
"\x3d\x4e\xd3\x9b\x18\xfd\xd6\x8f\x95\xef\xa3\xbf\xa9\x2f\x33\xa8"
"\xc2\x37\x69\x58\x92\x42\x3a\x30\x46\x12\x1b\x2c\x04\xf0\xbf\xa9"
"\x79\x55\xcd\xac\x45\x36\x79\xc0\xb4\xb2\x5f\x82\x88\x49\xe8\xa3"
"\xbf\x33\x41\x7a\xcb\xc4\x11\x0e\xcc\x61\xed\xd1\x6b\x59\x5f\x9d"
"\x20\x6f\x85\x01\xd0\x16\x2a\x51\x1b\x79\x35\x42\x5e\x49\xdf\x6f"
"\x64\x68\x31\xac\x49\x34\xfb\x2b\xbd\xb1\xd9\x12\x4e\x4b\x16\xc5"
"\xa6\xfe\x15\xd3\xaf\xac\x51\x08\x95\x1f\x8c\xd2\x52\x37\x8b\x88"
"\xf3\x20\xe2\xf7\x09\x55\x82\x83\x1c\x38\x5f\x17\xfc\x37\x26\x21"
"\xb8\xf1\xfe\xa9\xac\x54\x1e\x53\x83\x53\x3f\x43\xe4\x67\x22\xd5"
"\x86\xec\xf2\xb6\x4a\x8b\x8a\x66\xea\xe0\x92\x50\x3b\x51\xe4\x00"
"\x25\x2a\x7a\x64\x14\xd6\x09\xe1\x6c\x75\x32\x28\x53\x5e\xb3\xab",
"\x5d\x4b\xb2\x8f\xfe\xa5\x7f\x01\x6d\x78\x6c\x13\x58\x08\xe4\x94" },
/* After setiv, ctr_low: 0xfffffff9 */
{ 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\x90\xc4\x42\x97",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\xf5\xc1\xed\xb8\x7f\x55\x7b\xb5\x47\xed\xaa\x42\xd2\xda\x33\x41"
"\x4a\xe0\x36\x6d\x51\x28\x40\x9c\x35\xfb\x11\x65\x18\x83\x9c\xb5"
"\x02\xb2\xa7\xe5\x52\x27\xa4\xe8\x57\x3d\xb3\xf5\xea\xcb\x21\x07"
"\x67\xbe\xbe\x0f\xf6\xaa\x32\xa1\x4b\x5e\x79\x4f\x50\x67\xcd\x80"
"\xfc\xf1\x65\xf2\x6c\xd0\xdb\x17\xcc\xf9\x52\x93\xfd\x5e\xa6\xb9"
"\x5c\x9f\xa8\xc6\x36\xb7\x80\x80\x6a\xea\x62\xdc\x61\x13\x45\xbe"
"\xab\x8f\xd8\x99\x17\x51\x9b\x29\x04\x6e\xdb\x3e\x9f\x83\xc6\x35"
"\xb3\x90\xce\xcc\x74\xec\xcb\x04\x41\xac\xb1\x92\xde\x20\xb1\x67"
"\xb0\x38\x14\xaa\x7d\xee\x3c\xb2\xd3\xbb\x2f\x88\x0b\x73\xcf\x7b"
"\x69\xc1\x55\x5b\x2b\xf2\xd4\x38\x2b\x3c\xef\x04\xc9\x14\x7c\x31"
"\xd6\x61\x88\xa8\xb3\x8c\x69\xb4\xbc\xaa\x0d\x15\xd2\xd5\x27\x63"
"\xc4\xa4\x80\xe9\x2b\xe9\xd2\x34\xc9\x0e\x3f\x7b\xd3\x43\x0d\x47"
"\x5d\x37\x8e\x42\xa4\x4e\xef\xcd\xbb\x3a\x5b\xa4\xe1\xb0\x8d\x64"
"\xb7\x0b\x58\x52\xec\x55\xd0\xef\x23\xfe\xf2\x8d\xe0\xd1\x6a\x2c"
"\xaa\x1c\x03\xc7\x3e\x58\x4c\x61\x72\x07\xc6\xfd\x0e\xbc\xd4\x6b"
"\x99\x4f\x91\xda\xff\x6f\xea\x81\x0c\x76\x85\x5d\x0c\x7f\x1c\xb8"
"\x84\x8c\x2f\xe1\x36\x3e\x68\xa0\x57\xf5\xdf\x13\x0a\xd6\xe1\xcd"
"\xae\x23\x99\x4e\xed\x7a\x72\x1b\x7c\xe5\x65\xd1\xb7\xcf\x2f\x73",
"\x1e\x2f\xcf\x3c\x95\x9a\x29\xec\xd3\x37\x90\x8c\x84\x8a\xfb\x95" },
/* After setiv, ctr_low: 0xfffffff8 */
{ 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\xb7\xfa\xc7\x4f",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x14\x33\xc6\x9d\x04\xd3\x48\x29\x0c\x6a\x24\x27\xdf\x5f\x0a\xd2"
"\x71\xd6\xd0\x18\x04\xc0\x9f\x72\x0a\x60\xb7\x10\x52\x56\xf7\xae"
"\x64\xb0\x28\xd4\xfd\x25\x93\x8e\x67\x7e\xac\xc2\x93\xc7\x54\x2e"
"\x82\x93\x88\x6a\xb9\x8b\x73\xbc\x88\xec\x27\xdd\x4f\x9b\x21\x9e"
"\x77\x98\x70\x0b\xf4\xd8\x55\xfe\xf4\xc3\x3a\xcb\xca\x3a\xfb\xd4"
"\x52\x72\x2f\xf8\xac\xa9\x6a\xf5\x13\xab\x7a\x2e\x9f\x52\x41\xbd"
"\x87\x90\x68\xad\x17\xbd\x5a\xff\xc3\xc6\x10\x4d\xc1\xfe\xfc\x72"
"\x21\xb5\x53\x4a\x3f\xe0\x15\x9f\x29\x36\x23\xc0\x9a\x31\xb2\x0f"
"\xcd\x2f\xa6\xd0\xfc\xe6\x4d\xed\x68\xb3\x3d\x26\x67\xab\x40\xf0"
"\xab\xcf\x72\xc0\x50\xb1\x1e\x86\x38\xe2\xe0\x46\x3a\x2e\x3e\x1d"
"\x07\xd6\x9d\xe8\xfc\xa3\xe7\xac\xc9\xa0\xb3\x22\x05\xbc\xbf\xd2"
"\x63\x44\x66\xfc\xb4\x7b\xb4\x70\x7e\x96\xa9\x16\x1b\xb2\x7d\x93"
"\x44\x92\x5e\xbd\x16\x34\xa7\x11\xd0\xdf\x52\xad\x6f\xbd\x23\x3c"
"\x3d\x58\x16\xaf\x99\x8b\xbb\xa0\xdc\x3a\xff\x17\xda\x56\xba\x77"
"\xae\xc4\xb1\x51\xe2\x61\x4f\xf0\x66\x1b\x4c\xac\x79\x34\x1c\xfd"
"\x6c\x5f\x9a\x2c\x60\xfc\x47\x00\x5f\x2d\x81\xcc\xa9\xdd\x2b\xf4"
"\x5b\x53\x44\x61\xd4\x13\x5a\xf3\x93\xf0\xc9\x24\xd4\xe6\x60\x6f"
"\x78\x02\x0c\x75\x9d\x0d\x23\x97\x35\xe2\x06\x8a\x49\x5e\xe5\xbe",
"\x23\xc0\x4a\x2f\x98\x93\xca\xbd\x2e\x44\xde\x05\xcc\xe7\xf1\xf5" },
/* After setiv, ctr_low: 0xfffffff7 */
{ 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\x4c\xa7\x1e\x02",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x51\x51\x64\x89\xeb\x9f\xf9\xd6\xb1\xa6\x73\x5f\xf1\x62\xb5\xe4"
"\x00\x80\xdb\x4c\x1c\xce\xe5\x00\xeb\xea\x6c\x57\xe4\x27\xfc\x71"
"\x08\x8c\xa1\xfc\x59\x1d\x07\x45\x3c\xc9\x4e\x0f\xb6\xea\x96\x90"
"\xae\xf7\x81\x1e\x7e\x6c\x5e\x50\xaf\x34\x3e\xa0\x55\x59\x8e\xe7"
"\xc1\xba\x48\xfa\x9e\x07\xf6\x6a\x24\x54\x3e\x9b\xa5\xfe\x31\x16"
"\x3d\x4d\x9c\xc4\xe1\xec\x26\xa0\x8b\x59\xa6\xf3\x94\xf8\x88\xda"
"\x1f\x88\x23\x5f\xfb\xfd\x79\xa2\xd3\x62\x30\x66\x69\xd9\x0d\x05"
"\xc0\x75\x4c\xb8\x48\x34\x1d\x97\xcf\x29\x6a\x12\x1c\x26\x54\x1d"
"\x80\xa9\x06\x74\x86\xff\xc6\xb4\x72\xee\x34\xe2\x56\x06\x6c\xf5"
"\x11\xe7\x26\x71\x47\x6b\x05\xbd\xe4\x0b\x40\x78\x84\x3c\xf9\xf2"
"\x78\x34\x2b\x3c\x5f\x0e\x4c\xfb\x17\x39\xdc\x59\x6b\xd1\x56\xac"
"\xe4\x1f\xb9\x19\xbc\xec\xb1\xd0\x6d\x47\x3b\x37\x4d\x0d\x6b\x65"
"\x7c\x70\xe9\xec\x58\xcc\x09\xd4\xd9\xbf\x9f\xe0\x6c\x7f\x60\x28"
"\xd8\xdf\x8e\xd1\x6a\x73\x42\xf3\x50\x01\x79\x68\x41\xc3\xba\x19"
"\x1e\x2d\x30\xc2\x81\x2c\x9f\x11\x8b\xd0\xdc\x31\x3b\x01\xfe\x53"
"\xa5\x11\x13\x22\x89\x40\xb9\x1b\x12\x89\xef\x9a\xcb\xa8\x03\x4f"
"\x54\x1a\x15\x6d\x11\xba\x05\x09\xd3\xdb\xbf\x05\x42\x3a\x5a\x27"
"\x3b\x34\x5c\x58\x8a\x5c\xa4\xc2\x28\xdc\xb2\x3a\xe9\x99\x01\xd6",
"\x30\xb2\xb5\x11\x8a\x3a\x8d\x70\x67\x71\x14\xde\xed\xa7\x43\xb5" },
/* After setiv, ctr_low: 0xfffffff6 */
{ 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\x47\xab\x9f\x3a",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x05\x72\x44\xa0\x99\x11\x1d\x2c\x4b\x03\x4f\x20\x92\x88\xbe\x55"
"\xee\x31\x2c\xd9\xc0\xc1\x64\x77\x79\xd7\x3e\xfa\x5a\x7d\xf0\x48"
"\xf8\xc8\xfe\x81\x8f\x89\x92\xa6\xc2\x07\xdc\x9f\x3f\xb2\xc8\xf2"
"\xf3\xe9\xe1\xd3\xed\x55\xb4\xab\xc3\x22\xed\x8f\x00\xde\x32\x95"
"\x91\xc0\xc5\xf3\xd3\x93\xf0\xee\x56\x14\x8f\x96\xff\xd0\x6a\xbd"
"\xfc\x57\xc2\xc3\x7b\xc1\x1d\x56\x48\x3f\xa6\xc7\x92\x47\xf7\x2f"
"\x0b\x85\x1c\xff\x87\x29\xe1\xbb\x9b\x14\x6c\xac\x51\x0a\xc0\x7b"
"\x22\x25\xb0\x48\x92\xad\x09\x09\x6e\x39\x8e\x96\x13\x05\x55\x92"
"\xbd\xd7\x5d\x95\x35\xdd\x8a\x9d\x05\x59\x60\xae\xbb\xc0\x85\x92"
"\x4c\x8b\xa0\x3f\xa2\x4a\xe5\x2e\xde\x85\x1a\x39\x10\x22\x11\x1b"
"\xdd\xcc\x96\xf4\x93\x97\xf5\x81\x85\xf3\x33\xda\xa1\x9a\xba\xfd"
"\xb8\xaf\x60\x81\x37\xf1\x02\x88\x54\x15\xeb\x21\xd1\x19\x1a\x1f"
"\x28\x9f\x02\x27\xca\xce\x97\xda\xdc\xd2\x0f\xc5\x0e\x2e\xdd\x4f"
"\x1d\x24\x62\xe4\x6e\x4a\xbe\x96\x95\x38\x0c\xe9\x26\x14\xf3\xf0"
"\x92\xbc\x97\xdc\x38\xeb\x64\xc3\x04\xc1\xa2\x6c\xad\xbd\xf8\x03"
"\xa0\xa4\x68\xaa\x9d\x1f\x09\xe6\x62\x95\xa2\x1c\x32\xef\x62\x28"
"\x7e\x54\x6d\x4b\x6a\xcc\x4a\xd0\x82\x47\x46\x0d\x45\x3c\x36\x03"
"\x86\x90\x44\x65\x18\xac\x19\x75\xe6\xba\xb1\x9a\xb4\x5d\x84\x9b",
"\x31\x22\x2b\x11\x6e\x2b\x94\x56\x37\x9d\xc3\xa5\xde\xe7\x6e\xc9" },
/* After setiv, ctr_low: 0xfffffff5 */
{ 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\xbc\xf6\x46\x77",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x6e\x32\xdb\x04\x32\x57\x15\x78\x0e\x4c\x70\x66\x5c\x91\x43\x0c"
"\x63\x73\xb8\x86\xad\xb0\xf1\x34\x0f\x0c\x7e\xd3\x4e\xcb\xc9\xea"
"\x19\x3c\xb8\x14\xd0\xab\x9e\x9b\x22\xda\x7a\x96\xa7\xf5\xa2\x99"
"\x58\xe3\xd6\x72\x0f\xf5\xdf\x88\xd1\x33\xb1\xe5\x03\x72\x62\x1c"
"\xa7\xf2\x67\x50\x0e\x70\xc3\x7a\x6c\x4a\x90\xba\x78\x9e\xd2\x0b"
"\x29\xd4\xc8\xa7\x57\x06\xf2\xf4\x01\x4b\x30\x53\xea\xf7\xde\xbf"
"\x1c\x12\x03\xcf\x9f\xcf\x80\x8b\x77\xfd\x73\x48\x79\x19\xbe\x38"
"\x75\x0b\x6d\x78\x7d\x79\x05\x98\x65\x3b\x35\x8f\x68\xff\x30\x7a"
"\x6e\xf7\x10\x9e\x11\x25\xc4\x95\x97\x7d\x92\x0f\xbf\x38\x95\xbd"
"\x5d\x2a\xf2\x06\x2c\xd9\x5a\x80\x91\x4e\x22\x7d\x5f\x69\x85\x03"
"\xa7\x5d\xda\x22\x09\x2b\x8d\x29\x67\x7c\x8c\xf6\xb6\x49\x20\x63"
"\xb9\xb6\x4d\xb6\x37\xa3\x7b\x19\xa4\x28\x90\x83\x55\x3d\x4e\x18"
"\xc8\x65\xbc\xd1\xe7\xb5\xcf\x65\x28\xea\x19\x11\x5c\xea\x83\x8c"
"\x44\x1f\xac\xc5\xf5\x3a\x4b\x1c\x2b\xbf\x76\xd8\x98\xdb\x50\xeb"
"\x64\x45\xae\xa5\x39\xb7\xc8\xdf\x5a\x73\x6d\x2d\x0f\x4a\x5a\x17"
"\x37\x66\x1c\x3d\x27\xd5\xd6\x7d\xe1\x08\x7f\xba\x4d\x43\xc2\x29"
"\xf7\xbe\x83\xec\xd0\x3b\x2e\x19\x9e\xf7\xbf\x1b\x16\x34\xd8\xfa"
"\x32\x17\x2a\x90\x55\x93\xd5\x3e\x14\x8d\xd6\xa1\x40\x45\x09\x52",
"\x89\xf2\xae\x78\x38\x8e\xf2\xd2\x52\xa8\xba\xb6\xf2\x5d\x7c\xfc" },
/* After setiv, ctr_low: 0xfffffff4 */
{ 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\x51\xb2\x9d\x4a",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x1d\xb8\x77\xcd\xcd\xfe\xde\x07\x97\xcb\x97\x3a\x4f\xa0\xd0\xe6"
"\xcc\xcf\x8b\x71\xd5\x65\x3d\xc4\x17\x52\xe7\x1d\x6a\x68\x4a\x77"
"\xca\x04\x4a\xef\x8e\x7e\xce\x79\xa1\x80\x0d\x9e\xd5\xf4\xce\x66"
"\x4d\x54\xb1\x09\xd1\xb6\xb0\x43\x28\xe8\x53\xe2\x24\x9c\x76\xc5"
"\x4d\x22\xf3\x6e\x13\xf3\xd7\xe0\x85\xb8\x9e\x0b\x17\x22\xc0\x79"
"\x2b\x72\x57\xaa\xbd\x43\xc3\xf7\xde\xce\x22\x41\x3c\x7e\x37\x1a"
"\x55\x2e\x36\x0e\x7e\xdc\xb3\xde\xd7\x33\x36\xc9\xc8\x56\x93\x51"
"\x68\x77\x9a\xb0\x08\x5c\x22\x35\xef\x5c\x9b\xbf\x3e\x20\x8a\x84"
"\x3d\xb3\x60\x10\xe1\x97\x30\xd7\xb3\x6f\x40\x5a\x2c\xe0\xe5\x52"
"\x19\xb6\x2b\xed\x6e\x8e\x18\xb4\x8d\x78\xbd\xc4\x9f\x4f\xbd\x82"
"\x98\xd6\x71\x3d\x71\x5b\x78\x73\xee\x8e\x4b\x37\x88\x9e\x21\xca"
"\x00\x6c\xc2\x96\x8d\xf0\xcd\x09\x58\x54\x5a\x58\x59\x8e\x9b\xf8"
"\x72\x93\xd7\xa0\xf9\xc4\xdc\x48\x89\xaa\x31\x95\xda\x4e\x2f\x79"
"\x1e\x37\x49\x92\x2e\x32\x2e\x76\x54\x2a\x64\xa8\x96\x67\xe9\x75"
"\x10\xa6\xeb\xad\xc6\xa8\xec\xb7\x18\x0a\x32\x26\x8d\x6e\x03\x74"
"\x0e\x1f\xfc\xde\x76\xff\x6e\x96\x42\x2d\x80\x0a\xc6\x78\x70\xc4"
"\xd8\x56\x7b\xa6\x38\x2f\xf6\xc0\x9b\xd7\x21\x6e\x88\x5d\xc8\xe5"
"\x02\x6a\x09\x1e\xb3\x46\x44\x80\x82\x5b\xd1\x66\x06\x61\x4f\xb8",
"\x16\x0e\x73\xa3\x14\x43\xdb\x15\x9c\xb0\x0d\x30\x6d\x9b\xe1\xb1" },
/* After setiv, ctr_low: 0xfffffff3 */
{ 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\xaa\xef\x44\x07",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x42\x71\x54\xe2\xdb\x50\x5d\x3c\x10\xbd\xf8\x60\xbd\xdb\x26\x14"
"\x7d\x13\x59\x98\x28\xfb\x43\x42\xca\x72\xe6\xd8\x58\x00\xa2\x1b"
"\x6a\x61\xb4\x3a\x80\x6b\x9e\x14\xbd\x11\x33\xab\xe9\xb9\x91\x95"
"\xd7\x5d\xc3\x98\x1f\x7f\xcb\xa8\xf0\xec\x31\x26\x51\xea\x2e\xdf"
"\xd9\xde\x70\xf5\x84\x27\x3a\xac\x22\x05\xb9\xce\x2a\xfb\x2a\x83"
"\x1e\xce\x0e\xb2\x31\x35\xc6\xe6\xc0\xd7\xb0\x5f\xf5\xca\xdb\x13"
"\xa7\xfe\x4f\x85\xa3\x4f\x94\x5c\xc1\x04\x12\xde\x6f\xa1\xdb\x41"
"\x59\x82\x22\x22\x65\x97\x6d\xc8\x67\xab\xf3\x90\xeb\xa4\x00\xb3"
"\x7d\x94\x3d\x7b\x2a\xe2\x85\x36\x87\x16\xb8\x19\x92\x02\xe0\x43"
"\x42\x85\xa1\xe6\xb8\x11\x30\xcc\x2c\xd8\x63\x09\x0e\x53\x5f\xa3"
"\xe0\xd4\xee\x0e\x04\xee\x65\x61\x96\x84\x42\x0c\x68\x8d\xb7\x48"
"\xa3\x02\xb4\x82\x69\xf2\x35\xe4\xce\x3b\xe3\x44\xce\xad\x49\x32"
"\xab\xda\x04\xea\x06\x60\xa6\x2a\x7d\xee\x0f\xb8\x95\x90\x22\x62"
"\x9c\x78\x59\xd3\x7b\x61\x02\x65\x63\x96\x9f\x67\x50\xa0\x61\x43"
"\x53\xb2\x3f\x22\xed\x8c\x42\x39\x97\xd9\xbc\x6e\x81\xb9\x21\x97"
"\xc6\x5b\x68\xd7\x7f\xd0\xc5\x4a\xfb\x74\xc4\xfd\x9a\x2a\xb8\x9b"
"\x48\xe0\x00\xea\x6d\xf5\x30\x26\x61\x8f\xa5\x45\x70\xc9\x3a\xea"
"\x6d\x19\x11\x57\x0f\x21\xe6\x0a\x53\x94\xe3\x0c\x99\xb0\x2f\xc5",
"\x92\x92\x89\xcd\x4f\x3c\x6d\xbc\xe8\xb3\x70\x14\x5b\x3c\x12\xe4" },
/* After setiv, ctr_low: 0xfffffff2 */
{ 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\xa1\xe3\xc5\x3f",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\x41\xc3\xcb\xd7\x6e\xde\x2a\xc6\x15\x05\xc6\xba\x27\xae\xcd\x37"
"\xc0\xe5\xbf\xb9\x5c\xdc\xd6\xad\x1a\xe1\x35\x7c\xc0\x85\x85\x51"
"\x8c\x98\x06\xc0\x72\x43\x71\x7a\x2d\x7c\x81\x3c\xe7\xd6\x32\x8e"
"\x22\x2b\x46\x95\x6a\xde\x45\x40\x56\xe9\x63\x32\x68\xbf\xb6\x78"
"\xb7\x86\x00\x9d\x2c\x9e\xed\x67\xc1\x9b\x09\x9e\xd9\x0a\x56\xcb"
"\x57\xc9\x48\x14\x23\x4e\x97\x04\xb5\x85\x25\x1d\xcb\x1a\x79\x9b"
"\x54\x06\x95\xad\x16\x81\x84\x3a\x38\xec\x41\x90\x2a\xfa\x50\xe0"
"\xb9\x20\xa6\xeb\xfe\x2e\x5c\xa1\xf6\x3c\x69\x4c\xce\xf8\x30\xe0"
"\x87\x68\xa2\x3a\x9d\xad\x75\xd4\xa5\x6b\x0a\x90\x65\xa2\x27\x64"
"\x9d\xf5\xa0\x6f\xd0\xd3\x62\xa5\x2d\xae\x02\x89\xb4\x1a\xfa\x32"
"\x9b\xa0\x44\xdd\x50\xde\xaf\x41\xa9\x89\x1e\xb0\x41\xbc\x9c\x41"
"\xb0\x35\x5e\xf1\x9a\xd9\xab\x57\x53\x21\xca\x39\xfc\x8b\xb4\xd4"
"\xb2\x19\x8a\xe9\xb2\x24\x1e\xce\x2e\x19\xb0\xd2\x93\x30\xc4\x70"
"\xe2\xf8\x6a\x8a\x99\x3b\xed\x71\x7e\x9e\x98\x99\x2a\xc6\xdd\xcf"
"\x43\x32\xdb\xfb\x27\x22\x89\xa4\xc5\xe0\xa2\x94\xe9\xcf\x9d\x48"
"\xab\x3f\xfa\x4f\x75\x63\x46\xdd\xfe\xfa\xf0\xbf\x6e\xa1\xf9\xca"
"\xb1\x77\x79\x35\x6c\x33\xe1\x57\x68\x50\xe9\x78\x4e\xe4\xe2\xf0"
"\xcf\xe4\x23\xde\xf4\xa7\x34\xb3\x44\x97\x38\xd2\xbd\x27\x44\x0e",
"\x75\x0a\x41\x3b\x87\xe3\xc7\xf6\xd6\xe3\xab\xfa\x4b\xbe\x2e\x56" },
/* After setiv, ctr_low: 0xfffffff1 */
{ 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\x5a\xbe\x1c\x72",
16,
"", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
288,
"\xf1\x3c\x7a\xa4\xa9\xaf\xe7\x49\x19\x7d\xad\x50\xc1\x6a\x84\x87"
"\xf5\x69\xe4\xe5\xc2\x0a\x90\x33\xc3\xeb\x76\x63\x5f\x9b\x1d\xf9"
"\x53\x4a\x2a\x6d\x6b\x61\xe0\x5d\xed\xcb\x98\x0d\xf2\x57\x33\x12"
"\xd1\x44\xaa\x7a\x7e\x4e\x41\x0e\xe6\xa7\x9f\x17\x92\x28\x91\xad"
"\xca\xce\xf2\xa8\x73\x4a\xad\x89\x62\x73\x0b\x9a\x68\x91\xa8\x11"
"\x44\x01\xfd\x57\xe4\xf8\x84\x55\x2b\x66\xdb\xb9\xd6\xee\x83\xe5"
"\x57\xea\x5c\x6a\x23\x87\xdd\x0a\x45\x63\xb4\x0c\x8f\xc5\x9f\x22"
"\xf3\x4f\x4e\x6f\x7b\x14\x62\xf7\x80\x59\x4a\xc5\xc8\xae\x8a\x6f"
"\x5e\xe3\x1e\xe6\xae\xec\x99\x77\x6b\x88\x14\xe3\x58\x88\x61\x74"
"\x38\x91\xa1\x32\xb8\xd2\x39\x6b\xe2\xcb\x8e\x77\xde\x92\x36\x78"
"\xad\x50\xcf\x08\xb8\xfa\x29\x59\xb4\x68\x1b\x23\x10\x57\x32\x92"
"\xf8\xec\xe1\x97\xdb\x30\x85\x22\xb5\x68\x2f\xf2\x98\xda\x06\xee"
"\x65\x02\xe7\xf9\xc8\xc1\xca\x8f\xd3\xed\x4a\x3c\x09\xdd\xde\x64"
"\xd9\x85\x17\x2c\x62\x41\x35\x24\xed\x6b\x87\x78\x1e\xb5\x7a\x9b"
"\xa3\x90\xa3\x99\xc7\x39\x51\x10\xb7\x6a\x12\x3b\x64\xfe\x32\x3c"
"\xb6\x84\x9a\x3f\x95\xd3\xcb\x22\x69\x9c\xf9\xb7\xc2\x8b\xf4\x55"
"\x68\x60\x11\x20\xc5\x3e\x0a\xc0\xba\x00\x0e\x88\x96\x66\xfa\xf0"
"\x75\xbc\x2b\x9c\xff\xc5\x33\x7b\xaf\xb2\xa6\x34\x78\x44\x9c\xa7",
"\x01\x24\x0e\x17\x17\xe5\xfc\x90\x07\xfa\x78\xd5\x5d\x66\xa3\xf5" },
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_GCM_DATA_LEN];
unsigned char tag[GCRY_GCM_BLOCK_LEN];
int i, keylen;
gcry_error_t err = 0;
size_t pos, poslen, taglen2;
int byteNum;
if (verbose)
fprintf (stderr, " Starting GCM checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
if (verbose)
fprintf (stderr, " checking GCM 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, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_GCM, 0);
if (err)
{
fail ("aes-gcm, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("aes-gcm, 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, 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].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("aes-gcm, 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-gcm, gcryctl_get_taglen failed (tv %d): %s\n",
i, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (taglen2 != GCRY_GCM_BLOCK_LEN)
{
fail ("cipher-gcm, gcryctl_get_taglen returned bad length"
" (tv %d): got=%zu want=%d\n",
i, taglen2, GCRY_GCM_BLOCK_LEN);
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
for (pos = 0; pos < tv[i].aadlen; pos += step)
{
poslen = (pos + step < tv[i].aadlen) ? step : tv[i].aadlen - pos;
err = gcry_cipher_authenticate(hde, tv[i].aad + pos, poslen);
if (err)
{
fail ("aes-gcm, 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].aad + pos, poslen);
if (err)
{
fail ("aes-gcm, 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-gcm, 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-gcm, 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-gcm, 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-gcm, decrypt mismatch entry %d (step %d)\n", i, step);
taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN;
err = gcry_cipher_gettag (hde, out, taglen2);
if (err)
{
if (tv[i].should_fail)
goto next_tv;
fail ("aes-gcm, 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))
fail ("aes-gcm, encrypt tag mismatch entry %d\n", i);
err = gcry_cipher_checktag (hdd, out, taglen2);
if (err)
{
fail ("aes-gcm, 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-gcm, 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].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("aes-gcm, 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].aadlen; ++byteNum)
{
err = gcry_cipher_authenticate(hde, tv[i].aad + byteNum, 1);
if (err)
{
fail ("aes-gcm, 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].aad + byteNum, 1);
if (err)
{
fail ("aes-gcm, 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-gcm, 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-gcm, encrypt mismatch entry %d, (byte-buf)\n", i);
/* Test output to larger than 16-byte buffer. */
taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN + 1;
err = gcry_cipher_gettag (hde, tag, taglen2);
if (err)
{
if (tv[i].should_fail)
goto next_tv;
fail ("aes-gcm, 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 : GCRY_GCM_BLOCK_LEN;
if (memcmp (tv[i].tag, tag, taglen2))
fail ("aes-gcm, 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-gcm, 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-gcm, decrypt mismatch entry %d\n", i);
err = gcry_cipher_checktag (hdd, tag, taglen2);
if (err)
{
fail ("aes-gcm, 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, 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 */
+ /* Test vectors from https://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++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
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_poly1305_cipher (unsigned int step)
{
static const struct tv
{
int algo;
const char *key;
const char *iv;
int ivlen;
const char *aad;
int aadlen;
const char *plaintext;
int inlen;
const char *out;
const char *tag;
} tv[] =
{
/* draft-irtf-cfrg-chacha20-poly1305-03 */
{ 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,
"\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20"
"\x61\x72\x65\x20\x64\x72\x61\x66\x74\x20\x64\x6f\x63\x75\x6d\x65"
"\x6e\x74\x73\x20\x76\x61\x6c\x69\x64\x20\x66\x6f\x72\x20\x61\x20"
"\x6d\x61\x78\x69\x6d\x75\x6d\x20\x6f\x66\x20\x73\x69\x78\x20\x6d"
"\x6f\x6e\x74\x68\x73\x20\x61\x6e\x64\x20\x6d\x61\x79\x20\x62\x65"
"\x20\x75\x70\x64\x61\x74\x65\x64\x2c\x20\x72\x65\x70\x6c\x61\x63"
"\x65\x64\x2c\x20\x6f\x72\x20\x6f\x62\x73\x6f\x6c\x65\x74\x65\x64"
"\x20\x62\x79\x20\x6f\x74\x68\x65\x72\x20\x64\x6f\x63\x75\x6d\x65"
"\x6e\x74\x73\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x2e"
"\x20\x49\x74\x20\x69\x73\x20\x69\x6e\x61\x70\x70\x72\x6f\x70\x72"
"\x69\x61\x74\x65\x20\x74\x6f\x20\x75\x73\x65\x20\x49\x6e\x74\x65"
"\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x73\x20\x72"
"\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x6d\x61\x74\x65\x72\x69\x61"
"\x6c\x20\x6f\x72\x20\x74\x6f\x20\x63\x69\x74\x65\x20\x74\x68\x65"
"\x6d\x20\x6f\x74\x68\x65\x72\x20\x74\x68\x61\x6e\x20\x61\x73\x20"
"\x2f\xe2\x80\x9c\x77\x6f\x72\x6b\x20\x69\x6e\x20\x70\x72\x6f\x67"
"\x72\x65\x73\x73\x2e\x2f\xe2\x80\x9d", 265,
"\x64\xa0\x86\x15\x75\x86\x1a\xf4\x60\xf0\x62\xc7\x9b\xe6\x43\xbd"
"\x5e\x80\x5c\xfd\x34\x5c\xf3\x89\xf1\x08\x67\x0a\xc7\x6c\x8c\xb2"
"\x4c\x6c\xfc\x18\x75\x5d\x43\xee\xa0\x9e\xe9\x4e\x38\x2d\x26\xb0"
"\xbd\xb7\xb7\x3c\x32\x1b\x01\x00\xd4\xf0\x3b\x7f\x35\x58\x94\xcf"
"\x33\x2f\x83\x0e\x71\x0b\x97\xce\x98\xc8\xa8\x4a\xbd\x0b\x94\x81"
"\x14\xad\x17\x6e\x00\x8d\x33\xbd\x60\xf9\x82\xb1\xff\x37\xc8\x55"
"\x97\x97\xa0\x6e\xf4\xf0\xef\x61\xc1\x86\x32\x4e\x2b\x35\x06\x38"
"\x36\x06\x90\x7b\x6a\x7c\x02\xb0\xf9\xf6\x15\x7b\x53\xc8\x67\xe4"
"\xb9\x16\x6c\x76\x7b\x80\x4d\x46\xa5\x9b\x52\x16\xcd\xe7\xa4\xe9"
"\x90\x40\xc5\xa4\x04\x33\x22\x5e\xe2\x82\xa1\xb0\xa0\x6c\x52\x3e"
"\xaf\x45\x34\xd7\xf8\x3f\xa1\x15\x5b\x00\x47\x71\x8c\xbc\x54\x6a"
"\x0d\x07\x2b\x04\xb3\x56\x4e\xea\x1b\x42\x22\x73\xf5\x48\x27\x1a"
"\x0b\xb2\x31\x60\x53\xfa\x76\x99\x19\x55\xeb\xd6\x31\x59\x43\x4e"
"\xce\xbb\x4e\x46\x6d\xae\x5a\x10\x73\xa6\x72\x76\x27\x09\x7a\x10"
"\x49\xe6\x17\xd9\x1d\x36\x10\x94\xfa\x68\xf0\xff\x77\x98\x71\x30"
"\x30\x5b\xea\xba\x2e\xda\x04\xdf\x99\x7b\x71\x4d\x6c\x6f\x2c\x29"
"\xa6\xad\x5c\xb4\x02\x2b\x02\x70\x9b",
"\xee\xad\x9d\x67\x89\x0c\xbb\x22\x39\x23\x36\xfe\xa1\x85\x1f\x38" },
/* draft-irtf-cfrg-chacha20-poly1305-03 */
{ GCRY_CIPHER_CHACHA20,
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
"\x07\x00\x00\x00\x40\x41\x42\x43\x44\x45\x46\x47", 12,
"\x50\x51\x52\x53\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", 12,
"Ladies and Gentlemen of the class of '99: If I could offer you "
"only one tip for the future, sunscreen would be it.", 114,
"\xd3\x1a\x8d\x34\x64\x8e\x60\xdb\x7b\x86\xaf\xbc\x53\xef\x7e\xc2"
"\xa4\xad\xed\x51\x29\x6e\x08\xfe\xa9\xe2\xb5\xa7\x36\xee\x62\xd6"
"\x3d\xbe\xa4\x5e\x8c\xa9\x67\x12\x82\xfa\xfb\x69\xda\x92\x72\x8b"
"\x1a\x71\xde\x0a\x9e\x06\x0b\x29\x05\xd6\xa5\xb6\x7e\xcd\x3b\x36"
"\x92\xdd\xbd\x7f\x2d\x77\x8b\x8c\x98\x03\xae\xe3\x28\x09\x1b\x58"
"\xfa\xb3\x24\xe4\xfa\xd6\x75\x94\x55\x85\x80\x8b\x48\x31\xd7\xbc"
"\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" },
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[1024];
unsigned char tag[16];
int i, keylen;
gcry_error_t err = 0;
size_t pos, poslen, taglen2;
int byteNum;
if (verbose)
fprintf (stderr, " Starting POLY1305 checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (verbose)
fprintf (stderr, " checking POLY1305 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_POLY1305, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_POLY1305, 0);
if (err)
{
fail ("poly1305, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("poly1305, 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 ("poly1305, 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].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("poly1305, 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-poly1305, 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-poly1305, 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].aadlen; pos += step)
{
poslen = (pos + step < tv[i].aadlen) ? step : tv[i].aadlen - pos;
err = gcry_cipher_authenticate(hde, tv[i].aad + pos, poslen);
if (err)
{
fail ("poly1305, 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].aad + pos, poslen);
if (err)
{
fail ("poly1305, 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 ("poly1305, 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 ("poly1305, 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 ("poly1305, 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 ("poly1305, decrypt mismatch entry %d (step %d)\n", i, step);
err = gcry_cipher_gettag (hde, out, 16);
if (err)
{
fail ("poly1305, 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, 16))
fail ("poly1305, encrypt tag mismatch entry %d\n", i);
err = gcry_cipher_checktag (hdd, out, 16);
if (err)
{
fail ("poly1305, 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 ("poly1305, 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].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("poly1305, 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].aadlen; ++byteNum)
{
err = gcry_cipher_authenticate(hde, tv[i].aad + byteNum, 1);
if (err)
{
fail ("poly1305, 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].aad + byteNum, 1);
if (err)
{
fail ("poly1305, 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 ("poly1305, 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 ("poly1305, encrypt mismatch entry %d, (byte-buf)\n", i);
err = gcry_cipher_gettag (hde, tag, 16);
if (err)
{
fail ("poly1305, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n",
i, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (memcmp (tv[i].tag, tag, 16))
fail ("poly1305, 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 ("poly1305, 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 ("poly1305, decrypt mismatch entry %d\n", i);
err = gcry_cipher_checktag (hdd, tag, 16);
if (err)
{
fail ("poly1305, gcry_cipher_checktag(%d) (byte-buf) 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 POLY1305 checks.\n");
}
static void
check_poly1305_cipher (void)
{
/* Large buffers, no splitting. */
_check_poly1305_cipher(0xffffffff);
/* Split input to one byte buffers. */
_check_poly1305_cipher(1);
/* Split input to 7 byte buffers. */
_check_poly1305_cipher(7);
/* Split input to 16 byte buffers. */
_check_poly1305_cipher(16);
}
static void
check_ccm_cipher (void)
{
static const struct tv
{
int algo;
int keylen;
const char *key;
int noncelen;
const char *nonce;
int aadlen;
const char *aad;
int plainlen;
const char *plaintext;
int cipherlen;
const char *ciphertext;
} tv[] =
{
/* RFC 3610 */
{ GCRY_CIPHER_AES, /* 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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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"},
/* RFC 5528 */
{ GCRY_CIPHER_CAMELLIA128, /* 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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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 */
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",
23,
"\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 */
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",
24,
"\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 */
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",
25,
"\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 */
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",
19,
"\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 */
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",
20,
"\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 */
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",
21,
"\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"}
};
static const int cut[] = { 0, 1, 8, 10, 16, 19, -1 };
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
u64 ctl_params[3];
int split, aadsplit;
size_t j, i, keylen, blklen, authlen, taglen2;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting CCM checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
if (verbose)
fprintf (stderr, " checking CCM mode for %s [%i]\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo);
for (j = 0; j < sizeof (cut) / sizeof (cut[0]); j++)
{
split = cut[j] < 0 ? tv[i].plainlen : cut[j];
if (tv[i].plainlen < split)
continue;
err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CCM, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CCM, 0);
if (err)
{
fail ("cipher-ccm, gcry_cipher_open failed: %s\n",
gpg_strerror (err));
return;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("cipher-ccm, 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 ("cipher-ccm, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("cipher-ccm, gcry_cipher_get_algo_blklen failed\n");
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 ("cipher-ccm, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
authlen = tv[i].cipherlen - tv[i].plainlen;
ctl_params[0] = tv[i].plainlen; /* encryptedlen */
ctl_params[1] = tv[i].aadlen; /* aadlen */
ctl_params[2] = authlen; /* authtaglen */
err = gcry_cipher_ctl (hde, GCRYCTL_SET_CCM_LENGTHS, ctl_params,
sizeof(ctl_params));
if (!err)
err = gcry_cipher_ctl (hdd, GCRYCTL_SET_CCM_LENGTHS, ctl_params,
sizeof(ctl_params));
if (err)
{
fail ("cipher-ccm, gcry_cipher_ctl GCRYCTL_SET_CCM_LENGTHS "
"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-ccm, gcryctl_get_taglen failed (tv %lu): %s\n",
(unsigned long) i, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (taglen2 != authlen)
{
fail ("cipher-ccm, gcryctl_get_taglen returned bad length"
" (tv %lu): got=%zu want=%zu\n",
(unsigned long) i, taglen2, authlen);
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
aadsplit = split > tv[i].aadlen ? 0 : split;
err = gcry_cipher_authenticate (hde, tv[i].aad,
tv[i].aadlen - aadsplit);
if (!err)
err = gcry_cipher_authenticate (hde,
&tv[i].aad[tv[i].aadlen - aadsplit],
aadsplit);
if (!err)
err = gcry_cipher_authenticate (hdd, tv[i].aad,
tv[i].aadlen - aadsplit);
if (!err)
err = gcry_cipher_authenticate (hdd,
&tv[i].aad[tv[i].aadlen - aadsplit],
aadsplit);
if (err)
{
fail ("cipher-ccm, gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, tv[i].plaintext,
tv[i].plainlen - split);
if (!err)
err = gcry_cipher_encrypt (hde, &out[tv[i].plainlen - split],
MAX_DATA_LEN - (tv[i].plainlen - split),
&tv[i].plaintext[tv[i].plainlen - split],
split);
if (err)
{
fail ("cipher-ccm, gcry_cipher_encrypt (%lu:%lu) failed: %s\n",
(unsigned long) i, (unsigned long) j, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_gettag (hde, &out[tv[i].plainlen], authlen);
if (err)
{
fail ("cipher-ccm, gcry_cipher_gettag (%lu:%lu) failed: %s\n",
(unsigned long) i, (unsigned long) j, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (memcmp (tv[i].ciphertext, out, tv[i].cipherlen))
fail ("cipher-ccm, encrypt mismatch entry %lu:%lu\n",
(unsigned long) i, (unsigned long) j);
err = gcry_cipher_decrypt (hdd, out, tv[i].plainlen - split, NULL, 0);
if (!err)
err = gcry_cipher_decrypt (hdd, &out[tv[i].plainlen - split], split,
NULL, 0);
if (err)
{
fail ("cipher-ccm, gcry_cipher_decrypt (%lu:%lu) failed: %s\n",
(unsigned long) i, (unsigned long) j, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (memcmp (tv[i].plaintext, out, tv[i].plainlen))
fail ("cipher-ccm, decrypt mismatch entry %lu:%lu\n",
(unsigned long) i, (unsigned long) j);
err = gcry_cipher_checktag (hdd, &out[tv[i].plainlen], authlen);
if (err)
{
fail ("cipher-ccm, gcry_cipher_checktag (%lu:%lu) failed: %s\n",
(unsigned long) i, (unsigned long) j, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
}
/* Large buffer tests. */
/* Test encoding of aadlen > 0xfeff. */
{
static const char key[]={0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
static const char iv[]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19};
static const char tag[]={0x9C,0x76,0xE7,0x33,0xD5,0x15,0xB3,0x6C,
0xBA,0x76,0x95,0xF7,0xFB,0x91};
char buf[1024];
size_t enclen = 0x20000;
size_t aadlen = 0x20000;
size_t taglen = sizeof(tag);
err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CCM, 0);
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_open failed: %s\n",
gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hde, key, sizeof (key));
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
err = gcry_cipher_setiv (hde, iv, sizeof (iv));
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
ctl_params[0] = enclen; /* encryptedlen */
ctl_params[1] = aadlen; /* aadlen */
ctl_params[2] = taglen; /* authtaglen */
err = gcry_cipher_ctl (hde, GCRYCTL_SET_CCM_LENGTHS, ctl_params,
sizeof(ctl_params));
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_ctl GCRYCTL_SET_CCM_LENGTHS "
"failed: %s\n", gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
memset (buf, 0xaa, sizeof(buf));
for (i = 0; i < aadlen; i += sizeof(buf))
{
err = gcry_cipher_authenticate (hde, buf, sizeof (buf));
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
}
for (i = 0; i < enclen; i += sizeof(buf))
{
memset (buf, 0xee, sizeof(buf));
err = gcry_cipher_encrypt (hde, buf, sizeof (buf), NULL, 0);
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
}
err = gcry_cipher_gettag (hde, buf, taglen);
if (err)
{
fail ("cipher-ccm-large, gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
if (memcmp (buf, tag, taglen) != 0)
fail ("cipher-ccm-large, encrypt mismatch entry\n");
gcry_cipher_close (hde);
}
#if 0
/* Test encoding of aadlen > 0xffffffff. */
{
static const char key[]={0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
static const char iv[]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19};
static const char tag[]={0x01,0xB2,0xC3,0x4A,0xA6,0x6A,0x07,0x6D,
0xBC,0xBD,0xEA,0x17,0xD3,0x73,0xD7,0xD4};
char buf[1024];
size_t enclen = (size_t)0xffffffff + 1 + 1024;
size_t aadlen = (size_t)0xffffffff + 1 + 1024;
size_t taglen = sizeof(tag);
err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CCM, 0);
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_open failed: %s\n",
gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hde, key, sizeof (key));
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
err = gcry_cipher_setiv (hde, iv, sizeof (iv));
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
ctl_params[0] = enclen; /* encryptedlen */
ctl_params[1] = aadlen; /* aadlen */
ctl_params[2] = taglen; /* authtaglen */
err = gcry_cipher_ctl (hde, GCRYCTL_SET_CCM_LENGTHS, ctl_params,
sizeof(ctl_params));
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_ctl GCRYCTL_SET_CCM_LENGTHS failed:"
"%s\n", gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
memset (buf, 0xaa, sizeof(buf));
for (i = 0; i < aadlen; i += sizeof(buf))
{
err = gcry_cipher_authenticate (hde, buf, sizeof (buf));
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
}
for (i = 0; i < enclen; i += sizeof(buf))
{
memset (buf, 0xee, sizeof(buf));
err = gcry_cipher_encrypt (hde, buf, sizeof (buf), NULL, 0);
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
}
err = gcry_cipher_gettag (hde, buf, taglen);
if (err)
{
fail ("cipher-ccm-huge, gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
if (memcmp (buf, tag, taglen) != 0)
fail ("cipher-ccm-huge, encrypt mismatch entry\n");
gcry_cipher_close (hde);
}
if (verbose)
fprintf (stderr, " Completed CCM checks.\n");
#endif
}
static void
do_check_ocb_cipher (int inplace)
{
/* Note that we use hex strings and not binary strings in TV. That
makes it easier to maintain the test vectors. */
static const struct
{
int algo;
int taglen; /* 16, 12, or 8 bytes */
const char *key; /* NULL means "000102030405060708090A0B0C0D0E0F" */
const char *nonce;
const char *aad;
const char *plain;
const char *ciph;
} tv[] = {
/* The RFC-7253 test vectos*/
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221100",
"",
"",
"785407BFFFC8AD9EDCC5520AC9111EE6"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221101",
"0001020304050607",
"0001020304050607",
"6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221102",
"0001020304050607",
"",
"81017F8203F081277152FADE694A0A00"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221103",
"",
"0001020304050607",
"45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221104",
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F",
"571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5"
"701C1CCEC8FC3358"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221105",
"000102030405060708090A0B0C0D0E0F",
"",
"8CF761B6902EF764462AD86498CA6B97"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221106",
"",
"000102030405060708090A0B0C0D0E0F",
"5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436B"
"DF06D8FA1ECA343D"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221107",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"1CA2207308C87C010756104D8840CE1952F09673A448A122"
"C92C62241051F57356D7F3C90BB0E07F"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221108",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"",
"6DC225A071FC1B9F7C69F93B0F1E10DE"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA99887766554433221109",
"",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3C"
"E725F32494B9F914D85C0B1EB38357FF"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110A",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F",
"BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE"
"AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110B",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F",
"",
"FE80690BEE8A485D11F32965BC9D2A32"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110C",
"",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F",
"2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4"
"6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460"
"6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483"
"A7035490C5769E60"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110E",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"",
"C5CD9D1850C141E358649994EE701B68"
},
{ GCRY_CIPHER_AES, 16, NULL,
"BBAA9988776655443322110F",
"",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15"
"A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95"
"A98CA5F3000B1479"
},
{ GCRY_CIPHER_AES, 12, "0F0E0D0C0B0A09080706050403020100",
"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627",
"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[1024];
unsigned char tag[16];
int tidx;
if (verbose)
fprintf (stderr, " Starting OCB checks.\n");
for (tidx = 0; tidx < DIM (tv); tidx++)
{
char *key, *nonce, *aad, *ciph, *plain;
size_t keylen, noncelen, aadlen, ciphlen, plainlen;
int taglen;
size_t taglen2;
if (verbose)
fprintf (stderr, " checking OCB mode for %s [%i] (tv %d)\n",
gcry_cipher_algo_name (tv[tidx].algo), tv[tidx].algo, tidx);
/* Convert to hex strings to binary. */
key = hex2buffer (tv[tidx].key? tv[tidx].key
/* */: "000102030405060708090A0B0C0D0E0F",
&keylen);
nonce = hex2buffer (tv[tidx].nonce, &noncelen);
aad = hex2buffer (tv[tidx].aad, &aadlen);
plain = hex2buffer (tv[tidx].plain, &plainlen);
ciph = hex2buffer (tv[tidx].ciph, &ciphlen);
/* Check that our test vectors are sane. */
assert (plainlen <= sizeof out);
assert (tv[tidx].taglen <= ciphlen);
assert (tv[tidx].taglen <= sizeof tag);
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);
if (err)
{
fail ("cipher-ocb, gcry_cipher_open failed (tv %d): %s\n",
tidx, gpg_strerror (err));
return;
}
/* Set the taglen. For the first handle we do this only for a
non-default taglen. For the second handle we check that we
can also set to the default taglen. */
taglen = tv[tidx].taglen;
if (taglen != 16)
{
err = gcry_cipher_ctl (hde, GCRYCTL_SET_TAGLEN,
&taglen, sizeof taglen);
if (err)
{
fail ("cipher-ocb, gcryctl_set_taglen failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
}
err = gcry_cipher_ctl (hdd, GCRYCTL_SET_TAGLEN,
&taglen, sizeof taglen);
if (err)
{
fail ("cipher-ocb, gcryctl_set_taglen failed (tv %d): %s\n",
tidx, 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-ocb, gcryctl_get_taglen failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
if (taglen2 != tv[tidx].taglen)
{
fail ("cipher-ocb, gcryctl_get_taglen returned bad length (tv %d): "
"got=%zu want=%d\n",
tidx, taglen2, tv[tidx].taglen);
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_setkey (hde, key, keylen);
if (!err)
err = gcry_cipher_setkey (hdd, key, keylen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_setkey failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_setiv (hde, nonce, noncelen);
if (!err)
err = gcry_cipher_setiv (hdd, nonce, noncelen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_setiv failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_authenticate (hde, aad, aadlen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_authenticate failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_final (hde);
if (!err)
{
if (inplace)
{
memcpy(out, plain, plainlen);
err = gcry_cipher_encrypt (hde, out, plainlen, NULL, 0);
}
else
{
err = gcry_cipher_encrypt (hde, out, sizeof(out),
plain, plainlen);
}
}
if (err)
{
fail ("cipher-ocb, gcry_cipher_encrypt failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
/* Check that the encrypt output matches the expected cipher
text without the tag (i.e. at the length of plaintext). */
if (memcmp (ciph, out, plainlen))
{
mismatch (ciph, plainlen, out, plainlen);
fail ("cipher-ocb, encrypt data mismatch (tv %d)\n", tidx);
}
/* Check that the tag matches TAGLEN bytes from the end of the
expected ciphertext. */
err = gcry_cipher_gettag (hde, tag, tv[tidx].taglen);
if (err)
{
fail ("cipher_ocb, gcry_cipher_gettag failed (tv %d): %s\n",
tidx, gpg_strerror (err));
}
if (memcmp (ciph + ciphlen - tv[tidx].taglen, tag, tv[tidx].taglen))
{
mismatch (ciph + ciphlen - tv[tidx].taglen, tv[tidx].taglen,
tag, tv[tidx].taglen);
fail ("cipher-ocb, encrypt tag mismatch (tv %d)\n", tidx);
}
err = gcry_cipher_authenticate (hdd, aad, aadlen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_authenticate failed (tv %d): %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
/* Now for the decryption. */
err = gcry_cipher_final (hdd);
if (!err)
{
if (inplace)
{
err = gcry_cipher_decrypt (hdd, out, plainlen, NULL, 0);
}
else
{
unsigned char tmp[sizeof(out)];
memcpy(tmp, out, plainlen);
err = gcry_cipher_decrypt (hdd, out, plainlen, tmp, plainlen);
}
}
if (err)
{
fail ("cipher-ocb, gcry_cipher_decrypt (tv %d) failed: %s\n",
tidx, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
/* We still have TAG from the encryption. */
err = gcry_cipher_checktag (hdd, tag, tv[tidx].taglen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_checktag failed (tv %d): %s\n",
tidx, gpg_strerror (err));
}
/* Check that the decrypt output matches the original plaintext. */
if (memcmp (plain, out, plainlen))
{
mismatch (plain, plainlen, out, plainlen);
fail ("cipher-ocb, decrypt data mismatch (tv %d)\n", tidx);
}
/* Check that gettag also works for decryption. */
err = gcry_cipher_gettag (hdd, tag, tv[tidx].taglen);
if (err)
{
fail ("cipher_ocb, decrypt gettag failed (tv %d): %s\n",
tidx, gpg_strerror (err));
}
if (memcmp (ciph + ciphlen - tv[tidx].taglen, tag, tv[tidx].taglen))
{
mismatch (ciph + ciphlen - tv[tidx].taglen, tv[tidx].taglen,
tag, tv[tidx].taglen);
fail ("cipher-ocb, decrypt tag mismatch (tv %d)\n", tidx);
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
xfree (nonce);
xfree (aad);
xfree (ciph);
xfree (plain);
xfree (key);
}
if (verbose)
fprintf (stderr, " Completed OCB checks.\n");
}
static void
check_ocb_cipher_largebuf_split (int algo, int keylen, const char *tagexpect,
unsigned int splitpos)
{
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 = 1024 * 1024 * 2 + 32;
unsigned char *inbuf;
unsigned char *outbuf;
gpg_error_t err = 0;
gcry_cipher_hd_t hde, hdd;
unsigned char tag[16];
int i;
inbuf = xmalloc(buflen);
if (!inbuf)
{
fail ("out-of-memory\n");
return;
}
outbuf = xmalloc(buflen);
if (!outbuf)
{
fail ("out-of-memory\n");
xfree(inbuf);
return;
}
for (i = 0; i < buflen; i++)
inbuf[i] = (i + 181081) * 5039;
err = gcry_cipher_open (&hde, 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 (large, algo %d): %s\n",
algo, gpg_strerror (err));
goto out_free;
}
err = gcry_cipher_setkey (hde, key, keylen);
if (!err)
err = gcry_cipher_setkey (hdd, key, keylen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_setkey failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
goto out_free;
}
err = gcry_cipher_setiv (hde, nonce, 12);
if (!err)
err = gcry_cipher_setiv (hdd, nonce, 12);
if (err)
{
fail ("cipher-ocb, gcry_cipher_setiv failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
goto out_free;
}
if (splitpos)
{
err = gcry_cipher_authenticate (hde, inbuf, splitpos);
}
if (!err)
{
err = gcry_cipher_authenticate (hde, inbuf + splitpos, buflen - splitpos);
}
if (err)
{
fail ("cipher-ocb, gcry_cipher_authenticate failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
goto out_free;
}
if (splitpos)
{
err = gcry_cipher_encrypt (hde, outbuf, splitpos, inbuf, splitpos);
}
if (!err)
{
err = gcry_cipher_final (hde);
if (!err)
{
err = gcry_cipher_encrypt (hde, outbuf + splitpos, buflen - splitpos,
inbuf + splitpos, buflen - splitpos);
}
}
if (err)
{
fail ("cipher-ocb, gcry_cipher_encrypt failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
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 (large, algo %d): %s\n",
algo, gpg_strerror (err));
}
if (memcmp (tagexpect, tag, 16))
{
mismatch (tagexpect, 16, tag, 16);
fail ("cipher-ocb, encrypt tag mismatch (large, algo %d)\n", algo);
}
err = gcry_cipher_authenticate (hdd, inbuf, buflen);
if (err)
{
fail ("cipher-ocb, gcry_cipher_authenticate failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
goto out_free;
}
/* Now for the decryption. */
if (splitpos)
{
err = gcry_cipher_decrypt (hdd, outbuf, splitpos, NULL, 0);
}
if (!err)
{
err = gcry_cipher_final (hdd);
if (!err)
{
err = gcry_cipher_decrypt (hdd, outbuf + splitpos, buflen - splitpos,
NULL, 0);
}
}
if (err)
{
fail ("cipher-ocb, gcry_cipher_decrypt (large, algo %d) failed: %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
goto out_free;
}
/* We still have TAG from the encryption. */
err = gcry_cipher_checktag (hdd, tag, 16);
if (err)
{
fail ("cipher-ocb, gcry_cipher_checktag failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
}
/* Check that the decrypt output matches the original plaintext. */
if (memcmp (inbuf, outbuf, buflen))
{
/*mismatch (inbuf, buflen, outbuf, buflen);*/
fail ("cipher-ocb, decrypt data mismatch (large, algo %d)\n", algo);
}
/* Check that gettag also works for decryption. */
err = gcry_cipher_gettag (hdd, tag, 16);
if (err)
{
fail ("cipher_ocb, decrypt gettag failed (large, algo %d): %s\n",
algo, gpg_strerror (err));
}
if (memcmp (tagexpect, tag, 16))
{
mismatch (tagexpect, 16, tag, 16);
fail ("cipher-ocb, decrypt tag mismatch (large, algo %d)\n", algo);
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
out_free:
xfree(outbuf);
xfree(inbuf);
}
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;
unsigned char tag[16];
unsigned char tag2[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;
}
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)
{
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)
{
fail ("cipher-ocb, gcry_cipher_setkey failed (checksum, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hde2);
goto out_free;
}
err = gcry_cipher_setiv (hde, nonce, 12);
if (!err)
err = gcry_cipher_setiv (hde2, 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);
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)
{
fail ("cipher-ocb, gcry_cipher_encrypt failed (checksum, algo %d): %s\n",
algo, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hde2);
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));
}
if (memcmp (tag, tag2, 16))
{
mismatch (tag, 16, tag2, 16);
fail ("cipher-ocb, encrypt tag mismatch (checksum, algo %d)\n", algo);
}
gcry_cipher_close (hde);
gcry_cipher_close (hde2);
out_free:
xfree(inbuf);
xfree(outbuf);
}
static void
check_ocb_cipher_largebuf (int algo, int keylen, const char *tagexpect)
{
unsigned int split;
for (split = 0; split < 32 * 16; split = split * 2 + 16)
{
check_ocb_cipher_largebuf_split(algo, keylen, tagexpect, split);
}
check_ocb_cipher_checksum(algo, keylen);
}
static void
check_ocb_cipher_splitaad (void)
{
const char t_nonce[] = ("BBAA9988776655443322110D");
const char t_plain[] = ("000102030405060708090A0B0C0D0E0F1011121314151617"
"18191A1B1C1D1E1F2021222324252627");
const char t_ciph[] = ("D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460"
"6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483"
"A7035490C5769E60");
struct {
const char *aad0;
const char *aad1;
const char *aad2;
const char *aad3;
} tv[] = {
{
"000102030405060708090A0B0C0D0E0F"
"101112131415161718191A1B1C1D1E1F2021222324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"2021222324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"1011121314151617",
"18191A1B1C1D1E1F",
"2021222324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"20",
"21222324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"2021",
"222324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"202122",
"2324252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"20212223",
"24252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"2021222324",
"252627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"202122232425",
"2627"
},
{
"000102030405060708090A0B0C0D0E0F",
"101112131415161718191A1B1C1D1E1F",
"20212223242526"
"27"
},
{
"000102030405060708090A0B0C0D0E0F",
"1011121314151617",
"18191A1B1C1D1E1F2021222324252627"
},
{
"00",
"0102030405060708090A0B0C0D0E0F",
"1011121314151617",
"18191A1B1C1D1E1F2021222324252627"
},
{
"0001",
"02030405060708090A0B0C0D0E0F",
"1011121314151617",
"18191A1B1C1D1E1F2021222324252627"
},
{
"000102030405060708090A0B0C0D",
"0E0F",
"1011121314151617",
"18191A1B1C1D1E1F2021222324252627"
},
{
"000102030405060708090A0B0C0D0E",
"0F",
"1011121314151617",
"18191A1B1C1D1E1F2021222324252627"
},
{
"000102030405060708090A0B0C0D0E",
"0F101112131415161718191A1B1C1D1E1F20212223242526",
"27"
}
};
gpg_error_t err = 0;
gcry_cipher_hd_t hde;
unsigned char out[MAX_DATA_LEN];
unsigned char tag[16];
int tidx;
char *key, *nonce, *ciph, *plain;
size_t keylen, noncelen, ciphlen, plainlen;
int i;
/* Convert to hex strings to binary. */
key = hex2buffer ("000102030405060708090A0B0C0D0E0F", &keylen);
nonce = hex2buffer (t_nonce, &noncelen);
plain = hex2buffer (t_plain, &plainlen);
ciph = hex2buffer (t_ciph, &ciphlen);
/* Check that our test vectors are sane. */
assert (plainlen <= sizeof out);
assert (16 <= ciphlen);
assert (16 <= sizeof tag);
for (tidx = 0; tidx < DIM (tv); tidx++)
{
char *aad[4];
size_t aadlen[4];
if (verbose)
fprintf (stderr, " checking OCB aad split (tv %d)\n", tidx);
aad[0] = tv[tidx].aad0? hex2buffer (tv[tidx].aad0, aadlen+0) : NULL;
aad[1] = tv[tidx].aad1? hex2buffer (tv[tidx].aad1, aadlen+1) : NULL;
aad[2] = tv[tidx].aad2? hex2buffer (tv[tidx].aad2, aadlen+2) : NULL;
aad[3] = tv[tidx].aad3? hex2buffer (tv[tidx].aad3, aadlen+3) : NULL;
err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB, 0);
if (err)
{
fail ("cipher-ocb-splitadd, gcry_cipher_open failed: %s\n",
gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hde, key, keylen);
if (err)
{
fail ("cipher-ocb-splitaad, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
err = gcry_cipher_setiv (hde, nonce, noncelen);
if (err)
{
fail ("cipher-ocb-splitaad, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
for (i=0; i < DIM (aad); i++)
{
if (!aad[i])
continue;
err = gcry_cipher_authenticate (hde, aad[i], aadlen[i]);
if (err)
{
fail ("cipher-ocb-splitaad,"
" gcry_cipher_authenticate failed (tv=%d,i=%d): %s\n",
tidx, i, gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
}
err = gcry_cipher_final (hde);
if (!err)
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, plain, plainlen);
if (err)
{
fail ("cipher-ocb-splitaad, gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
return;
}
/* Check that the encrypt output matches the expected cipher
text without the tag (i.e. at the length of plaintext). */
if (memcmp (ciph, out, plainlen))
{
mismatch (ciph, plainlen, out, plainlen);
fail ("cipher-ocb-splitaad, encrypt data mismatch\n");
}
/* Check that the tag matches TAGLEN bytes from the end of the
expected ciphertext. */
err = gcry_cipher_gettag (hde, tag, 16);
if (err)
{
fail ("cipher-ocb-splitaad, gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
}
if (memcmp (ciph + ciphlen - 16, tag, 16))
{
mismatch (ciph + ciphlen - 16, 16, tag, 16);
fail ("cipher-ocb-splitaad, encrypt tag mismatch\n");
}
gcry_cipher_close (hde);
xfree (aad[0]);
xfree (aad[1]);
xfree (aad[2]);
xfree (aad[3]);
}
xfree (nonce);
xfree (ciph);
xfree (plain);
xfree (key);
}
static void
check_ocb_cipher (void)
{
/* Check OCB cipher with separate destination and source buffers for
* encryption/decryption. */
do_check_ocb_cipher(0);
/* Check OCB cipher with inplace encrypt/decrypt. */
do_check_ocb_cipher(1);
/* Check large buffer encryption/decryption. */
check_ocb_cipher_largebuf(GCRY_CIPHER_AES, 16,
"\xc1\x5b\xf1\x80\xa4\xd5\xea\xfd\xae\x17\xa6\xcd\x6b\x10\xa8\xea");
check_ocb_cipher_largebuf(GCRY_CIPHER_AES256, 32,
"\x2b\xb7\x25\x6b\x77\xc7\xfb\x21\x5c\xc9\x6c\x36\x17\x1a\x1a\xd5");
check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA128, 16,
"\xe0\xae\x3f\x29\x3a\xee\xd8\xe3\xf2\x20\xc1\xa2\xd8\x72\x12\xd9");
check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA192, 24,
"\xd7\x98\x71\xcf\x19\x5c\xa3\x3d\x6c\xfc\xc9\xbe\x9f\x13\x6b\xbd");
check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA256, 32,
"\x03\xf6\xec\x1a\x0e\xae\x66\x24\x2b\xba\x26\x0f\xb3\xb3\x1f\xb9");
check_ocb_cipher_largebuf(GCRY_CIPHER_TWOFISH, 16,
"\x1c\xf9\xc7\xfc\x3a\x32\xac\xc7\x5e\x0a\xc2\x5c\x90\xd6\xf6\xf9");
check_ocb_cipher_largebuf(GCRY_CIPHER_TWOFISH, 32,
"\x53\x02\xc8\x0d\x4e\x9a\x44\x9e\x43\xd4\xaa\x06\x30\x93\xcc\x16");
check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT128, 16,
"\xd3\x64\xac\x40\x48\x88\x77\xe2\x41\x26\x4c\xde\x21\x29\x21\x8d");
check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT192, 24,
"\x99\xeb\x35\xb0\x62\x4e\x7b\xf1\x5e\x9f\xed\x32\x78\x90\x0b\xd0");
check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT256, 32,
"\x71\x66\x2f\x68\xbf\xdd\xcc\xb1\xbf\x81\x56\x5f\x01\x73\xeb\x44");
/* Check that the AAD data is correctly buffered. */
check_ocb_cipher_splitaad ();
}
static void
do_check_xts_cipher (int inplace)
{
/* Note that we use hex strings and not binary strings in TV. That
makes it easier to maintain the test vectors. */
static const struct
{
int algo;
const char *key; /* NULL means "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" */
const char *iv;
const char *plain;
const char *ciph;
} tv[] = {
/* CAVS; hex/XTSGenAES128.rsp; COUNT=100 */
{ GCRY_CIPHER_AES,
"bcb6613c495de4bdad9c19f04e4b3915f9ecb379e1a575b633337e934fca1050",
"64981173159d58ac355a20120c8e81f1",
"189acacee06dfa7c94484c7dae59e166",
"7900191d0f19a97668fdba9def84eedc"
},
/* CAVS; hex/XTSGenAES128.rsp; COUNT=101 */
{ GCRY_CIPHER_AES,
"b7b93f516aef295eff3a29d837cf1f135347e8a21dae616ff5062b2e8d78ce5e",
"873edea653b643bd8bcf51403197ed14",
"236f8a5b58dd55f6194ed70c4ac1a17f1fe60ec9a6c454d087ccb77d6b638c47",
"22e6a3c6379dcf7599b052b5a749c7f78ad8a11b9f1aa9430cf3aef445682e19"
},
/* CAVS; hex/XTSGenAES128.rsp; COUNT=301 */
{ GCRY_CIPHER_AES,
"394c97881abd989d29c703e48a72b397a7acf51b59649eeea9b33274d8541df4",
"4b15c684a152d485fe9937d39b168c29",
"2f3b9dcfbae729583b1d1ffdd16bb6fe2757329435662a78f0",
"f3473802e38a3ffef4d4fb8e6aa266ebde553a64528a06463e"
},
/* CAVS; hex/XTSGenAES128.rsp; COUNT=500 */
{ GCRY_CIPHER_AES,
"783a83ec52a27405dff9de4c57f9c979b360b6a5df88d67ec1a052e6f582a717",
"886e975b29bdf6f0c01bb47f61f6f0f5",
"b04d84da856b9a59ce2d626746f689a8051dacd6bce3b990aa901e4030648879",
"f941039ebab8cac39d59247cbbcb4d816c726daed11577692c55e4ac6d3e6820"
},
/* CAVS; hex/XTSGenAES256.rsp; COUNT=1 */
{ GCRY_CIPHER_AES256,
"1ea661c58d943a0e4801e42f4b0947149e7f9f8e3e68d0c7505210bd311a0e7c"
"d6e13ffdf2418d8d1911c004cda58da3d619b7e2b9141e58318eea392cf41b08",
"adf8d92627464ad2f0428e84a9f87564",
"2eedea52cd8215e1acc647e810bbc3642e87287f8d2e57e36c0a24fbc12a202e",
"cbaad0e2f6cea3f50b37f934d46a9b130b9d54f07e34f36af793e86f73c6d7db"
},
/* CAVS; hex/XTSGenAES256.rsp; COUNT=101 */
{ GCRY_CIPHER_AES256,
"266c336b3b01489f3267f52835fd92f674374b88b4e1ebd2d36a5f457581d9d0"
"42c3eef7b0b7e5137b086496b4d9e6ac658d7196a23f23f036172fdb8faee527",
"06b209a7a22f486ecbfadb0f3137ba42",
"ca7d65ef8d3dfad345b61ccddca1ad81de830b9e86c7b426d76cb7db766852d9"
"81c6b21409399d78f42cc0b33a7bbb06",
"c73256870cc2f4dd57acc74b5456dbd776912a128bc1f77d72cdebbf270044b7"
"a43ceed29025e1e8be211fa3c3ed002d"
},
/* CAVS; hex/XTSGenAES256.rsp; COUNT=401 */
{ GCRY_CIPHER_AES256,
"33e89e817ff8d037d6ac5a2296657503f20885d94c483e26449066bd9284d130"
"2dbdbb4b66b6b9f4687f13dd028eb6aa528ca91deb9c5f40db93218806033801",
"a78c04335ab7498a52b81ed74b48e6cf",
"14c3ac31291b075f40788247c3019e88c7b40bac3832da45bbc6c4fe7461371b"
"4dfffb63f71c9f8edb98f28ff4f33121",
"dead7e587519bc78c70d99279fbe3d9b1ad13cdaae69824e0ab8135413230bfd"
"b13babe8f986fbb30d46ab5ec56b916e"
},
/* From https://github.com/heisencoder/XTS-AES/blob/master/testvals/ */
{ GCRY_CIPHER_AES,
"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0",
"9a785634120000000000000000000000",
"000102030405060708090a0b0c0d0e0f10",
"7fb2e8beccbb5c118aa52ddca31220bb1b"
},
{ GCRY_CIPHER_AES,
"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0",
"9a785634120000000000000000000000",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e",
"d05bc090a8e04f1b3d3ecdd5baec0fd4edbf9dace45d6f6a7306e64be5dd82"
},
{ GCRY_CIPHER_AES,
"2718281828459045235360287471352631415926535897932384626433832795",
"00000000000000000000000000000000",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"
"20212223",
"27A7479BEFA1D476489F308CD4CFA6E288F548E5C4239F91712A587E2B05AC3D"
"A96E4BBE"
},
{ GCRY_CIPHER_AES256,
"2718281828459045235360287471352662497757247093699959574966967627"
"3141592653589793238462643383279502884197169399375105820974944592",
"11000000000000000000000000000000",
"3A060A8CAD115A6F44572E3759E43C8F8832FEDC28A8E35B357B5CF3EDBEF788"
"CAD8BFCB23",
"6D1C78A8BAD91DB2924C507CCEDE835F5BADD157DA0AF55C98BBC28CF676F9FA"
"61618FA696"
},
{ GCRY_CIPHER_AES256,
"2718281828459045235360287471352662497757247093699959574966967627"
"3141592653589793238462643383279502884197169399375105820974944592",
"11000000000000000000000000000000",
"3A060A8CAD115A6F44572E3759E43C8F8832FEDC28A8E35B357B5CF3EDBEF788"
"CAD8BFCB23",
"6D1C78A8BAD91DB2924C507CCEDE835F5BADD157DA0AF55C98BBC28CF676F9FA"
"61618FA696"
},
{ GCRY_CIPHER_AES,
"e0e1e2e3e4e5e6e7e8e9eaebecedeeefc0c1c2c3c4c5c6c7c8c9cacbcccdcecf",
"21436587a90000000000000000000000",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
"0001020304050607",
"38b45812ef43a05bd957e545907e223b954ab4aaf088303ad910eadf14b42be6"
"8b2461149d8c8ba85f992be970bc621f1b06573f63e867bf5875acafa04e42cc"
"bd7bd3c2a0fb1fff791ec5ec36c66ae4ac1e806d81fbf709dbe29e471fad3854"
"9c8e66f5345d7c1eb94f405d1ec785cc6f6a68f6254dd8339f9d84057e01a177"
"41990482999516b5611a38f41bb6478e6f173f320805dd71b1932fc333cb9ee3"
"9936beea9ad96fa10fb4112b901734ddad40bc1878995f8e11aee7d141a2f5d4"
"8b7a4e1e7f0b2c04830e69a4fd1378411c2f287edf48c6c4e5c247a19680f7fe"
"41cefbd49b582106e3616cbbe4dfb2344b2ae9519391f3e0fb4922254b1d6d2d"
"19c6d4d537b3a26f3bcc51588b32f3eca0829b6a5ac72578fb814fb43cf80d64"
"a233e3f997a3f02683342f2b33d25b492536b93becb2f5e1a8b82f5b88334272"
"9e8ae09d16938841a21a97fb543eea3bbff59f13c1a18449e398701c1ad51648"
"346cbc04c27bb2da3b93a1372ccae548fb53bee476f9e9c91773b1bb19828394"
"d55d3e1a20ed69113a860b6829ffa847224604435070221b257e8dff783615d2"
"cae4803a93aa4334ab482a0afac9c0aeda70b45a481df5dec5df8cc0f423c77a"
"5fd46cd312021d4b438862419a791be03bb4d97c0e59578542531ba466a83baf"
"92cefc151b5cc1611a167893819b63fb37ec662bc0fc907db74a94468a55a7bc"
"8a6b18e86de60290"
},
{ GCRY_CIPHER_AES256,
"2718281828459045235360287471352662497757247093699959574966967627"
"3141592653589793238462643383279502884197169399375105820974944592",
"ffffffff000000000000000000000000",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
"bf53d2dade78e822a4d949a9bc6766b01b06a8ef70d26748c6a7fc36d80ae4c5"
"520f7c4ab0ac8544424fa405162fef5a6b7f229498063618d39f0003cb5fb8d1"
"c86b643497da1ff945c8d3bedeca4f479702a7a735f043ddb1d6aaade3c4a0ac"
"7ca7f3fa5279bef56f82cd7a2f38672e824814e10700300a055e1630b8f1cb0e"
"919f5e942010a416e2bf48cb46993d3cb6a51c19bacf864785a00bc2ecff15d3"
"50875b246ed53e68be6f55bd7e05cfc2b2ed6432198a6444b6d8c247fab941f5"
"69768b5c429366f1d3f00f0345b96123d56204c01c63b22ce78baf116e525ed9"
"0fdea39fa469494d3866c31e05f295ff21fea8d4e6e13d67e47ce722e9698a1c"
"1048d68ebcde76b86fcf976eab8aa9790268b7068e017a8b9b749409514f1053"
"027fd16c3786ea1bac5f15cb79711ee2abe82f5cf8b13ae73030ef5b9e4457e7"
"5d1304f988d62dd6fc4b94ed38ba831da4b7634971b6cd8ec325d9c61c00f1df"
"73627ed3745a5e8489f3a95c69639c32cd6e1d537a85f75cc844726e8a72fc00"
"77ad22000f1d5078f6b866318c668f1ad03d5a5fced5219f2eabbd0aa5c0f460"
"d183f04404a0d6f469558e81fab24a167905ab4c7878502ad3e38fdbe62a4155"
"6cec37325759533ce8f25f367c87bb5578d667ae93f9e2fd99bcbc5f2fbba88c"
"f6516139420fcff3b7361d86322c4bd84c82f335abb152c4a93411373aaa8220"
}
};
gpg_error_t err = 0;
gcry_cipher_hd_t hde, hdd;
int tidx;
int got_err = 0;
if (verbose)
fprintf (stderr, " Starting XTS checks.\n");
for (tidx = 0; !got_err && tidx < DIM (tv); tidx++)
{
const char *hexkey = tv[tidx].key;
char *key, *iv, *ciph, *plain, *out;
size_t keylen, ivlen, ciphlen, plainlen, outlen;
if (verbose)
fprintf (stderr, " checking XTS mode for %s [%i] (tv %d)\n",
gcry_cipher_algo_name (tv[tidx].algo), tv[tidx].algo, tidx);
if (!hexkey)
hexkey = "000102030405060708090A0B0C0D0E0F"
"101112131415161718191A1B1C1D1E1F";
/* Convert to hex strings to binary. */
key = hex2buffer (hexkey, &keylen);
iv = hex2buffer (tv[tidx].iv, &ivlen);
plain = hex2buffer (tv[tidx].plain, &plainlen);
ciph = hex2buffer (tv[tidx].ciph, &ciphlen);
outlen = plainlen + 5;
out = xmalloc (outlen);
assert (plainlen == ciphlen);
assert (plainlen <= outlen);
assert (out);
err = gcry_cipher_open (&hde, tv[tidx].algo, GCRY_CIPHER_MODE_XTS, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[tidx].algo, GCRY_CIPHER_MODE_XTS, 0);
if (err)
{
fail ("cipher-xts, gcry_cipher_open failed (tv %d): %s\n",
tidx, gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hde, key, keylen);
if (err && in_fips_mode && memcmp(key, key + keylen/2, keylen/2) == 0)
{
/* Since both halves of key are the same, fail to set key in FIPS
mode is expected. */
goto next_tv;
}
if (!err)
err = gcry_cipher_setkey (hdd, key, keylen);
if (err)
{
fail ("cipher-xts, gcry_cipher_setkey failed (tv %d): %s\n",
tidx, gpg_strerror (err));
goto err_out;
}
err = gcry_cipher_setiv (hde, iv, ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, iv, ivlen);
if (err)
{
fail ("cipher-xts, gcry_cipher_setiv failed (tv %d): %s\n",
tidx, gpg_strerror (err));
goto err_out;
}
if (inplace)
{
memcpy(out, plain, plainlen);
err = gcry_cipher_encrypt (hde, out, plainlen, NULL, 0);
}
else
{
err = gcry_cipher_encrypt (hde, out, outlen, plain, plainlen);
}
if (err)
{
fail ("cipher-xts, gcry_cipher_encrypt failed (tv %d): %s\n",
tidx, gpg_strerror (err));
goto err_out;
}
/* Check that the encrypt output matches the expected cipher text. */
if (memcmp (ciph, out, plainlen))
{
mismatch (ciph, plainlen, out, plainlen);
fail ("cipher-xts, encrypt data mismatch (tv %d)\n", tidx);
}
/* Now for the decryption. */
if (inplace)
{
err = gcry_cipher_decrypt (hdd, out, plainlen, NULL, 0);
}
else
{
memcpy(ciph, out, ciphlen);
err = gcry_cipher_decrypt (hdd, out, plainlen, ciph, ciphlen);
}
if (err)
{
fail ("cipher-xts, gcry_cipher_decrypt (tv %d) failed: %s\n",
tidx, gpg_strerror (err));
goto err_out;
}
/* Check that the decrypt output matches the expected plain text. */
if (memcmp (plain, out, plainlen))
{
mismatch (plain, plainlen, out, plainlen);
fail ("cipher-xts, decrypt data mismatch (tv %d)\n", tidx);
}
if (0)
{
err_out:
got_err = 1;
}
next_tv:
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
xfree (iv);
xfree (ciph);
xfree (plain);
xfree (key);
xfree (out);
}
if (verbose)
fprintf (stderr, " Completed XTS checks.\n");
}
static void
check_xts_cipher (void)
{
/* Check XTS cipher with separate destination and source buffers for
* encryption/decryption. */
do_check_xts_cipher(0);
/* Check XTS cipher with inplace encrypt/decrypt. */
do_check_xts_cipher(1);
}
static void
check_gost28147_cipher (void)
{
#if USE_GOST28147
static const struct {
char key[MAX_DATA_LEN];
const char *oid;
unsigned char plaintext[MAX_DATA_LEN];
int inlen;
char out[MAX_DATA_LEN];
} tv[] =
{
{
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.7.1.2.5.1.1",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\xce\x5a\x5e\xd7\xe0\x57\x7a\x5f",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.31.0",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\x98\x56\xcf\x8b\xfc\xc2\x82\xf4",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.31.1",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\x66\x81\x84\xae\xdc\x48\xc9\x17",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.31.2",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\xdb\xee\x81\x14\x7b\x74\xb0\xf2",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.31.3",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\x31\xa3\x85\x9d\x0a\xee\xb8\x0e",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.31.4",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\xb1\x32\x3e\x0b\x21\x73\xcb\xd1",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.30.0",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\xce\xd5\x2a\x7f\xf7\xf2\x60\xd5",
}, {
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x80"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xd0",
"1.2.643.2.2.30.1",
"\x01\x02\x03\x04\x05\x06\x07\x08",
8,
"\xe4\x21\x75\xe1\x69\x22\xd0\xa8",
}
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
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 (!keylen)
{
fail ("gost28147, gcry_cipher_get_algo_keylen failed\n");
return;
}
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
err = gcry_cipher_open (&hde, GCRY_CIPHER_GOST28147,
GCRY_CIPHER_MODE_ECB, 0);
if (!err)
err = gcry_cipher_open (&hdd, GCRY_CIPHER_GOST28147,
GCRY_CIPHER_MODE_ECB, 0);
if (err)
{
fail ("gost28147, gcry_cipher_open failed: %s\n", gpg_strerror (err));
return;
}
err = gcry_cipher_setkey (hde, tv[i].key, keylen);
if (!err)
err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
if (err)
{
fail ("gost28147, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_set_sbox (hde, tv[i].oid);
if (!err)
err = gcry_cipher_set_sbox (hdd, tv[i].oid);
if (err)
{
fail ("gost28147, gcry_cipher_set_sbox failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
tv[i].plaintext,
tv[i].inlen == -1 ?
strlen ((char*)tv[i].plaintext) :
tv[i].inlen);
if (err)
{
fail ("gost28147, 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))
{
fail ("gost28147, encrypt mismatch entry %d\n", i);
mismatch (tv[i].out, tv[i].inlen,
out, tv[i].inlen);
}
err = gcry_cipher_decrypt (hdd, out, tv[i].inlen, NULL, 0);
if (err)
{
fail ("gost28147, 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 ("gost28147, decrypt mismatch entry %d\n", i);
mismatch (tv[i].plaintext, tv[i].inlen,
out, tv[i].inlen);
}
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
#endif
}
static void
check_stream_cipher (void)
{
static const struct tv
{
const char *name;
int algo;
int keylen;
int ivlen;
const char *key;
const char *iv;
struct data
{
unsigned int inlen;
const char *plaintext;
const char *out;
} data[MAX_DATA_LEN];
} tv[] = {
#ifdef USE_SALSA20
{
"Salsa20 128 bit, test 1",
GCRY_CIPHER_SALSA20, 16, 8,
"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x4D\xFA\x5E\x48\x1D\xA2\x3E\xA0"
}
}
},
{
"Salsa20 128 bit, test 2",
GCRY_CIPHER_SALSA20, 16, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x80\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xB6\x6C\x1E\x44\x46\xDD\x95\x57"
}
}
},
{
"Salsa20 128 bit, test 3",
GCRY_CIPHER_SALSA20, 16, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x05\xE1\xE7\xBE\xB6\x97\xD9\x99"
}
}
},
{
"Salsa20 256 bit, test 1",
GCRY_CIPHER_SALSA20, 32, 8,
"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xE3\xBE\x8F\xDD\x8B\xEC\xA2\xE3"
}
}
},
{
"Salsa20 256 bit, test 2",
GCRY_CIPHER_SALSA20, 32, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x80\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x2A\xBA\x3D\xC4\x5B\x49\x47\x00"
}
}
},
{
"Salsa20 256 bit, ecrypt verified, set 6, vector 0",
GCRY_CIPHER_SALSA20, 32, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD"
"\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xF5\xFA\xD5\x3F\x79\xF9\xDF\x58"
},
{ 64,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xF5\xFA\xD5\x3F\x79\xF9\xDF\x58\xC4\xAE\xA0\xD0\xED\x9A\x96\x01"
"\xF2\x78\x11\x2C\xA7\x18\x0D\x56\x5B\x42\x0A\x48\x01\x96\x70\xEA"
"\xF2\x4C\xE4\x93\xA8\x62\x63\xF6\x77\xB4\x6A\xCE\x19\x24\x77\x3D"
"\x2B\xB2\x55\x71\xE1\xAA\x85\x93\x75\x8F\xC3\x82\xB1\x28\x0B\x71"
}
}
},
{
"Salsa20/12 128 bit, test 1",
GCRY_CIPHER_SALSA20R12, 16, 8,
"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xFC\x20\x7D\xBF\xC7\x6C\x5E\x17"
}
}
},
{
"Salsa20/12 128 bit, test 2",
GCRY_CIPHER_SALSA20R12, 16, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x80\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x08\x28\x39\x9A\x6F\xEF\x20\xDA"
}
}
},
{
"Salsa20/12 128 bit, test 3",
GCRY_CIPHER_SALSA20R12, 16, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xAD\x9E\x60\xE6\xD2\xA2\x64\xB8"
}
}
},
{
"Salsa20/12 256 bit, test 1",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\xAF\xE4\x11\xED\x1C\x4E\x07\xE4"
}
}
},
{
"Salsa20/12 256 bit, test 2",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x80\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x17\x2C\x51\x92\xCB\x6E\x64\x5B"
}
}
},
{
"Salsa20/12 256 bit, ecrypt verified, set 6, vector 0",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD"
"\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x52\xE2\x0C\xF8\x77\x5A\xE8\x82"
},
{ 64,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x52\xE2\x0C\xF8\x77\x5A\xE8\x82\xF2\x00\xC2\x99\x9F\xE4\xBA\x31"
"\xA7\xA1\x8F\x1D\x5C\x97\x16\x19\x1D\x12\x31\x75\xE1\x47\xBD\x4E"
"\x8C\xA6\xED\x16\x6C\xE0\xFC\x8E\x65\xA5\xCA\x60\x84\x20\xFC\x65"
"\x44\xC9\x70\x0A\x0F\x21\x38\xE8\xC1\xA2\x86\xFB\x8C\x1F\xBF\xA0"
}
}
},
#endif /*USE_SALSA20*/
#ifdef USE_CHACHA20
/* From draft-strombergson-chacha-test-vectors-01 */
{
"ChaCha20 128 bit, TC1",
GCRY_CIPHER_CHACHA20, 16, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x89\x67\x09\x52\x60\x83\x64\xfd"
},
{ 112,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x89\x67\x09\x52\x60\x83\x64\xfd\x00\xb2\xf9\x09\x36\xf0\x31\xc8"
"\xe7\x56\xe1\x5d\xba\x04\xb8\x49\x3d\x00\x42\x92\x59\xb2\x0f\x46"
"\xcc\x04\xf1\x11\x24\x6b\x6c\x2c\xe0\x66\xbe\x3b\xfb\x32\xd9\xaa"
"\x0f\xdd\xfb\xc1\x21\x23\xd4\xb9\xe4\x4f\x34\xdc\xa0\x5a\x10\x3f"
"\x6c\xd1\x35\xc2\x87\x8c\x83\x2b\x58\x96\xb1\x34\xf6\x14\x2a\x9d"
"\x4d\x8d\x0d\x8f\x10\x26\xd2\x0a\x0a\x81\x51\x2c\xbc\xe6\xe9\x75"
"\x8a\x71\x43\xd0\x21\x97\x80\x22\xa3\x84\x14\x1a\x80\xce\xa3\x06"
},
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x89\x67\x09\x52\x60\x83\x64\xfd\x00\xb2\xf9\x09\x36\xf0\x31\xc8"
"\xe7\x56\xe1\x5d\xba\x04\xb8\x49\x3d\x00\x42\x92\x59\xb2\x0f\x46"
"\xcc\x04\xf1\x11\x24\x6b\x6c\x2c\xe0\x66\xbe\x3b\xfb\x32\xd9\xaa"
"\x0f\xdd\xfb\xc1\x21\x23\xd4\xb9\xe4\x4f\x34\xdc\xa0\x5a\x10\x3f"
"\x6c\xd1\x35\xc2\x87\x8c\x83\x2b\x58\x96\xb1\x34\xf6\x14\x2a\x9d"
"\x4d\x8d\x0d\x8f\x10\x26\xd2\x0a\x0a\x81\x51\x2c\xbc\xe6\xe9\x75"
"\x8a\x71\x43\xd0\x21\x97\x80\x22\xa3\x84\x14\x1a\x80\xce\xa3\x06"
"\x2f\x41\xf6\x7a\x75\x2e\x66\xad\x34\x11\x98\x4c\x78\x7e\x30\xad"
}
}
},
{
"ChaCha20 256 bit, TC1",
GCRY_CIPHER_CHACHA20, 32, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 8,
"\x00\x00\x00\x00\x00\x00\x00\x00",
"\x76\xb8\xe0\xad\xa0\xf1\x3d\x90"
},
{ 112,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28"
"\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7"
"\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37"
"\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86"
"\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d"
"\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed"
"\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5"
},
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28"
"\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7"
"\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37"
"\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86"
"\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d"
"\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed"
"\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5"
"\x31\xed\x1f\x28\x51\x0a\xfb\x45\xac\xe1\x0a\x1f\x4b\x79\x4d\x6f"
}
}
},
{
"ChaCha20 256 bit, TC2",
GCRY_CIPHER_CHACHA20, 32, 8,
"\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",
"\x00\x00\x00\x00\x00\x00\x00\x00",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xc5\xd3\x0a\x7c\xe1\xec\x11\x93\x78\xc8\x4f\x48\x7d\x77\x5a\x85"
"\x42\xf1\x3e\xce\x23\x8a\x94\x55\xe8\x22\x9e\x88\x8d\xe8\x5b\xbd"
"\x29\xeb\x63\xd0\xa1\x7a\x5b\x99\x9b\x52\xda\x22\xbe\x40\x23\xeb"
"\x07\x62\x0a\x54\xf6\xfa\x6a\xd8\x73\x7b\x71\xeb\x04\x64\xda\xc0"
"\x10\xf6\x56\xe6\xd1\xfd\x55\x05\x3e\x50\xc4\x87\x5c\x99\x30\xa3"
"\x3f\x6d\x02\x63\xbd\x14\xdf\xd6\xab\x8c\x70\x52\x1c\x19\x33\x8b"
"\x23\x08\xb9\x5c\xf8\xd0\xbb\x7d\x20\x2d\x21\x02\x78\x0e\xa3\x52"
"\x8f\x1c\xb4\x85\x60\xf7\x6b\x20\xf3\x82\xb9\x42\x50\x0f\xce\xac"
}
}
},
{
"ChaCha20 256 bit, TC3",
GCRY_CIPHER_CHACHA20, 32, 8,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x01\x00\x00\x00\x00\x00\x00\x00",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xef\x3f\xdf\xd6\xc6\x15\x78\xfb\xf5\xcf\x35\xbd\x3d\xd3\x3b\x80"
"\x09\x63\x16\x34\xd2\x1e\x42\xac\x33\x96\x0b\xd1\x38\xe5\x0d\x32"
"\x11\x1e\x4c\xaf\x23\x7e\xe5\x3c\xa8\xad\x64\x26\x19\x4a\x88\x54"
"\x5d\xdc\x49\x7a\x0b\x46\x6e\x7d\x6b\xbd\xb0\x04\x1b\x2f\x58\x6b"
"\x53\x05\xe5\xe4\x4a\xff\x19\xb2\x35\x93\x61\x44\x67\x5e\xfb\xe4"
"\x40\x9e\xb7\xe8\xe5\xf1\x43\x0f\x5f\x58\x36\xae\xb4\x9b\xb5\x32"
"\x8b\x01\x7c\x4b\x9d\xc1\x1f\x8a\x03\x86\x3f\xa8\x03\xdc\x71\xd5"
"\x72\x6b\x2b\x6b\x31\xaa\x32\x70\x8a\xfe\x5a\xf1\xd6\xb6\x90\x58"
}
}
},
{
"ChaCha20 256 bit, TC4",
GCRY_CIPHER_CHACHA20, 32, 8,
"\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",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xd9\xbf\x3f\x6b\xce\x6e\xd0\xb5\x42\x54\x55\x77\x67\xfb\x57\x44"
"\x3d\xd4\x77\x89\x11\xb6\x06\x05\x5c\x39\xcc\x25\xe6\x74\xb8\x36"
"\x3f\xea\xbc\x57\xfd\xe5\x4f\x79\x0c\x52\xc8\xae\x43\x24\x0b\x79"
"\xd4\x90\x42\xb7\x77\xbf\xd6\xcb\x80\xe9\x31\x27\x0b\x7f\x50\xeb"
"\x5b\xac\x2a\xcd\x86\xa8\x36\xc5\xdc\x98\xc1\x16\xc1\x21\x7e\xc3"
"\x1d\x3a\x63\xa9\x45\x13\x19\xf0\x97\xf3\xb4\xd6\xda\xb0\x77\x87"
"\x19\x47\x7d\x24\xd2\x4b\x40\x3a\x12\x24\x1d\x7c\xca\x06\x4f\x79"
"\x0f\x1d\x51\xcc\xaf\xf6\xb1\x66\x7d\x4b\xbc\xa1\x95\x8c\x43\x06"
}
}
},
{
"ChaCha20 256 bit, TC5",
GCRY_CIPHER_CHACHA20, 32, 8,
"\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55"
"\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55",
"\x55\x55\x55\x55\x55\x55\x55\x55",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xbe\xa9\x41\x1a\xa4\x53\xc5\x43\x4a\x5a\xe8\xc9\x28\x62\xf5\x64"
"\x39\x68\x55\xa9\xea\x6e\x22\xd6\xd3\xb5\x0a\xe1\xb3\x66\x33\x11"
"\xa4\xa3\x60\x6c\x67\x1d\x60\x5c\xe1\x6c\x3a\xec\xe8\xe6\x1e\xa1"
"\x45\xc5\x97\x75\x01\x7b\xee\x2f\xa6\xf8\x8a\xfc\x75\x80\x69\xf7"
"\xe0\xb8\xf6\x76\xe6\x44\x21\x6f\x4d\x2a\x34\x22\xd7\xfa\x36\xc6"
"\xc4\x93\x1a\xca\x95\x0e\x9d\xa4\x27\x88\xe6\xd0\xb6\xd1\xcd\x83"
"\x8e\xf6\x52\xe9\x7b\x14\x5b\x14\x87\x1e\xae\x6c\x68\x04\xc7\x00"
"\x4d\xb5\xac\x2f\xce\x4c\x68\xc7\x26\xd0\x04\xb1\x0f\xca\xba\x86"
}
}
},
{
"ChaCha20 256 bit, TC6",
GCRY_CIPHER_CHACHA20, 32, 8,
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x9a\xa2\xa9\xf6\x56\xef\xde\x5a\xa7\x59\x1c\x5f\xed\x4b\x35\xae"
"\xa2\x89\x5d\xec\x7c\xb4\x54\x3b\x9e\x9f\x21\xf5\xe7\xbc\xbc\xf3"
"\xc4\x3c\x74\x8a\x97\x08\x88\xf8\x24\x83\x93\xa0\x9d\x43\xe0\xb7"
"\xe1\x64\xbc\x4d\x0b\x0f\xb2\x40\xa2\xd7\x21\x15\xc4\x80\x89\x06"
"\x72\x18\x44\x89\x44\x05\x45\xd0\x21\xd9\x7e\xf6\xb6\x93\xdf\xe5"
"\xb2\xc1\x32\xd4\x7e\x6f\x04\x1c\x90\x63\x65\x1f\x96\xb6\x23\xe6"
"\x2a\x11\x99\x9a\x23\xb6\xf7\xc4\x61\xb2\x15\x30\x26\xad\x5e\x86"
"\x6a\x2e\x59\x7e\xd0\x7b\x84\x01\xde\xc6\x3a\x09\x34\xc6\xb2\xa9"
}
}
},
{
"ChaCha20 256 bit, TC7",
GCRY_CIPHER_CHACHA20, 32, 8,
"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
"\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00",
"\x0f\x1e\x2d\x3c\x4b\x5a\x69\x78",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x9f\xad\xf4\x09\xc0\x08\x11\xd0\x04\x31\xd6\x7e\xfb\xd8\x8f\xba"
"\x59\x21\x8d\x5d\x67\x08\xb1\xd6\x85\x86\x3f\xab\xbb\x0e\x96\x1e"
"\xea\x48\x0f\xd6\xfb\x53\x2b\xfd\x49\x4b\x21\x51\x01\x50\x57\x42"
"\x3a\xb6\x0a\x63\xfe\x4f\x55\xf7\xa2\x12\xe2\x16\x7c\xca\xb9\x31"
"\xfb\xfd\x29\xcf\x7b\xc1\xd2\x79\xed\xdf\x25\xdd\x31\x6b\xb8\x84"
"\x3d\x6e\xde\xe0\xbd\x1e\xf1\x21\xd1\x2f\xa1\x7c\xbc\x2c\x57\x4c"
"\xcc\xab\x5e\x27\x51\x67\xb0\x8b\xd6\x86\xf8\xa0\x9d\xf8\x7e\xc3"
"\xff\xb3\x53\x61\xb9\x4e\xbf\xa1\x3f\xec\x0e\x48\x89\xd1\x8d\xa5"
}
}
},
{
"ChaCha20 256 bit, TC8",
GCRY_CIPHER_CHACHA20, 32, 8,
"\xc4\x6e\xc1\xb1\x8c\xe8\xa8\x78\x72\x5a\x37\xe7\x80\xdf\xb7\x35"
"\x1f\x68\xed\x2e\x19\x4c\x79\xfb\xc6\xae\xbe\xe1\xa6\x67\x97\x5d",
"\x1a\xda\x31\xd5\xcf\x68\x82\x21",
{
{ 128,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xf6\x3a\x89\xb7\x5c\x22\x71\xf9\x36\x88\x16\x54\x2b\xa5\x2f\x06"
"\xed\x49\x24\x17\x92\x30\x2b\x00\xb5\xe8\xf8\x0a\xe9\xa4\x73\xaf"
"\xc2\x5b\x21\x8f\x51\x9a\xf0\xfd\xd4\x06\x36\x2e\x8d\x69\xde\x7f"
"\x54\xc6\x04\xa6\xe0\x0f\x35\x3f\x11\x0f\x77\x1b\xdc\xa8\xab\x92"
"\xe5\xfb\xc3\x4e\x60\xa1\xd9\xa9\xdb\x17\x34\x5b\x0a\x40\x27\x36"
"\x85\x3b\xf9\x10\xb0\x60\xbd\xf1\xf8\x97\xb6\x29\x0f\x01\xd1\x38"
"\xae\x2c\x4c\x90\x22\x5b\xa9\xea\x14\xd5\x18\xf5\x59\x29\xde\xa0"
"\x98\xca\x7a\x6c\xcf\xe6\x12\x27\x05\x3c\x84\xe4\x9a\x4a\x33\x32"
},
{ 127,
"\xf6\x3a\x89\xb7\x5c\x22\x71\xf9\x36\x88\x16\x54\x2b\xa5\x2f\x06"
"\xed\x49\x24\x17\x92\x30\x2b\x00\xb5\xe8\xf8\x0a\xe9\xa4\x73\xaf"
"\xc2\x5b\x21\x8f\x51\x9a\xf0\xfd\xd4\x06\x36\x2e\x8d\x69\xde\x7f"
"\x54\xc6\x04\xa6\xe0\x0f\x35\x3f\x11\x0f\x77\x1b\xdc\xa8\xab\x92"
"\xe5\xfb\xc3\x4e\x60\xa1\xd9\xa9\xdb\x17\x34\x5b\x0a\x40\x27\x36"
"\x85\x3b\xf9\x10\xb0\x60\xbd\xf1\xf8\x97\xb6\x29\x0f\x01\xd1\x38"
"\xae\x2c\x4c\x90\x22\x5b\xa9\xea\x14\xd5\x18\xf5\x59\x29\xde\xa0"
"\x98\xca\x7a\x6c\xcf\xe6\x12\x27\x05\x3c\x84\xe4\x9a\x4a\x33",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
}
}
},
/* from draft-nir-cfrg-chacha20-poly1305-02 */
{
"ChaCha20 256 bit, IV96-bit",
GCRY_CIPHER_CHACHA20, 32, 12,
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
"\x07\x00\x00\x00\x40\x41\x42\x43\x44\x45\x46\x47",
{
{ 64,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x7b\xac\x2b\x25\x2d\xb4\x47\xaf\x09\xb6\x7a\x55\xa4\xe9\x55\x84"
"\x0a\xe1\xd6\x73\x10\x75\xd9\xeb\x2a\x93\x75\x78\x3e\xd5\x53\xff"
"\xa2\x7e\xcc\xde\xad\xdb\x4d\xb4\xd1\x17\x9c\xe4\xc9\x0b\x43\xd8"
"\xbc\xb7\x94\x8c\x4b\x4b\x7d\x8b\x7d\xf6\x27\x39\x32\xa4\x69\x16"
},
},
},
#endif /*USE_CHACHA20*/
};
gcry_cipher_hd_t hde, hdd;
unsigned char out[MAX_DATA_LEN];
int i, j;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting stream cipher checks.\n");
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
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);
if (gcry_cipher_get_algo_blklen(tv[i].algo) != 1)
{
fail ("stream, gcry_cipher_get_algo_blklen: bad block length\n");
continue;
}
err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_STREAM, 0);
if (!err)
err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_STREAM, 0);
if (err)
{
fail ("stream, gcry_cipher_open for stream mode failed: %s\n",
gpg_strerror (err));
continue;
}
/* Now loop over all the data samples. */
for (j = 0; tv[i].data[j].inlen; j++)
{
err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
if (!err)
err = gcry_cipher_setkey (hdd, tv[i].key, tv[i].keylen);
if (err)
{
fail ("stream, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
goto next;
}
err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("stream, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
goto next;
}
err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
tv[i].data[j].plaintext,
tv[i].data[j].inlen);
if (err)
{
fail ("stream, gcry_cipher_encrypt (%d, %d) failed: %s\n",
i, j, gpg_strerror (err));
goto next;
}
if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen))
{
fail ("stream, encrypt mismatch entry %d:%d\n", i, j);
mismatch (tv[i].data[j].out, tv[i].data[j].inlen,
out, tv[i].data[j].inlen);
}
err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
if (err)
{
fail ("stream, gcry_cipher_decrypt (%d, %d) failed: %s\n",
i, j, gpg_strerror (err));
goto next;
}
if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen))
fail ("stream, decrypt mismatch entry %d:%d\n", i, j);
}
/* This time we encrypt and decrypt one byte at a time */
for (j = 0; tv[i].data[j].inlen; j++)
{
int byteNum;
err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
if (!err)
err = gcry_cipher_setkey (hdd, tv[i].key, tv[i].keylen);
if (err)
{
fail ("stream, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
goto next;
}
err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("stream, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
goto next;
}
for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum)
{
err = gcry_cipher_encrypt (hde, out+byteNum, 1,
(tv[i].data[j].plaintext) + byteNum,
1);
if (err)
{
fail ("stream, gcry_cipher_encrypt (%d, %d) failed: %s\n",
i, j, gpg_strerror (err));
goto next;
}
}
if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen))
fail ("stream, encrypt mismatch entry %d:%d (byte-wise)\n", i, j);
for (byteNum = 0; byteNum < tv[i].data[j].inlen; ++byteNum)
{
err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0);
if (err)
{
fail ("stream, gcry_cipher_decrypt (%d, %d) failed: %s\n",
i, j, gpg_strerror (err));
goto next;
}
}
if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen))
fail ("stream, decrypt mismatch entry %d:%d (byte-wise)\n", i, j);
}
next:
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
if (verbose)
fprintf (stderr, " Completed stream cipher checks.\n");
}
static void
check_stream_cipher_large_block (void)
{
static const struct tv
{
const char *name;
int algo;
int keylen;
int ivlen;
const char *key;
const char *iv;
struct data
{
int offset, length;
const char *result;
} data[MAX_DATA_LEN];
} tv[] = {
#ifdef USE_SALSA20
{
"Salsa20 256 bit, ecrypt verified, set 6, vector 0",
GCRY_CIPHER_SALSA20, 32, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD"
"\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 0, 64,
"\xF5\xFA\xD5\x3F\x79\xF9\xDF\x58\xC4\xAE\xA0\xD0\xED\x9A\x96\x01"
"\xF2\x78\x11\x2C\xA7\x18\x0D\x56\x5B\x42\x0A\x48\x01\x96\x70\xEA"
"\xF2\x4C\xE4\x93\xA8\x62\x63\xF6\x77\xB4\x6A\xCE\x19\x24\x77\x3D"
"\x2B\xB2\x55\x71\xE1\xAA\x85\x93\x75\x8F\xC3\x82\xB1\x28\x0B\x71"
},
{ 65472, 64,
"\xB7\x0C\x50\x13\x9C\x63\x33\x2E\xF6\xE7\x7A\xC5\x43\x38\xA4\x07"
"\x9B\x82\xBE\xC9\xF9\xA4\x03\xDF\xEA\x82\x1B\x83\xF7\x86\x07\x91"
"\x65\x0E\xF1\xB2\x48\x9D\x05\x90\xB1\xDE\x77\x2E\xED\xA4\xE3\xBC"
"\xD6\x0F\xA7\xCE\x9C\xD6\x23\xD9\xD2\xFD\x57\x58\xB8\x65\x3E\x70"
},
{ 65536, 64,
"\x81\x58\x2C\x65\xD7\x56\x2B\x80\xAE\xC2\xF1\xA6\x73\xA9\xD0\x1C"
"\x9F\x89\x2A\x23\xD4\x91\x9F\x6A\xB4\x7B\x91\x54\xE0\x8E\x69\x9B"
"\x41\x17\xD7\xC6\x66\x47\x7B\x60\xF8\x39\x14\x81\x68\x2F\x5D\x95"
"\xD9\x66\x23\xDB\xC4\x89\xD8\x8D\xAA\x69\x56\xB9\xF0\x64\x6B\x6E"
},
{ 131008, 64,
"\xA1\x3F\xFA\x12\x08\xF8\xBF\x50\x90\x08\x86\xFA\xAB\x40\xFD\x10"
"\xE8\xCA\xA3\x06\xE6\x3D\xF3\x95\x36\xA1\x56\x4F\xB7\x60\xB2\x42"
"\xA9\xD6\xA4\x62\x8C\xDC\x87\x87\x62\x83\x4E\x27\xA5\x41\xDA\x2A"
"\x5E\x3B\x34\x45\x98\x9C\x76\xF6\x11\xE0\xFE\xC6\xD9\x1A\xCA\xCC"
}
}
},
{
"Salsa20 256 bit, ecrypt verified, set 6, vector 1",
GCRY_CIPHER_SALSA20, 32, 8,
"\x05\x58\xAB\xFE\x51\xA4\xF7\x4A\x9D\xF0\x43\x96\xE9\x3C\x8F\xE2"
"\x35\x88\xDB\x2E\x81\xD4\x27\x7A\xCD\x20\x73\xC6\x19\x6C\xBF\x12",
"\x16\x7D\xE4\x4B\xB2\x19\x80\xE7",
{
{ 0, 64,
"\x39\x44\xF6\xDC\x9F\x85\xB1\x28\x08\x38\x79\xFD\xF1\x90\xF7\xDE"
"\xE4\x05\x3A\x07\xBC\x09\x89\x6D\x51\xD0\x69\x0B\xD4\xDA\x4A\xC1"
"\x06\x2F\x1E\x47\xD3\xD0\x71\x6F\x80\xA9\xB4\xD8\x5E\x6D\x60\x85"
"\xEE\x06\x94\x76\x01\xC8\x5F\x1A\x27\xA2\xF7\x6E\x45\xA6\xAA\x87"
},
{ 65472, 64,
"\x36\xE0\x3B\x4B\x54\xB0\xB2\xE0\x4D\x06\x9E\x69\x00\x82\xC8\xC5"
"\x92\xDF\x56\xE6\x33\xF5\xD8\xC7\x68\x2A\x02\xA6\x5E\xCD\x13\x71"
"\x8C\xA4\x35\x2A\xAC\xCB\x0D\xA2\x0E\xD6\xBB\xBA\x62\xE1\x77\xF2"
"\x10\xE3\x56\x0E\x63\xBB\x82\x2C\x41\x58\xCA\xA8\x06\xA8\x8C\x82"
},
{ 65536, 64,
"\x1B\x77\x9E\x7A\x91\x7C\x8C\x26\x03\x9F\xFB\x23\xCF\x0E\xF8\xE0"
"\x8A\x1A\x13\xB4\x3A\xCD\xD9\x40\x2C\xF5\xDF\x38\x50\x10\x98\xDF"
"\xC9\x45\xA6\xCC\x69\xA6\xA1\x73\x67\xBC\x03\x43\x1A\x86\xB3\xED"
"\x04\xB0\x24\x5B\x56\x37\x9B\xF9\x97\xE2\x58\x00\xAD\x83\x7D\x7D"
},
{ 131008, 64,
"\x7E\xC6\xDA\xE8\x1A\x10\x5E\x67\x17\x2A\x0B\x8C\x4B\xBE\x7D\x06"
"\xA7\xA8\x75\x9F\x91\x4F\xBE\xB1\xAF\x62\xC8\xA5\x52\xEF\x4A\x4F"
"\x56\x96\x7E\xA2\x9C\x74\x71\xF4\x6F\x3B\x07\xF7\xA3\x74\x6E\x95"
"\x3D\x31\x58\x21\xB8\x5B\x6E\x8C\xB4\x01\x22\xB9\x66\x35\x31\x3C"
}
}
},
{
"Salsa20 256 bit, ecrypt verified, set 6, vector 2",
GCRY_CIPHER_SALSA20, 32, 8,
"\x0A\x5D\xB0\x03\x56\xA9\xFC\x4F\xA2\xF5\x48\x9B\xEE\x41\x94\xE7"
"\x3A\x8D\xE0\x33\x86\xD9\x2C\x7F\xD2\x25\x78\xCB\x1E\x71\xC4\x17",
"\x1F\x86\xED\x54\xBB\x22\x89\xF0",
{
{ 0, 64,
"\x3F\xE8\x5D\x5B\xB1\x96\x0A\x82\x48\x0B\x5E\x6F\x4E\x96\x5A\x44"
"\x60\xD7\xA5\x45\x01\x66\x4F\x7D\x60\xB5\x4B\x06\x10\x0A\x37\xFF"
"\xDC\xF6\xBD\xE5\xCE\x3F\x48\x86\xBA\x77\xDD\x5B\x44\xE9\x56\x44"
"\xE4\x0A\x8A\xC6\x58\x01\x15\x5D\xB9\x0F\x02\x52\x2B\x64\x40\x23"
},
{ 65472, 64,
"\xC8\xD6\xE5\x4C\x29\xCA\x20\x40\x18\xA8\x30\xE2\x66\xCE\xEE\x0D"
"\x03\x7D\xC4\x7E\x92\x19\x47\x30\x2A\xCE\x40\xD1\xB9\x96\xA6\xD8"
"\x0B\x59\x86\x77\xF3\x35\x2F\x1D\xAA\x6D\x98\x88\xF8\x91\xAD\x95"
"\xA1\xC3\x2F\xFE\xB7\x1B\xB8\x61\xE8\xB0\x70\x58\x51\x51\x71\xC9"
},
{ 65536, 64,
"\xB7\x9F\xD7\x76\x54\x2B\x46\x20\xEF\xCB\x88\x44\x95\x99\xF2\x34"
"\x03\xE7\x4A\x6E\x91\xCA\xCC\x50\xA0\x5A\x8F\x8F\x3C\x0D\xEA\x8B"
"\x00\xE1\xA5\xE6\x08\x1F\x55\x26\xAE\x97\x5B\x3B\xC0\x45\x0F\x1A"
"\x0C\x8B\x66\xF8\x08\xF1\x90\x4B\x97\x13\x61\x13\x7C\x93\x15\x6F"
},
{ 131008, 64,
"\x79\x98\x20\x4F\xED\x70\xCE\x8E\x0D\x02\x7B\x20\x66\x35\xC0\x8C"
"\x8B\xC4\x43\x62\x26\x08\x97\x0E\x40\xE3\xAE\xDF\x3C\xE7\x90\xAE"
"\xED\xF8\x9F\x92\x26\x71\xB4\x53\x78\xE2\xCD\x03\xF6\xF6\x23\x56"
"\x52\x9C\x41\x58\xB7\xFF\x41\xEE\x85\x4B\x12\x35\x37\x39\x88\xC8"
}
}
},
{
"Salsa20 256 bit, ecrypt verified, set 6, vector 3",
GCRY_CIPHER_SALSA20, 32, 8,
"\x0F\x62\xB5\x08\x5B\xAE\x01\x54\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC"
"\x3F\x92\xE5\x38\x8B\xDE\x31\x84\xD7\x2A\x7D\xD0\x23\x76\xC9\x1C",
"\x28\x8F\xF6\x5D\xC4\x2B\x92\xF9",
{
{ 0, 64,
"\x5E\x5E\x71\xF9\x01\x99\x34\x03\x04\xAB\xB2\x2A\x37\xB6\x62\x5B"
"\xF8\x83\xFB\x89\xCE\x3B\x21\xF5\x4A\x10\xB8\x10\x66\xEF\x87\xDA"
"\x30\xB7\x76\x99\xAA\x73\x79\xDA\x59\x5C\x77\xDD\x59\x54\x2D\xA2"
"\x08\xE5\x95\x4F\x89\xE4\x0E\xB7\xAA\x80\xA8\x4A\x61\x76\x66\x3F"
},
{ 65472, 64,
"\x2D\xA2\x17\x4B\xD1\x50\xA1\xDF\xEC\x17\x96\xE9\x21\xE9\xD6\xE2"
"\x4E\xCF\x02\x09\xBC\xBE\xA4\xF9\x83\x70\xFC\xE6\x29\x05\x6F\x64"
"\x91\x72\x83\x43\x6E\x2D\x3F\x45\x55\x62\x25\x30\x7D\x5C\xC5\xA5"
"\x65\x32\x5D\x89\x93\xB3\x7F\x16\x54\x19\x5C\x24\x0B\xF7\x5B\x16"
},
{ 65536, 64,
"\xAB\xF3\x9A\x21\x0E\xEE\x89\x59\x8B\x71\x33\x37\x70\x56\xC2\xFE"
"\xF4\x2D\xA7\x31\x32\x75\x63\xFB\x67\xC7\xBE\xDB\x27\xF3\x8C\x7C"
"\x5A\x3F\xC2\x18\x3A\x4C\x6B\x27\x7F\x90\x11\x52\x47\x2C\x6B\x2A"
"\xBC\xF5\xE3\x4C\xBE\x31\x5E\x81\xFD\x3D\x18\x0B\x5D\x66\xCB\x6C"
},
{ 131008, 64,
"\x1B\xA8\x9D\xBD\x3F\x98\x83\x97\x28\xF5\x67\x91\xD5\xB7\xCE\x23"
"\x50\x36\xDE\x84\x3C\xCC\xAB\x03\x90\xB8\xB5\x86\x2F\x1E\x45\x96"
"\xAE\x8A\x16\xFB\x23\xDA\x99\x7F\x37\x1F\x4E\x0A\xAC\xC2\x6D\xB8"
"\xEB\x31\x4E\xD4\x70\xB1\xAF\x6B\x9F\x8D\x69\xDD\x79\xA9\xD7\x50"
}
}
},
{
"Salsa20/12 256 bit, ecrypt verified, set 6, vector 0",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD"
"\x30\x83\xD6\x29\x7C\xCF\x22\x75\xC8\x1B\x6E\xC1\x14\x67\xBA\x0D",
"\x0D\x74\xDB\x42\xA9\x10\x77\xDE",
{
{ 0, 64,
"\x52\xE2\x0C\xF8\x77\x5A\xE8\x82\xF2\x00\xC2\x99\x9F\xE4\xBA\x31"
"\xA7\xA1\x8F\x1D\x5C\x97\x16\x19\x1D\x12\x31\x75\xE1\x47\xBD\x4E"
"\x8C\xA6\xED\x16\x6C\xE0\xFC\x8E\x65\xA5\xCA\x60\x84\x20\xFC\x65"
"\x44\xC9\x70\x0A\x0F\x21\x38\xE8\xC1\xA2\x86\xFB\x8C\x1F\xBF\xA0"
},
{ 65472, 64,
"\x8F\xBC\x9F\xE8\x69\x1B\xD4\xF0\x82\xB4\x7F\x54\x05\xED\xFB\xC1"
"\x6F\x4D\x5A\x12\xDD\xCB\x2D\x75\x4E\x8A\x99\x98\xD0\xB2\x19\x55"
"\x7D\xFE\x29\x84\xF4\xA1\xD2\xDD\xA7\x6B\x95\x96\x92\x8C\xCE\x05"
"\x56\xF5\x00\x66\xCD\x59\x9E\x44\xEF\x5C\x14\xB2\x26\x68\x3A\xEF"
},
{ 65536, 64,
"\xBC\xBD\x01\xDD\x28\x96\x1C\xC7\xAD\x30\x47\x38\x6C\xBC\xC6\x7C"
"\x10\x8D\x6A\xF1\x11\x67\xE4\x0D\x7A\xE1\xB2\xFC\x45\x18\xA8\x67"
"\xEF\xE4\x02\x65\x1D\x1D\x88\x51\xC4\xFD\x23\x30\xC5\x97\xB3\x6A"
"\x46\xD5\x68\x9E\x00\xFC\x96\xFE\xCF\x9C\xE3\xE2\x21\x1D\x44\xBE"
},
{ 131008, 64,
"\x91\x66\xF3\x1C\xD8\x5B\x5B\xB1\x8F\xC6\x14\xE5\x4E\x4A\xD6\x7F"
"\xB8\x65\x8E\x3B\xF9\xFB\x19\xB7\xA8\x2F\x0F\xE7\xDC\x90\x2D\xF5"
"\x63\xC6\xAC\x4F\x44\x67\x48\xC4\xBC\x3E\x14\x05\xE1\x24\x82\x0D"
"\xC4\x09\x41\x99\x8F\x44\xA8\x10\xE7\x22\x78\x7F\xCD\x47\x78\x4C"
}
}
},
{
"Salsa20/12 256 bit, ecrypt verified, set 6, vector 1",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x05\x58\xAB\xFE\x51\xA4\xF7\x4A\x9D\xF0\x43\x96\xE9\x3C\x8F\xE2"
"\x35\x88\xDB\x2E\x81\xD4\x27\x7A\xCD\x20\x73\xC6\x19\x6C\xBF\x12",
"\x16\x7D\xE4\x4B\xB2\x19\x80\xE7",
{
{ 0, 64,
"\xC0\x75\x60\xB3\xE7\x76\xB4\x71\xC5\xE2\x93\x14\x26\xCA\xF1\xED"
"\x3A\xE4\xB8\x67\x08\x76\x82\xCA\x9D\xFD\xC2\xBA\xE8\x93\x50\xBD"
"\x84\x82\x1C\xAE\xFF\x85\xAA\xC4\x9D\x74\x35\xA7\xD9\x88\x93\x52"
"\xF5\x27\x9E\x36\x12\x3F\x41\x72\x8A\x14\xEF\x26\x9F\xCB\x94\x4B"
},
{ 65472, 64,
"\xEE\xD1\xBB\x58\xF9\x0C\x89\xE0\x5C\xC6\x8B\x2D\xB6\x05\x58\x49"
"\xB3\xD2\xB1\x87\xB7\xF0\x2F\x9A\x24\xCE\x34\x2A\xF0\xFC\x47\xA3"
"\x74\xBD\x75\x90\xFB\xF4\xFD\x9E\xE5\x9B\x1A\x38\x1E\xBF\xD2\x29"
"\xAD\x2A\x29\x01\xB3\xFB\x61\x08\x12\x90\x0B\x92\x30\xE6\x22\xE9"
},
{ 65536, 64,
"\x70\xF0\x49\x3A\x1B\x62\x53\xCC\x5E\xD3\x45\x0A\x31\xCF\x37\x7D"
"\x83\x4B\xAD\x20\x72\x30\x29\x27\xCC\xD8\x30\x10\x4B\xD3\x05\xFF"
"\x59\xD2\x94\x17\xB2\x32\x88\x4E\xC9\x59\x19\x4D\x60\x47\xC3\xDD"
"\x66\x56\xC4\x7E\x32\x00\x64\xEB\x01\x44\xF7\x34\x1B\xC3\xD6\x97"
},
{ 131008, 64,
"\xD2\xCC\xF7\xC1\xAF\x2A\xB4\x66\xE6\x27\xDB\x44\x08\x40\x96\x9A"
"\xBD\xAB\x68\xD8\x86\xAE\x6A\x38\xA1\x3F\xEE\x17\x50\xCA\x97\xB5"
"\xD3\x31\x5B\x84\x08\x47\x28\x86\x2F\xBC\xC7\xD4\xA9\x7C\x75\xC8"
"\x65\x5F\xF9\xD6\xBB\xC2\x61\x88\x63\x6F\x3E\xDF\xE1\x5C\x7D\x30"
}
}
},
{
"Salsa20/12 256 bit, ecrypt verified, set 6, vector 2",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x0A\x5D\xB0\x03\x56\xA9\xFC\x4F\xA2\xF5\x48\x9B\xEE\x41\x94\xE7"
"\x3A\x8D\xE0\x33\x86\xD9\x2C\x7F\xD2\x25\x78\xCB\x1E\x71\xC4\x17",
"\x1F\x86\xED\x54\xBB\x22\x89\xF0",
{
{ 0, 64,
"\x51\x22\x52\x91\x01\x90\xD1\x54\xD1\x4D\x0B\x92\x32\xB8\x84\x31"
"\x8C\xCB\x43\x81\x9B\xD5\x42\x19\x32\xC0\x3A\x13\xF0\x7B\x40\x10"
"\x83\xD7\x89\x72\x5A\xA9\xDA\x0B\x41\xCB\x62\x24\x94\x5E\xDC\xB0"
"\xFB\x6F\xD7\xC2\x34\x22\x35\xC9\x70\xF6\x4E\x10\x1C\x25\x68\x64"
},
{ 65472, 64,
"\x97\x96\x74\x55\x84\x0A\x4A\xE5\xC1\xCA\xCE\x49\x15\x19\x13\x8A"
"\xA3\x5E\x5F\x02\x40\x7D\x4A\x1F\xE5\x08\x6D\x35\xF3\x55\x1E\xF4"
"\x77\xD9\x28\x9D\x17\x23\x79\x7C\x1A\x49\xEC\x26\x62\x9A\xFA\xDC"
"\x56\xA0\x38\xA3\x8C\x75\x88\x1B\x62\x17\xFD\x74\x67\x25\x59\x09"
},
{ 65536, 64,
"\x1B\xF8\x2E\x3D\x5C\x54\xDA\xAB\xCF\x84\x15\xF8\xA2\xA1\xA2\x2E"
"\x86\x88\x06\x33\x4F\xF3\x11\x36\x04\x74\x1C\x1D\xF2\xB9\x84\x0F"
"\x87\xDE\xEF\xB0\x07\x23\xA8\xA1\xB2\x4A\x4D\xA1\x7E\xCD\xAD\x00"
"\x01\xF9\x79\xDD\xAE\x2D\xF0\xC5\xE1\xE5\x32\xC4\x8F\x8E\x0D\x34"
},
{ 131008, 64,
"\x06\xD8\x4F\x6A\x71\x34\x84\x20\x32\x9F\xCD\x0C\x41\x75\x9A\xD1"
"\x8F\x99\x57\xA3\x8F\x22\x89\x3B\xA5\x58\xC5\x05\x11\x97\x28\x5C"
"\x6B\xE2\xFD\x6C\x96\xA5\xC6\x62\xAF\xD3\x11\x78\xE7\x0F\x96\x0A"
"\xAB\x3F\x47\x96\x23\xA4\x44\xB6\x81\x91\xE4\xC5\x28\x46\x93\x88"
}
}
},
{
"Salsa20/12 256 bit, ecrypt verified, set 6, vector 3",
GCRY_CIPHER_SALSA20R12, 32, 8,
"\x0F\x62\xB5\x08\x5B\xAE\x01\x54\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC"
"\x3F\x92\xE5\x38\x8B\xDE\x31\x84\xD7\x2A\x7D\xD0\x23\x76\xC9\x1C",
"\x28\x8F\xF6\x5D\xC4\x2B\x92\xF9",
{
{ 0, 64,
"\x99\xDB\x33\xAD\x11\xCE\x0C\xCB\x3B\xFD\xBF\x8D\x0C\x18\x16\x04"
"\x52\xD0\x14\xCD\xE9\x89\xB4\xC4\x11\xA5\x59\xFF\x7C\x20\xA1\x69"
"\xE6\xDC\x99\x09\xD8\x16\xBE\xCE\xDC\x40\x63\xCE\x07\xCE\xA8\x28"
"\xF4\x4B\xF9\xB6\xC9\xA0\xA0\xB2\x00\xE1\xB5\x2A\xF4\x18\x59\xC5"
},
{ 65472, 64,
"\x2F\xF2\x02\x64\xEE\xAF\x47\xAB\x7D\x57\xC3\x62\x24\x53\x54\x51"
"\x73\x5A\xC8\x36\xD3\x2D\xD2\x8A\xE6\x36\x45\xCE\x95\x2F\x7F\xDB"
"\xE6\x68\x9C\x69\x59\x77\xB1\xC7\x6E\x60\xDD\x5B\x27\xAC\xA4\x76"
"\xD2\x62\x0F\xDC\x93\x13\xE8\x48\x9B\xA5\x6A\x70\xC9\xF4\xC3\xA8"
},
{ 65536, 64,
"\xEB\x30\xCD\xA7\x27\xC0\xF8\xB7\xE4\x5D\x5E\xF3\x0D\xB7\xCB\xE0"
"\x21\xF2\x29\x1E\x5F\x56\x93\x8D\x56\xF6\x87\xB7\x37\xC3\xB4\x27"
"\x54\x5C\x56\xA6\xD3\xA0\xBF\x2B\x2F\x47\xB4\x84\x93\xFA\xE4\x5E"
"\xD5\x0C\x2E\x9B\xBE\x49\xFD\x92\xD6\x7C\x76\x49\x05\x5F\x06\xFD"
},
{ 131008, 64,
"\x0E\xBF\x6C\xC3\xCB\xCB\xE7\x4E\x6E\xE8\x07\x47\x1B\x49\x2A\x67"
"\x39\xA5\x2F\x57\x11\x31\xA2\x50\xBC\xDF\xA0\x76\xA2\x65\x90\xD7"
"\xED\xE6\x75\x1C\x03\x26\xA0\x2C\xB1\x1C\x58\x77\x35\x52\x80\x4F"
"\xD8\x68\x67\x15\x35\x5C\x5A\x5C\xC5\x91\x96\x3A\x75\xE9\x94\xB4"
}
}
}
#endif /*USE_SALSA20*/
};
char zeroes[512];
gcry_cipher_hd_t hde;
unsigned char *buffer;
unsigned char *p;
size_t buffersize;
unsigned int n;
int i, j;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, " Starting large block stream cipher checks.\n");
memset (zeroes, 0, 512);
buffersize = 128 * 1024;
buffer = gcry_xmalloc (buffersize+1024);
memset (buffer+buffersize, 0x5a, 1024);
for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
{
if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
tv[i].algo);
continue;
}
if (verbose)
fprintf (stderr, " checking large block stream for %s [%i] (%s)\n",
gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_STREAM, 0);
if (err)
{
fail ("large stream, gcry_cipher_open for stream mode failed: %s\n",
gpg_strerror (err));
continue;
}
err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
if (err)
{
fail ("large stream, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
goto next;
}
err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("large stream, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
goto next;
}
for (j=0, p=buffer; j < buffersize/512; j++, p += 512)
{
err = gcry_cipher_encrypt (hde, p, 512, zeroes, 512);
if (err)
{
fail ("large stream, "
"gcry_cipher_encrypt (%d) block %d failed: %s\n",
i, j, gpg_strerror (err));
goto next;
}
}
for (j=0, p=buffer+buffersize; j < 1024; j++, p++)
if (*p != 0x5a)
die ("large stream, buffer corrupted at j=%d\n", j);
/* Now loop over all the data samples. */
for (j = 0; tv[i].data[j].length; j++)
{
assert (tv[i].data[j].offset + tv[i].data[j].length <= buffersize);
if (memcmp (tv[i].data[j].result,
buffer + tv[i].data[j].offset, tv[i].data[j].length))
{
fail ("large stream, encrypt mismatch entry %d:%d\n", i, j);
mismatch (tv[i].data[j].result, tv[i].data[j].length,
buffer + tv[i].data[j].offset, tv[i].data[j].length);
}
}
/*
* Let's do the same thing again but using changing block sizes.
*/
err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
if (err)
{
fail ("large stream, gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
goto next;
}
err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("large stream, gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
goto next;
}
for (n=0, p=buffer, j = 0; n < buffersize; n += j, p += j)
{
switch (j)
{
case 0: j = 1; break;
case 1: j = 64; break;
case 64: j= 384; break;
case 384: j = 63; break;
case 63: j = 512; break;
case 512: j = 32; break;
case 32: j = 503; break;
default: j = 509; break;
}
if ( n + j >= buffersize )
j = buffersize - n;
assert (j <= 512);
err = gcry_cipher_encrypt (hde, p, j, zeroes, j);
if (err)
{
fail ("large stream, "
"gcry_cipher_encrypt (%d) offset %u failed: %s\n",
i, n, gpg_strerror (err));
goto next;
}
}
for (j=0, p=buffer+buffersize; j < 1024; j++, p++)
if (*p != 0x5a)
die ("large stream, buffer corrupted at j=%d (line %d)\n",
j, __LINE__);
/* Now loop over all the data samples. */
for (j = 0; tv[i].data[j].length; j++)
{
assert (tv[i].data[j].offset + tv[i].data[j].length <= buffersize);
if (memcmp (tv[i].data[j].result,
buffer + tv[i].data[j].offset, tv[i].data[j].length))
{
fail ("large stream var, encrypt mismatch entry %d:%d\n", i, j);
mismatch (tv[i].data[j].result, tv[i].data[j].length,
buffer + tv[i].data[j].offset, tv[i].data[j].length);
}
}
next:
gcry_cipher_close (hde);
}
gcry_free (buffer);
if (verbose)
fprintf (stderr, " Completed large block stream cipher checks.\n");
}
/* Check that our bulk encryption functions work properly. */
static void
check_bulk_cipher_modes (void)
{
static const struct
{
int algo;
int mode;
const char *key;
int keylen;
const char *iv;
int ivlen;
char t1_hash[20];
} tv[] = {
{ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB,
"abcdefghijklmnop", 16,
"1234567890123456", 16,
/*[0]*/
{ 0x53, 0xda, 0x27, 0x3c, 0x78, 0x3d, 0x54, 0x66, 0x19, 0x63,
0xd7, 0xe6, 0x20, 0x10, 0xcd, 0xc0, 0x5a, 0x0b, 0x06, 0xcc }
},
{ GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB,
"abcdefghijklmnopABCDEFG", 24,
"1234567890123456", 16,
/*[1]*/
{ 0xc7, 0xb1, 0xd0, 0x09, 0x95, 0x04, 0x34, 0x61, 0x2b, 0xd9,
0xcb, 0xb3, 0xc7, 0xcb, 0xef, 0xea, 0x16, 0x19, 0x9b, 0x3e }
},
{ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB,
"abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
"1234567890123456", 16,
/*[2]*/
{ 0x31, 0xe1, 0x1f, 0x63, 0x65, 0x47, 0x8c, 0x3f, 0x53, 0xdb,
0xd9, 0x4d, 0x91, 0x1d, 0x02, 0x9c, 0x05, 0x25, 0x58, 0x29 }
},
{ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC,
"abcdefghijklmnop", 16,
"1234567890123456", 16,
/*[3]*/
{ 0xdc, 0x0c, 0xc2, 0xd9, 0x6b, 0x47, 0xf9, 0xeb, 0x06, 0xb4,
0x2f, 0x6e, 0xec, 0x72, 0xbf, 0x55, 0x26, 0x7f, 0xa9, 0x97 }
},
{ GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC,
"abcdefghijklmnopABCDEFG", 24,
"1234567890123456", 16,
/*[4]*/
{ 0x2b, 0x90, 0x9b, 0xe6, 0x40, 0xab, 0x6e, 0xc2, 0xc5, 0xb1,
0x87, 0xf5, 0x43, 0x84, 0x7b, 0x04, 0x06, 0x47, 0xd1, 0x8f }
},
{ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC,
"abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
"1234567890123456", 16,
/*[5]*/
{ 0xaa, 0xa8, 0xdf, 0x03, 0xb0, 0xba, 0xc4, 0xe3, 0xc1, 0x02,
0x38, 0x31, 0x8d, 0x86, 0xcb, 0x49, 0x6d, 0xad, 0xae, 0x01 }
},
{ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OFB,
"abcdefghijklmnop", 16,
"1234567890123456", 16,
/*[6]*/
{ 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,
/*[7]*/
{ 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,
/*[8]*/
{ 0x38, 0x8c, 0xe1, 0xe2, 0xbe, 0x67, 0x60, 0xe8, 0xeb, 0xce,
0xd0, 0xc6, 0xaa, 0xd6, 0xf6, 0x26, 0x15, 0x56, 0xd0, 0x2b }
},
{ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CTR,
"abcdefghijklmnop", 16,
"1234567890123456", 16,
/*[9]*/
{ 0x9a, 0x48, 0x94, 0xd6, 0x50, 0x46, 0x81, 0xdb, 0x68, 0x34,
0x3b, 0xc5, 0x9e, 0x66, 0x94, 0x81, 0x98, 0xa0, 0xf9, 0xff }
},
{ GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR,
"abcdefghijklmnopABCDEFG", 24,
"1234567890123456", 16,
/*[10]*/
{ 0x2c, 0x2c, 0xd3, 0x75, 0x81, 0x2a, 0x59, 0x07, 0xeb, 0x08,
0xce, 0x28, 0x4c, 0x0c, 0x6a, 0xa8, 0x8f, 0xa3, 0x98, 0x7e }
},
{ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR,
"abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
"1234567890123456", 16,
/*[11]*/
{ 0x64, 0xce, 0x73, 0x03, 0xc7, 0x89, 0x99, 0x1f, 0xf1, 0xce,
0xfe, 0xfb, 0xb9, 0x42, 0x30, 0xdf, 0xbb, 0x68, 0x6f, 0xd3 }
},
{ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB,
"abcdefghijklmnop", 16,
"1234567890123456", 16,
/*[12]*/
{ 0x51, 0xae, 0xf5, 0xac, 0x22, 0xa0, 0xba, 0x11, 0xc5, 0xaa,
0xb4, 0x70, 0x99, 0xce, 0x18, 0x08, 0x12, 0x9b, 0xb1, 0xc5 }
},
{ GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB,
"abcdefghijklmnopABCDEFG", 24,
"1234567890123456", 16,
/*[13]*/
{ 0x57, 0x91, 0xea, 0x48, 0xd8, 0xbf, 0x9e, 0xc1, 0xae, 0x33,
0xb3, 0xfd, 0xf7, 0x7a, 0xeb, 0x30, 0xb1, 0x62, 0x0d, 0x82 }
},
{ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB,
"abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
"1234567890123456", 16,
/*[14]*/
{ 0x2d, 0x71, 0x54, 0xb9, 0xc5, 0x28, 0x76, 0xff, 0x76, 0xb5,
0x99, 0x37, 0x99, 0x9d, 0xf7, 0x10, 0x6d, 0x86, 0x4f, 0x3f }
},
{ GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_XTS,
"abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
"1234567890123456", 16,
/*[15]*/
{ 0x71, 0x46, 0x40, 0xb0, 0xed, 0x6f, 0xc4, 0x82, 0x2b, 0x3f,
0xb6, 0xf7, 0x81, 0x08, 0x4c, 0x8b, 0xc1, 0x66, 0x4c, 0x1b }
},
{ GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_XTS,
"abcdefghijklmnopABCDEFGHIJKLMNOP_abcdefghijklmnopABCDEFGHIJKLMNO", 64,
"1234567890123456", 16,
/*[16]*/
{ 0x8e, 0xbc, 0xa5, 0x21, 0x0a, 0x4b, 0x53, 0x14, 0x79, 0x81,
0x25, 0xad, 0x24, 0x45, 0x98, 0xbd, 0x9f, 0x27, 0x5f, 0x01 }
}
};
gcry_cipher_hd_t hde = NULL;
gcry_cipher_hd_t hdd = NULL;
unsigned char *buffer_base, *outbuf_base; /* Allocated buffers. */
unsigned char *buffer, *outbuf; /* Aligned buffers. */
size_t buflen;
unsigned char hash[20];
int i, j, keylen, blklen;
gcry_error_t err = 0;
if (verbose)
fprintf (stderr, "Starting bulk cipher checks.\n");
buflen = 16*100; /* We check a 1600 byte buffer. */
buffer_base = gcry_xmalloc (buflen+16);
buffer = buffer_base + (16 - ((size_t)buffer_base & 0x0f));
outbuf_base = gcry_xmalloc (buflen+16);
outbuf = outbuf_base + (16 - ((size_t)outbuf_base & 0x0f));
for (i = 0; i < DIM (tv); i++)
{
if (verbose)
fprintf (stderr, " checking bulk encryption for %s [%i], mode %d\n",
gcry_cipher_algo_name (tv[i].algo),
tv[i].algo, tv[i].mode);
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);
if (err)
{
fail ("gcry_cipher_open failed: %s\n", gpg_strerror (err));
goto leave;
}
keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
if (!keylen)
{
fail ("gcry_cipher_get_algo_keylen failed\n");
goto leave;
}
err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
if (!err)
err = gcry_cipher_setkey (hdd, tv[i].key, tv[i].keylen);
if (err)
{
fail ("gcry_cipher_setkey failed: %s\n", gpg_strerror (err));
goto leave;
}
blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
if (!blklen)
{
fail ("gcry_cipher_get_algo_blklen failed\n");
goto leave;
}
err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
if (!err)
err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen);
if (err)
{
fail ("gcry_cipher_setiv failed: %s\n", gpg_strerror (err));
goto leave;
}
/* Fill the buffer with our test pattern. */
for (j=0; j < buflen; j++)
buffer[j] = ((j & 0xff) ^ ((j >> 8) & 0xff));
err = gcry_cipher_encrypt (hde, outbuf, buflen, buffer, buflen);
if (err)
{
fail ("gcry_cipher_encrypt (algo %d, mode %d) failed: %s\n",
tv[i].algo, tv[i].mode, gpg_strerror (err));
goto leave;
}
gcry_md_hash_buffer (GCRY_MD_SHA1, hash, outbuf, buflen);
#if 0
printf ("/*[%d]*/\n", i);
fputs (" {", stdout);
for (j=0; j < 20; j++)
printf (" 0x%02x%c%s", hash[j], j==19? ' ':',', j == 9? "\n ":"");
puts ("}");
#endif
if (memcmp (hash, tv[i].t1_hash, 20))
fail ("encrypt mismatch (algo %d, mode %d)\n",
tv[i].algo, tv[i].mode);
err = gcry_cipher_decrypt (hdd, outbuf, buflen, NULL, 0);
if (err)
{
fail ("gcry_cipher_decrypt (algo %d, mode %d) failed: %s\n",
tv[i].algo, tv[i].mode, gpg_strerror (err));
goto leave;
}
if (memcmp (buffer, outbuf, buflen))
fail ("decrypt mismatch (algo %d, mode %d)\n",
tv[i].algo, tv[i].mode);
gcry_cipher_close (hde); hde = NULL;
gcry_cipher_close (hdd); hdd = NULL;
}
if (verbose)
fprintf (stderr, "Completed bulk cipher checks.\n");
leave:
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
gcry_free (buffer_base);
gcry_free (outbuf_base);
}
static unsigned int
get_algo_mode_blklen (int algo, int mode)
{
unsigned int blklen = gcry_cipher_get_algo_blklen(algo);
/* Some modes override blklen. */
switch (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;
}
return blklen;
}
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)
{
static const unsigned char iv[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
u64 ctl_params[3];
int err;
gcry_cipher_reset (hd);
if (mode == GCRY_CIPHER_MODE_OCB || mode == GCRY_CIPHER_MODE_CCM)
{
err = gcry_cipher_setiv (hd, iv, sizeof(iv));
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;
}
}
if (mode == GCRY_CIPHER_MODE_CCM)
{
ctl_params[0] = nplain; /* encryptedlen */
ctl_params[1] = 0; /* aadlen */
ctl_params[2] = 16; /* authtaglen */
err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, ctl_params,
sizeof(ctl_params));
if (err)
{
fail ("pass %d, algo %d, mode %d, gcry_cipher_ctl "
"GCRYCTL_SET_CCM_LENGTHS failed: %s\n",
pass, algo, mode, gpg_strerror (err));
gcry_cipher_close (hd);
return -1;
}
}
return 0;
}
/* The core of the cipher check. In addition to the parameters passed
to check_one_cipher it also receives the KEY and the plain data.
PASS is printed with error messages. The function returns 0 on
success. */
static int
check_one_cipher_core (int algo, int mode, int flags,
const char *key, size_t nkey,
const unsigned char *plain, size_t nplain,
int bufshift, int pass)
{
gcry_cipher_hd_t hd;
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 > 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. */
blklen = nplain;
}
if (!bufshift)
{
in = in_buffer;
out = out_buffer;
}
else if (bufshift == 1)
{
in = in_buffer+1;
out = out_buffer;
}
else if (bufshift == 2)
{
in = in_buffer+1;
out = out_buffer+1;
}
else
{
in = in_buffer;
out = out_buffer+1;
}
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;
}
if (mode == GCRY_CIPHER_MODE_XTS)
{
keylen *= 2;
}
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;
}
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_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
err = gcry_cipher_encrypt (hd, out, nplain, plain, nplain);
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;
}
if (taglen > 0)
{
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)
goto err_out_free;
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);
goto err_out_free;
}
if (taglen > 0)
{
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))
fail ("pass %d, algo %d, mode %d, encrypt-decrypt mismatch\n",
pass, algo, mode);
/* Again, using in-place encryption. */
if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
memcpy (out, plain, nplain);
err = gcry_cipher_encrypt (hd, out, nplain, NULL, 0);
if (err)
{
fail ("pass %d, algo %d, mode %d, in-place, gcry_cipher_encrypt failed:"
" %s\n",
pass, algo, mode, gpg_strerror (err));
gcry_cipher_close (hd);
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))
fail ("pass %d, algo %d, mode %d, in-place, encrypt mismatch\n",
pass, algo, mode);
if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
err = gcry_cipher_decrypt (hd, out, nplain, NULL, 0);
if (err)
{
fail ("pass %d, algo %d, mode %d, in-place, gcry_cipher_decrypt failed:"
" %s\n",
pass, algo, mode, gpg_strerror (err));
gcry_cipher_close (hd);
goto err_out_free;
}
if (taglen > 0)
{
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))
fail ("pass %d, algo %d, mode %d, in-place, encrypt-decrypt mismatch\n",
pass, algo, mode);
/* Again, splitting encryption in multiple operations. */
if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
piecelen = blklen;
pos = 0;
while (pos < nplain)
{
if (piecelen > nplain - pos)
piecelen = nplain - pos;
err = gcry_cipher_encrypt (hd, out + pos, piecelen, plain + pos,
piecelen);
if (err)
{
fail ("pass %d, algo %d, mode %d, split-buffer (pos: %d, "
"piecelen: %d), gcry_cipher_encrypt failed: %s\n",
pass, algo, mode, pos, piecelen, gpg_strerror (err));
gcry_cipher_close (hd);
goto err_out_free;
}
pos += piecelen;
piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
}
if (taglen > 0)
{
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)
goto err_out_free;
piecelen = blklen;
pos = 0;
while (pos < nplain)
{
if (piecelen > nplain - pos)
piecelen = nplain - pos;
err = gcry_cipher_decrypt (hd, in + pos, piecelen, out + pos, piecelen);
if (err)
{
fail ("pass %d, algo %d, mode %d, split-buffer (pos: %d, "
"piecelen: %d), gcry_cipher_decrypt failed: %s\n",
pass, algo, mode, pos, piecelen, gpg_strerror (err));
gcry_cipher_close (hd);
goto err_out_free;
}
pos += piecelen;
piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
}
if (taglen > 0)
{
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);
/* Again, using in-place encryption and splitting encryption in multiple
* operations. */
if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
piecelen = blklen;
pos = 0;
while (pos < nplain)
{
if (piecelen > nplain - pos)
piecelen = nplain - pos;
memcpy (out + pos, plain + pos, piecelen);
err = gcry_cipher_encrypt (hd, out + pos, piecelen, NULL, 0);
if (err)
{
fail ("pass %d, algo %d, mode %d, in-place split-buffer (pos: %d, "
"piecelen: %d), gcry_cipher_encrypt failed: %s\n",
pass, algo, mode, pos, piecelen, gpg_strerror (err));
gcry_cipher_close (hd);
goto err_out_free;
}
pos += piecelen;
piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
}
if (memcmp (enc_result, out, nplain))
fail ("pass %d, algo %d, mode %d, in-place split-buffer, encrypt mismatch\n",
pass, algo, mode);
if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
goto err_out_free;
piecelen = blklen;
pos = 0;
while (pos < nplain)
{
if (piecelen > nplain - pos)
piecelen = nplain - pos;
err = gcry_cipher_decrypt (hd, out + pos, piecelen, NULL, 0);
if (err)
{
fail ("pass %d, algo %d, mode %d, in-place split-buffer (pos: %d, "
"piecelen: %d), gcry_cipher_decrypt failed: %s\n",
pass, algo, mode, pos, piecelen, gpg_strerror (err));
gcry_cipher_close (hd);
goto err_out_free;
}
pos += piecelen;
piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
}
if (memcmp (plain, out, nplain))
fail ("pass %d, algo %d, mode %d, in-place split-buffer, encrypt-decrypt"
" mismatch\n", pass, algo, mode);
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 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;
int bufshift, i;
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 < medium_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,
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,
medium_buffer_size, bufshift,
1+10*bufshift))
goto out;
/* Pass 2: Key not aligned and data not aligned. */
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,
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;
out:
free (plain);
}
static void
check_ciphers (void)
{
static const int algos[] = {
#if USE_BLOWFISH
GCRY_CIPHER_BLOWFISH,
#endif
#if USE_DES
GCRY_CIPHER_DES,
GCRY_CIPHER_3DES,
#endif
#if USE_CAST5
GCRY_CIPHER_CAST5,
#endif
#if USE_AES
GCRY_CIPHER_AES,
GCRY_CIPHER_AES192,
GCRY_CIPHER_AES256,
#endif
#if USE_TWOFISH
GCRY_CIPHER_TWOFISH,
GCRY_CIPHER_TWOFISH128,
#endif
#if USE_SERPENT
GCRY_CIPHER_SERPENT128,
GCRY_CIPHER_SERPENT192,
GCRY_CIPHER_SERPENT256,
#endif
#if USE_RFC2268
GCRY_CIPHER_RFC2268_40,
#endif
#if USE_SEED
GCRY_CIPHER_SEED,
#endif
#if USE_CAMELLIA
GCRY_CIPHER_CAMELLIA128,
GCRY_CIPHER_CAMELLIA192,
GCRY_CIPHER_CAMELLIA256,
#endif
#if USE_IDEA
GCRY_CIPHER_IDEA,
#endif
#if USE_GOST28147
GCRY_CIPHER_GOST28147,
#endif
0
};
static const int algos2[] = {
#if USE_ARCFOUR
GCRY_CIPHER_ARCFOUR,
#endif
#if USE_SALSA20
GCRY_CIPHER_SALSA20,
GCRY_CIPHER_SALSA20R12,
#endif
#if USE_CHACHA20
GCRY_CIPHER_CHACHA20,
#endif
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 (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
algos[i]);
continue;
}
if (verbose)
fprintf (stderr, " checking %s [%i]\n",
gcry_cipher_algo_name (algos[i]),
gcry_cipher_map_name (gcry_cipher_algo_name (algos[i])));
check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0);
check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0);
check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB8, 0);
check_one_cipher (algos[i], GCRY_CIPHER_MODE_OFB, 0);
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)
check_one_cipher (algos[i], GCRY_CIPHER_MODE_GCM, 0);
if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_OCB_BLOCK_LEN)
check_one_cipher (algos[i], GCRY_CIPHER_MODE_OCB, 0);
if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_XTS_BLOCK_LEN)
check_one_cipher (algos[i], GCRY_CIPHER_MODE_XTS, 0);
}
for (i = 0; algos2[i]; i++)
{
if (gcry_cipher_test_algo (algos2[i]) && in_fips_mode)
{
if (verbose)
fprintf (stderr, " algorithm %d not available in fips mode\n",
algos2[i]);
continue;
}
if (verbose)
fprintf (stderr, " checking %s\n",
gcry_cipher_algo_name (algos2[i]));
check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0);
if (algos2[i] == GCRY_CIPHER_CHACHA20)
check_one_cipher (algos2[i], GCRY_CIPHER_MODE_POLY1305, 0);
}
/* we have now run all cipher's selftests */
if (verbose)
fprintf (stderr, "Completed Cipher checks.\n");
/* TODO: add some extra encryption to test the higher level functions */
}
static void
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 ();
check_poly1305_cipher ();
check_ocb_cipher ();
check_xts_cipher ();
check_eax_cipher ();
check_gost28147_cipher ();
check_stream_cipher ();
check_stream_cipher_large_block ();
if (verbose)
fprintf (stderr, "Completed Cipher Mode checks.\n");
}
static void
fillbuf_count (char *buf, size_t buflen, unsigned char pos)
{
while (buflen--)
*((unsigned char *)(buf++)) = pos++;
}
static void
check_one_md (int algo, const char *data, int len, const char *expect, int elen,
const char *key, int klen)
{
gcry_md_hd_t hd, hd2;
unsigned char *p;
int mdlen;
int i, j;
int xof = 0;
gcry_error_t err = 0;
err = gcry_md_open (&hd, algo, 0);
if (err)
{
fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
return;
}
mdlen = gcry_md_get_algo_dlen (algo);
if (mdlen < 1 || mdlen > 500)
{
if (mdlen == 0 && (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256))
{
xof = 1;
}
else
{
gcry_md_close (hd);
fail ("algo %d, gcry_md_get_algo_dlen failed: %d\n", algo, mdlen);
return;
}
}
if (key && klen)
{
err = gcry_md_setkey (hd, key, klen);
if (err)
{
gcry_md_close (hd);
fail ("algo %d, gcry_md_setkey failed: %s\n", algo, gpg_strerror (err));
return;
}
}
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)
{
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);
gcry_md_write (hd, buf, i);
for (j = 0; j < i; j++)
gcry_md_write (hd2, &buf[j], 1);
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,... */
{
char aaa[1000];
size_t left = 1000 * 1000;
size_t startlen = 1;
size_t piecelen = startlen;
if (*data == '!')
memset (aaa, 'a', 1000);
/* Write in chuck with all sizes 1 to 1000 (500500 bytes) */
for (i = 1; i <= 1000 && left > 0; i++)
{
piecelen = i;
if (piecelen > sizeof(aaa))
piecelen = sizeof(aaa);
if (piecelen > left)
piecelen = left;
if (*data == '?')
fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
gcry_md_write (hd, aaa, piecelen);
left -= piecelen;
}
/* Write in odd size chunks so that we test the buffering. */
while (left > 0)
{
if (piecelen > sizeof(aaa))
piecelen = sizeof(aaa);
if (piecelen > left)
piecelen = left;
if (*data == '?')
fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
gcry_md_write (hd, aaa, piecelen);
left -= piecelen;
if (piecelen == sizeof(aaa))
piecelen = ++startlen;
else
piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0);
}
}
else
gcry_md_write (hd, data, len);
err = gcry_md_copy (&hd2, hd);
if (err)
{
fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
}
gcry_md_close (hd);
if (!xof)
{
p = gcry_md_read (hd2, algo);
if (memcmp (p, expect, mdlen))
{
printf ("computed: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", p[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
}
else
{
char buf[1000];
int outmax = sizeof(buf) > elen ? elen : sizeof(buf);
err = gcry_md_copy (&hd, hd2);
if (err)
{
fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
}
err = gcry_md_extract(hd2, algo, buf, outmax);
if (err)
{
fail ("algo %d, gcry_md_extract failed: %s\n", algo, gpg_strerror (err));
}
if (memcmp (buf, expect, outmax))
{
printf ("computed: ");
for (i = 0; i < outmax; i++)
printf ("%02x ", buf[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < outmax; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
memset(buf, 0, sizeof(buf));
/* Extract one byte at time. */
for (i = 0; i < outmax && !err; i++)
err = gcry_md_extract(hd, algo, &buf[i], 1);
if (err)
{
fail ("algo %d, gcry_md_extract failed: %s\n", algo, gpg_strerror (err));
}
if (memcmp (buf, expect, outmax))
{
printf ("computed: ");
for (i = 0; i < outmax; i++)
printf ("%02x ", buf[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < outmax; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
if (*data == '!' && !data[1])
{
int crcalgo = GCRY_MD_RMD160;
gcry_md_hd_t crc1, crc2;
size_t startlen;
size_t piecelen;
size_t left;
const unsigned char *p1, *p2;
int crclen;
crclen = gcry_md_get_algo_dlen (crcalgo);
err = gcry_md_open (&crc1, crcalgo, 0);
if (err)
{
fail ("algo %d, crcalgo: %d, gcry_md_open failed: %s\n", algo,
crcalgo, gpg_strerror (err));
return;
}
err = gcry_md_open (&crc2, crcalgo, 0);
if (err)
{
fail ("algo %d, crcalgo: %d, gcry_md_open failed: %s\n", algo,
crcalgo, gpg_strerror (err));
return;
}
/* Extract large chucks, total 1000000 additional bytes. */
for (i = 0; i < 1000; i++)
{
err = gcry_md_extract(hd, algo, buf, 1000);
if (!err)
gcry_md_write(crc1, buf, 1000);
}
if (err)
{
fail ("algo %d, gcry_md_extract failed: %s\n", algo,
gpg_strerror (err));
}
/* Extract in odd size chunks, total 1000000 additional bytes. */
left = 1000 * 1000;
startlen = 1;
piecelen = startlen;
while (!err && left > 0)
{
if (piecelen > sizeof(buf))
piecelen = sizeof(buf);
if (piecelen > left)
piecelen = left;
err = gcry_md_extract (hd2, algo, buf, piecelen);
if (!err)
gcry_md_write(crc2, buf, piecelen);
if (err)
{
fail ("algo %d, gcry_md_extract failed: %s\n", algo,
gpg_strerror (err));
}
left -= piecelen;
if (piecelen == sizeof(buf))
piecelen = ++startlen;
else
piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0);
}
p1 = gcry_md_read (crc1, crcalgo);
p2 = gcry_md_read (crc2, crcalgo);
if (memcmp (p1, p2, crclen))
{
printf ("computed: ");
for (i = 0; i < crclen; i++)
printf ("%02x ", p2[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < crclen; i++)
printf ("%02x ", p1[i] & 0xFF);
printf ("\n");
fail ("algo %d, large xof output mismatch\n", algo);
}
gcry_md_close (crc1);
gcry_md_close (crc2);
}
gcry_md_close (hd);
}
gcry_md_close (hd2);
}
static void
check_one_md_multi (int algo, const char *data, int len, const char *expect)
{
gpg_error_t err;
gcry_buffer_t iov[3];
int iovcnt;
char digest[64];
int mdlen;
int i;
mdlen = gcry_md_get_algo_dlen (algo);
if (mdlen < 1 || mdlen > 64)
{
if (mdlen == 0 && (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256))
return;
fail ("check_one_md_multi: algo %d, gcry_md_get_algo_dlen failed: %d\n",
algo, mdlen);
return;
}
if (*data == '!' && !data[1])
return; /* We can't do that here. */
if (*data == '?' && !data[1])
return; /* We can't do that here. */
memset (iov, 0, sizeof iov);
iov[0].data = (void*)data;
if (len)
{
iov[0].len = 1;
len--;
data++;
}
iovcnt = 1;
if (len >= 4)
{
iov[iovcnt].data = (void*)data;
iov[iovcnt].len = 4;
iovcnt++;
data += 4;
len -= 4;
}
iov[iovcnt].data = (void*)data;
iov[iovcnt].len = len;
iovcnt++;
assert (iovcnt <= DIM (iov));
err = gcry_md_hash_buffers (algo, 0, digest, iov, iovcnt);
if (err)
{
fail ("check_one_md_multi: algo %d, gcry_hash_buffers failed: %s\n",
algo, gpg_strerror (err));
return;
}
if (memcmp (digest, expect, mdlen))
{
printf ("computed: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", digest[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("check_one_md_multi: algo %d, digest mismatch\n", algo);
}
}
static void
check_one_md_final(int algo, const char *expect, unsigned int expectlen)
{
char inbuf[288 + 1];
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;
}
for (i = 0; i < sizeof(inbuf); i++)
inbuf[i] = i;
gcry_md_hash_buffer (algo, xorbuf, NULL, 0);
for (i = 1; i < sizeof(inbuf); i++)
{
gcry_md_hash_buffer (algo, digest, inbuf, i);
for (j = 0; j < expectlen; j++)
xorbuf[j] ^= digest[j];
}
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[] =
"\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"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
static const struct algos
{
int md;
const char *data;
const char *expect;
int datalen;
int expectlen;
const char *key;
int keylen;
} algos[] =
{
{ GCRY_MD_MD2, "",
"\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73" },
{ GCRY_MD_MD2, "a",
"\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0\xb5\xd1" },
{ GCRY_MD_MD2, "message digest",
"\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0" },
{ GCRY_MD_MD4, "",
"\x31\xD6\xCF\xE0\xD1\x6A\xE9\x31\xB7\x3C\x59\xD7\xE0\xC0\x89\xC0" },
{ GCRY_MD_MD4, "a",
"\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24" },
{ GCRY_MD_MD4, "message digest",
"\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b" },
{ GCRY_MD_MD5, "",
"\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\x09\x98\xEC\xF8\x42\x7E" },
{ GCRY_MD_MD5, "a",
"\x0C\xC1\x75\xB9\xC0\xF1\xB6\xA8\x31\xC3\x99\xE2\x69\x77\x26\x61" },
{ GCRY_MD_MD5, "abc",
"\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72" },
{ GCRY_MD_MD5, "message digest",
"\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0" },
{ GCRY_MD_MD5,
"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.",
"\xc4\x1a\x5c\x0b\x44\x5f\xba\x1a\xda\xbc\xc0\x38\x0e\x0c\x9e\x33" },
{ GCRY_MD_MD5, "!",
"\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21" },
{ GCRY_MD_MD5, "?",
"\x5c\x72\x5c\xbc\x2d\xbb\xe1\x14\x81\x59\xe9\xd9\xcf\x90\x64\x8f" },
{ GCRY_MD_SHA1, "abc",
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E"
"\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" },
{ GCRY_MD_SHA1,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE"
"\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1" },
{ GCRY_MD_SHA1, "!" /* kludge for "a"*1000000 */ ,
"\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E"
"\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" },
{ GCRY_MD_SHA1, "?" /* kludge for "\x00\x01\x02"..."\xfe\xff\x00\x01"... (length 1000000) */ ,
"\x5f\x8d\x3c\x4f\x12\xf0\x49\x9e\x28\x73"
"\x79\xec\x97\x3b\x98\x4c\x94\x75\xaa\x8f" },
{ GCRY_MD_SHA1,
"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.",
"\xf5\xd9\xcb\x66\x91\xb4\x7a\x7c\x60\x35\xe2\x1c\x38\x26\x52\x13"
"\x8e\xd5\xe5\xdf" },
/* From RFC3874 */
{ GCRY_MD_SHA224, "abc",
"\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3"
"\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7" },
{ GCRY_MD_SHA224,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50"
"\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25" },
{ GCRY_MD_SHA224, "!",
"\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b"
"\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" },
{ GCRY_MD_SHA224, "?",
"\xfa\xb9\xf0\xdf\x12\xfe\xa1\x1a\x34\x78\x96\x31\xe6\x53\x48\xbf"
"\x3b\xca\x70\x78\xf2\x44\xdf\x62\xab\x27\xb8\xda" },
{ GCRY_MD_SHA224,
"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.",
"\x80\xf0\x60\x79\xb0\xe9\x65\xab\x8a\x76\xbf\x6e\x88\x64\x75\xe7"
"\xfd\xf0\xc2\x4c\xf6\xf2\xa6\x01\xed\x50\x71\x08" },
{ GCRY_MD_SHA256, "abc",
"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
"\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" },
{ GCRY_MD_SHA256,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
"\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
{ GCRY_MD_SHA256, "!",
"\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
"\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" },
{ GCRY_MD_SHA256, "?",
"\x67\x87\x0d\xfc\x9c\x64\xe7\xaa\x27\x0a\x3f\x7e\x80\x51\xae\x65"
"\xd2\x07\xf9\x3f\xc3\xdf\x04\xd7\x57\x2e\x63\x65\xaf\x69\xcd\x0d" },
{ GCRY_MD_SHA256,
"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.",
"\xb0\x18\x70\x67\xb8\xac\x68\x50\xec\x95\x43\x77\xb5\x44\x5b\x0f"
"\x2e\xbd\x40\xc9\xdc\x2a\x2c\x33\x8b\x53\xeb\x3e\x9e\x01\xd7\x02" },
{ GCRY_MD_SHA384, "abc",
"\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
"\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
"\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7" },
{ GCRY_MD_SHA384,
"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.",
"\xe4\x6d\xb4\x28\x33\x77\x99\x49\x94\x0f\xcf\x87\xc2\x2f\x30\xd6"
"\x06\x24\x82\x9d\x80\x64\x8a\x07\xa1\x20\x8f\x5f\xf3\x85\xb3\xaa"
"\x39\xb8\x61\x00\xfc\x7f\x18\xc6\x82\x23\x4b\x45\xfa\xf1\xbc\x69" },
{ GCRY_MD_SHA384, "!",
"\x9d\x0e\x18\x09\x71\x64\x74\xcb\x08\x6e\x83\x4e\x31\x0a\x4a\x1c"
"\xed\x14\x9e\x9c\x00\xf2\x48\x52\x79\x72\xce\xc5\x70\x4c\x2a\x5b"
"\x07\xb8\xb3\xdc\x38\xec\xc4\xeb\xae\x97\xdd\xd8\x7f\x3d\x89\x85" },
{ GCRY_MD_SHA384, "?",
"\xfa\x77\xbb\x86\x3a\xd5\xae\x88\xa9\x9c\x5e\xda\xb5\xc7\xcb\x40"
"\xcd\xf4\x30\xef\xa8\x1b\x23\x7b\xa9\xde\xfd\x81\x12\xf6\x7e\xed"
"\xa7\xd2\x27\x91\xd1\xbc\x76\x44\x57\x59\x71\x11\xe6\x8a\x2c\xde" },
{ GCRY_MD_SHA512, "abc",
"\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31"
"\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A"
"\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD"
"\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F" },
{ GCRY_MD_SHA512,
"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.",
"\x72\x8c\xde\xd8\xe4\xd7\xb6\xa5\x0f\xde\x6b\x4d\x33\xaf\x15\x19"
"\xdd\xec\x62\x0f\xf7\x1a\x1e\x10\x32\x05\x02\xa6\xb0\x1f\x70\x37"
"\xbc\xd7\x15\xed\x71\x6c\x78\x20\xc8\x54\x87\xd0\x66\x6a\x17\x83"
"\x05\x61\x92\xbe\xcc\x8f\x3b\xbf\x11\x72\x22\x69\x23\x5b\x48\x5c" },
{ GCRY_MD_SHA512, "!",
"\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
"\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
"\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
"\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b" },
{ GCRY_MD_SHA512, "?",
"\x91\xe9\x42\x4e\xa9\xdc\x44\x01\x40\x64\xa4\x5a\x69\xcc\xac\xa3"
"\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" },
{ GCRY_MD_SHA3_256, "abc",
"\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd"
"\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32" },
{ GCRY_MD_SHA3_384, "abc",
"\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d"
"\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2"
"\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25" },
{ GCRY_MD_SHA3_512, "abc",
"\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e"
"\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e"
"\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40"
"\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0" },
{ GCRY_MD_SHA3_224, "",
"\x6b\x4e\x03\x42\x36\x67\xdb\xb7\x3b\x6e\x15\x45\x4f\x0e\xb1\xab"
"\xd4\x59\x7f\x9a\x1b\x07\x8e\x3f\x5b\x5a\x6b\xc7" },
{ GCRY_MD_SHA3_256, "",
"\xa7\xff\xc6\xf8\xbf\x1e\xd7\x66\x51\xc1\x47\x56\xa0\x61\xd6\x62"
"\xf5\x80\xff\x4d\xe4\x3b\x49\xfa\x82\xd8\x0a\x4b\x80\xf8\x43\x4a" },
{ GCRY_MD_SHA3_384, "",
"\x0c\x63\xa7\x5b\x84\x5e\x4f\x7d\x01\x10\x7d\x85\x2e\x4c\x24\x85"
"\xc5\x1a\x50\xaa\xaa\x94\xfc\x61\x99\x5e\x71\xbb\xee\x98\x3a\x2a"
"\xc3\x71\x38\x31\x26\x4a\xdb\x47\xfb\x6b\xd1\xe0\x58\xd5\xf0\x04" },
{ GCRY_MD_SHA3_512, "",
"\xa6\x9f\x73\xcc\xa2\x3a\x9a\xc5\xc8\xb5\x67\xdc\x18\x5a\x75\x6e"
"\x97\xc9\x82\x16\x4f\xe2\x58\x59\xe0\xd1\xdc\xc1\x47\x5c\x80\xa6"
"\x15\xb2\x12\x3a\xf1\xf5\xf9\x4c\x11\xe3\xe9\x40\x2c\x3a\xc5\x58"
"\xf5\x00\x19\x9d\x95\xb6\xd3\xe3\x01\x75\x85\x86\x28\x1d\xcd\x26" },
{ GCRY_MD_SHA3_224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
"nomnopnopq",
"\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79\xba"
"\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33" },
{ GCRY_MD_SHA3_256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
"nomnopnopq",
"\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e\x2c"
"\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d\x33\x76" },
{ GCRY_MD_SHA3_384, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
"nomnopnopq",
"\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49\x2e"
"\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4\xad\x5a"
"\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0\x65\x7c\x22" },
{ GCRY_MD_SHA3_512, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
"nomnopnopq",
"\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8\x18"
"\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91\x63\x6d"
"\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7\x8c\x08\x63"
"\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11\x39\xd6\xe7\x5e" },
{ GCRY_MD_SHA3_224, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk"
"lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
"\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5"
"\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc" },
{ GCRY_MD_SHA3_256, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk"
"lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
"\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb"
"\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18" },
{ GCRY_MD_SHA3_384, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk"
"lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
"\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91"
"\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc"
"\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7" },
{ GCRY_MD_SHA3_512, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk"
"lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
"\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9"
"\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa"
"\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89"
"\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85" },
{ GCRY_MD_SHA3_224, "!",
"\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c"
"\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c" },
{ GCRY_MD_SHA3_256, "!",
"\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6"
"\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1" },
{ GCRY_MD_SHA3_384, "!",
"\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad"
"\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84"
"\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40" },
{ GCRY_MD_SHA3_512, "!",
"\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e"
"\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59"
"\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66"
"\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87" },
{ GCRY_MD_SHA3_224, "?",
"\x1b\xd1\xc6\x12\x02\x35\x52\x8b\x44\x7e\x16\x39\x20\x05\xec\x67"
"\x2d\x57\x20\xe0\x90\xc9\x78\x08\x86\x4f\x1b\xd0" },
{ GCRY_MD_SHA3_256, "?",
"\xfe\xb7\xf4\x76\x78\x97\x48\x2f\xe2\x29\x1b\x66\x85\xc1\x7b\x45"
"\xc5\x08\xed\x82\x50\xcc\x5d\x99\x96\xd2\xc3\x82\x1a\xa8\xd4\xa7" },
{ GCRY_MD_SHA3_384, "?",
"\x45\x1f\x0b\x93\x4b\xca\x3e\x65\x93\xd4\xaa\x8c\x18\xc1\x04\x84"
"\x12\xd5\x1e\x35\xe1\x05\xd9\x77\x3f\xc1\x08\x8b\x77\x36\xad\x4a"
"\x33\x70\xaf\x49\x8b\xea\x4c\x5c\x52\xe7\x5b\xed\x31\x74\x57\x12" },
{ GCRY_MD_SHA3_512, "?",
"\xa2\xee\xb5\x6f\x2a\x87\xa5\xb3\x9b\xd9\x1c\xf0\xaa\xdf\xb1\xd5"
"\xad\x0a\x1a\xaa\xd3\x63\x81\xcf\xb8\x7c\x36\xa7\x80\x3b\x03\xd6"
"\x31\x5c\x5d\x33\x8e\x52\xb1\x42\x4d\x27\x1c\xa2\xa5\xf2\xc5\x97"
"\x10\x12\xe5\xee\x86\xa3\xcc\xaf\x91\x7a\x94\x28\x65\xea\x66\xe3" },
{ GCRY_MD_RMD160, "",
"\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28"
"\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" },
{ GCRY_MD_RMD160, "a",
"\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae"
"\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe" },
{ GCRY_MD_RMD160, "abc",
"\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04"
"\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc" },
{ GCRY_MD_RMD160, "message digest",
"\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8"
"\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" },
{ GCRY_MD_RMD160,
"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.",
"\x06\x6d\x3c\x4e\xc9\xba\x89\x75\x16\x90\x96\x4e\xfd\x43\x07\xde"
"\x04\xca\x69\x6b" },
{ GCRY_MD_RMD160, "!",
"\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83"
"\x25\xdc\x15\x28" },
{ GCRY_MD_RMD160, "?",
"\x68\x14\x86\x70\x3d\x51\x4e\x36\x68\x50\xf8\xb3\x00\x75\xda\x49"
"\x0a\xaa\x2c\xf6" },
{ GCRY_MD_CRC32, "", "\x00\x00\x00\x00" },
{ GCRY_MD_CRC32, "foo", "\x8c\x73\x65\x21" },
{ GCRY_MD_CRC32,
"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.",
"\x4A\x53\x7D\x67" },
{ GCRY_MD_CRC32, "123456789", "\xcb\xf4\x39\x26" },
{ GCRY_MD_CRC32, "!", "\xdc\x25\xbf\xbc" },
{ GCRY_MD_CRC32, "?", "\x61\x82\x29\x1B" },
{ GCRY_MD_CRC32_RFC1510, "", "\x00\x00\x00\x00" },
{ GCRY_MD_CRC32_RFC1510, "foo", "\x73\x32\xbc\x33" },
{ GCRY_MD_CRC32_RFC1510, "test0123456789", "\xb8\x3e\x88\xd6" },
{ GCRY_MD_CRC32_RFC1510, "MASSACHVSETTS INSTITVTE OF TECHNOLOGY",
"\xe3\x41\x80\xf7" },
{ GCRY_MD_CRC32_RFC1510, "\x80\x00", "\x3b\x83\x98\x4b", 2 },
{ GCRY_MD_CRC32_RFC1510, "\x00\x08", "\x0e\xdb\x88\x32", 2 },
{ GCRY_MD_CRC32_RFC1510, "\x00\x80", "\xed\xb8\x83\x20", 2 },
{ GCRY_MD_CRC32_RFC1510, "\x80", "\xed\xb8\x83\x20" },
{ GCRY_MD_CRC32_RFC1510, "\x80\x00\x00\x00", "\xed\x59\xb6\x3b", 4 },
{ GCRY_MD_CRC32_RFC1510, "\x00\x00\x00\x01", "\x77\x07\x30\x96", 4 },
{ GCRY_MD_CRC32_RFC1510, "123456789", "\x2d\xfd\x2d\x88" },
{ GCRY_MD_CRC32_RFC1510, "!", "\xce\x5c\x74\x22" },
{ GCRY_MD_CRC32_RFC1510, "?", "\x73\xfb\xe2\x85" },
{ GCRY_MD_CRC24_RFC2440, "", "\xb7\x04\xce" },
{ GCRY_MD_CRC24_RFC2440, "foo", "\x4f\xc2\x55" },
{ GCRY_MD_CRC24_RFC2440, "123456789", "\x21\xcf\x02" },
{ GCRY_MD_CRC24_RFC2440, "!", "\xa5\xcb\x6b" },
{ GCRY_MD_CRC24_RFC2440, "?", "\x7f\x67\x03" },
{ GCRY_MD_TIGER, "",
"\x24\xF0\x13\x0C\x63\xAC\x93\x32\x16\x16\x6E\x76"
"\xB1\xBB\x92\x5F\xF3\x73\xDE\x2D\x49\x58\x4E\x7A" },
{ GCRY_MD_TIGER, "abc",
"\xF2\x58\xC1\xE8\x84\x14\xAB\x2A\x52\x7A\xB5\x41"
"\xFF\xC5\xB8\xBF\x93\x5F\x7B\x95\x1C\x13\x29\x51" },
{ GCRY_MD_TIGER, "Tiger",
"\x9F\x00\xF5\x99\x07\x23\x00\xDD\x27\x6A\xBB\x38"
"\xC8\xEB\x6D\xEC\x37\x79\x0C\x11\x6F\x9D\x2B\xDF" },
{ GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg"
"hijklmnopqrstuvwxyz0123456789+-",
"\x87\xFB\x2A\x90\x83\x85\x1C\xF7\x47\x0D\x2C\xF8"
"\x10\xE6\xDF\x9E\xB5\x86\x44\x50\x34\xA5\xA3\x86" },
{ GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdef"
"ghijklmnopqrstuvwxyz+0123456789",
"\x46\x7D\xB8\x08\x63\xEB\xCE\x48\x8D\xF1\xCD\x12"
"\x61\x65\x5D\xE9\x57\x89\x65\x65\x97\x5F\x91\x97" },
{ GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
"by Ross Anderson and Eli Biham",
"\x0C\x41\x0A\x04\x29\x68\x86\x8A\x16\x71\xDA\x5A"
"\x3F\xD2\x9A\x72\x5E\xC1\xE4\x57\xD3\xCD\xB3\x03" },
{ GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
"by Ross Anderson and Eli Biham, proceedings of Fa"
"st Software Encryption 3, Cambridge.",
"\xEB\xF5\x91\xD5\xAF\xA6\x55\xCE\x7F\x22\x89\x4F"
"\xF8\x7F\x54\xAC\x89\xC8\x11\xB6\xB0\xDA\x31\x93" },
{ GCRY_MD_TIGER, "Tiger - A Fast New Hash Function, "
"by Ross Anderson and Eli Biham, proceedings of Fa"
"st Software Encryption 3, Cambridge, 1996.",
"\x3D\x9A\xEB\x03\xD1\xBD\x1A\x63\x57\xB2\x77\x4D"
"\xFD\x6D\x5B\x24\xDD\x68\x15\x1D\x50\x39\x74\xFC" },
{ GCRY_MD_TIGER, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefgh"
"ijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRS"
"TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
"\x00\xB8\x3E\xB4\xE5\x34\x40\xC5\x76\xAC\x6A\xAE"
"\xE0\xA7\x48\x58\x25\xFD\x15\xE7\x0A\x59\xFF\xE4" },
{ GCRY_MD_TIGER1, "",
"\x32\x93\xAC\x63\x0C\x13\xF0\x24\x5F\x92\xBB\xB1"
"\x76\x6E\x16\x16\x7A\x4E\x58\x49\x2D\xDE\x73\xF3" },
{ GCRY_MD_TIGER1, "a",
"\x77\xBE\xFB\xEF\x2E\x7E\xF8\xAB\x2E\xC8\xF9\x3B"
"\xF5\x87\xA7\xFC\x61\x3E\x24\x7F\x5F\x24\x78\x09" },
{ GCRY_MD_TIGER1, "abc",
"\x2A\xAB\x14\x84\xE8\xC1\x58\xF2\xBF\xB8\xC5\xFF"
"\x41\xB5\x7A\x52\x51\x29\x13\x1C\x95\x7B\x5F\x93" },
{ GCRY_MD_TIGER1, "message digest",
"\xD9\x81\xF8\xCB\x78\x20\x1A\x95\x0D\xCF\x30\x48"
"\x75\x1E\x44\x1C\x51\x7F\xCA\x1A\xA5\x5A\x29\xF6" },
{ GCRY_MD_TIGER1, "abcdefghijklmnopqrstuvwxyz",
"\x17\x14\xA4\x72\xEE\xE5\x7D\x30\x04\x04\x12\xBF"
"\xCC\x55\x03\x2A\x0B\x11\x60\x2F\xF3\x7B\xEE\xE9" },
{ GCRY_MD_TIGER1,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"\x0F\x7B\xF9\xA1\x9B\x9C\x58\xF2\xB7\x61\x0D\xF7"
"\xE8\x4F\x0A\xC3\xA7\x1C\x63\x1E\x7B\x53\xF7\x8E" },
{ GCRY_MD_TIGER1,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "0123456789",
"\x8D\xCE\xA6\x80\xA1\x75\x83\xEE\x50\x2B\xA3\x8A"
"\x3C\x36\x86\x51\x89\x0F\xFB\xCC\xDC\x49\xA8\xCC" },
{ GCRY_MD_TIGER1,
"1234567890" "1234567890" "1234567890" "1234567890"
"1234567890" "1234567890" "1234567890" "1234567890",
"\x1C\x14\x79\x55\x29\xFD\x9F\x20\x7A\x95\x8F\x84"
"\xC5\x2F\x11\xE8\x87\xFA\x0C\xAB\xDF\xD9\x1B\xFD" },
{ GCRY_MD_TIGER1, "!",
"\x6D\xB0\xE2\x72\x9C\xBE\xAD\x93\xD7\x15\xC6\xA7"
"\xD3\x63\x02\xE9\xB3\xCE\xE0\xD2\xBC\x31\x4B\x41" },
{ GCRY_MD_TIGER1,
"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.",
"\x60\xee\xdf\x95\x39\xc8\x44\x94\x64\xdc\xdf\x3d\x2e\x1c\xe5\x79"
"\x6a\x95\xbd\x30\x68\x8c\x7e\xb8" },
{ GCRY_MD_TIGER1, "?",
"\x4b\xe2\x3f\x23\xf5\x34\xbe\xbf\x97\x42\x95\x80"
"\x54\xe4\x6c\x12\x64\x85\x44\x0a\xa9\x49\x9b\x65" },
{ GCRY_MD_TIGER2, "",
"\x44\x41\xBE\x75\xF6\x01\x87\x73\xC2\x06\xC2\x27"
"\x45\x37\x4B\x92\x4A\xA8\x31\x3F\xEF\x91\x9F\x41" },
{ GCRY_MD_TIGER2, "a",
"\x67\xE6\xAE\x8E\x9E\x96\x89\x99\xF7\x0A\x23\xE7"
"\x2A\xEA\xA9\x25\x1C\xBC\x7C\x78\xA7\x91\x66\x36" },
{ GCRY_MD_TIGER2, "abc",
"\xF6\x8D\x7B\xC5\xAF\x4B\x43\xA0\x6E\x04\x8D\x78"
"\x29\x56\x0D\x4A\x94\x15\x65\x8B\xB0\xB1\xF3\xBF" },
{ GCRY_MD_TIGER2, "message digest",
"\xE2\x94\x19\xA1\xB5\xFA\x25\x9D\xE8\x00\x5E\x7D"
"\xE7\x50\x78\xEA\x81\xA5\x42\xEF\x25\x52\x46\x2D" },
{ GCRY_MD_TIGER2, "abcdefghijklmnopqrstuvwxyz",
"\xF5\xB6\xB6\xA7\x8C\x40\x5C\x85\x47\xE9\x1C\xD8"
"\x62\x4C\xB8\xBE\x83\xFC\x80\x4A\x47\x44\x88\xFD" },
{ GCRY_MD_TIGER2,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"\xA6\x73\x7F\x39\x97\xE8\xFB\xB6\x3D\x20\xD2\xDF"
"\x88\xF8\x63\x76\xB5\xFE\x2D\x5C\xE3\x66\x46\xA9" },
{ GCRY_MD_TIGER2,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "0123456789",
"\xEA\x9A\xB6\x22\x8C\xEE\x7B\x51\xB7\x75\x44\xFC"
"\xA6\x06\x6C\x8C\xBB\x5B\xBA\xE6\x31\x95\x05\xCD" },
{ GCRY_MD_TIGER2,
"1234567890" "1234567890" "1234567890" "1234567890"
"1234567890" "1234567890" "1234567890" "1234567890",
"\xD8\x52\x78\x11\x53\x29\xEB\xAA\x0E\xEC\x85\xEC"
"\xDC\x53\x96\xFD\xA8\xAA\x3A\x58\x20\x94\x2F\xFF" },
{ GCRY_MD_TIGER2, "!",
"\xE0\x68\x28\x1F\x06\x0F\x55\x16\x28\xCC\x57\x15"
"\xB9\xD0\x22\x67\x96\x91\x4D\x45\xF7\x71\x7C\xF4" },
{ GCRY_MD_WHIRLPOOL, "",
"\x19\xFA\x61\xD7\x55\x22\xA4\x66\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
"\xC5\x30\x23\x21\x30\xD4\x07\xF8\x9A\xFE\xE0\x96\x49\x97\xF7\xA7"
"\x3E\x83\xBE\x69\x8B\x28\x8F\xEB\xCF\x88\xE3\xE0\x3C\x4F\x07\x57"
"\xEA\x89\x64\xE5\x9B\x63\xD9\x37\x08\xB1\x38\xCC\x42\xA6\x6E\xB3" },
{ GCRY_MD_WHIRLPOOL, "a",
"\x8A\xCA\x26\x02\x79\x2A\xEC\x6F\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
"\xF0\xDF\xF5\x94\x13\x14\x5E\x69\x73\xC4\x50\x01\xD0\x08\x7B\x42"
"\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6\x3A\x42\x39\x1A\x39\x14\x5A\x59"
"\x1A\x92\x20\x0D\x56\x01\x95\xE5\x3B\x47\x85\x84\xFD\xAE\x23\x1A" },
{ GCRY_MD_WHIRLPOOL, "?",
"\x88\xf0\x78\x6d\x0d\x47\xe5\x32\x1f\x88\xb1\x48\x05\x53\x58\x7d"
"\x19\x4b\x32\x9b\xf1\xfb\x17\xc5\x98\x3a\x87\xa2\x48\x61\x3d\x2b"
"\xb2\xbc\x9f\x0d\xd2\x14\x37\x30\x55\x30\x91\xa7\xb8\x0c\x0f\x80"
"\x7c\x7b\x94\xf6\x55\xf6\x0b\x12\x85\x0c\x8e\x6d\x17\x5b\x1e\x71" },
{ GCRY_MD_WHIRLPOOL,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
"\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
"\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E"
"\x08\xEB\xA2\x66\x29\x12\x9D\x8F\xB7\xCB\x57\x21\x1B\x92\x81\xA6"
"\x55\x17\xCC\x87\x9D\x7B\x96\x21\x42\xC6\x5F\x5A\x7A\xF0\x14\x67" },
{ GCRY_MD_WHIRLPOOL,
"!",
"\x0C\x99\x00\x5B\xEB\x57\xEF\xF5\x0A\x7C\xF0\x05\x56\x0D\xDF\x5D"
"\x29\x05\x7F\xD8\x6B\x20\xBF\xD6\x2D\xEC\xA0\xF1\xCC\xEA\x4A\xF5"
"\x1F\xC1\x54\x90\xED\xDC\x47\xAF\x32\xBB\x2B\x66\xC3\x4F\xF9\xAD"
"\x8C\x60\x08\xAD\x67\x7F\x77\x12\x69\x53\xB2\x26\xE4\xED\x8B\x01" },
{ GCRY_MD_WHIRLPOOL,
"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.",
"\xcd\x4a\xa4\xaf\xf6\x7f\xec\xce\xbb\x6c\xdf\x91\x96\xe1\xf3\xf6"
"\x78\xe2\x8e\x3a\x76\xcf\x06\xc7\xa1\x20\x7b\x81\x32\x60\xf7\x8e"
"\x68\x19\x62\x33\x4f\xe5\x0a\x24\xfb\x9e\x74\x03\x74\xe4\x61\x29"
"\x6f\xb3\x13\xe6\x7e\xc2\x88\x99\x9e\xfb\xe7\x9d\x11\x30\x89\xd2" },
{ GCRY_MD_GOSTR3411_94,
"This is message, length=32 bytes",
"\xB1\xC4\x66\xD3\x75\x19\xB8\x2E\x83\x19\x81\x9F\xF3\x25\x95\xE0"
"\x47\xA2\x8C\xB6\xF8\x3E\xFF\x1C\x69\x16\xA8\x15\xA6\x37\xFF\xFA" },
{ GCRY_MD_GOSTR3411_94,
"Suppose the original message has length = 50 bytes",
"\x47\x1A\xBA\x57\xA6\x0A\x77\x0D\x3A\x76\x13\x06\x35\xC1\xFB\xEA"
"\x4E\xF1\x4D\xE5\x1F\x78\xB4\xAE\x57\xDD\x89\x3B\x62\xF5\x52\x08" },
{ GCRY_MD_GOSTR3411_94,
"",
"\xCE\x85\xB9\x9C\xC4\x67\x52\xFF\xFE\xE3\x5C\xAB\x9A\x7B\x02\x78"
"\xAB\xB4\xC2\xD2\x05\x5C\xFF\x68\x5A\xF4\x91\x2C\x49\x49\x0F\x8D" },
{ GCRY_MD_GOSTR3411_94,
"!",
"\x5C\x00\xCC\xC2\x73\x4C\xDD\x33\x32\xD3\xD4\x74\x95\x76\xE3\xC1"
"\xA7\xDB\xAF\x0E\x7E\xA7\x4E\x9F\xA6\x02\x41\x3C\x90\xA1\x29\xFA" },
{ GCRY_MD_GOSTR3411_94,
"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.",
"\x00\x0c\x85\xc8\x54\xd2\x9a\x6e\x47\x2e\xff\xa4\xa2\xe7\xd0\x2e"
"\x8a\xcc\x14\x53\xb4\x87\xc8\x5c\x95\x9a\x3e\x85\x8c\x7d\x6e\x0c" },
{ GCRY_MD_STRIBOG512,
"012345678901234567890123456789012345678901234567890123456789012",
"\x1b\x54\xd0\x1a\x4a\xf5\xb9\xd5\xcc\x3d\x86\xd6\x8d\x28\x54\x62"
"\xb1\x9a\xbc\x24\x75\x22\x2f\x35\xc0\x85\x12\x2b\xe4\xba\x1f\xfa"
"\x00\xad\x30\xf8\x76\x7b\x3a\x82\x38\x4c\x65\x74\xf0\x24\xc3\x11"
"\xe2\xa4\x81\x33\x2b\x08\xef\x7f\x41\x79\x78\x91\xc1\x64\x6f\x48" },
{ GCRY_MD_STRIBOG256,
"012345678901234567890123456789012345678901234567890123456789012",
"\x9d\x15\x1e\xef\xd8\x59\x0b\x89\xda\xa6\xba\x6c\xb7\x4a\xf9\x27"
"\x5d\xd0\x51\x02\x6b\xb1\x49\xa4\x52\xfd\x84\xe5\xe5\x7b\x55\x00" },
{ GCRY_MD_STRIBOG512,
"\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
"\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
"\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
"\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
"\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
"\x1e\x88\xe6\x22\x26\xbf\xca\x6f\x99\x94\xf1\xf2\xd5\x15\x69\xe0"
"\xda\xf8\x47\x5a\x3b\x0f\xe6\x1a\x53\x00\xee\xe4\x6d\x96\x13\x76"
"\x03\x5f\xe8\x35\x49\xad\xa2\xb8\x62\x0f\xcd\x7c\x49\x6c\xe5\xb3"
"\x3f\x0c\xb9\xdd\xdc\x2b\x64\x60\x14\x3b\x03\xda\xba\xc9\xfb\x28" },
{ GCRY_MD_STRIBOG256,
"\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
"\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
"\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
"\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
"\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"
#include "./sha3-512.h"
{ GCRY_MD_SHAKE128,
"",
"\x7F\x9C\x2B\xA4\xE8\x8F\x82\x7D\x61\x60\x45\x50\x76\x05\x85\x3E"
"\xD7\x3B\x80\x93\xF6\xEF\xBC\x88\xEB\x1A\x6E\xAC\xFA\x66\xEF\x26"
"\x3C\xB1\xEE\xA9\x88\x00\x4B\x93\x10\x3C\xFB\x0A\xEE\xFD\x2A\x68"
"\x6E\x01\xFA\x4A\x58\xE8\xA3\x63\x9C\xA8\xA1\xE3\xF9\xAE\x57\xE2"
"\x35\xB8\xCC\x87\x3C\x23\xDC\x62\xB8\xD2\x60\x16\x9A\xFA\x2F\x75"
"\xAB\x91\x6A\x58\xD9\x74\x91\x88\x35\xD2\x5E\x6A\x43\x50\x85\xB2"
"\xBA\xDF\xD6\xDF\xAA\xC3\x59\xA5\xEF\xBB\x7B\xCC\x4B\x59\xD5\x38"
"\xDF\x9A\x04\x30\x2E\x10\xC8\xBC\x1C\xBF\x1A\x0B\x3A\x51\x20\xEA"
"\x17\xCD\xA7\xCF\xAD\x76\x5F\x56\x23\x47\x4D\x36\x8C\xCC\xA8\xAF"
"\x00\x07\xCD\x9F\x5E\x4C\x84\x9F\x16\x7A\x58\x0B\x14\xAA\xBD\xEF"
"\xAE\xE7\xEE\xF4\x7C\xB0\xFC\xA9\x76\x7B\xE1\xFD\xA6\x94\x19\xDF"
"\xB9\x27\xE9\xDF\x07\x34\x8B\x19\x66\x91\xAB\xAE\xB5\x80\xB3\x2D"
"\xEF\x58\x53\x8B\x8D\x23\xF8\x77\x32\xEA\x63\xB0\x2B\x4F\xA0\xF4"
"\x87\x33\x60\xE2\x84\x19\x28\xCD\x60\xDD\x4C\xEE\x8C\xC0\xD4\xC9"
"\x22\xA9\x61\x88\xD0\x32\x67\x5C\x8A\xC8\x50\x93\x3C\x7A\xFF\x15"
"\x33\xB9\x4C\x83\x4A\xDB\xB6\x9C\x61\x15\xBA\xD4\x69\x2D\x86\x19"
"\xF9\x0B\x0C\xDF\x8A\x7B\x9C\x26\x40\x29\xAC\x18\x5B\x70\xB8\x3F"
"\x28\x01\xF2\xF4\xB3\xF7\x0C\x59\x3E\xA3\xAE\xEB\x61\x3A\x7F\x1B"
"\x1D\xE3\x3F\xD7\x50\x81\xF5\x92\x30\x5F\x2E\x45\x26\xED\xC0\x96"
"\x31\xB1\x09\x58\xF4\x64\xD8\x89\xF3\x1B\xA0\x10\x25\x0F\xDA\x7F"
"\x13\x68\xEC\x29\x67\xFC\x84\xEF\x2A\xE9\xAF\xF2\x68\xE0\xB1\x70"
"\x0A\xFF\xC6\x82\x0B\x52\x3A\x3D\x91\x71\x35\xF2\xDF\xF2\xEE\x06"
"\xBF\xE7\x2B\x31\x24\x72\x1D\x4A\x26\xC0\x4E\x53\xA7\x5E\x30\xE7"
"\x3A\x7A\x9C\x4A\x95\xD9\x1C\x55\xD4\x95\xE9\xF5\x1D\xD0\xB5\xE9"
"\xD8\x3C\x6D\x5E\x8C\xE8\x03\xAA\x62\xB8\xD6\x54\xDB\x53\xD0\x9B"
"\x8D\xCF\xF2\x73\xCD\xFE\xB5\x73\xFA\xD8\xBC\xD4\x55\x78\xBE\xC2"
"\xE7\x70\xD0\x1E\xFD\xE8\x6E\x72\x1A\x3F\x7C\x6C\xCE\x27\x5D\xAB"
"\xE6\xE2\x14\x3F\x1A\xF1\x8D\xA7\xEF\xDD\xC4\xC7\xB7\x0B\x5E\x34"
"\x5D\xB9\x3C\xC9\x36\xBE\xA3\x23\x49\x1C\xCB\x38\xA3\x88\xF5\x46"
"\xA9\xFF\x00\xDD\x4E\x13\x00\xB9\xB2\x15\x3D\x20\x41\xD2\x05\xB4"
"\x43\xE4\x1B\x45\xA6\x53\xF2\xA5\xC4\x49\x2C\x1A\xDD\x54\x45\x12"
"\xDD\xA2\x52\x98\x33\x46\x2B\x71\xA4\x1A\x45\xBE\x97\x29\x0B\x6F",
0, 512, },
{ GCRY_MD_SHAKE128,
"\x5A\xAB\x62\x75\x6D\x30\x7A\x66\x9D\x14\x6A\xBA\x98\x8D\x90\x74"
"\xC5\xA1\x59\xB3\xDE\x85\x15\x1A\x81\x9B\x11\x7C\xA1\xFF\x65\x97"
"\xF6\x15\x6E\x80\xFD\xD2\x8C\x9C\x31\x76\x83\x51\x64\xD3\x7D\xA7"
"\xDA\x11\xD9\x4E\x09\xAD\xD7\x70\xB6\x8A\x6E\x08\x1C\xD2\x2C\xA0"
"\xC0\x04\xBF\xE7\xCD\x28\x3B\xF4\x3A\x58\x8D\xA9\x1F\x50\x9B\x27"
"\xA6\x58\x4C\x47\x4A\x4A\x2F\x3E\xE0\xF1\xF5\x64\x47\x37\x92\x40"
"\xA5\xAB\x1F\xB7\x7F\xDC\xA4\x9B\x30\x5F\x07\xBA\x86\xB6\x27\x56"
"\xFB\x9E\xFB\x4F\xC2\x25\xC8\x68\x45\xF0\x26\xEA\x54\x20\x76\xB9"
"\x1A\x0B\xC2\xCD\xD1\x36\xE1\x22\xC6\x59\xBE\x25\x9D\x98\xE5\x84"
"\x1D\xF4\xC2\xF6\x03\x30\xD4\xD8\xCD\xEE\x7B\xF1\xA0\xA2\x44\x52"
"\x4E\xEC\xC6\x8F\xF2\xAE\xF5\xBF\x00\x69\xC9\xE8\x7A\x11\xC6\xE5"
"\x19\xDE\x1A\x40\x62\xA1\x0C\x83\x83\x73\x88\xF7\xEF\x58\x59\x8A"
"\x38\x46\xF4\x9D\x49\x96\x82\xB6\x83\xC4\xA0\x62\xB4\x21\x59\x4F"
"\xAF\xBC\x13\x83\xC9\x43\xBA\x83\xBD\xEF\x51\x5E\xFC\xF1\x0D",
"\xF0\x71\x5D\xE3\x56\x92\xFD\x70\x12\x3D\xC6\x83\x68\xD0\xFE\xEC"
"\x06\xA0\xC7\x4C\xF8\xAD\xB0\x5D\xDC\x25\x54\x87\xB1\xA8\xD4\xD1"
"\x21\x3E\x9E\xAB\xAF\x41\xF1\x16\x17\x19\xD0\x65\xD7\x94\xB7\x50"
"\xF8\x4B\xE3\x2A\x32\x34\xB4\xD5\x36\x46\x0D\x55\x20\x68\x8A\x5A"
"\x79\xA1\x7A\x4B\xA8\x98\x7F\xCB\x61\xBF\x7D\xAA\x8B\x54\x7B\xF5"
"\xC1\xCE\x36\xB5\x6A\x73\x25\x7D\xBB\xF1\xBA\xBB\x64\xF2\x49\xBD"
"\xCE\xB6\x7B\xA1\xC8\x88\x37\x0A\x96\x3D\xFD\x6B\x6A\x2A\xDE\x2C"
"\xEF\xD1\x4C\x32\x52\xCB\x37\x58\x52\x0F\x0C\x65\xF4\x52\x46\x82"
"\x77\x24\x99\x46\x3A\xE1\xA3\x41\x80\x01\x83\xAA\x60\xEF\xA0\x51"
"\x18\xA2\x82\x01\x74\x4F\x7B\xA0\xB0\xA3\x92\x8D\xD7\xC0\x26\x3F"
"\xD2\x64\xB7\xCD\x7B\x2E\x2E\x09\xB3\x22\xBF\xCE\xA8\xEE\xD0\x42"
"\x75\x79\x5B\xE7\xC0\xF0\x0E\x11\x38\x27\x37\x0D\x05\x1D\x50\x26"
"\x95\x80\x30\x00\x05\xAC\x12\x88\xFE\xA6\xCD\x9A\xE9\xF4\xF3\x7C"
"\xE0\xF8\xAC\xE8\xBF\x3E\xBE\x1D\x70\x56\x25\x59\x54\xC7\x61\x93"
"\x1D\x3C\x42\xED\x62\xF7\xF1\xCE\x1B\x94\x5C\xDE\xCC\x0A\x74\x32"
"\x2D\x7F\x64\xD6\x00\x4F\xF2\x16\x84\x14\x93\x07\x28\x8B\x44\x8E"
"\x45\x43\x34\x75\xB1\xEA\x13\x14\xB0\x0F\x1F\xC4\x50\x08\x9A\x9D"
"\x1F\x77\x10\xC6\xD7\x65\x2E\xCF\x65\x4F\x3B\x48\x7D\x02\x83\xD4"
"\xD8\xA2\x8E\xFB\x50\x66\xC4\x25\x0D\x5A\xD6\x98\xE1\x5D\xBA\x88"
"\xE9\x25\xE4\xDE\x99\xB6\x9B\xC3\x83\xAC\x80\x45\xB7\xF1\x02\x2A"
"\xDD\x39\xD4\x43\x54\x6A\xE0\x92\x4F\x13\xF4\x89\x60\x96\xDF\xDF"
"\x37\xCA\x72\x20\x79\x87\xC4\xA7\x70\x5A\x7A\xBE\x72\x4B\x7F\xA1"
"\x0C\x90\x9F\x39\x25\x44\x9F\x01\x0D\x61\xE2\x07\xAD\xD9\x52\x19"
"\x07\x1A\xCE\xED\xB9\xB9\xDC\xED\x32\xA9\xE1\x23\x56\x1D\x60\x82"
"\xD4\x6A\xEF\xAE\x07\xEE\x1B\xD1\x32\x76\x5E\x3E\x51\x3C\x66\x50"
"\x1B\x38\x7A\xB2\xEE\x09\xA0\x4A\xE6\x3E\x25\x80\x85\x17\xAF\xEA"
"\x3E\x05\x11\x69\xCF\xD2\xFF\xF8\xC5\x85\x8E\x2D\x96\x23\x89\x7C"
"\x9E\x85\x17\x5A\xC5\xA8\x63\x94\xCD\x0A\x32\xA0\xA6\x2A\x8F\x5D"
"\x6C\xCC\xBF\x49\x3D\xAA\x43\xF7\x83\x62\xBB\xCA\x40\xAD\xF7\x33"
"\xF8\x71\xE0\xC0\x09\x98\xD9\xBF\xD6\x88\x06\x56\x66\x6C\xD7\xBE"
"\x4F\xE9\x89\x2C\x61\xDC\xD5\xCD\x23\xA5\xE4\x27\x7E\xEE\x8B\x4A"
"\xFD\x29\xB6\x9B\xBA\x55\x66\x0A\x21\x71\x12\xFF\x6E\x34\x56\xB1",
223, 512, },
{ GCRY_MD_SHAKE128,
"!",
"\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11"
"\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58"
"\x42\x4c\x4b\x5c\x28\x47\x5f\xfd\xcf\x98\x16\x63\x86\x7f\xec\x63"
"\x21\xc1\x26\x2e\x38\x7b\xcc\xf8\xca\x67\x68\x84\xc4\xa9\xd0\xc1"
"\x3b\xfa\x68\x69\x76\x3d\x5a\xe4\xbb\xc9\xb3\xcc\xd0\x9d\x1c\xa5"
"\xea\x74\x46\x53\x8d\x69\xb3\xfb\x98\xc7\x2b\x59\xa2\xb4\x81\x7d"
"\xb5\xea\xdd\x90\x11\xf9\x0f\xa7\x10\x91\x93\x1f\x81\x34\xf4\xf0"
"\x0b\x56\x2e\x2f\xe1\x05\x93\x72\x70\x36\x1c\x19\x09\x86\x2a\xd4"
"\x50\x46\xe3\x93\x2f\x5d\xd3\x11\xec\x72\xfe\xc5\xf8\xfb\x8f\x60"
"\xb4\x5a\x3b\xee\x3f\x85\xbb\xf7\xfc\xed\xc6\xa5\x55\x67\x76\x48"
"\xe0\x65\x4b\x38\x19\x41\xa8\x6b\xd3\xe5\x12\x65\x7b\x0d\x57\xa7"
"\x99\x1f\xc4\x54\x3f\x89\xd8\x29\x04\x92\x22\x2c\xe4\xa3\x3e\x17"
"\x60\x2b\x3b\x99\xc0\x09\xf7\x65\x5f\x87\x53\x5c\xda\xa3\x71\x6f"
"\x58\xc4\x7b\x8a\x15\x7a\xd1\x95\xf0\x28\x09\xf2\x75\x00\xb9\x25"
"\x49\x79\x31\x1c\x6b\xb4\x15\x96\x8c\xd1\x04\x31\x16\x9a\x27\xd5"
"\xa8\xd6\x1e\x13\xa6\xb8\xb7\x7a\xf1\xf8\xb6\xdd\x2e\xef\xde\xa0"
"\x40\x78\x96\x80\x49\x0b\x5e\xdc\xb1\xd3\xe5\x38\xa4\x66\xf7\x57"
"\xad\x71\x8f\xe1\xfd\x9f\xae\xef\xa4\x72\x46\xad\x5e\x36\x7f\x87"
"\xd3\xb4\x85\x0d\x44\x86\xeb\x21\x99\xe9\x4a\x79\x79\xe2\x09\x1a"
"\xbc\xdf\x3b\xc1\x33\x79\xc8\x96\xdc\xeb\x79\xa8\xfd\x08\xf1\x10"
"\x73\xf3\x3e\x3f\x99\x23\x22\xb3\x12\x02\xde\xe2\x34\x33\x0c\xf3"
"\x30\x4a\x58\x8f\x0d\x59\xda\xe4\xe6\x3b\xa2\xac\x3c\xe6\x82\xcc"
"\x19\xd4\xe3\x41\x67\x8c\xc3\xa6\x7a\x47\xc1\x13\xb4\xdb\x89\x0f"
"\x30\xa9\x2a\xa0\x8a\x1f\x6d\xc8\xfb\x64\x63\xf8\x03\x8c\x2b\x40"
"\xb2\x53\x00\x77\xb2\x36\xce\x88\xaf\xcc\xcd\xa0\x8a\xd6\xd7\x5e"
"\xee\x18\x99\xb1\x0c\xd8\x00\xc2\xce\x53\x72\xbf\xf2\x2e\xe3\xa3"
"\x39\xd4\xb9\xc1\xa2\xf5\xf4\xb8\x20\xf6\x87\xe5\x51\x9b\xd0\x5b"
"\x1f\xc5\xda\x0e\xb4\x53\x36\x81\x4f\x48\x13\x2c\x64\x0e\x66\xc3"
"\xa0\x2a\x22\xe6\x35\x98\xf9\x4f\x22\xf3\x51\x84\x11\x04\x46\xb6"
"\x48\xcf\x84\x74\xf3\x0c\x43\xea\xd5\x83\x09\xfb\x25\x90\x16\x09"
"\xe2\x41\x87\xe8\x01\xc8\x09\x56\x1a\x64\x80\x94\x50\xe6\x03\xc4"
"\xa8\x03\x95\x25\xc4\x76\xb5\x8e\x32\xce\x2c\x47\xb3\x7d\xa5\x91",
0, 512, },
{ GCRY_MD_SHAKE256,
"",
"\x46\xB9\xDD\x2B\x0B\xA8\x8D\x13\x23\x3B\x3F\xEB\x74\x3E\xEB\x24"
"\x3F\xCD\x52\xEA\x62\xB8\x1B\x82\xB5\x0C\x27\x64\x6E\xD5\x76\x2F"
"\xD7\x5D\xC4\xDD\xD8\xC0\xF2\x00\xCB\x05\x01\x9D\x67\xB5\x92\xF6"
"\xFC\x82\x1C\x49\x47\x9A\xB4\x86\x40\x29\x2E\xAC\xB3\xB7\xC4\xBE"
"\x14\x1E\x96\x61\x6F\xB1\x39\x57\x69\x2C\xC7\xED\xD0\xB4\x5A\xE3"
"\xDC\x07\x22\x3C\x8E\x92\x93\x7B\xEF\x84\xBC\x0E\xAB\x86\x28\x53"
"\x34\x9E\xC7\x55\x46\xF5\x8F\xB7\xC2\x77\x5C\x38\x46\x2C\x50\x10"
"\xD8\x46\xC1\x85\xC1\x51\x11\xE5\x95\x52\x2A\x6B\xCD\x16\xCF\x86"
"\xF3\xD1\x22\x10\x9E\x3B\x1F\xDD\x94\x3B\x6A\xEC\x46\x8A\x2D\x62"
"\x1A\x7C\x06\xC6\xA9\x57\xC6\x2B\x54\xDA\xFC\x3B\xE8\x75\x67\xD6"
"\x77\x23\x13\x95\xF6\x14\x72\x93\xB6\x8C\xEA\xB7\xA9\xE0\xC5\x8D"
"\x86\x4E\x8E\xFD\xE4\xE1\xB9\xA4\x6C\xBE\x85\x47\x13\x67\x2F\x5C"
"\xAA\xAE\x31\x4E\xD9\x08\x3D\xAB\x4B\x09\x9F\x8E\x30\x0F\x01\xB8"
"\x65\x0F\x1F\x4B\x1D\x8F\xCF\x3F\x3C\xB5\x3F\xB8\xE9\xEB\x2E\xA2"
"\x03\xBD\xC9\x70\xF5\x0A\xE5\x54\x28\xA9\x1F\x7F\x53\xAC\x26\x6B"
"\x28\x41\x9C\x37\x78\xA1\x5F\xD2\x48\xD3\x39\xED\xE7\x85\xFB\x7F"
"\x5A\x1A\xAA\x96\xD3\x13\xEA\xCC\x89\x09\x36\xC1\x73\xCD\xCD\x0F"
"\xAB\x88\x2C\x45\x75\x5F\xEB\x3A\xED\x96\xD4\x77\xFF\x96\x39\x0B"
"\xF9\xA6\x6D\x13\x68\xB2\x08\xE2\x1F\x7C\x10\xD0\x4A\x3D\xBD\x4E"
"\x36\x06\x33\xE5\xDB\x4B\x60\x26\x01\xC1\x4C\xEA\x73\x7D\xB3\xDC"
"\xF7\x22\x63\x2C\xC7\x78\x51\xCB\xDD\xE2\xAA\xF0\xA3\x3A\x07\xB3"
"\x73\x44\x5D\xF4\x90\xCC\x8F\xC1\xE4\x16\x0F\xF1\x18\x37\x8F\x11"
"\xF0\x47\x7D\xE0\x55\xA8\x1A\x9E\xDA\x57\xA4\xA2\xCF\xB0\xC8\x39"
"\x29\xD3\x10\x91\x2F\x72\x9E\xC6\xCF\xA3\x6C\x6A\xC6\xA7\x58\x37"
"\x14\x30\x45\xD7\x91\xCC\x85\xEF\xF5\xB2\x19\x32\xF2\x38\x61\xBC"
"\xF2\x3A\x52\xB5\xDA\x67\xEA\xF7\xBA\xAE\x0F\x5F\xB1\x36\x9D\xB7"
"\x8F\x3A\xC4\x5F\x8C\x4A\xC5\x67\x1D\x85\x73\x5C\xDD\xDB\x09\xD2"
"\xB1\xE3\x4A\x1F\xC0\x66\xFF\x4A\x16\x2C\xB2\x63\xD6\x54\x12\x74"
"\xAE\x2F\xCC\x86\x5F\x61\x8A\xBE\x27\xC1\x24\xCD\x8B\x07\x4C\xCD"
"\x51\x63\x01\xB9\x18\x75\x82\x4D\x09\x95\x8F\x34\x1E\xF2\x74\xBD"
"\xAB\x0B\xAE\x31\x63\x39\x89\x43\x04\xE3\x58\x77\xB0\xC2\x8A\x9B"
"\x1F\xD1\x66\xC7\x96\xB9\xCC\x25\x8A\x06\x4A\x8F\x57\xE2\x7F\x2A",
0, 512, },
{ GCRY_MD_SHAKE256,
"\xB3\x2D\x95\xB0\xB9\xAA\xD2\xA8\x81\x6D\xE6\xD0\x6D\x1F\x86\x00"
"\x85\x05\xBD\x8C\x14\x12\x4F\x6E\x9A\x16\x3B\x5A\x2A\xDE\x55\xF8"
"\x35\xD0\xEC\x38\x80\xEF\x50\x70\x0D\x3B\x25\xE4\x2C\xC0\xAF\x05"
"\x0C\xCD\x1B\xE5\xE5\x55\xB2\x30\x87\xE0\x4D\x7B\xF9\x81\x36\x22"
"\x78\x0C\x73\x13\xA1\x95\x4F\x87\x40\xB6\xEE\x2D\x3F\x71\xF7\x68"
"\xDD\x41\x7F\x52\x04\x82\xBD\x3A\x08\xD4\xF2\x22\xB4\xEE\x9D\xBD"
"\x01\x54\x47\xB3\x35\x07\xDD\x50\xF3\xAB\x42\x47\xC5\xDE\x9A\x8A"
"\xBD\x62\xA8\xDE\xCE\xA0\x1E\x3B\x87\xC8\xB9\x27\xF5\xB0\x8B\xEB"
"\x37\x67\x4C\x6F\x8E\x38\x0C\x04",
"\xCC\x2E\xAA\x04\xEE\xF8\x47\x9C\xDA\xE8\x56\x6E\xB8\xFF\xA1\x10"
"\x0A\x40\x79\x95\xBF\x99\x9A\xE9\x7E\xDE\x52\x66\x81\xDC\x34\x90"
"\x61\x6F\x28\x44\x2D\x20\xDA\x92\x12\x4C\xE0\x81\x58\x8B\x81\x49"
"\x1A\xED\xF6\x5C\xAA\xF0\xD2\x7E\x82\xA4\xB0\xE1\xD1\xCA\xB2\x38"
"\x33\x32\x8F\x1B\x8D\xA4\x30\xC8\xA0\x87\x66\xA8\x63\x70\xFA\x84"
"\x8A\x79\xB5\x99\x8D\xB3\xCF\xFD\x05\x7B\x96\xE1\xE2\xEE\x0E\xF2"
"\x29\xEC\xA1\x33\xC1\x55\x48\xF9\x83\x99\x02\x04\x37\x30\xE4\x4B"
"\xC5\x2C\x39\xFA\xDC\x1D\xDE\xEA\xD9\x5F\x99\x39\xF2\x20\xCA\x30"
"\x06\x61\x54\x0D\xF7\xED\xD9\xAF\x37\x8A\x5D\x4A\x19\xB2\xB9\x3E"
"\x6C\x78\xF4\x9C\x35\x33\x43\xA0\xB5\xF1\x19\x13\x2B\x53\x12\xD0"
"\x04\x83\x1D\x01\x76\x9A\x31\x6D\x2F\x51\xBF\x64\xCC\xB2\x0A\x21"
"\xC2\xCF\x7A\xC8\xFB\x6F\x6E\x90\x70\x61\x26\xBD\xAE\x06\x11\xDD"
"\x13\x96\x2E\x8B\x53\xD6\xEA\xE2\x6C\x7B\x0D\x25\x51\xDA\xF6\x24"
"\x8E\x9D\x65\x81\x73\x82\xB0\x4D\x23\x39\x2D\x10\x8E\x4D\x34\x43"
"\xDE\x5A\xDC\x72\x73\xC7\x21\xA8\xF8\x32\x0E\xCF\xE8\x17\x7A\xC0"
"\x67\xCA\x8A\x50\x16\x9A\x6E\x73\x00\x0E\xBC\xDC\x1E\x4E\xE6\x33"
"\x9F\xC8\x67\xC3\xD7\xAE\xAB\x84\x14\x63\x98\xD7\xBA\xDE\x12\x1D"
"\x19\x89\xFA\x45\x73\x35\x56\x4E\x97\x57\x70\xA3\xA0\x02\x59\xCA"
"\x08\x70\x61\x08\x26\x1A\xA2\xD3\x4D\xE0\x0F\x8C\xAC\x7D\x45\xD3"
"\x5E\x5A\xA6\x3E\xA6\x9E\x1D\x1A\x2F\x7D\xAB\x39\x00\xD5\x1E\x0B"
"\xC6\x53\x48\xA2\x55\x54\x00\x70\x39\xA5\x2C\x3C\x30\x99\x80\xD1"
"\x7C\xAD\x20\xF1\x15\x63\x10\xA3\x9C\xD3\x93\x76\x0C\xFE\x58\xF6"
"\xF8\xAD\xE4\x21\x31\x28\x82\x80\xA3\x5E\x1D\xB8\x70\x81\x83\xB9"
"\x1C\xFA\xF5\x82\x7E\x96\xB0\xF7\x74\xC4\x50\x93\xB4\x17\xAF\xF9"
"\xDD\x64\x17\xE5\x99\x64\xA0\x1B\xD2\xA6\x12\xFF\xCF\xBA\x18\xA0"
"\xF1\x93\xDB\x29\x7B\x9A\x6C\xC1\xD2\x70\xD9\x7A\xAE\x8F\x8A\x3A"
"\x6B\x26\x69\x5A\xB6\x64\x31\xC2\x02\xE1\x39\xD6\x3D\xD3\xA2\x47"
"\x78\x67\x6C\xEF\xE3\xE2\x1B\x02\xEC\x4E\x8F\x5C\xFD\x66\x58\x7A"
"\x12\xB4\x40\x78\xFC\xD3\x9E\xEE\x44\xBB\xEF\x4A\x94\x9A\x63\xC0"
"\xDF\xD5\x8C\xF2\xFB\x2C\xD5\xF0\x02\xE2\xB0\x21\x92\x66\xCF\xC0"
"\x31\x81\x74\x86\xDE\x70\xB4\x28\x5A\x8A\x70\xF3\xD3\x8A\x61\xD3"
"\x15\x5D\x99\xAA\xF4\xC2\x53\x90\xD7\x36\x45\xAB\x3E\x8D\x80\xF0",
136, 512, },
{ GCRY_MD_SHAKE256,
"!",
"\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb"
"\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a"
"\x3f\xd1\x24\xd4\xdf\x76\xc0\xa5\x39\xee\x7d\xd2\xf6\xe1\xec\x34"
"\x61\x24\xc8\x15\xd9\x41\x0e\x14\x5e\xb5\x61\xbc\xd9\x7b\x18\xab"
"\x6c\xe8\xd5\x55\x3e\x0e\xab\x3d\x1f\x7d\xfb\x8f\x9d\xee\xfe\x16"
"\x84\x7e\x21\x92\xf6\xf6\x1f\xb8\x2f\xb9\x0d\xde\x60\xb1\x90\x63"
"\xc5\x6a\x4c\x55\xcd\xd7\xb6\x72\xb7\x5b\xf5\x15\xad\xbf\xe2\x04"
"\x90\x3c\x8c\x00\x36\xde\x54\xa2\x99\x9a\x92\x0d\xe9\x0f\x66\xd7"
"\xff\x6e\xc8\xe4\xc9\x3d\x24\xae\x34\x6f\xdc\xb3\xa5\xa5\xbd\x57"
"\x39\xec\x15\xa6\xed\xdb\x5c\xe5\xb0\x2d\xa5\x30\x39\xfa\xc6\x3e"
"\x19\x55\x5f\xaa\x2e\xdd\xc6\x93\xb1\xf0\xc2\xa6\xfc\xbe\x7c\x0a"
"\x0a\x09\x1d\x0e\xe7\x00\xd7\x32\x2e\x4b\x0f\xf0\x95\x90\xde\x16"
"\x64\x22\xf9\xea\xd5\xda\x4c\x99\x3d\x60\x5f\xe4\xd9\xc6\x34\x84"
"\x3a\xa1\x78\xb1\x76\x72\xc6\x56\x8c\x8a\x2e\x62\xab\xeb\xea\x2c"
"\x21\xc3\x02\xbd\x36\x6a\xd6\x98\x95\x9e\x1f\x6e\x43\x4a\xf1\x55"
"\x56\x8b\x27\x34\xd8\x37\x9f\xcd\x3f\xfe\x64\x89\xba\xff\xa6\xd7"
"\x11\x09\x44\x2e\x1b\x34\x4f\x13\x8a\x09\xca\xe3\xe2\xd3\x94\x2e"
"\xee\x82\x8f\xc4\x7e\x64\xde\xb5\xe0\x0a\x02\x4a\xe1\xf2\xc0\x77"
"\xe6\xb7\xb1\x33\xf6\xc1\xde\x91\x30\x92\xd4\xe8\x29\xec\xd2\xb2"
"\xef\x28\xca\x80\x20\x82\x1e\x2b\x8b\xe5\x17\xd9\x3e\xd0\x88\x36"
"\xf6\xf0\x66\xcc\x3d\x03\xb6\x25\xd8\x49\x7f\x29\xdb\xc1\xc3\x9e"
"\x6f\xe4\x63\x22\x6f\x85\xc1\x28\xa2\xc2\x98\x88\x11\x2e\x06\xa9"
"\x9c\x5d\x17\xb2\x5e\x90\x0d\x20\x4f\x39\x72\x31\xcd\xf7\x9c\x31"
"\x34\x46\x53\x2d\xad\x07\xf4\xc0\xbd\x9f\xba\x1d\xd4\x13\xd8\xa7"
"\xe6\xcb\xc0\xa0\x86\x2c\xc7\x69\x23\x9a\x89\xf9\xdb\x08\x5b\x78"
"\xa0\x54\x59\x6a\xd7\x08\x0d\xdf\x96\x01\x9b\x73\x99\xb5\x03\x48"
"\x0e\x5a\x65\xa2\x20\x8d\x74\x72\x4c\x98\x7d\x32\x5e\x9b\x0e\x82"
"\xfe\xcd\x4f\x27\xf3\x13\x5b\x1d\x9e\x27\xb4\x8e\x69\xdd\x6f\x59"
"\x62\xb8\xa6\x3b\x48\x92\x1e\xc8\xee\x53\x86\x9f\x1a\xc1\xc8\x18"
"\x23\x87\xee\x0d\x6c\xfe\xf6\x53\xff\x8b\xf6\x05\xf1\x47\x04\xb7"
"\x1b\xeb\x65\x53\xf2\x81\xfa\x75\x69\x48\xc4\x38\x49\x4b\x19\xb4"
"\xee\x69\xa5\x43\x6b\x22\x2b\xc9\x88\xed\xa4\xac\x60\x00\x24\xc9",
0, 512, },
{ GCRY_MD_BLAKE2B_512, "abc",
"\xBA\x80\xA5\x3F\x98\x1C\x4D\x0D\x6A\x27\x97\xB6\x9F\x12\xF6\xE9"
"\x4C\x21\x2F\x14\x68\x5A\xC4\xB7\x4B\x12\xBB\x6F\xDB\xFF\xA2\xD1"
"\x7D\x87\xC5\x39\x2A\xAB\x79\x2D\xC2\x52\xD5\xDE\x45\x33\xCC\x95"
"\x18\xD3\x8A\xA8\xDB\xF1\x92\x5A\xB9\x23\x86\xED\xD4\x00\x99\x23" },
{ GCRY_MD_BLAKE2B_512, "\x00",
"\x96\x1f\x6d\xd1\xe4\xdd\x30\xf6\x39\x01\x69\x0c\x51\x2e\x78\xe4"
"\xb4\x5e\x47\x42\xed\x19\x7c\x3c\x5e\x45\xc5\x49\xfd\x25\xf2\xe4"
"\x18\x7b\x0b\xc9\xfe\x30\x49\x2b\x16\xb0\xd0\xbc\x4e\xf9\xb0\xf3"
"\x4c\x70\x03\xfa\xc0\x9a\x5e\xf1\x53\x2e\x69\x43\x02\x34\xce\xbd",
1, 64,
"\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"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f",
64 },
#include "./blake2b.h"
{ GCRY_MD_BLAKE2B_160,
"",
"\xad\x75\xea\xd7\x9f\x71\x21\xd1\xf0\x8a\xfe\x59\x99\x27\xa5\xa3"
"\x8b\xe1\xb1\x79",
0, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2B_160,
"\x9c\x9c\x38",
"\x82\x79\x9d\x7b\xe8\xf4\xd1\x69\xfb\x85\xe6\x63\x6a\x7b\x6c\x50"
"\xa0\x1f\x70\xa2",
3, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2B_256,
"",
"\x89\x36\x29\x47\x52\x79\xdf\xd8\x2a\x84\x1a\x8f\x21\xa3\x72\xed"
"\x30\xcc\xb8\xae\x34\x62\xe1\x90\x7f\x50\x66\x3f\x3c\x03\x66\x83",
0, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2B_256,
"\x9c\x9c\x38",
"\x01\x6a\x18\xbb\x10\xe0\xc3\xa5\xe5\x9f\xce\xfd\x1a\x40\x7a\xb7"
"\xf1\xc0\x36\x1b\x3f\x98\x34\x77\x42\x54\xd3\xf0\x4c\xda\x38\x98",
3, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2B_384,
"",
"\xd7\x2c\x9b\x4a\x73\x4e\xb2\x07\xe9\xdd\xbf\xf0\x0b\x10\xc3\x70"
"\xc8\x9d\x67\xd7\x96\xc3\xa7\xb9\x68\x15\xa9\x53\x92\x1b\xb2\x97"
"\x59\xd2\x9d\x25\x63\xf3\xda\x4d\x7f\x3e\xa4\xa6\xe3\x4c\x32\x6b",
0, 48,
"\xc0\xc0\x80\x41\xc2\x03\xc6\xca\x90\x5b\xeb\x46\x32\x79\xac\x26"
"\xd3\xf9\xcc\xc6\x93\x5a\xed\x48\x35\x7d\xb3\x31\xe5\x16\xfb\x12"
"\x0e\x21\x2f\x51\x80\xd1\x52\x24\x77\x9c\x13\xaf\xc3\x73\x37\xaa",
48 },
{ GCRY_MD_BLAKE2B_384,
"\x9c\x9c\x38",
"\xef\x46\xfa\x54\xa2\xc2\x20\xda\x06\xa8\x4c\x77\x6e\x87\xdd\x0a"
"\x21\xee\xb5\xe9\x40\x1a\x0a\x78\x11\x19\x74\x18\xfe\x92\x70\x15"
"\x77\xd0\xa8\x53\x24\x48\xe8\xb8\x53\x6a\xa6\xc7\x42\xcd\x2c\x62",
3, 48,
"\xc0\xc0\x80\x41\xc2\x03\xc6\xca\x90\x5b\xeb\x46\x32\x79\xac\x26"
"\xd3\xf9\xcc\xc6\x93\x5a\xed\x48\x35\x7d\xb3\x31\xe5\x16\xfb\x12"
"\x0e\x21\x2f\x51\x80\xd1\x52\x24\x77\x9c\x13\xaf\xc3\x73\x37\xaa",
48 },
{ GCRY_MD_BLAKE2B_512,
"",
"\xd7\x4b\xf3\x1e\x5c\xe5\xd8\xa2\x5d\x09\x21\x52\x53\xca\xd2\xf8"
"\xd2\xfd\xa9\x10\x09\x30\x16\x05\xa6\x8c\xc3\x86\x5b\xb7\x93\x5b"
"\xca\xff\x6f\x2a\xf6\x43\xa7\x76\x99\xe8\x02\x61\xa1\xfd\x2c\x80"
"\xe8\x37\xb5\x62\x32\xf7\xb1\x46\x43\x4a\xa7\x4d\x71\x18\xbb\x16",
0, 64,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
64 },
{ GCRY_MD_BLAKE2B_512,
"\x9c\x9c\x38",
"\x70\xfc\x57\xe1\x49\x5f\xe4\x39\x0d\x38\xa1\xd3\x97\x05\xee\xf6"
"\xaa\xbb\xd2\x64\xc7\xce\x66\x11\x8d\x0a\x87\xd4\x25\x94\xb3\x87"
"\xdc\x50\x18\x8b\xba\x61\xf0\x91\xd6\xb3\x4f\xf5\x4e\x09\x1e\x70"
"\x24\x01\x83\xcd\xb9\x21\x1f\x14\x39\x77\x5c\xc6\xe6\xe9\x35\x73",
3, 64,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
64 },
{ GCRY_MD_BLAKE2B_512, "!",
"\x98\xfb\x3e\xfb\x72\x06\xfd\x19\xeb\xf6\x9b\x6f\x31\x2c\xf7\xb6"
"\x4e\x3b\x94\xdb\xe1\xa1\x71\x07\x91\x39\x75\xa7\x93\xf1\x77\xe1"
"\xd0\x77\x60\x9d\x7f\xba\x36\x3c\xbb\xa0\x0d\x05\xf7\xaa\x4e\x4f"
"\xa8\x71\x5d\x64\x28\x10\x4c\x0a\x75\x64\x3b\x0f\xf3\xfd\x3e\xaf" },
{ GCRY_MD_BLAKE2B_512, "?",
"\xae\x9c\xf5\x7a\xc2\xff\x7b\x37\x7a\x5b\xb5\xcc\x2e\x62\x92\x20"
"\xa9\xba\x0a\x09\xc2\x2a\x0f\xdb\xd9\xa3\xae\xd6\x32\xc1\x72\x0e"
"\x6d\x82\x9f\x74\x7f\xba\x12\xe8\x31\xa2\x45\x8d\xf0\x73\x4e\xe0"
"\x12\x27\x52\xd3\xe2\x2c\x36\xc4\x42\x89\x3b\xcd\xd1\xbd\xd9\x08" },
{ GCRY_MD_BLAKE2B_384, "?",
"\x22\x66\x8e\x05\x81\x44\x52\xa5\x23\x84\xce\x67\xd4\xad\x0e\x03"
"\xdf\xe7\x1a\xc1\x56\x9d\x95\x4a\xd2\x22\x7a\x70\x2a\xfe\x6c\x68"
"\x5c\x7d\x65\x30\x2b\xc0\xde\xc6\xea\x72\x1e\xdd\x46\xdf\xb2\x08" },
{ GCRY_MD_BLAKE2B_256, "?",
"\xfa\x11\x30\xd8\xba\x8a\x4c\x5a\x0e\x6f\x4f\x4c\xd2\xd1\x38\x0c"
"\xb9\x22\x2a\xbd\xf6\x20\x70\xf8\x02\x1b\x34\xdd\xd7\x24\x92\x1b" },
{ GCRY_MD_BLAKE2B_160, "?",
"\xe7\x86\x08\x31\xf8\x96\x8d\x64\x9b\xe0\x15\x68\x33\xf3\xbd\x2a"
"\x5f\x0b\xdb\x40" },
{ GCRY_MD_BLAKE2S_256, "abc",
"\x50\x8C\x5E\x8C\x32\x7C\x14\xE2\xE1\xA7\x2B\xA3\x4E\xEB\x45\x2F"
"\x37\x45\x8B\x20\x9E\xD6\x3A\x29\x4D\x99\x9B\x4C\x86\x67\x59\x82" },
#include "./blake2s.h"
{ GCRY_MD_BLAKE2S_128,
"",
"\x84\x89\x68\xb3\x59\x01\xe9\x57\x9a\x4d\xbf\x28\xdf\x99\xec\x23",
0, 16,
"\xea\xea\xd5\xc0\x96\x56\xec\x43\x30\x73\xa3\x17\xbb\xd3\x8e\x62",
16 },
{ GCRY_MD_BLAKE2S_128,
"\x9c\x9c\x38",
"\x2e\xbb\x18\x78\xda\x34\x05\xad\x98\x1a\x33\x06\x50\x35\xd3\x75",
3, 16,
"\xea\xea\xd5\xc0\x96\x56\xec\x43\x30\x73\xa3\x17\xbb\xd3\x8e\x62",
16 },
{ GCRY_MD_BLAKE2S_128,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
"\x3c\xd4\xea\xd7\x88\x0b\x8e\x82\xde\x07\x9c\x1f\xad\x34\x17\xd4",
64, 16,
"\xea\xea\xd5\xc0\x96\x56\xec\x43\x30\x73\xa3\x17\xbb\xd3\x8e\x62",
16 },
{ GCRY_MD_BLAKE2S_128,
"\x8a\x8a\x14\x9e\xb2\x50\x02\x52\x54\xa6\xfa\xa0\x9a\x3a\xd4\x0e"
"\xe3\xf2\xd5\xc7\x9d\x64\x02\x66\x68\xcf\x38\x08\x41\x49\x8a\xd3"
"\x5e\x32\x90\xc2\x53\x15\x68\x7e\xe6\x65\x4b\xb0\xfc\xad\xaa\x58"
"\x02\x5b\x5e\xb9\x18\xd1\xe9\xbb\xa5\x61\x07\x68\x70\xd9\x49\x22"
"\x6b",
"\xee\x92\xc5\x25\x4c\x29\x7a\x88\xe6\x9a\x23\x69\x56\xb6\x7c\xee",
65, 16,
"\xea\xea\xd5\xc0\x96\x56\xec\x43\x30\x73\xa3\x17\xbb\xd3\x8e\x62",
16 },
{ GCRY_MD_BLAKE2S_160,
"",
"\x68\x64\x48\x80\x0c\x80\xc6\xd0\x4f\xb7\x3f\xc1\x7f\xa0\x8c\xa2"
"\x39\x03\xe1\xe9",
0, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2S_160,
"\x9c\x9c\x38",
"\xba\xb3\x5b\x8c\x87\x04\x1a\x00\x24\x44\xa5\xca\x45\x13\x2d\x75"
"\xef\xd3\x4c\xb9",
3, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2S_160,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
"\xe8\xc3\xf1\xdb\x1c\xf8\xe9\xd1\xb5\x4a\x54\x0a\xdc\xe7\x18\x13"
"\x0f\xf4\x12\x98",
64, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2S_160,
"\x8a\x8a\x14\x9e\xb2\x50\x02\x52\x54\xa6\xfa\xa0\x9a\x3a\xd4\x0e"
"\xe3\xf2\xd5\xc7\x9d\x64\x02\x66\x68\xcf\x38\x08\x41\x49\x8a\xd3"
"\x5e\x32\x90\xc2\x53\x15\x68\x7e\xe6\x65\x4b\xb0\xfc\xad\xaa\x58"
"\x02\x5b\x5e\xb9\x18\xd1\xe9\xbb\xa5\x61\x07\x68\x70\xd9\x49\x22"
"\x6b",
"\x59\x02\xf8\x38\x18\x77\x9c\xd8\x13\x40\x0f\xd6\xbb\x23\x04\x1b"
"\x64\x9a\x57\xa7",
65, 20,
"\x65\x65\xcb\x30\xfb\x2c\x28\x54\x7c\xd0\x4c\x1d\x6a\x88\xf2\x7a"
"\x6d\xe8\x55\x3d",
20 },
{ GCRY_MD_BLAKE2S_224,
"",
"\xa8\x66\x86\x63\x35\x3a\xe0\x8f\x4e\x4b\x6b\x1e\xcb\x43\x19\xc8"
"\x2b\x41\x3f\x5e\xe5\x43\x95\x9c\xa5\x9a\x73\x1b",
0, 28,
"\x5a\x5a\xb5\x10\xc6\xd7\x9e\x76\x14\x8a\x9e\x29\xc8\xf1\xba\xab"
"\x65\x11\x77\x89\x00\x89\x8a\x14\x9f\xb4\x53\x07",
28 },
{ GCRY_MD_BLAKE2S_224,
"\x9c\x9c\x38",
"\x1a\x34\x9d\xc1\x51\xbd\x8b\xa2\xa7\xa6\x6b\xe4\x93\x98\x51\x88"
"\x33\x49\x71\x02\x09\xb1\x20\x85\x8c\x4c\x67\xb8",
3, 28,
"\x5a\x5a\xb5\x10\xc6\xd7\x9e\x76\x14\x8a\x9e\x29\xc8\xf1\xba\xab"
"\x65\x11\x77\x89\x00\x89\x8a\x14\x9f\xb4\x53\x07",
28 },
{ GCRY_MD_BLAKE2S_224,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
"\x3a\x0e\xd5\x46\x95\x8c\xd6\xf9\x7c\x38\xd0\xe7\x1c\xfd\xd4\xc5"
"\x67\x6d\x5c\xcc\x35\x06\xec\x87\x87\x09\x26\x39",
64, 28,
"\x5a\x5a\xb5\x10\xc6\xd7\x9e\x76\x14\x8a\x9e\x29\xc8\xf1\xba\xab"
"\x65\x11\x77\x89\x00\x89\x8a\x14\x9f\xb4\x53\x07",
28 },
{ GCRY_MD_BLAKE2S_224,
"\x8a\x8a\x14\x9e\xb2\x50\x02\x52\x54\xa6\xfa\xa0\x9a\x3a\xd4\x0e"
"\xe3\xf2\xd5\xc7\x9d\x64\x02\x66\x68\xcf\x38\x08\x41\x49\x8a\xd3"
"\x5e\x32\x90\xc2\x53\x15\x68\x7e\xe6\x65\x4b\xb0\xfc\xad\xaa\x58"
"\x02\x5b\x5e\xb9\x18\xd1\xe9\xbb\xa5\x61\x07\x68\x70\xd9\x49\x22"
"\x6b",
"\x63\xd7\x98\xcc\x8e\xe3\x00\x45\x2f\xd8\x19\x83\x02\x94\x7f\xf1"
"\xb3\x82\x73\xaa\x19\xae\x72\x8b\x1f\x64\xbe\x88",
65, 28,
"\x5a\x5a\xb5\x10\xc6\xd7\x9e\x76\x14\x8a\x9e\x29\xc8\xf1\xba\xab"
"\x65\x11\x77\x89\x00\x89\x8a\x14\x9f\xb4\x53\x07",
28 },
{ GCRY_MD_BLAKE2S_256,
"",
"\x98\xf3\x21\xe5\x43\xb8\x07\x35\x27\x9c\x86\x1c\x36\x33\x9b\x43"
"\x45\x50\xc6\x9d\x23\xc6\xc8\xff\x96\xbf\x4e\x03\x86\x10\x24\xfd",
0, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2S_256,
"\x9c\x9c\x38",
"\x7b\x10\xa3\x67\xb8\x5d\x29\x9a\x91\x27\x37\x05\x9d\x05\x9d\x3d"
"\xe6\x42\xa3\x19\x04\x57\x01\xb6\x25\x0b\xfd\x3c\x6c\xb9\x4f\x87",
3, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2S_256,
"\xab\xab\x56\x01\x58\x5a\xb3\x0d\xc1\xce\x8f\x5e\xee\x4d\x3b\x88"
"\xc4\x4c\x11\x5e\x6f\xcd\x3d\x0a\x47\x52\x9a\xec\x86\x73\xfa\x6e"
"\x68\xd6\x3f\x16\x55\x6b\xc1\x2d\xef\x1d\x0c\x29\x35\x5f\x94\xf3"
"\x88\x7c\x04\x81\x86\x07\x8e\x95\x23\xb9\xdd\x97\x74\x0c\x80\x8c",
"\xd7\x8b\x98\x28\x54\x4c\xc1\x62\x9e\xab\x7d\xfe\xb1\xfa\xdd\x2b"
"\xed\x98\x1c\xe6\x5f\xef\xd8\x08\x42\x9a\x11\x1e\x97\x44\x92\xa3",
64, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2S_256,
"\x8a\x8a\x14\x9e\xb2\x50\x02\x52\x54\xa6\xfa\xa0\x9a\x3a\xd4\x0e"
"\xe3\xf2\xd5\xc7\x9d\x64\x02\x66\x68\xcf\x38\x08\x41\x49\x8a\xd3"
"\x5e\x32\x90\xc2\x53\x15\x68\x7e\xe6\x65\x4b\xb0\xfc\xad\xaa\x58"
"\x02\x5b\x5e\xb9\x18\xd1\xe9\xbb\xa5\x61\x07\x68\x70\xd9\x49\x22"
"\x6b",
"\x1b\x9e\x26\x9a\x90\xf8\x73\x51\x73\xbc\x4f\x65\xce\x29\x2c\x61"
"\x16\x65\xc7\xb0\x72\x07\xa8\x0b\xfb\x2e\xea\x12\x7d\x97\xcd\x06",
65, 32,
"\xd5\xd5\xab\x80\x2c\xad\xd9\x86\x60\xe7\x47\x2f\x77\xa6\x1d\xc4"
"\xe2\xa6\x88\x2f\xb7\xe6\x9e\x85\x23\xa9\xcd\x76\x43\xb9\xfd\xb7",
32 },
{ GCRY_MD_BLAKE2S_256, "!",
"\xbe\xc0\xc0\xe6\xcd\xe5\xb6\x7a\xcb\x73\xb8\x1f\x79\xa6\x7a\x40"
"\x79\xae\x1c\x60\xda\xc9\xd2\x66\x1a\xf1\x8e\x9f\x8b\x50\xdf\xa5" },
{ GCRY_MD_BLAKE2S_256, "?",
"\xdc\x5a\xe7\x1b\xd4\x63\xa1\xf8\x4d\x73\x33\x44\x63\x6b\xa6\x87"
"\xe6\xbd\xf4\xba\xed\xc3\xef\xc8\xb3\x86\x55\xbb\x08\x56\x3e\xdb" },
{ GCRY_MD_BLAKE2S_224, "?",
"\x2e\x34\x7d\x6b\xcc\x80\xbe\xc3\xf8\x61\x35\x6a\x88\x27\xcd\x84"
"\x32\xd4\xd4\x05\xe0\x43\x20\x58\xc7\xb6\xda\xa3" },
{ GCRY_MD_BLAKE2S_160, "?",
"\xaa\x83\xe1\xcd\x8d\x4e\x9c\xb7\xf4\x6b\x43\xe1\xbc\x6f\x73\x3b"
"\x0e\xfc\x29\xde" },
{ GCRY_MD_BLAKE2S_128, "?",
"\x70\x0b\x8a\x71\x1d\x34\x0a\xf0\x13\x93\x19\x93\x5e\xd7\x54\x9c" },
{ 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" },
{ 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" },
{ 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" },
{ 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;
int i;
if (verbose)
fprintf (stderr, "Starting hash checks.\n");
for (i = 0; algos[i].md; i++)
{
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);
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),
algos[i].md,
(!strcmp (algos[i].data, "!") || !strcmp (algos[i].data, "?"))?
1000000 : (int)strlen(algos[i].data));
check_one_md (algos[i].md, algos[i].data,
algos[i].datalen > 0 ? algos[i].datalen
: strlen (algos[i].data),
algos[i].expect, algos[i].expectlen,
algos[i].key, algos[i].keylen);
if (algos[i].key && algos[i].keylen)
continue;
check_one_md_multi (algos[i].md, algos[i].data,
algos[i].datalen > 0 ? algos[i].datalen
: strlen (algos[i].data),
algos[i].expect);
}
/* Check the Whirlpool bug emulation. */
if (!gcry_md_test_algo (GCRY_MD_WHIRLPOOL) && !in_fips_mode)
{
static const char expect[] =
"\x35\x28\xd6\x4c\x56\x2c\x55\x2e\x3b\x91\x93\x95\x7b\xdd\xcc\x6e"
"\x6f\xb7\xbf\x76\x22\x9c\xc6\x23\xda\x3e\x09\x9b\x36\xe8\x6d\x76"
"\x2f\x94\x3b\x0c\x63\xa0\xba\xa3\x4d\x66\x71\xe6\x5d\x26\x67\x28"
"\x36\x1f\x0e\x1a\x40\xf0\xce\x83\x50\x90\x1f\xfa\x3f\xed\x6f\xfd";
gcry_md_hd_t hd;
int algo = GCRY_MD_WHIRLPOOL;
unsigned char *p;
int mdlen;
err = gcry_md_open (&hd, GCRY_MD_WHIRLPOOL, GCRY_MD_FLAG_BUGEMU1);
if (err)
{
fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
goto leave;
}
mdlen = gcry_md_get_algo_dlen (algo);
if (mdlen < 1 || mdlen > 500)
{
fail ("algo %d, gcry_md_get_algo_dlen failed: %d\n", algo, mdlen);
gcry_md_close (hd);
goto leave;
}
/* Hash 62 byes in chunks. */
gcry_md_write (hd, "1234567890", 10);
gcry_md_write (hd, "1234567890123456789012345678901234567890123456789012",
52);
p = gcry_md_read (hd, algo);
if (memcmp (p, expect, mdlen))
{
printf ("computed: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", p[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
gcry_md_close (hd);
}
leave:
if (verbose)
fprintf (stderr, "Completed hash checks.\n");
}
static void
check_one_hmac (int algo, const char *data, int datalen,
const char *key, int keylen, const char *expect)
{
gcry_md_hd_t hd, hd2;
unsigned char *p;
int mdlen;
int i;
gcry_error_t err = 0;
err = gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC);
if (err)
{
fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
return;
}
mdlen = gcry_md_get_algo_dlen (algo);
if (mdlen < 1 || mdlen > 500)
{
fail ("algo %d, gcry_md_get_algo_dlen failed: %d\n", algo, mdlen);
return;
}
gcry_md_setkey( hd, key, keylen );
gcry_md_write (hd, data, datalen);
err = gcry_md_copy (&hd2, hd);
if (err)
{
fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
}
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))
{
printf ("computed: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", p[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < mdlen; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
gcry_md_close (hd2);
}
static void
check_hmac (void)
{
static const struct algos
{
int md;
const char *data;
const char *key;
const char *expect;
} algos[] =
{
{ GCRY_MD_MD5, "what do ya want for nothing?", "Jefe",
"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" },
{ GCRY_MD_MD5,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
"\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" },
{ GCRY_MD_MD5,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" },
{ GCRY_MD_MD5,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" },
{ GCRY_MD_MD5, "Test With Truncation",
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
"\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" },
{ GCRY_MD_MD5, "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",
"\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" },
{ GCRY_MD_MD5,
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa",
"\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", },
{ GCRY_MD_SHA256, "what do ya want for nothing?", "Jefe",
"\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a"
"\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" },
{ GCRY_MD_SHA256,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88"
"\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" },
{ GCRY_MD_SHA256,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7"
"\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" },
{ GCRY_MD_SHA256,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08"
"\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" },
{ GCRY_MD_SHA256,
"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",
"\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f"
"\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" },
{ GCRY_MD_SHA256,
"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",
"\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44"
"\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" },
{ GCRY_MD_SHA224, "what do ya want for nothing?", "Jefe",
"\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f"
"\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" },
{ GCRY_MD_SHA224,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47"
"\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" },
{ GCRY_MD_SHA224,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64"
"\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" },
{ GCRY_MD_SHA224,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62"
"\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" },
{ GCRY_MD_SHA224,
"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",
"\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2"
"\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" },
{ GCRY_MD_SHA224,
"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",
"\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd"
"\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" },
{ GCRY_MD_SHA384, "what do ya want for nothing?", "Jefe",
"\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b"
"\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e"
"\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" },
{ GCRY_MD_SHA384,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15"
"\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea"
"\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" },
{ GCRY_MD_SHA384,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f"
"\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b"
"\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" },
{ GCRY_MD_SHA384,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7"
"\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e"
"\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" },
{ GCRY_MD_SHA384,
"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",
"\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4"
"\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6"
"\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" },
{ GCRY_MD_SHA384,
"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",
"\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c"
"\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5"
"\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" },
{ GCRY_MD_SHA512, "what do ya want for nothing?", "Jefe",
"\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3"
"\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54"
"\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd"
"\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" },
{ GCRY_MD_SHA512,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0"
"\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde"
"\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4"
"\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" },
{ GCRY_MD_SHA512,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9"
"\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39"
"\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07"
"\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" },
{ GCRY_MD_SHA512,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7"
"\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb"
"\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63"
"\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" },
{ GCRY_MD_SHA512,
"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",
"\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4"
"\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52"
"\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52"
"\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" },
{ GCRY_MD_SHA512,
"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",
"\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd"
"\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
"\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
"\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" },
{ 0 },
};
int i;
if (verbose)
fprintf (stderr, "Starting hashed MAC checks.\n");
for (i = 0; algos[i].md; i++)
{
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);
continue;
}
if (verbose)
fprintf (stderr,
" checking %s [%i] for %d byte key and %d byte data\n",
gcry_md_algo_name (algos[i].md),
algos[i].md,
(int)strlen(algos[i].key), (int)strlen(algos[i].data));
check_one_hmac (algos[i].md, algos[i].data, strlen (algos[i].data),
algos[i].key, strlen(algos[i].key),
algos[i].expect);
}
if (verbose)
fprintf (stderr, "Completed hashed MAC checks.\n");
}
static void
check_one_mac (int algo, const char *data, int datalen,
const char *key, int keylen, const char *iv, int ivlen,
const char *expect, int test_buffering)
{
gcry_mac_hd_t hd;
unsigned char *p;
unsigned int maclen;
size_t macoutlen;
int i;
gcry_error_t err = 0;
if (test_buffering)
{
if ((*data == '!' && !data[1]) ||
(*data == '?' && !data[1]))
{
return; /* Skip. */
}
}
err = gcry_mac_open (&hd, algo, 0, NULL);
if (err)
{
fail ("algo %d, gcry_mac_open failed: %s\n", algo, gpg_strerror (err));
return;
}
i = gcry_mac_get_algo (hd);
if (i != algo)
{
fail ("algo %d, gcry_mac_get_algo failed: %d\n", algo, i);
}
maclen = gcry_mac_get_algo_maclen (algo);
if (maclen < 1 || maclen > 500)
{
fail ("algo %d, gcry_mac_get_algo_maclen failed: %d\n", algo, maclen);
return;
}
p = malloc(maclen);
if (!p)
{
fail ("algo %d, could not malloc %d bytes\n", algo, maclen);
return;
}
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 (ivlen && iv)
{
err = gcry_mac_setiv (hd, iv, ivlen);
if (err)
fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo,
gpg_strerror (err));
if (err)
goto out;
}
if (test_buffering)
{
for (i = 0; i < datalen; i++)
{
err = gcry_mac_write (hd, &data[i], 1);
if (err)
fail("algo %d, mac gcry_mac_write [buf-offset: %d] failed: %s\n",
algo, i, gpg_strerror (err));
if (err)
goto out;
}
}
else
{
if ((*data == '!' && !data[1]) || /* hash one million times a "a" */
(*data == '?' && !data[1])) /* hash million byte data-set with byte pattern 0x00,0x01,0x02,... */
{
char aaa[1000];
size_t left = 1000 * 1000;
size_t startlen = 1;
size_t piecelen = startlen;
if (*data == '!')
memset (aaa, 'a', 1000);
/* Write in chuck with all sizes 1 to 1000 (500500 bytes) */
for (i = 1; i <= 1000 && left > 0; i++)
{
piecelen = i;
if (piecelen > sizeof(aaa))
piecelen = sizeof(aaa);
if (piecelen > left)
piecelen = left;
if (*data == '?')
fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
gcry_mac_write (hd, aaa, piecelen);
left -= piecelen;
}
/* Write in odd size chunks so that we test the buffering. */
while (left > 0)
{
if (piecelen > sizeof(aaa))
piecelen = sizeof(aaa);
if (piecelen > left)
piecelen = left;
if (*data == '?')
fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
gcry_mac_write (hd, aaa, piecelen);
left -= piecelen;
if (piecelen == sizeof(aaa))
piecelen = ++startlen;
else
piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0);
}
}
else
{
err = gcry_mac_write (hd, data, datalen);
}
if (err)
fail("algo %d, mac gcry_mac_write failed: %s\n", algo, gpg_strerror (err));
if (err)
goto out;
}
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;
err = gcry_mac_read (hd, p, &macoutlen);
if (err)
fail("algo %d, mac gcry_mac_read failed: %s\n", algo, gpg_strerror (err));
if (err)
goto out;
if (memcmp (p, expect, maclen))
{
printf ("computed: ");
for (i = 0; i < maclen; i++)
printf ("%02x ", p[i] & 0xFF);
printf ("\nexpected: ");
for (i = 0; i < maclen; i++)
printf ("%02x ", expect[i] & 0xFF);
printf ("\n");
fail ("algo %d, digest mismatch\n", algo);
}
if (err)
goto out;
out:
free (p);
gcry_mac_close (hd);
}
static void
check_mac (void)
{
static const struct algos
{
int algo;
const char *data;
const char *key;
const char *expect;
const char *iv;
unsigned int dlen;
unsigned int klen;
} algos[] =
{
{ GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe",
"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" },
{ GCRY_MAC_HMAC_MD5,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
"\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" },
{ GCRY_MAC_HMAC_MD5,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" },
{ GCRY_MAC_HMAC_MD5,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" },
{ GCRY_MAC_HMAC_MD5, "Test With Truncation",
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
"\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" },
{ GCRY_MAC_HMAC_MD5, "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",
"\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" },
{ GCRY_MAC_HMAC_MD5,
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa\xaa\xaa",
"\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", },
{ GCRY_MAC_HMAC_MD5, "?", "????????????????",
"\x7e\x28\xf8\x8e\xf4\x6c\x48\x30\xa2\x0c\xe3\xe1\x42\xd4\xb5\x6b" },
{ GCRY_MAC_HMAC_SHA256, "what do ya want for nothing?", "Jefe",
"\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a"
"\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" },
{ GCRY_MAC_HMAC_SHA256,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88"
"\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" },
{ GCRY_MAC_HMAC_SHA256,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7"
"\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" },
{ GCRY_MAC_HMAC_SHA256,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08"
"\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" },
{ GCRY_MAC_HMAC_SHA256,
"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",
"\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f"
"\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" },
{ GCRY_MAC_HMAC_SHA256,
"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",
"\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44"
"\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" },
{ GCRY_MAC_HMAC_SHA256, "?", "????????????????",
"\x1c\x0e\x57\xad\x4a\x02\xd2\x30\xce\x7e\xf8\x08\x23\x25\x71\x5e"
"\x16\x9b\x30\xca\xc3\xf4\x99\xc5\x1d\x4c\x25\x32\xa9\xf2\x15\x28" },
{ GCRY_MAC_HMAC_SHA224, "what do ya want for nothing?", "Jefe",
"\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f"
"\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" },
{ GCRY_MAC_HMAC_SHA224,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47"
"\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" },
{ GCRY_MAC_HMAC_SHA224,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64"
"\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" },
{ GCRY_MAC_HMAC_SHA224,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62"
"\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" },
{ GCRY_MAC_HMAC_SHA224,
"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",
"\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2"
"\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" },
{ GCRY_MAC_HMAC_SHA224,
"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",
"\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd"
"\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" },
{ GCRY_MAC_HMAC_SHA224, "?", "????????????????",
"\xc1\x88\xaf\xcf\xce\x51\xa2\x14\x3d\xc1\xaf\x93\xcc\x2b\xe9\x4d"
"\x39\x55\x90\x4c\x46\x70\xfc\xc2\x04\xcf\xab\xfa" },
{ GCRY_MAC_HMAC_SHA384, "what do ya want for nothing?", "Jefe",
"\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b"
"\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e"
"\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" },
{ GCRY_MAC_HMAC_SHA384,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15"
"\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea"
"\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" },
{ GCRY_MAC_HMAC_SHA384,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f"
"\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b"
"\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" },
{ GCRY_MAC_HMAC_SHA384,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7"
"\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e"
"\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" },
{ GCRY_MAC_HMAC_SHA384,
"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",
"\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4"
"\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6"
"\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" },
{ GCRY_MAC_HMAC_SHA384,
"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",
"\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c"
"\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5"
"\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" },
{ GCRY_MAC_HMAC_SHA384, "?", "????????????????",
"\xe7\x96\x29\xa3\x40\x5f\x1e\x6e\x92\xa5\xdb\xa5\xc6\xe9\x60\xa8"
"\xf5\xd1\x6d\xcb\x10\xec\x30\x2f\x6b\x9c\x37\xe0\xea\xf1\x53\x28"
"\x08\x01\x9b\xe3\x4a\x43\xc6\xc2\x2b\x0c\xd9\x43\x64\x35\x25\x78" },
{ GCRY_MAC_HMAC_SHA512, "what do ya want for nothing?", "Jefe",
"\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3"
"\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54"
"\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd"
"\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" },
{ GCRY_MAC_HMAC_SHA512,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0"
"\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde"
"\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4"
"\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" },
{ GCRY_MAC_HMAC_SHA512,
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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",
"\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9"
"\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39"
"\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07"
"\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" },
{ GCRY_MAC_HMAC_SHA512,
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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",
"\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7"
"\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb"
"\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63"
"\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" },
{ GCRY_MAC_HMAC_SHA512,
"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",
"\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4"
"\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52"
"\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52"
"\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" },
{ GCRY_MAC_HMAC_SHA512,
"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",
"\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd"
"\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
"\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
"\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" },
{ GCRY_MAC_HMAC_SHA512, "?", "????????????????",
"\xd4\x43\x61\xfa\x3d\x3d\x57\xd6\xac\xc3\x9f\x1c\x3d\xd9\x26\x84"
"\x1f\xfc\x4d\xf2\xbf\x78\x87\x72\x5e\x6c\x3e\x00\x6d\x39\x5f\xfa"
"\xd7\x3a\xf7\x83\xb7\xb5\x61\xbd\xfb\x33\xe0\x03\x97\xa7\x72\x79"
"\x66\x66\xbf\xbd\x44\xfa\x04\x01\x1b\xc1\x48\x1d\x9e\xde\x5b\x8e" },
/* HMAC-SHA3 test vectors from
* http://wolfgang-ehrhardt.de/hmac-sha3-testvectors.html */
{ GCRY_MAC_HMAC_SHA3_224,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\x3b\x16\x54\x6b\xbc\x7b\xe2\x70\x6a\x03\x1d\xca\xfd\x56\x37\x3d"
"\x98\x84\x36\x76\x41\xd8\xc5\x9a\xf3\xc8\x60\xf7" },
{ GCRY_MAC_HMAC_SHA3_256,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xba\x85\x19\x23\x10\xdf\xfa\x96\xe2\xa3\xa4\x0e\x69\x77\x43\x51"
"\x14\x0b\xb7\x18\x5e\x12\x02\xcd\xcc\x91\x75\x89\xf9\x5e\x16\xbb" },
{ GCRY_MAC_HMAC_SHA3_512,
"Hi There",
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b",
"\xeb\x3f\xbd\x4b\x2e\xaa\xb8\xf5\xc5\x04\xbd\x3a\x41\x46\x5a\xac"
"\xec\x15\x77\x0a\x7c\xab\xac\x53\x1e\x48\x2f\x86\x0b\x5e\xc7\xba"
"\x47\xcc\xb2\xc6\xf2\xaf\xce\x8f\x88\xd2\x2b\x6d\xc6\x13\x80\xf2"
"\x3a\x66\x8f\xd3\x88\x8b\xb8\x05\x37\xc0\xa0\xb8\x64\x07\x68\x9e" },
{ GCRY_MAC_HMAC_SHA3_224, "what do ya want for nothing?", "Jefe",
"\x7f\xdb\x8d\xd8\x8b\xd2\xf6\x0d\x1b\x79\x86\x34\xad\x38\x68\x11"
"\xc2\xcf\xc8\x5b\xfa\xf5\xd5\x2b\xba\xce\x5e\x66" },
{ GCRY_MAC_HMAC_SHA3_256, "what do ya want for nothing?", "Jefe",
"\xc7\xd4\x07\x2e\x78\x88\x77\xae\x35\x96\xbb\xb0\xda\x73\xb8\x87"
"\xc9\x17\x1f\x93\x09\x5b\x29\x4a\xe8\x57\xfb\xe2\x64\x5e\x1b\xa5" },
{ GCRY_MAC_HMAC_SHA3_384, "what do ya want for nothing?", "Jefe",
"\xf1\x10\x1f\x8c\xbf\x97\x66\xfd\x67\x64\xd2\xed\x61\x90\x3f\x21"
"\xca\x9b\x18\xf5\x7c\xf3\xe1\xa2\x3c\xa1\x35\x08\xa9\x32\x43\xce"
"\x48\xc0\x45\xdc\x00\x7f\x26\xa2\x1b\x3f\x5e\x0e\x9d\xf4\xc2\x0a" },
{ GCRY_MAC_HMAC_SHA3_512, "what do ya want for nothing?", "Jefe",
"\x5a\x4b\xfe\xab\x61\x66\x42\x7c\x7a\x36\x47\xb7\x47\x29\x2b\x83"
"\x84\x53\x7c\xdb\x89\xaf\xb3\xbf\x56\x65\xe4\xc5\xe7\x09\x35\x0b"
"\x28\x7b\xae\xc9\x21\xfd\x7c\xa0\xee\x7a\x0c\x31\xd0\x22\xa9\x5e"
"\x1f\xc9\x2b\xa9\xd7\x7d\xf8\x83\x96\x02\x75\xbe\xb4\xe6\x20\x24" },
{ GCRY_MAC_HMAC_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",
"\xb9\x6d\x73\x0c\x14\x8c\x2d\xaa\xd8\x64\x9d\x83\xde\xfa\xa3\x71"
"\x97\x38\xd3\x47\x75\x39\x7b\x75\x71\xc3\x85\x15" },
{ GCRY_MAC_HMAC_SHA3_256,
"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",
"\xa6\x07\x2f\x86\xde\x52\xb3\x8b\xb3\x49\xfe\x84\xcd\x6d\x97\xfb"
"\x6a\x37\xc4\xc0\xf6\x2a\xae\x93\x98\x11\x93\xa7\x22\x9d\x34\x67" },
{ GCRY_MAC_HMAC_SHA3_384,
"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",
"\x71\x3d\xff\x03\x02\xc8\x50\x86\xec\x5a\xd0\x76\x8d\xd6\x5a\x13"
"\xdd\xd7\x90\x68\xd8\xd4\xc6\x21\x2b\x71\x2e\x41\x64\x94\x49\x11"
"\x14\x80\x23\x00\x44\x18\x5a\x99\x10\x3e\xd8\x20\x04\xdd\xbf\xcc" },
{ GCRY_MAC_HMAC_SHA3_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\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa",
"\xb1\x48\x35\xc8\x19\xa2\x90\xef\xb0\x10\xac\xe6\xd8\x56\x8d\xc6"
"\xb8\x4d\xe6\x0b\xc4\x9b\x00\x4c\x3b\x13\xed\xa7\x63\x58\x94\x51"
"\xe5\xdd\x74\x29\x28\x84\xd1\xbd\xce\x64\xe6\xb9\x19\xdd\x61\xdc"
"\x9c\x56\xa2\x82\xa8\x1c\x0b\xd1\x4f\x1f\x36\x5b\x49\xb8\x3a\x5b" },
{ GCRY_MAC_HMAC_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",
"\xc7\x9c\x9b\x09\x34\x24\xe5\x88\xa9\x87\x8b\xbc\xb0\x89\xe0\x18"
"\x27\x00\x96\xe9\xb4\xb1\xa9\xe8\x22\x0c\x86\x6a" },
{ GCRY_MAC_HMAC_SHA3_256,
"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",
"\xe6\xa3\x6d\x9b\x91\x5f\x86\xa0\x93\xca\xc7\xd1\x10\xe9\xe0\x4c"
"\xf1\xd6\x10\x0d\x30\x47\x55\x09\xc2\x47\x5f\x57\x1b\x75\x8b\x5a" },
{ GCRY_MAC_HMAC_SHA3_384,
"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",
"\xca\xd1\x8a\x8f\xf6\xc4\xcc\x3a\xd4\x87\xb9\x5f\x97\x69\xe9\xb6"
"\x1c\x06\x2a\xef\xd6\x95\x25\x69\xe6\xe6\x42\x18\x97\x05\x4c\xfc"
"\x70\xb5\xfd\xc6\x60\x5c\x18\x45\x71\x12\xfc\x6a\xaa\xd4\x55\x85" },
{ GCRY_MAC_HMAC_SHA3_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\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xaa\xaa\xaa",
"\xdc\x03\x0e\xe7\x88\x70\x34\xf3\x2c\xf4\x02\xdf\x34\x62\x2f\x31"
"\x1f\x3e\x6c\xf0\x48\x60\xc6\xbb\xd7\xfa\x48\x86\x74\x78\x2b\x46"
"\x59\xfd\xbd\xf3\xfd\x87\x78\x52\x88\x5c\xfe\x6e\x22\x18\x5f\xe7"
"\xb2\xee\x95\x20\x43\x62\x9b\xc9\xd5\xf3\x29\x8a\x41\xd0\x2c\x66" },
{ GCRY_MAC_HMAC_SHA3_224, "?", "????????????????",
"\x80\x2b\x3c\x84\xfe\x3e\x01\x22\x14\xf8\xba\x74\x79\xfd\xb5\x02"
"\xea\x0c\x06\xa4\x7e\x01\xe3\x2c\xc7\x24\x89\xc3" },
{ GCRY_MAC_HMAC_SHA3_256, "?", "????????????????",
"\x6c\x7c\x96\x5b\x19\xba\xcd\x61\x69\x8a\x2c\x7a\x2b\x96\xa1\xc3"
"\x33\xa0\x3c\x5d\x54\x87\x37\x60\xc8\x2f\xa2\xa6\x12\x38\x8d\x1b" },
{ GCRY_MAC_HMAC_SHA3_384, "?", "????????????????",
"\xc0\x20\xd0\x9b\xa7\xb9\xd5\xb8\xa6\xa4\xba\x20\x55\xd9\x0b\x35"
"\x8b\xe0\xb7\xec\x1e\x9f\xe6\xb9\xbd\xd5\xe9\x9b\xfc\x0a\x11\x3a"
"\x15\x41\xed\xfd\xef\x30\x8d\x03\xb8\xca\x3a\xa8\xc7\x2d\x89\x32" },
{ GCRY_MAC_HMAC_SHA3_512, "?", "????????????????",
"\xb4\xef\x24\xd2\x07\xa7\x01\xb3\xe1\x81\x11\x22\x93\x83\x64\xe0"
"\x5e\xad\x03\xb7\x43\x4f\x87\xa1\x14\x8e\x17\x8f\x2a\x97\x7d\xe8"
"\xbd\xb0\x37\x3b\x67\xb9\x97\x36\xa5\x82\x9b\xdc\x0d\xe4\x5a\x8c"
"\x5e\xda\xb5\xca\xea\xa9\xb4\x6e\xba\xca\x25\xc8\xbf\xa1\x0e\xb0" },
{ GCRY_MAC_HMAC_STRIBOG256,
"\x01\x26\xbd\xb8\x78\x00\xaf\x21\x43\x41\x45\x65\x63\x78\x01\x00",
"\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",
"\xa1\xaa\x5f\x7d\xe4\x02\xd7\xb3\xd3\x23\xf2\x99\x1c\x8d\x45\x34"
"\x01\x31\x37\x01\x0a\x83\x75\x4f\xd0\xaf\x6d\x7c\xd4\x92\x2e\xd9",
NULL, 16, 32 },
{ GCRY_MAC_HMAC_STRIBOG512,
"\x01\x26\xbd\xb8\x78\x00\xaf\x21\x43\x41\x45\x65\x63\x78\x01\x00",
"\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",
"\xa5\x9b\xab\x22\xec\xae\x19\xc6\x5f\xbd\xe6\xe5\xf4\xe9\xf5\xd8"
"\x54\x9d\x31\xf0\x37\xf9\xdf\x9b\x90\x55\x00\xe1\x71\x92\x3a\x77"
"\x3d\x5f\x15\x30\xf2\xed\x7e\x96\x4c\xb2\xee\xdc\x29\xe9\xad\x2f"
"\x3a\xfe\x93\xb2\x81\x4f\x79\xf5\x00\x0f\xfc\x03\x66\xc2\x51\xe6",
NULL, 16, 32 },
/* CMAC AES and DES test vectors from
- http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica\
+ https://web.archive.org/web/20130930212819/https://csrc.nist.gov/publica\
tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */
{ GCRY_MAC_CMAC_AES,
"",
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"",
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"",
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES,
"\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" },
{ GCRY_MAC_CMAC_AES, "?", "????????????????????????????????",
"\x9f\x72\x73\x68\xb0\x49\x2e\xb1\x35\xa0\x1d\xf9\xa8\x0a\xf6\xee" },
{ GCRY_MAC_CMAC_3DES,
"",
"\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" },
{ GCRY_MAC_CMAC_3DES,
"\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" },
{ GCRY_MAC_CMAC_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" },
{ GCRY_MAC_CMAC_3DES,
"\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" },
{ GCRY_MAC_CMAC_3DES,
"",
"\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" },
{ GCRY_MAC_CMAC_3DES,
"\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" },
{ GCRY_MAC_CMAC_3DES,
"\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" },
{ GCRY_MAC_CMAC_3DES,
"\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" },
{ GCRY_MAC_CMAC_3DES, "?", "????????????????????????",
"\xc1\x38\x13\xb2\x31\x8f\x3a\xdf" },
/* CMAC Camellia test vectors from
- http://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */
+ https://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */
{ GCRY_MAC_CMAC_CAMELLIA,
"",
"\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
"\xba\x92\x57\x82\xaa\xa1\xf5\xd9\xa0\x0f\x89\x64\x80\x94\xfc\x71" },
{ GCRY_MAC_CMAC_CAMELLIA,
"\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",
"\x6d\x96\x28\x54\xa3\xb9\xfd\xa5\x6d\x7d\x45\xa9\x5e\xe1\x79\x93" },
{ GCRY_MAC_CMAC_CAMELLIA,
"\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",
"\x5c\x18\xd1\x19\xcc\xd6\x76\x61\x44\xac\x18\x66\x13\x1d\x9f\x22" },
{ GCRY_MAC_CMAC_CAMELLIA,
"\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",
"\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" },
- /* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */
+ /* https://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */
{ GCRY_MAC_GMAC_AES,
"",
"\x11\x75\x4c\xd7\x2a\xec\x30\x9b\xf5\x2f\x76\x87\x21\x2e\x89\x57",
"\x25\x03\x27\xc6\x74\xaa\xf4\x77\xae\xf2\x67\x57\x48\xcf\x69\x71",
"\x3c\x81\x9d\x9a\x9b\xed\x08\x76\x15\x03\x0b\x65" },
{ GCRY_MAC_GMAC_AES,
"\x2b\x63\x26\x64\x29\x67\x4a\xb5\xe2\xea\xff\x63\x9c\x23\x14\x66"
"\x2f\x92\x57\x4b\x29\x8f\x57\x7a\xcf\x7d\x6f\x99\x1a\x87\x92\x1f"
"\xc2\x32\xea\xfc\xc7\xb1\x46\x48\x96\x63\x2d\x6c\x8a\xbe\x88\xc2"
"\xcc\xa4\x04\xdb\xf8\x7c\x20\x6a\x19\xd3\x73\xed\x99\x50\x17\x34"
"\x69\x13\x4d\x7c\x14\xc2\x84\x7d\xf2\x4a\x88\xc1\xc5\x3b\x4d\xe4"
"\x9d\xb3\x66\x39\x2b\x6d\xc6\x51\x27\x6e",
"\x0f\x3b\x17\xde\xae\x62\x13\x64\x55\x4a\xe5\x39\xdb\x09\xde\x11",
"\xff\xb0\xbb\x6d\xfc\x23\x58\x75\x4f\x17\x78\x48\x5b\x59\x65\x7f",
"\xa7\xf6\x07\x4c\xda\x56\x1c\xd2\xaa\x15\xba\x8c\x2f\xa6\x39\x42"
"\x59\x3e\x7c\xcf\x45\xc2\x9a\x57\xda\xd8\xa6\xe2\xea\x63\x54\xce"
"\x8a\xde\x39\xdd\xde\x4a\xc4\x5b\xbd\xc6\x63\xf0\xa5\x37\xc9\x48"
"\x18\x23\x5a\x73\xd8\xa0\x8b\xd8\x98\xab\xd0\x99\xe1\x5c\x08\x8c"
"\x6e\x21\x17\x5a\xf4\xe9\xa4\x99\x70\x12\x82\xed\x32\x81\x50\xa6"
"\xd9\x90\xe8\xec\x87\x85\xce\x26\x1b\xe1\xb8\x3f\xd8\x59\x1e\x57"
"\x76\x5f\x3d\xc1\x11\x3f\xd0\x2a\x40\xf5\x01\x6a\xd0\xd0\xed\xc4"
"\x92\x9a\x02\xe0\x17\xb2\xc5\xf4\x18\xd2\x96\xab\xd6\xc2\xea\x2e" },
{ GCRY_MAC_GMAC_AES,
"\x61\x14\x60\x11\x90\xf6\xef\x5e\x59\x23\x5d\xc0\x42\x8c\x09\xe3"
"\x27\x0b\x19\xea",
"\x15\xa4\x14\x46\x6a\x7f\x90\xea\x32\xbf\xd7\xf6\xe5\x8b\xfa\x06"
"\xe9\x07\xfc\x41\x66\x89\xd9\x60\x39\x45\xd7\x94\x54\xd4\x23\x17",
"\x19\x6e\x0e\x01\x0f\x08\x56\xf9\x82\xb4\x08\x92\x41\xd6\x24\x84",
"\xab" },
{ GCRY_MAC_GMAC_AES,
"\x8b\x5c\x12\x4b\xef\x6e\x2f\x0f\xe4\xd8\xc9\x5c\xd5\xfa\x4c\xf1",
"\x41\xc5\xda\x86\x67\xef\x72\x52\x20\xff\xe3\x9a\xe0\xac\x59\x0a"
"\xc9\xfc\xa7\x29\xab\x60\xad\xa0",
"\x20\x4b\xdb\x1b\xd6\x21\x54\xbf\x08\x92\x2a\xaa\x54\xee\xd7\x05",
"\x05\xad\x13\xa5\xe2\xc2\xab\x66\x7e\x1a\x6f\xbc" },
{ GCRY_MAC_GMAC_AES, "?", "????????????????????????????????",
"\x84\x37\xc3\x42\xae\xf5\xd0\x40\xd3\x73\x90\xa9\x36\xed\x8a\x12" },
/* from NaCl */
{ GCRY_MAC_POLY1305,
"\x8e\x99\x3b\x9f\x48\x68\x12\x73\xc2\x96\x50\xba\x32\xfc\x76\xce"
"\x48\x33\x2e\xa7\x16\x4d\x96\xa4\x47\x6f\xb8\xc5\x31\xa1\x18\x6a"
"\xc0\xdf\xc1\x7c\x98\xdc\xe8\x7b\x4d\xa7\xf0\x11\xec\x48\xc9\x72"
"\x71\xd2\xc2\x0f\x9b\x92\x8f\xe2\x27\x0d\x6f\xb8\x63\xd5\x17\x38"
"\xb4\x8e\xee\xe3\x14\xa7\xcc\x8a\xb9\x32\x16\x45\x48\xe5\x26\xae"
"\x90\x22\x43\x68\x51\x7a\xcf\xea\xbd\x6b\xb3\x73\x2b\xc0\xe9\xda"
"\x99\x83\x2b\x61\xca\x01\xb6\xde\x56\x24\x4a\x9e\x88\xd5\xf9\xb3"
"\x79\x73\xf6\x22\xa4\x3d\x14\xa6\x59\x9b\x1f\x65\x4c\xb4\x5a\x74"
"\xe3\x55\xa5",
"\xee\xa6\xa7\x25\x1c\x1e\x72\x91\x6d\x11\xc2\xcb\x21\x4d\x3c\x25"
"\x25\x39\x12\x1d\x8e\x23\x4e\x65\x2d\x65\x1f\xa4\xc8\xcf\xf8\x80",
"\xf3\xff\xc7\x70\x3f\x94\x00\xe5\x2a\x7d\xfb\x4b\x3d\x33\x05\xd9" },
/* from draft-nir-cfrg-chacha20-poly1305-03 */
{ GCRY_MAC_POLY1305,
"Cryptographic Forum Research Group",
"\x85\xd6\xbe\x78\x57\x55\x6d\x33\x7f\x44\x52\xfe\x42\xd5\x06\xa8"
"\x01\x03\x80\x8a\xfb\x0d\xb2\xfd\x4a\xbf\xf6\xaf\x41\x49\xf5\x1b",
"\xa8\x06\x1d\xc1\x30\x51\x36\xc6\xc2\x2b\x8b\xaf\x0c\x01\x27\xa9" },
{ GCRY_MAC_POLY1305,
"'Twas brillig, and the slithy toves\n"
"Did gyre and gimble in the wabe:\n"
"All mimsy were the borogoves,\n"
"And the mome raths outgrabe.",
"\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",
"\x45\x41\x66\x9a\x7e\xaa\xee\x61\xe7\x08\xdc\x7c\xbc\xc5\xeb\x62" },
{ GCRY_MAC_POLY1305,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
NULL,
191, 32 },
{ GCRY_MAC_POLY1305,
"Any submission to the IETF intended by the Contributor for "
"publication as all or part of an IETF Internet-Draft or RFC and "
"any statement made within the context of an IETF activity is "
"considered an \"IETF Contribution\". Such statements include "
"oral statements in IETF sessions, as well as written and "
"electronic communications made at any time or place, which are "
"addressed to",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e",
"\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e",
NULL,
0, 32 },
{ GCRY_MAC_POLY1305,
"Any submission to the IETF intended by the Contributor for "
"publication as all or part of an IETF Internet-Draft or RFC and "
"any statement made within the context of an IETF activity is "
"considered an \"IETF Contribution\". Such statements include "
"oral statements in IETF sessions, as well as written and "
"electronic communications made at any time or place, which are "
"addressed to",
"\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xf3\x47\x7e\x7c\xd9\x54\x17\xaf\x89\xa6\xb8\x79\x4c\x31\x0c\xf0",
NULL,
0, 32 },
/* draft-irtf-cfrg-chacha20-poly1305-01 */
/* TV#5 */
{ GCRY_MAC_POLY1305,
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
"\x02\x00\x00\x00\x00\x00\x00\x00\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\x00\x00\x00\x00",
NULL,
16, 32 },
/* TV#6 */
{ GCRY_MAC_POLY1305,
"\x02\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"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
"\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
NULL,
16, 32 },
/* TV#7 */
{ GCRY_MAC_POLY1305,
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\x11\x00\x00\x00\x00\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"
"\x00\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",
NULL,
48, 32 },
/* TV#8 */
{ GCRY_MAC_POLY1305,
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFB\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE\xFE"
"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",
"\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",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
NULL,
48, 32 },
/* TV#9 */
{ GCRY_MAC_POLY1305,
"\xFD\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\xFA\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
NULL,
16, 32 },
/* TV#10 */
{ GCRY_MAC_POLY1305,
"\xE3\x35\x94\xD7\x50\x5E\x43\xB9\x00\x00\x00\x00\x00\x00\x00\x00"
"\x33\x94\xD7\x50\x5E\x43\x79\xCD\x01\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\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",
"\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x14\x00\x00\x00\x00\x00\x00\x00\x55\x00\x00\x00\x00\x00\x00\x00",
NULL,
64, 32 },
/* TV#11 */
{ GCRY_MAC_POLY1305,
"\xE3\x35\x94\xD7\x50\x5E\x43\xB9\x00\x00\x00\x00\x00\x00\x00\x00"
"\x33\x94\xD7\x50\x5E\x43\x79\xCD\x01\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
NULL,
48, 32 },
- /* from http://cr.yp.to/mac/poly1305-20050329.pdf */
+ /* from https://cr.yp.to/mac/poly1305-20050329.pdf */
{ GCRY_MAC_POLY1305,
"\xf3\xf6",
"\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00"
"\x58\x0b\x3b\x0f\x94\x47\xbb\x1e\x69\xd0\x95\xb5\x92\x8b\x6d\xbc",
"\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde",
NULL,
0, 32 },
{ GCRY_MAC_POLY1305,
"",
"\xa0\xf3\x08\x00\x00\xf4\x64\x00\xd0\xc7\xe9\x07\x6c\x83\x44\x03"
"\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7",
"\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7",
NULL,
0, 32 },
{ GCRY_MAC_POLY1305,
"\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24"
"\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36",
"\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08"
"\x83\x14\x9c\x69\xb5\x61\xdd\x88\x29\x8a\x17\x98\xb1\x07\x16\xef",
"\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe",
NULL,
0, 32 },
{ GCRY_MAC_POLY1305,
"\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1"
"\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0"
"\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67"
"\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9",
"\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07"
"\x80\xf8\xc2\x0a\xa7\x12\x02\xd1\xe2\x91\x79\xcb\xcb\x55\x5a\x57",
"\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b" },
{ GCRY_MAC_POLY1305, "?", "????????????????????????????????",
"\xc3\x88\xce\x8a\x52\xd6\xe7\x21\x86\xfa\xaa\x5d\x2d\x16\xf9\xa3" },
- /* from http://cr.yp.to/mac/poly1305-20050329.pdf */
+ /* from https://cr.yp.to/mac/poly1305-20050329.pdf */
{ GCRY_MAC_POLY1305_AES,
"\xf3\xf6",
"\xec\x07\x4c\x83\x55\x80\x74\x17\x01\x42\x5b\x62\x32\x35\xad\xd6"
"\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00",
"\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde",
"\xfb\x44\x73\x50\xc4\xe8\x68\xc5\x2a\xc3\x27\x5c\xf9\xd4\x32\x7e",
0, 32 },
{ GCRY_MAC_POLY1305_AES,
"",
"\x75\xde\xaa\x25\xc0\x9f\x20\x8e\x1d\xc4\xce\x6b\x5c\xad\x3f\xbf"
"\xa0\xf3\x08\x00\x00\xf4\x64\x00\xd0\xc7\xe9\x07\x6c\x83\x44\x03",
"\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7",
"\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc",
0, 32 },
{ GCRY_MAC_POLY1305_AES,
"\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24"
"\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36",
"\x6a\xcb\x5f\x61\xa7\x17\x6d\xd3\x20\xc5\xc1\xeb\x2e\xdc\xdc\x74"
"\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08",
"\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe",
"\xae\x21\x2a\x55\x39\x97\x29\x59\x5d\xea\x45\x8b\xc6\x21\xff\x0e",
0, 32 },
{ GCRY_MAC_POLY1305_AES,
"\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1"
"\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0"
"\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67"
"\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9",
"\xe1\xa5\x66\x8a\x4d\x5b\x66\xa5\xf6\x8c\xc5\x42\x4e\xd5\x98\x2d"
"\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07",
"\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b",
"\x9a\xe8\x31\xe7\x43\x97\x8d\x3a\x23\x52\x7c\x71\x28\x14\x9e\x3a",
0, 32 },
{ GCRY_MAC_POLY1305_AES, "?", "????????????????????????????????",
"\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 },
{ 0 },
};
int i;
if (verbose)
fprintf (stderr, "Starting MAC checks.\n");
for (i = 0; algos[i].algo; i++)
{
size_t klen, dlen;
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);
continue;
}
if (verbose)
fprintf (stderr,
" checking %s [%i] for %d byte key and %d byte data\n",
gcry_mac_algo_name (algos[i].algo),
algos[i].algo, (int)strlen(algos[i].key),
(!strcmp(algos[i].data, "!") || !strcmp(algos[i].data, "?"))
? 1000000 : (int)strlen(algos[i].data));
klen = algos[i].klen ? algos[i].klen : strlen(algos[i].key);
dlen = algos[i].dlen ? algos[i].dlen : strlen (algos[i].data);
check_one_mac (algos[i].algo, algos[i].data, dlen, algos[i].key, klen,
algos[i].iv, algos[i].iv ? strlen(algos[i].iv) : 0,
algos[i].expect, 0);
check_one_mac (algos[i].algo, algos[i].data, dlen, algos[i].key, klen,
algos[i].iv, algos[i].iv ? strlen(algos[i].iv) : 0,
algos[i].expect, 1);
}
if (verbose)
fprintf (stderr, "Completed MAC checks.\n");
}
/* Check that the signature SIG matches the hash HASH. PKEY is the
public key used for the verification. BADHASH is a hash value which
should result in a bad signature status. */
static void
verify_one_signature (gcry_sexp_t pkey, gcry_sexp_t hash,
gcry_sexp_t badhash, gcry_sexp_t sig)
{
gcry_error_t rc;
rc = gcry_pk_verify (sig, hash, pkey);
if (rc)
fail ("gcry_pk_verify failed: %s\n", gpg_strerror (rc));
rc = gcry_pk_verify (sig, badhash, pkey);
if (gcry_err_code (rc) != GPG_ERR_BAD_SIGNATURE)
fail ("gcry_pk_verify failed to detect a bad signature: %s\n",
gpg_strerror (rc));
}
/* Test the public key sign function using the private ket SKEY. PKEY
is used for verification. */
static void
check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
{
gcry_error_t rc;
gcry_sexp_t sig, badhash, hash;
int dataidx;
static const char baddata[] =
"(data\n (flags pkcs1)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203041#))\n";
static const struct
{
const char *data;
int algo;
int expected_rc;
} datas[] =
{
{ "(data\n (flags pkcs1)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
GCRY_PK_RSA,
0 },
{ "(data\n (flags pkcs1-raw)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
GCRY_PK_RSA,
GPG_ERR_CONFLICT },
{ "(data\n (flags oaep)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
0,
GPG_ERR_CONFLICT },
/* This test is to see whether hash algorithms not hard wired in
pubkey.c are detected: */
{ "(data\n (flags pkcs1)\n"
" (hash oid.1.3.14.3.2.29 "
" #11223344556677889900AABBCCDDEEFF10203040#))\n",
GCRY_PK_RSA,
0 },
{ "(data\n (flags )\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
0,
GPG_ERR_CONFLICT },
{ "(data\n (flags pkcs1)\n"
" (hash foo #11223344556677889900AABBCCDDEEFF10203040#))\n",
GCRY_PK_RSA,
GPG_ERR_DIGEST_ALGO },
{ "(data\n (flags )\n" " (value #11223344556677889900AA#))\n",
0,
0 },
{ "(data\n (flags )\n" " (value #0090223344556677889900AA#))\n",
0,
0 },
{ "(data\n (flags raw)\n" " (value #11223344556677889900AA#))\n",
0,
0 },
{ "(data\n (flags pkcs1)\n"
" (value #11223344556677889900AA#))\n",
GCRY_PK_RSA,
GPG_ERR_CONFLICT },
{ "(data\n (flags pkcs1-raw)\n"
" (value #11223344556677889900AA#))\n",
GCRY_PK_RSA,
0 },
{ "(data\n (flags raw foo)\n"
" (value #11223344556677889900AA#))\n",
0,
GPG_ERR_INV_FLAG },
{ "(data\n (flags pss)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
GCRY_PK_RSA,
0 },
{ "(data\n (flags pss)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#)\n"
" (random-override #4253647587980912233445566778899019283747#))\n",
GCRY_PK_RSA,
0 },
{ NULL }
};
rc = gcry_sexp_sscan (&badhash, NULL, baddata, strlen (baddata));
if (rc)
die ("converting data failed: %s\n", gpg_strerror (rc));
for (dataidx = 0; datas[dataidx].data; dataidx++)
{
if (datas[dataidx].algo && datas[dataidx].algo != algo)
continue;
if (verbose)
fprintf (stderr, " test %d, signature test %d (%s)\n",
n, dataidx, gcry_pk_algo_name (algo));
rc = gcry_sexp_sscan (&hash, NULL, datas[dataidx].data,
strlen (datas[dataidx].data));
if (rc)
die ("converting data failed: %s\n", gpg_strerror (rc));
rc = gcry_pk_sign (&sig, hash, skey);
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);
gcry_sexp_release (sig);
sig = NULL;
gcry_sexp_release (hash);
hash = NULL;
}
gcry_sexp_release (badhash);
}
/* Test the public key sign function using the private ket 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)
{
gcry_error_t rc;
gcry_sexp_t sig, badhash, hash;
unsigned int nbits;
int dataidx;
static const struct
{
unsigned int nbits;
const char *data;
int expected_rc;
const char *baddata;
int dummy;
} datas[] =
{
{ 192,
"(data (flags raw)\n"
" (value #00112233445566778899AABBCCDDEEFF0001020304050607#))",
0,
"(data (flags raw)\n"
" (value #80112233445566778899AABBCCDDEEFF0001020304050607#))",
0
},
{ 256,
"(data (flags raw)\n"
" (value #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0,
"(data (flags raw)\n"
" (value #80112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0
},
{ 256,
"(data (flags raw)\n"
" (hash sha256 #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0,
"(data (flags raw)\n"
" (hash sha256 #80112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0
},
{ 256,
"(data (flags gost)\n"
" (value #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0,
"(data (flags gost)\n"
" (value #80112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0
},
{ 512,
"(data (flags gost)\n"
" (value #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0,
"(data (flags gost)\n"
" (value #80112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F#))",
0
},
{ 0, NULL }
};
nbits = gcry_pk_get_nbits (skey);
for (dataidx = 0; datas[dataidx].data; dataidx++)
{
if (datas[dataidx].nbits != nbits)
continue;
if (verbose)
fprintf (stderr, " test %d, signature test %d (%u bit ecdsa)\n",
n, dataidx, nbits);
rc = gcry_sexp_sscan (&hash, NULL, datas[dataidx].data,
strlen (datas[dataidx].data));
if (rc)
die ("converting data failed: %s\n", gpg_strerror (rc));
rc = gcry_sexp_sscan (&badhash, NULL, datas[dataidx].baddata,
strlen (datas[dataidx].baddata));
if (rc)
die ("converting data failed: %s\n", gpg_strerror (rc));
rc = gcry_pk_sign (&sig, hash, skey);
if (gcry_err_code (rc) != datas[dataidx].expected_rc)
fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc));
if (!rc && verbose > 1)
show_sexp ("ECDSA signature:\n", sig);
if (!rc)
verify_one_signature (pkey, hash, badhash, sig);
gcry_sexp_release (sig);
sig = NULL;
gcry_sexp_release (badhash);
badhash = NULL;
gcry_sexp_release (hash);
hash = NULL;
}
}
static void
check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
{
gcry_error_t rc;
gcry_sexp_t plain = NULL;
gcry_sexp_t ciph = NULL;
gcry_sexp_t data = NULL;
int dataidx;
static const struct
{
int algo; /* If not 0 run test only if ALGO matches. */
const char *data;
const char *hint;
int unpadded;
int encrypt_expected_rc;
int decrypt_expected_rc;
int special;
} datas[] =
{
{ GCRY_PK_RSA,
"(data\n (flags pkcs1)\n"
" (value #11223344556677889900AA#))\n",
NULL,
0,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags pkcs1)\n"
" (value #11223344556677889900AA#))\n",
"(flags pkcs1)",
1,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags oaep)\n"
" (value #11223344556677889900AA#))\n",
"(flags oaep)",
1,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags oaep)\n (hash-algo sha1)\n"
" (value #11223344556677889900AA#))\n",
"(flags oaep)(hash-algo sha1)",
1,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags oaep)\n (hash-algo sha1)\n (label \"test\")\n"
" (value #11223344556677889900AA#))\n",
"(flags oaep)(hash-algo sha1)(label \"test\")",
1,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags oaep)\n (hash-algo sha1)\n (label \"test\")\n"
" (value #11223344556677889900AA#)\n"
" (random-override #4253647587980912233445566778899019283747#))\n",
"(flags oaep)(hash-algo sha1)(label \"test\")",
1,
0,
0 },
{ 0,
"(data\n (flags )\n" " (value #11223344556677889900AA#))\n",
NULL,
1,
0,
0 },
{ 0,
"(data\n (flags )\n" " (value #0090223344556677889900AA#))\n",
NULL,
1,
0,
0 },
{ 0,
"(data\n (flags raw)\n" " (value #11223344556677889900AA#))\n",
NULL,
1,
0,
0 },
{ GCRY_PK_RSA,
"(data\n (flags pkcs1)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
NULL,
0,
GPG_ERR_CONFLICT,
0},
{ 0,
"(data\n (flags raw foo)\n"
" (hash sha1 #11223344556677889900AABBCCDDEEFF10203040#))\n",
NULL,
0,
GPG_ERR_INV_FLAG,
0},
{ 0,
"(data\n (flags raw)\n"
" (value #11223344556677889900AA#))\n",
"(flags oaep)",
1,
0,
GPG_ERR_ENCODING_PROBLEM, 1 },
{ GCRY_PK_RSA,
"(data\n (flags oaep)\n"
" (value #11223344556677889900AA#))\n",
"(flags pkcs1)",
1,
0,
GPG_ERR_ENCODING_PROBLEM, 1 },
{ 0,
"(data\n (flags pss)\n"
" (value #11223344556677889900AA#))\n",
NULL,
0,
GPG_ERR_CONFLICT },
{ 0, NULL }
};
(void)n;
for (dataidx = 0; datas[dataidx].data; dataidx++)
{
if (datas[dataidx].algo && datas[dataidx].algo != algo)
continue;
if (verbose)
fprintf (stderr, " encryption/decryption test %d (algo %d)\n",
dataidx, algo);
rc = gcry_sexp_sscan (&data, NULL, datas[dataidx].data,
strlen (datas[dataidx].data));
if (rc)
die ("converting data failed: %s\n", gpg_strerror (rc));
rc = gcry_pk_encrypt (&ciph, data, pkey);
if (gcry_err_code (rc) != datas[dataidx].encrypt_expected_rc)
fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (rc));
if (!rc)
{
int expect_mismatch = 0;
/* Insert decoding hint to CIPH. */
if (datas[dataidx].hint)
{
size_t hint_len, len;
char *hint, *buf;
gcry_sexp_t list;
/* Convert decoding hint into canonical sexp. */
hint_len = 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)
die ("can't allocate memory\n");
hint_len = gcry_sexp_sprint (list, GCRYSEXP_FMT_CANON, hint,
hint_len);
gcry_sexp_release (list);
/* Convert CIPH into canonical sexp. */
len = gcry_sexp_sprint (ciph, GCRYSEXP_FMT_CANON, NULL, 0);
buf = gcry_malloc (len + hint_len);
if (!buf)
die ("can't allocate memory\n");
len = gcry_sexp_sprint (ciph, GCRYSEXP_FMT_CANON, buf, len);
/* assert (!strcmp (buf, "(7:enc-val", 10)); */
/* Copy decoding hint into CIPH. */
memmove (buf + 10 + hint_len, buf + 10, len - 10);
memcpy (buf + 10, hint, hint_len);
gcry_free (hint);
gcry_sexp_new (&list, buf, len + hint_len, 1);
gcry_free (buf);
gcry_sexp_release (ciph);
ciph = list;
}
rc = gcry_pk_decrypt (&plain, ciph, skey);
if (!rc && datas[dataidx].special == 1)
{
/* It may happen that OAEP formatted data which is
decrypted as pkcs#1 data returns a valid pkcs#1
frame. However, the returned value will not be
identical - thus we expect a mismatch and test further on
whether this mismatch actually happened. */
expect_mismatch = 1;
}
else if (gcry_err_code (rc) != datas[dataidx].decrypt_expected_rc)
{
if (verbose)
{
show_sexp (" data:\n", data);
show_sexp (" ciph:\n", ciph);
show_sexp (" key:\n", skey);
}
fail ("gcry_pk_decrypt failed: expected %d (%s), got %d (%s)\n",
datas[dataidx].decrypt_expected_rc,
gpg_strerror (datas[dataidx].decrypt_expected_rc),
rc, gpg_strerror (rc));
}
if (!rc && datas[dataidx].unpadded)
{
gcry_sexp_t p1, p2;
p1 = gcry_sexp_find_token (data, "value", 0);
p2 = gcry_sexp_find_token (plain, "value", 0);
if (p1 && p2)
{
const char *s1, *s2;
size_t n1, n2;
s1 = gcry_sexp_nth_data (p1, 1, &n1);
s2 = gcry_sexp_nth_data (p2, 1, &n2);
if (n1 != n2 || memcmp (s1, s2, n1))
{
if (expect_mismatch)
expect_mismatch = 0;
else
fail ("gcry_pk_encrypt/gcry_pk_decrypt "
"do not roundtrip\n");
}
}
if (expect_mismatch)
fail ("gcry_pk_encrypt/gcry_pk_decrypt "
"expected mismatch did not happen\n");
gcry_sexp_release (p1);
gcry_sexp_release (p2);
}
}
gcry_sexp_release (plain);
plain = NULL;
gcry_sexp_release (ciph);
ciph = NULL;
gcry_sexp_release (data);
data = NULL;
}
}
static void
check_pubkey_grip (int n, const unsigned char *grip,
gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
{
unsigned char sgrip[20], pgrip[20];
(void)algo;
if (!gcry_pk_get_keygrip (skey, sgrip))
die ("get keygrip for private RSA key failed\n");
if (!gcry_pk_get_keygrip (pkey, pgrip))
die ("[%i] get keygrip for public RSA key failed\n", n);
if (memcmp (sgrip, pgrip, 20))
fail ("[%i] keygrips don't match\n", n);
if (memcmp (sgrip, grip, 20))
fail ("wrong keygrip for RSA key\n");
}
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 (algo == GCRY_PK_ECDSA)
check_pubkey_sign_ecdsa (n, skey, pkey);
else
check_pubkey_sign (n, skey, pkey, algo);
}
if (flags & FLAG_CRYPT)
check_pubkey_crypt (n, skey, pkey, algo);
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_sexp_t skey, pkey;
err = gcry_sexp_sscan (&skey, NULL, spec.key.secret,
strlen (spec.key.secret));
if (!err)
err = gcry_sexp_sscan (&pkey, NULL, spec.key.public,
strlen (spec.key.public));
if (err)
die ("converting sample key failed: %s\n", gpg_strerror (err));
do_check_one_pubkey (n, skey, pkey,
(const unsigned char*)spec.key.grip,
spec.id, spec.flags);
gcry_sexp_release (skey);
gcry_sexp_release (pkey);
}
static void
get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
if (verbose)
fprintf (stderr, " generating RSA key:");
rc = gcry_sexp_new (&key_spec,
in_fips_mode ? "(genkey (rsa (nbits 4:2048)))"
: "(genkey (rsa (nbits 4:1024)(transient-key)))",
0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, key_spec);
gcry_sexp_release (key_spec);
if (rc)
die ("error generating RSA key: %s\n", gpg_strerror (rc));
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
check_one_pubkey_new (int n)
{
gcry_sexp_t skey, pkey;
get_keys_new (&pkey, &skey);
do_check_one_pubkey (n, skey, pkey, NULL,
GCRY_PK_RSA, FLAG_SIGN | FLAG_CRYPT);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
}
/* Run all tests for the public key functions. */
static void
check_pubkey (void)
{
static const test_spec_pubkey_t pubkeys[] = {
{
GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN,
{
"(private-key\n"
" (rsa\n"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea2"
" 51#)\n"
" (e #010001#)\n"
" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
" 7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
" C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
" C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781"
" #)\n"
" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424"
" f1#)\n"
" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad3"
" 61#)\n"
" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b"
" #)))\n",
"(public-key\n"
" (rsa\n"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea2"
" 51#)\n"
" (e #010001#)))\n",
"\x32\x10\x0c\x27\x17\x3e\xf6\xe9\xc4\xe9"
"\xa2\x5d\x3d\x69\xf8\x6d\x37\xa4\xf9\x39"}
},
{
GCRY_PK_DSA, FLAG_SIGN,
{
"(private-key\n"
" (DSA\n"
" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D877"
" 7B#)\n"
" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)\n"
" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15"
" #)\n"
" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB"
" #)\n"
" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))\n",
"(public-key\n"
" (DSA\n"
" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191"
" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44"
" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D877"
" 7B#)\n"
" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)\n"
" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503"
" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E"
" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984"
" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15"
" #)\n"
" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46"
" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB"
" #)))\n",
"\xc6\x39\x83\x1a\x43\xe5\x05\x5d\xc6\xd8"
"\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" }
},
{
GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT,
{
"(private-key\n"
" (ELG\n"
" (p #00B93B93386375F06C2D38560F3B9C6D6D7B7506B20C1773F73F8DE56E6CD65D"
" F48DFAAA1E93F57A2789B168362A0F787320499F0B2461D3A4268757A7B27517"
" B7D203654A0CD484DEC6AF60C85FEB84AAC382EAF2047061FE5DAB81A20A0797"
" 6E87359889BAE3B3600ED718BE61D4FC993CC8098A703DD0DC942E965E8F18D2"
" A7#)\n"
" (g #05#)\n"
" (y #72DAB3E83C9F7DD9A931FDECDC6522C0D36A6F0A0FEC955C5AC3C09175BBFF2B"
" E588DB593DC2E420201BEB3AC17536918417C497AC0F8657855380C1FCF11C5B"
" D20DB4BEE9BDF916648DE6D6E419FA446C513AAB81C30CB7B34D6007637BE675"
" 56CE6473E9F9EE9B9FADD275D001563336F2186F424DEC6199A0F758F6A00FF4"
" #)\n"
" (x #03C28900087B38DABF4A0AB98ACEA39BB674D6557096C01D72E31C16BDD32214"
" #)))\n",
"(public-key\n"
" (ELG\n"
" (p #00B93B93386375F06C2D38560F3B9C6D6D7B7506B20C1773F73F8DE56E6CD65D"
" F48DFAAA1E93F57A2789B168362A0F787320499F0B2461D3A4268757A7B27517"
" B7D203654A0CD484DEC6AF60C85FEB84AAC382EAF2047061FE5DAB81A20A0797"
" 6E87359889BAE3B3600ED718BE61D4FC993CC8098A703DD0DC942E965E8F18D2"
" A7#)\n"
" (g #05#)\n"
" (y #72DAB3E83C9F7DD9A931FDECDC6522C0D36A6F0A0FEC955C5AC3C09175BBFF2B"
" E588DB593DC2E420201BEB3AC17536918417C497AC0F8657855380C1FCF11C5B"
" D20DB4BEE9BDF916648DE6D6E419FA446C513AAB81C30CB7B34D6007637BE675"
" 56CE6473E9F9EE9B9FADD275D001563336F2186F424DEC6199A0F758F6A00FF4"
" #)))\n",
"\xa7\x99\x61\xeb\x88\x83\xd2\xf4\x05\xc8"
"\x4f\xba\x06\xf8\x78\x09\xbc\x1e\x20\xe5" }
},
{ /* ECDSA test. */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecdsa\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)\n"
" (d #00D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D#)))\n",
"(public-key\n"
" (ecdsa\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)))\n",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
},
{ /* ECDSA test with the public key algorithm given as "ecc". */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecdsa\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)\n"
" (d #00D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D#)))\n",
"(public-key\n"
" (ecc\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)))\n",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
},
{ /* ECDSA test with the private key algorithm given as "ecc". */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecc\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)\n"
" (d #00D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D#)))\n",
"(public-key\n"
" (ecdsa\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)))\n",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
},
{ /* ECDSA test with the key algorithms given as "ecc". */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecc\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)\n"
" (d #00D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D#)))\n",
"(public-key\n"
" (ecc\n"
" (curve nistp192)\n"
" (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
" C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)))\n",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
},
{ /* ECDSA test 256 bit. */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecc\n"
" (curve nistp256)\n"
" (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2B"
" EB6644D3609FC781B71F9A8072F58CB66AE2F89BB1245187"
" 3ABF7D91F9E1FBF96BF2F70E73AAC9A283#)\n"
" (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F74"
" 4715E1D5BBE70378#)))\n",
"(public-key\n"
" (ecc\n"
" (curve nistp256)\n"
" (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2B"
" EB6644D3609FC781B71F9A8072F58CB66AE2F89BB1245187"
" 3ABF7D91F9E1FBF96BF2F70E73AAC9A283#)))\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,
{
"(private-key\n"
" (ecc\n"
" (curve GOST2001-test)\n"
" (q #047F2B49E270DB6D90D8595BEC458B50C58585BA1D4E9B78"
" 8F6689DBD8E56FD80B26F1B489D6701DD185C8413A977B3C"
" BBAF64D1C593D26627DFFB101A87FF77DA#)\n"
" (d #7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE"
" 1D19CE9891EC3B28#)))\n",
"(public-key\n"
" (ecc\n"
" (curve GOST2001-test)\n"
" (q #047F2B49E270DB6D90D8595BEC458B50C58585BA1D4E9B78"
" 8F6689DBD8E56FD80B26F1B489D6701DD185C8413A977B3C"
" BBAF64D1C593D26627DFFB101A87FF77DA#)))\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-2012 test 512 bit. */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecc\n"
" (curve GOST2012-test)\n"
" (q #04115DC5BC96760C7B48598D8AB9E740D4C4A85A65BE33C1"
" 815B5C320C854621DD5A515856D13314AF69BC5B924C8B"
" 4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4"
" 0B0F5621DC3AC1B751CFA0E2634FA0503B3D52639F5D7F"
" B72AFD61EA199441D943FFE7F0C70A2759A3CDB84C114E"
" 1F9339FDF27F35ECA93677BEEC#)\n"
" (d #0BA6048AADAE241BA40936D47756D7C93091A0E851466970"
" 0EE7508E508B102072E8123B2200A0563322DAD2827E2714"
" A2636B7BFD18AADFC62967821FA18DD4#)))\n",
"(public-key\n"
" (ecc\n"
" (curve GOST2012-test)\n"
" (q #04115DC5BC96760C7B48598D8AB9E740D4C4A85A65BE33C1"
" 815B5C320C854621DD5A515856D13314AF69BC5B924C8B"
" 4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4"
" 0B0F5621DC3AC1B751CFA0E2634FA0503B3D52639F5D7F"
" B72AFD61EA199441D943FFE7F0C70A2759A3CDB84C114E"
" 1F9339FDF27F35ECA93677BEEC#)))\n"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
},
{ /* secp256k1 test 256 bit. */
GCRY_PK_ECDSA, FLAG_SIGN,
{
"(private-key\n"
" (ecc\n"
" (curve secp256k1)\n"
" (q #0439A36013301597DAEF41FBE593A02CC513D0B55527EC2D"
" F1050E2E8FF49C85C23CBE7DED0E7CE6A594896B8F62888F"
" DBC5C8821305E2EA42BF01E37300116281#)\n"
" (d #E8F32E723DECF4051AEFAC8E2C93C9C5B214313817CDB01A"
" 1494B917C8436B35#)))\n",
"(public-key\n"
" (ecc\n"
" (curve secp256k1)\n"
" (q #0439A36013301597DAEF41FBE593A02CC513D0B55527EC2D"
" F1050E2E8FF49C85C23CBE7DED0E7CE6A594896B8F62888F"
" DBC5C8821305E2EA42BF01E37300116281#)))\n"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
}
};
int i;
if (verbose)
fprintf (stderr, "Starting 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 (i, pubkeys[i]);
}
if (verbose)
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);
}
if (verbose)
fprintf (stderr, "Completed additional public key checks.\n");
}
int
main (int argc, char **argv)
{
gpg_error_t err;
int last_argc = -1;
int use_fips = 0;
int selftest_only = 0;
int pubkey_only = 0;
int cipher_modes_only = 0;
int loop = 0;
unsigned int loopcount = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = debug = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--fips"))
{
use_fips = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--selftest"))
{
selftest_only = 1;
verbose += 2;
argc--; argv++;
}
else if (!strcmp (*argv, "--pubkey"))
{
pubkey_only = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--cipher-modes"))
{
cipher_modes_only = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--die"))
{
die_on_error = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--loop"))
{
argc--; argv++;
if (argc)
{
loop = atoi (*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--;
argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr,
PGM
": unknown hardware feature `%s' - option ignored\n",
*argv);
argc--;
argv++;
}
}
}
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);
if (verbose)
gcry_set_progress_handler (progress_handler, NULL);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (debug)
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);
do
{
if (pubkey_only)
check_pubkey ();
else if (cipher_modes_only)
{
check_ciphers ();
check_cipher_modes ();
}
else if (!selftest_only)
{
check_ciphers ();
check_cipher_modes ();
check_bulk_cipher_modes ();
check_digests ();
check_hmac ();
check_mac ();
check_pubkey ();
}
loopcount++;
if (loop)
{
fprintf (stderr, "Test iteration %u completed.\n", loopcount);
if (loop != -1)
loop--;
}
}
while (loop);
if (in_fips_mode && !selftest_only)
{
/* If we are in fips mode do some more tests. */
gcry_md_hd_t md;
/* First trigger a self-test. */
xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0))
fail ("not in operational state after self-test\n");
/* Get us into the error state. */
err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
if (err)
fail ("failed to open SHA-1 hash context: %s\n", gpg_strerror (err));
else
{
err = gcry_md_enable (md, GCRY_MD_SHA256);
if (err)
fail ("failed to add SHA-256 hash context: %s\n",
gpg_strerror (err));
else
{
/* gcry_md_get_algo is only defined for a context with
just one digest algorithm. With our setup it should
put the oibrary intoerror state. */
fputs ("Note: Two lines with error messages follow "
"- this is expected\n", stderr);
gcry_md_get_algo (md);
gcry_md_close (md);
if (gcry_control (GCRYCTL_OPERATIONAL_P, 0))
fail ("expected error state but still in operational state\n");
else
{
/* Now run a self-test and to get back into
operational state. */
xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0))
fail ("did not reach operational after error "
"and self-test\n");
}
}
}
}
else
{
/* If in standard mode, run selftests. */
if (gcry_control (GCRYCTL_SELFTEST, 0))
fail ("running self-test failed\n");
}
if (verbose)
fprintf (stderr, "\nAll tests completed. Errors: %i\n", error_count);
if (in_fips_mode && !gcry_fips_mode_active ())
fprintf (stderr, "FIPS mode is not anymore active\n");
return error_count ? 1 : 0;
}
diff --git a/tests/bench-slope.c b/tests/bench-slope.c
index 2ead3c9e..84171305 100644
--- a/tests/bench-slope.c
+++ b/tests/bench-slope.c
@@ -1,2363 +1,2363 @@
/* bench-slope.c - for libgcrypt
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <time.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
# include "../compat/libcompat.h"
#else
# include <gcrypt.h>
#endif
#ifndef STR
#define STR(v) #v
#define STR2(v) STR(v)
#endif
#define PGM "bench-slope"
#include "t-common.h"
static int verbose;
static int csv_mode;
static int unaligned_mode;
static int num_measurement_repetitions;
/* CPU Ghz value provided by user, allows constructing cycles/byte and other
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;
/* The name of the currently printed section. */
static char *current_section_name;
/* The name of the currently printed algorithm. */
static char *current_algo_name;
/* The name of the currently printed mode. */
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;
/*************************************** Default parameters for measurements. */
/* Start at small buffer size, to get reasonable timer calibration for fast
* implementations (AES-NI etc). Sixteen selected to support the largest block
* size of current set cipher blocks. */
#define BUF_START_SIZE 16
/* From ~0 to ~4kbytes give comparable results with results from academia
* (SUPERCOP). */
#define BUF_END_SIZE (BUF_START_SIZE + 4096)
/* With 128 byte steps, we get (4096)/64 = 64 data points. */
#define BUF_STEP_SIZE 64
/* Number of repeated measurements at each data point. The median of these
* 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. */
#undef NO_GET_NSEC_TIME
#if defined(_WIN32)
struct nsec_time
{
LARGE_INTEGER perf_count;
};
static void
get_nsec_time (struct nsec_time *t)
{
BOOL ok;
ok = QueryPerformanceCounter (&t->perf_count);
assert (ok);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
static double nsecs_per_count = 0.0;
double nsecs;
if (nsecs_per_count == 0.0)
{
LARGE_INTEGER perf_freq;
BOOL ok;
/* Get counts per second. */
ok = QueryPerformanceFrequency (&perf_freq);
assert (ok);
nsecs_per_count = 1.0 / perf_freq.QuadPart;
nsecs_per_count *= 1000000.0 * 1000.0; /* sec => nsec */
assert (nsecs_per_count > 0.0);
}
nsecs = end->perf_count.QuadPart - start->perf_count.QuadPart; /* counts */
nsecs *= nsecs_per_count; /* counts * (nsecs / count) => nsecs */
return nsecs;
}
#elif defined(HAVE_CLOCK_GETTIME)
struct nsec_time
{
struct timespec ts;
};
static void
get_nsec_time (struct nsec_time *t)
{
int err;
err = clock_gettime (CLOCK_REALTIME, &t->ts);
assert (err == 0);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
double nsecs;
nsecs = end->ts.tv_sec - start->ts.tv_sec;
nsecs *= 1000000.0 * 1000.0; /* sec => nsec */
/* This way we don't have to care if tv_nsec unsigned or signed. */
if (end->ts.tv_nsec >= start->ts.tv_nsec)
nsecs += end->ts.tv_nsec - start->ts.tv_nsec;
else
nsecs -= start->ts.tv_nsec - end->ts.tv_nsec;
return nsecs;
}
#elif defined(HAVE_GETTIMEOFDAY)
struct nsec_time
{
struct timeval tv;
};
static void
get_nsec_time (struct nsec_time *t)
{
int err;
err = gettimeofday (&t->tv, NULL);
assert (err == 0);
}
static double
get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
{
double nsecs;
nsecs = end->tv.tv_sec - start->tv.tv_sec;
nsecs *= 1000000; /* sec => µsec */
/* This way we don't have to care if tv_usec unsigned or signed. */
if (end->tv.tv_usec >= start->tv.tv_usec)
nsecs += end->tv.tv_usec - start->tv.tv_usec;
else
nsecs -= start->tv.tv_usec - end->tv.tv_usec;
nsecs *= 1000; /* µsec => nsec */
return nsecs;
}
#else
#define NO_GET_NSEC_TIME 1
#endif
/* If no high resolution timer found, provide dummy bench-slope. */
#ifdef NO_GET_NSEC_TIME
int
main (void)
{
/* No nsec timer => SKIP test. */
return 77;
}
#else /* !NO_GET_NSEC_TIME */
/********************************************** Slope benchmarking framework. */
struct bench_obj
{
const struct bench_ops *ops;
unsigned int num_measure_repetitions;
unsigned int min_bufsize;
unsigned int max_bufsize;
unsigned int step_size;
void *priv;
void *hd;
};
typedef int (*const bench_initialize_t) (struct bench_obj * obj);
typedef void (*const bench_finalize_t) (struct bench_obj * obj);
typedef void (*const bench_do_run_t) (struct bench_obj * obj, void *buffer,
size_t buflen);
struct bench_ops
{
bench_initialize_t initialize;
bench_finalize_t finalize;
bench_do_run_t do_run;
};
double
get_slope (double (*const get_x) (unsigned int idx, void *priv),
void *get_x_priv, double y_points[], unsigned int npoints,
double *overhead)
{
double sumx, sumy, sumx2, sumy2, sumxy;
unsigned int i;
double b, a;
sumx = sumy = sumx2 = sumy2 = sumxy = 0;
for (i = 0; i < npoints; i++)
{
double x, y;
x = get_x (i, get_x_priv); /* bytes */
y = y_points[i]; /* nsecs */
sumx += x;
sumy += y;
sumx2 += x * x;
/*sumy2 += y * y;*/
sumxy += x * y;
}
b = (npoints * sumxy - sumx * sumy) / (npoints * sumx2 - sumx * sumx);
a = (sumy - b * sumx) / npoints;
if (overhead)
*overhead = a; /* nsecs */
return b; /* nsecs per byte */
}
double
get_bench_obj_point_x (unsigned int idx, void *priv)
{
struct bench_obj *obj = priv;
return (double) (obj->min_bufsize + (idx * obj->step_size));
}
unsigned int
get_num_measurements (struct bench_obj *obj)
{
unsigned int buf_range = obj->max_bufsize - obj->min_bufsize;
unsigned int num = buf_range / obj->step_size + 1;
while (obj->min_bufsize + (num * obj->step_size) > obj->max_bufsize)
num--;
return num + 1;
}
static int
double_cmp (const void *_a, const void *_b)
{
const double *a, *b;
a = _a;
b = _b;
if (*a > *b)
return 1;
if (*a < *b)
return -1;
return 0;
}
double
do_bench_obj_measurement (struct bench_obj *obj, void *buffer, size_t buflen,
double *measurement_raw,
unsigned int loop_iterations)
{
const unsigned int num_repetitions = obj->num_measure_repetitions;
const bench_do_run_t do_run = obj->ops->do_run;
struct nsec_time start, end;
unsigned int rep, loop;
double res;
if (num_repetitions < 1 || loop_iterations < 1)
return 0.0;
for (rep = 0; rep < num_repetitions; rep++)
{
get_nsec_time (&start);
for (loop = 0; loop < loop_iterations; loop++)
do_run (obj, buffer, buflen);
get_nsec_time (&end);
measurement_raw[rep] = get_time_nsec_diff (&start, &end);
}
/* Return median of repeated measurements. */
qsort (measurement_raw, num_repetitions, sizeof (measurement_raw[0]),
double_cmp);
if (num_repetitions % 2 == 1)
return measurement_raw[num_repetitions / 2];
res = measurement_raw[num_repetitions / 2]
+ measurement_raw[num_repetitions / 2 - 1];
return res / 2;
}
unsigned int
adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer,
double *measurement_raw)
{
const double increase_thres = 3.0;
double tmp, nsecs;
unsigned int loop_iterations;
unsigned int test_bufsize;
test_bufsize = obj->min_bufsize;
if (test_bufsize == 0)
test_bufsize += obj->step_size;
loop_iterations = 0;
do
{
/* Increase loop iterations until we get other results than zero. */
nsecs =
do_bench_obj_measurement (obj, buffer, test_bufsize,
measurement_raw, ++loop_iterations);
}
while (nsecs < 1.0 - 0.1);
do
{
/* Increase loop iterations until we get reasonable increase for elapsed time. */
tmp =
do_bench_obj_measurement (obj, buffer, test_bufsize,
measurement_raw, ++loop_iterations);
}
while (tmp < nsecs * (increase_thres - 0.1));
return loop_iterations;
}
/* Benchmark and return linear regression slope in nanoseconds per byte. */
double
slope_benchmark (struct bench_obj *obj)
{
unsigned int num_measurements;
double *measurements = NULL;
double *measurement_raw = NULL;
double slope, overhead;
unsigned int loop_iterations, midx, i;
unsigned char *real_buffer = NULL;
unsigned char *buffer;
size_t cur_bufsize;
int err;
err = obj->ops->initialize (obj);
if (err < 0)
return -1;
num_measurements = get_num_measurements (obj);
measurements = calloc (num_measurements, sizeof (*measurements));
if (!measurements)
goto err_free;
measurement_raw =
calloc (obj->num_measure_repetitions, sizeof (*measurement_raw));
if (!measurement_raw)
goto err_free;
if (num_measurements < 1 || obj->num_measure_repetitions < 1 ||
obj->max_bufsize < 1 || obj->min_bufsize > obj->max_bufsize)
goto err_free;
real_buffer = malloc (obj->max_bufsize + 128 + unaligned_mode);
if (!real_buffer)
goto err_free;
/* Get aligned buffer */
buffer = real_buffer;
buffer += 128 - ((real_buffer - (unsigned char *) 0) & (128 - 1));
if (unaligned_mode)
buffer += unaligned_mode; /* Make buffer unaligned */
for (i = 0; i < obj->max_bufsize; i++)
buffer[i] = 0x55 ^ (-i);
/* Adjust number of loop iterations up to timer accuracy. */
loop_iterations = adjust_loop_iterations_to_timer_accuracy (obj, buffer,
measurement_raw);
/* Perform measurements */
for (midx = 0, cur_bufsize = obj->min_bufsize;
cur_bufsize <= obj->max_bufsize; cur_bufsize += obj->step_size, midx++)
{
measurements[midx] =
do_bench_obj_measurement (obj, buffer, cur_bufsize, measurement_raw,
loop_iterations);
measurements[midx] /= loop_iterations;
}
assert (midx == num_measurements);
slope =
get_slope (&get_bench_obj_point_x, obj, measurements, num_measurements,
&overhead);
free (measurement_raw);
free (measurements);
free (real_buffer);
obj->ops->finalize (obj);
return slope;
err_free:
if (measurement_raw)
free (measurement_raw);
if (measurements)
free (measurements);
if (real_buffer)
free (real_buffer);
obj->ops->finalize (obj);
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. */
do
{
#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
/* Use memory barrier to prevent compiler from optimizing this loop
* away. */
asm volatile ("":::"memory");
#else
/* TODO: Needs alternative way. */
#endif
}
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 cpu_ghz * 1024 / cycles_per_iteration;
}
double
do_slope_benchmark (struct bench_obj *obj)
{
double ret;
if (!auto_ghz)
{
/* Perform measurement without autodetection of CPU frequency. */
ret = slope_benchmark (obj);
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;
unsigned int try_count = 0;
/* Perform measurement with CPU frequency autodetection. */
do
{
/* Repeat measurement until CPU turbo frequency has stabilized. */
if (try_count++ > 4)
{
/* Too much frequency instability on the system, relax target
* accuracy. */
try_count = 0;
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 - (cpu_auto_ghz_before / cpu_auto_ghz_after);
diff = diff < 0 ? -diff : diff;
}
while (diff > target_diff);
ret = nsecs_per_iteration;
bench_ghz = (cpu_auto_ghz_before + cpu_auto_ghz_after) / 2;
bench_ghz_diff = diff;
}
return ret;
}
/********************************************************** Printing results. */
static void
double_to_str (char *out, size_t outlen, double value)
{
const char *fmt;
if (value < 1.0)
fmt = "%.3f";
else if (value < 100.0)
fmt = "%.2f";
else if (value < 1000.0)
fmt = "%.1f";
else
fmt = "%.0f";
snprintf (out, outlen, fmt, value);
}
static void
bench_print_result_csv (double nsecs_per_byte)
{
double cycles_per_byte, mbytes_per_sec;
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 (bench_ghz > 0.0)
{
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);
double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
/* We print two empty fields to allow for future enhancements. */
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
bench_print_result_std (double nsecs_per_byte)
{
double cycles_per_byte, mbytes_per_sec;
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 (bench_ghz > 0.0)
{
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 (mhz_buf, "-");
}
mbytes_per_sec =
(1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
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
bench_print_result (double nsecs_per_byte)
{
if (csv_mode)
bench_print_result_csv (nsecs_per_byte);
else
bench_print_result_std (nsecs_per_byte);
}
static void
bench_print_section (const char *section_name, const char *print_name)
{
if (csv_mode)
{
gcry_free (current_section_name);
current_section_name = gcry_xstrdup (section_name);
}
else
printf ("%s:\n", print_name);
}
static void
bench_print_header (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 %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_algo (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);
}
}
static void
bench_print_mode (int width, const char *mode_name)
{
if (csv_mode)
{
gcry_free (current_mode_name);
current_mode_name = gcry_xstrdup (mode_name);
}
else
{
if (width < 0)
printf (" %-*s | ", -width, mode_name);
else
printf (" %*s | ", width, mode_name);
fflush (stdout);
}
}
static void
bench_print_footer (int algo_width)
{
if (!csv_mode)
printf (" %-*s =\n", algo_width, "");
}
/********************************************************* Cipher benchmarks. */
struct bench_cipher_mode
{
int mode;
const char *name;
struct bench_ops *ops;
int algo;
};
static int
bench_encrypt_init (struct bench_obj *obj)
{
struct bench_cipher_mode *mode = obj->priv;
gcry_cipher_hd_t hd;
int err, keylen;
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);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n",
gcry_cipher_algo_name (mode->algo));
exit (1);
}
keylen = gcry_cipher_get_algo_keylen (mode->algo);
if (keylen)
{
char key[keylen];
int i;
for (i = 0; i < keylen; i++)
key[i] = 0x33 ^ (11 - i);
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
else
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
gcry_cipher_algo_name (mode->algo));
gcry_cipher_close (hd);
exit (1);
}
obj->hd = hd;
return 0;
}
static void
bench_encrypt_free (struct bench_obj *obj)
{
gcry_cipher_hd_t hd = obj->hd;
gcry_cipher_close (hd);
}
static void
bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->hd;
int err;
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",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->hd;
int err;
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",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static struct bench_ops encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_encrypt_do_bench
};
static struct bench_ops decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_decrypt_do_bench
};
static int
bench_xts_encrypt_init (struct bench_obj *obj)
{
struct bench_cipher_mode *mode = obj->priv;
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->num_measure_repetitions = num_measurement_repetitions;
err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n",
gcry_cipher_algo_name (mode->algo));
exit (1);
}
/* Double key-length for XTS. */
keylen = gcry_cipher_get_algo_keylen (mode->algo) * 2;
if (keylen)
{
char key[keylen];
int i;
for (i = 0; i < keylen; i++)
key[i] = 0x33 ^ (11 - i);
err = gcry_cipher_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
else
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
gcry_cipher_algo_name (mode->algo));
gcry_cipher_close (hd);
exit (1);
}
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->hd;
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->hd;
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
};
static struct bench_ops xts_decrypt_ops = {
&bench_xts_encrypt_init,
&bench_encrypt_free,
&bench_xts_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->hd;
int err;
char tag[8];
char nonce[11] = { 0x80, 0x01, };
u64 params[3];
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = buflen;
params[1] = 0; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_ccm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_cipher_hd_t hd = obj->hd;
int err;
char tag[8] = { 0, };
char nonce[11] = { 0x80, 0x01, };
u64 params[3];
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = buflen;
params[1] = 0; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_checktag (hd, tag, sizeof (tag));
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_NO_ERROR);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_ccm_authenticate_do_bench (struct bench_obj *obj, void *buf,
size_t buflen)
{
gcry_cipher_hd_t hd = obj->hd;
int err;
char tag[8] = { 0, };
char nonce[11] = { 0x80, 0x01, };
u64 params[3];
char data = 0xff;
gcry_cipher_setiv (hd, nonce, sizeof (nonce));
/* Set CCM lengths */
params[0] = sizeof (data); /*datalen */
params[1] = buflen; /*aadlen */
params[2] = sizeof (tag);
err =
gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_authenticate (hd, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static struct bench_ops ccm_encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_encrypt_do_bench
};
static struct bench_ops ccm_decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_decrypt_do_bench
};
static struct bench_ops ccm_authenticate_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ccm_authenticate_do_bench
};
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->hd;
int err;
char tag[16];
gcry_cipher_setiv (hd, nonce, noncelen);
gcry_cipher_final (hd);
err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
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->hd;
int err;
char tag[16] = { 0, };
gcry_cipher_setiv (hd, nonce, noncelen);
gcry_cipher_final (hd);
err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_checktag (hd, tag, sizeof (tag));
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = gpg_error (GPG_ERR_NO_ERROR);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
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->hd;
int err;
char tag[16] = { 0, };
char data = 0xff;
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);
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
gcry_cipher_final (hd);
err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
err = gcry_cipher_gettag (hd, tag, sizeof (tag));
if (err)
{
fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
static void
bench_gcm_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_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_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_encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_gcm_encrypt_do_bench
};
static struct bench_ops gcm_decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_gcm_decrypt_do_bench
};
static struct bench_ops gcm_authenticate_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_gcm_authenticate_do_bench
};
static void
bench_ocb_encrypt_do_bench (struct bench_obj *obj, void *buf,
size_t buflen)
{
char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
0x00, 0x00, 0x01 };
bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
}
static void
bench_ocb_decrypt_do_bench (struct bench_obj *obj, void *buf,
size_t buflen)
{
char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
0x00, 0x00, 0x01 };
bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
}
static void
bench_ocb_authenticate_do_bench (struct bench_obj *obj, void *buf,
size_t buflen)
{
char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
0x00, 0x00, 0x01 };
bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
}
static struct bench_ops ocb_encrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ocb_encrypt_do_bench
};
static struct bench_ops ocb_decrypt_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ocb_decrypt_do_bench
};
static struct bench_ops ocb_authenticate_ops = {
&bench_encrypt_init,
&bench_encrypt_free,
&bench_ocb_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_POLY1305, "POLY1305 enc", &poly1305_encrypt_ops},
{GCRY_CIPHER_MODE_POLY1305, "POLY1305 dec", &poly1305_decrypt_ops},
{GCRY_CIPHER_MODE_POLY1305, "POLY1305 auth", &poly1305_authenticate_ops},
{0},
};
static void
cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
{
struct bench_cipher_mode mode = *pmode;
struct bench_obj obj = { 0 };
double result;
unsigned int blklen;
mode.algo = algo;
/* Check if this mode is ok */
blklen = gcry_cipher_get_algo_blklen (algo);
if (!blklen)
return;
/* Stream cipher? Only test with "ECB" and POLY1305. */
if (blklen == 1 && (mode.mode != GCRY_CIPHER_MODE_ECB &&
mode.mode != GCRY_CIPHER_MODE_POLY1305))
return;
if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB)
{
mode.mode = GCRY_CIPHER_MODE_STREAM;
mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec";
}
/* Poly1305 has restriction for cipher algorithm */
if (mode.mode == GCRY_CIPHER_MODE_POLY1305 && algo != GCRY_CIPHER_CHACHA20)
return;
/* CCM has restrictions for block-size */
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)
return;
/* XTS has restrictions for block-size */
if (mode.mode == GCRY_CIPHER_MODE_XTS && blklen != GCRY_XTS_BLOCK_LEN)
return;
/* Our OCB implementation has restrictions for block-size. */
if (mode.mode == GCRY_CIPHER_MODE_OCB && blklen != GCRY_OCB_BLOCK_LEN)
return;
bench_print_mode (14, mode.name);
obj.ops = mode.ops;
obj.priv = &mode;
result = do_slope_benchmark (&obj);
bench_print_result (result);
}
static void
_cipher_bench (int algo)
{
const char *algoname;
int i;
algoname = gcry_cipher_algo_name (algo);
bench_print_header (14, algoname);
for (i = 0; cipher_modes[i].mode; i++)
cipher_bench_one (algo, &cipher_modes[i]);
bench_print_footer (14);
}
void
cipher_bench (char **argv, int argc)
{
int i, algo;
bench_print_section ("cipher", "Cipher");
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
algo = gcry_cipher_map_name (argv[i]);
if (algo)
_cipher_bench (algo);
}
}
else
{
for (i = 1; i < 400; i++)
if (!gcry_cipher_test_algo (i))
_cipher_bench (i);
}
}
/*********************************************************** Hash benchmarks. */
struct bench_hash_mode
{
const char *name;
struct bench_ops *ops;
int algo;
};
static int
bench_hash_init (struct bench_obj *obj)
{
struct bench_hash_mode *mode = obj->priv;
gcry_md_hd_t hd;
int err;
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_md_open (&hd, mode->algo, 0);
if (err)
{
fprintf (stderr, PGM ": error opening hash `%s'\n",
gcry_md_algo_name (mode->algo));
exit (1);
}
obj->hd = hd;
return 0;
}
static void
bench_hash_free (struct bench_obj *obj)
{
gcry_md_hd_t hd = obj->hd;
gcry_md_close (hd);
}
static void
bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_md_hd_t hd = obj->hd;
gcry_md_reset (hd);
gcry_md_write (hd, buf, buflen);
gcry_md_final (hd);
}
static struct bench_ops hash_ops = {
&bench_hash_init,
&bench_hash_free,
&bench_hash_do_bench
};
static struct bench_hash_mode hash_modes[] = {
{"", &hash_ops},
{0},
};
static void
hash_bench_one (int algo, struct bench_hash_mode *pmode)
{
struct bench_hash_mode mode = *pmode;
struct bench_obj obj = { 0 };
double result;
mode.algo = algo;
if (mode.name[0] == '\0')
bench_print_algo (-14, gcry_md_algo_name (algo));
else
bench_print_algo (14, mode.name);
obj.ops = mode.ops;
obj.priv = &mode;
result = do_slope_benchmark (&obj);
bench_print_result (result);
}
static void
_hash_bench (int algo)
{
int i;
for (i = 0; hash_modes[i].name; i++)
hash_bench_one (algo, &hash_modes[i]);
}
void
hash_bench (char **argv, int argc)
{
int i, algo;
bench_print_section ("hash", "Hash");
bench_print_header (14, "");
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
algo = gcry_md_map_name (argv[i]);
if (algo)
_hash_bench (algo);
}
}
else
{
for (i = 1; i < 400; i++)
if (!gcry_md_test_algo (i))
_hash_bench (i);
}
bench_print_footer (14);
}
/************************************************************ MAC benchmarks. */
struct bench_mac_mode
{
const char *name;
struct bench_ops *ops;
int algo;
};
static int
bench_mac_init (struct bench_obj *obj)
{
struct bench_mac_mode *mode = obj->priv;
gcry_mac_hd_t hd;
int err;
unsigned int keylen;
void *key;
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;
keylen = gcry_mac_get_algo_keylen (mode->algo);
if (keylen == 0)
keylen = 32;
key = malloc (keylen);
if (!key)
{
fprintf (stderr, PGM ": couldn't allocate %d bytes\n", keylen);
exit (1);
}
memset(key, 42, keylen);
err = gcry_mac_open (&hd, mode->algo, 0, NULL);
if (err)
{
fprintf (stderr, PGM ": error opening mac `%s'\n",
gcry_mac_algo_name (mode->algo));
free (key);
exit (1);
}
err = gcry_mac_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, PGM ": error setting key for mac `%s'\n",
gcry_mac_algo_name (mode->algo));
free (key);
exit (1);
}
switch (mode->algo)
{
default:
break;
case GCRY_MAC_POLY1305_AES:
case GCRY_MAC_POLY1305_CAMELLIA:
case GCRY_MAC_POLY1305_TWOFISH:
case GCRY_MAC_POLY1305_SERPENT:
case GCRY_MAC_POLY1305_SEED:
gcry_mac_setiv (hd, key, 16);
break;
}
obj->hd = hd;
free (key);
return 0;
}
static void
bench_mac_free (struct bench_obj *obj)
{
gcry_mac_hd_t hd = obj->hd;
gcry_mac_close (hd);
}
static void
bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
gcry_mac_hd_t hd = obj->hd;
size_t bs;
char b;
gcry_mac_reset (hd);
gcry_mac_write (hd, buf, buflen);
bs = sizeof(b);
gcry_mac_read (hd, &b, &bs);
}
static struct bench_ops mac_ops = {
&bench_mac_init,
&bench_mac_free,
&bench_mac_do_bench
};
static struct bench_mac_mode mac_modes[] = {
{"", &mac_ops},
{0},
};
static void
mac_bench_one (int algo, struct bench_mac_mode *pmode)
{
struct bench_mac_mode mode = *pmode;
struct bench_obj obj = { 0 };
double result;
mode.algo = algo;
if (mode.name[0] == '\0')
bench_print_algo (-18, gcry_mac_algo_name (algo));
else
bench_print_algo (18, mode.name);
obj.ops = mode.ops;
obj.priv = &mode;
result = do_slope_benchmark (&obj);
bench_print_result (result);
}
static void
_mac_bench (int algo)
{
int i;
for (i = 0; mac_modes[i].name; i++)
mac_bench_one (algo, &mac_modes[i]);
}
void
mac_bench (char **argv, int argc)
{
int i, algo;
bench_print_section ("mac", "MAC");
bench_print_header (18, "");
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
algo = gcry_mac_map_name (argv[i]);
if (algo)
_mac_bench (algo);
}
}
else
{
for (i = 1; i < 600; i++)
if (!gcry_mac_test_algo (i))
_mac_bench (i);
}
bench_print_footer (18);
}
/************************************************************ KDF benchmarks. */
struct bench_kdf_mode
{
struct bench_ops *ops;
int algo;
int subalgo;
};
static int
bench_kdf_init (struct bench_obj *obj)
{
struct bench_kdf_mode *mode = obj->priv;
if (mode->algo == GCRY_KDF_PBKDF2)
{
obj->min_bufsize = 2;
obj->max_bufsize = 2 * 32;
obj->step_size = 2;
}
obj->num_measure_repetitions = num_measurement_repetitions;
return 0;
}
static void
bench_kdf_free (struct bench_obj *obj)
{
(void)obj;
}
static void
bench_kdf_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
{
struct bench_kdf_mode *mode = obj->priv;
char keybuf[16];
(void)buf;
if (mode->algo == GCRY_KDF_PBKDF2)
{
gcry_kdf_derive("qwerty", 6, mode->algo, mode->subalgo, "01234567", 8,
buflen, sizeof(keybuf), keybuf);
}
}
static struct bench_ops kdf_ops = {
&bench_kdf_init,
&bench_kdf_free,
&bench_kdf_do_bench
};
static void
kdf_bench_one (int algo, int subalgo)
{
struct bench_kdf_mode mode = { &kdf_ops };
struct bench_obj obj = { 0 };
double nsecs_per_iteration;
double cycles_per_iteration;
char algo_name[32];
char nsecpiter_buf[16];
char cpiter_buf[16];
char mhz_buf[16];
mode.algo = algo;
mode.subalgo = subalgo;
switch (subalgo)
{
case GCRY_MD_CRC32:
case GCRY_MD_CRC32_RFC1510:
case GCRY_MD_CRC24_RFC2440:
case GCRY_MD_MD4:
/* Skip CRC32s. */
return;
}
if (gcry_md_get_algo_dlen (subalgo) == 0)
{
/* Skip XOFs */
return;
}
*algo_name = 0;
if (algo == GCRY_KDF_PBKDF2)
{
snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s",
gcry_md_algo_name (subalgo));
}
bench_print_algo (-24, algo_name);
obj.ops = mode.ops;
obj.priv = &mode;
nsecs_per_iteration = do_slope_benchmark (&obj);
strcpy(cpiter_buf, csv_mode ? "" : "-");
strcpy(mhz_buf, csv_mode ? "" : "-");
double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration);
/* If user didn't provide CPU speed, we cannot show cycles/iter results. */
if (bench_ghz > 0.0)
{
cycles_per_iteration = nsecs_per_iteration * bench_ghz;
double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration);
double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000);
}
if (csv_mode)
{
if (auto_ghz)
printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n",
current_section_name,
current_algo_name ? current_algo_name : "",
current_mode_name ? current_mode_name : "",
nsecpiter_buf,
cpiter_buf,
mhz_buf);
else
printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n",
current_section_name,
current_algo_name ? current_algo_name : "",
current_mode_name ? current_mode_name : "",
nsecpiter_buf,
cpiter_buf);
}
else
{
if (auto_ghz)
printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf);
else
printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf);
}
}
void
kdf_bench (char **argv, int argc)
{
char algo_name[32];
int i, j;
bench_print_section ("kdf", "KDF");
if (!csv_mode)
{
printf (" %-*s | ", 24, "");
if (auto_ghz)
printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz");
else
printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter");
}
if (argv && argc)
{
for (i = 0; i < argc; i++)
{
for (j = 1; j < 400; j++)
{
if (gcry_md_test_algo (j))
continue;
snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s",
gcry_md_algo_name (j));
if (!strcmp(argv[i], algo_name))
kdf_bench_one (GCRY_KDF_PBKDF2, j);
}
}
}
else
{
for (i = 1; i < 400; i++)
if (!gcry_md_test_algo (i))
kdf_bench_one (GCRY_KDF_PBKDF2, i);
}
bench_print_footer (24);
}
/************************************************************** Main program. */
void
print_help (void)
{
static const char *help_lines[] = {
"usage: bench-slope [options] [hash|mac|cipher|kdf [algonames]]",
"",
" options:",
" --cpu-mhz <mhz> Set CPU speed for calculating cycles",
" 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 "
STR2(NUM_MEASUREMENT_REPETITIONS) ")",
" --unaligned Use unaligned input buffers.",
" --csv Use CSV output format",
NULL
};
const char **line;
for (line = help_lines; *line; line++)
fprintf (stdout, "%s\n", *line);
}
/* Warm up CPU. */
static void
warm_up_cpu (void)
{
struct nsec_time start, end;
get_nsec_time (&start);
do
{
get_nsec_time (&end);
}
while (get_time_nsec_diff (&start, &end) < 1000.0 * 1000.0 * 1000.0);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
if (argc)
{
argc--;
argv++;
}
/* We skip this test if we are running under the test suite (no args
and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */
if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
exit (77);
if (getenv ("GCRYPT_IN_REGRESSION_TEST"))
{
in_regression_test = 1;
num_measurement_repetitions = 2;
}
else
num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
while (argc && last_argc != argc)
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--;
argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
print_help ();
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--;
argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--;
argv++;
}
else if (!strcmp (*argv, "--csv"))
{
csv_mode = 1;
argc--;
argv++;
}
else if (!strcmp (*argv, "--unaligned"))
{
unaligned_mode = 1;
argc--;
argv++;
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--;
argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr,
PGM
": unknown hardware feature `%s' - option ignored\n",
*argv);
argc--;
argv++;
}
}
else if (!strcmp (*argv, "--cpu-mhz"))
{
argc--;
argv++;
if (argc)
{
if (!strcmp (*argv, "auto"))
{
auto_ghz = 1;
}
else
{
cpu_ghz = atof (*argv);
cpu_ghz /= 1000; /* Mhz => Ghz */
}
argc--;
argv++;
}
}
else if (!strcmp (*argv, "--repetitions"))
{
argc--;
argv++;
if (argc)
{
num_measurement_repetitions = atof (*argv);
if (num_measurement_repetitions < 2)
{
fprintf (stderr,
PGM
": value for --repetitions too small - using %d\n",
NUM_MEASUREMENT_REPETITIONS);
num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
}
argc--;
argv++;
}
}
}
xgcry_control (GCRYCTL_SET_VERBOSITY, (int) verbose);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
GCRYPT_VERSION, gcry_check_version (NULL));
exit (1);
}
if (debug)
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);
if (in_regression_test)
fputs ("Note: " PGM " running in quick regression test mode.\n", stdout);
if (!argc)
{
warm_up_cpu ();
hash_bench (NULL, 0);
mac_bench (NULL, 0);
cipher_bench (NULL, 0);
kdf_bench (NULL, 0);
}
else if (!strcmp (*argv, "hash"))
{
argc--;
argv++;
warm_up_cpu ();
hash_bench ((argc == 0) ? NULL : argv, argc);
}
else if (!strcmp (*argv, "mac"))
{
argc--;
argv++;
warm_up_cpu ();
mac_bench ((argc == 0) ? NULL : argv, argc);
}
else if (!strcmp (*argv, "cipher"))
{
argc--;
argv++;
warm_up_cpu ();
cipher_bench ((argc == 0) ? NULL : argv, argc);
}
else if (!strcmp (*argv, "kdf"))
{
argc--;
argv++;
warm_up_cpu ();
kdf_bench ((argc == 0) ? NULL : argv, argc);
}
else
{
fprintf (stderr, PGM ": unknown argument: %s\n", *argv);
print_help ();
}
return 0;
}
#endif /* !NO_GET_NSEC_TIME */
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 418f9291..15f57bb4 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -1,2037 +1,2037 @@
/* benchmark.c - for libgcrypt
* Copyright (C) 2002, 2004, 2005, 2006, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
# include "../compat/libcompat.h"
#else
# include <gcrypt.h>
#endif
#include "stopwatch.h"
#define PGM "benchmark"
#include "t-common.h"
/* 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;
/* Number of hash repetitions. */
static int hash_repetitions;
/* Number of hash repetitions. */
static int mac_repetitions;
/* Alignment of the buffers. */
static int buffer_alignment;
/* Whether to include the keysetup in the cipher timings. */
static int cipher_with_keysetup;
/* Whether fips mode was active at startup. */
static int in_fips_mode;
/* Whether we are running as part of the regression test suite. */
static int in_regression_test;
/* Whether --progress is in use. */
static int with_progress;
/* Runtime flag to switch to a different progress output. */
static int single_char_progress;
static const char sample_private_dsa_key_1024[] =
"(private-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
" (x #4186F8A58C5DF46C5BCFC7006BEEBF05E93C0CA7#)\n"
"))\n";
static const char sample_public_dsa_key_1024[] =
"(public-key\n"
" (dsa\n"
" (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685"
"03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A"
"853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF"
"C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n"
" (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n"
" (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622"
"B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312"
"FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3"
"85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n"
" (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4"
"ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6"
"66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155"
"D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n"
"))\n";
static const char sample_private_dsa_key_2048[] =
"(private-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
" (x #477BD14676E22563C5ABA68025CEBA2A48D485F5B2D4AD4C0EBBD6D0#)\n"
"))\n";
static const char sample_public_dsa_key_2048[] =
"(public-key\n"
" (dsa\n"
" (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365"
"A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C"
"308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150"
"C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970"
"71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405"
"D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179"
"0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4"
"2F9C9F315ED409171EC35CA04CC06B275577B3#)\n"
" (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n"
" (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78"
"98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3"
"5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F"
"B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508"
"4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F"
"0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44"
"2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3"
"6EE4425A553AF8885FEA15A88135BE133520#)\n"
" (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C"
"2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB"
"4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79"
"328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F"
"8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3"
"E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923"
"79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7"
"14A264330AECCB24DE2A1107847B23490897#)\n"
"))\n";
static const char sample_private_dsa_key_3072[] =
"(private-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
" (x #00A9FFFC88E67D6F7B810E291C050BAFEA7FC4A75E8D2F16CFED3416FD77607232#)\n"
"))\n";
static const char sample_public_dsa_key_3072[] =
"(public-key\n"
" (dsa\n"
" (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938"
"877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5"
"62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83"
"B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988"
"AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46"
"0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2"
"AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902"
"D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60"
"B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E"
"95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7"
"62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33"
"8015353D3778B02B892AF7#)\n"
" (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n"
" (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4"
"DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474"
"7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98"
"9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC"
"134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C"
"7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89"
"F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB"
"120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6"
"374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0"
"21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F"
"D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC"
"4997AF9EB55C6660B01A#)\n"
" (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE"
"4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053"
"A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492"
"8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15"
"DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71"
"CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997"
"437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026"
"73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B"
"FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD"
"F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765"
"3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561"
"2703D518D8D49FF0EBE6#)\n"
"))\n";
static const char sample_public_elg_key_1024[] =
"(public-key"
" (elg"
" (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6"
"64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A"
"EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4"
"52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)"
" (g #06#)"
" (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C"
"80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7"
"3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85"
"D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)"
" ))";
static const char sample_private_elg_key_1024[] =
"(private-key"
" (elg"
" (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6"
"64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A"
"EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4"
"52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)"
" (g #06#)"
" (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C"
"80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7"
"3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85"
"D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)"
" (x #03656C6186FCD27D4A4B1F5010DC0D2AE7833B501E423FCD51DE5EB6D80DACFE#)"
" ))";
static const char sample_public_elg_key_2048[] =
"(public-key"
" (elg"
" (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6"
"38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D"
"C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97"
"73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0"
"EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5"
"5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8"
"D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135"
"768011AF6B622C5AF366EF0196FC4EAEAA8127#)"
" (g #07#)"
" (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8"
"D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210"
"2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354"
"D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E"
"5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F"
"6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8"
"2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237"
"D493E092AEA2371AA904009C8960B0969D12#)"
" ))";
static const char sample_private_elg_key_2048[] =
"(private-key"
" (elg"
" (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6"
"38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D"
"C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97"
"73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0"
"EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5"
"5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8"
"D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135"
"768011AF6B622C5AF366EF0196FC4EAEAA8127#)"
" (g #07#)"
" (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8"
"D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210"
"2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354"
"D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E"
"5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F"
"6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8"
"2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237"
"D493E092AEA2371AA904009C8960B0969D12#)"
" (x #0628C3903972C55BDC1BC4223075616D3F3BA57D55532DDB40CB14CF72070E0D28BF"
"D0402B9088D25ED8FC#)"
" ))";
static const char sample_public_elg_key_3072[] =
"(public-key"
" (elg"
" (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72"
"BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0"
"5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2"
"C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2"
"FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C"
"F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888"
"A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4"
"7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0"
"D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2"
"390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C"
"84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42"
"D226206FDF7D1FB93A5457#)"
" (g #0B#)"
" (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF"
"3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D"
"D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0"
"E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79"
"12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2"
"289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686"
"9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23"
"79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A"
"A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171"
"5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C"
"9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9"
"4DDDEFAFD2C7C66E235D#)"
" ))";
static const char sample_private_elg_key_3072[] =
"(private-key"
" (elg"
" (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72"
"BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0"
"5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2"
"C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2"
"FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C"
"F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888"
"A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4"
"7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0"
"D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2"
"390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C"
"84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42"
"D226206FDF7D1FB93A5457#)"
" (g #0B#)"
" (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF"
"3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D"
"D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0"
"E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79"
"12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2"
"289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686"
"9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23"
"79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A"
"A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171"
"5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C"
"9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9"
"4DDDEFAFD2C7C66E235D#)"
" (x #03A73F0389E470AAC831B039F8AA0C4EBD3A47DD083E32EEA08E4911236CD597C272"
"9823D47A51C8535DA52FE6DAB3E8D1C20D#)"
" ))";
#define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
exit(2);} while(0)
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = malloc (size);
if (!buf)
die ("out of core\n");
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
}
static void
progress_cb (void *cb_data, const char *what, int printchar,
int current, int total)
{
(void)cb_data;
if (single_char_progress)
{
fputc (printchar, stdout);
fflush (stderr);
}
else
{
fprintf (stderr, PGM ": progress (%s %c %d %d)\n",
what, printchar, current, total);
fflush (stderr);
}
}
static void
random_bench (int very_strong)
{
char buf[128];
int i;
printf ("%-10s", "random");
if (!very_strong)
{
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time (1));
}
start_timer ();
for (i=0; i < 100; i++)
gcry_randomize (buf, 8,
very_strong? GCRY_VERY_STRONG_RANDOM:GCRY_STRONG_RANDOM);
stop_timer ();
printf (" %s", elapsed_time (1));
putchar ('\n');
if (verbose)
xgcry_control (GCRYCTL_DUMP_RANDOM_STATS);
}
static void
md_bench ( const char *algoname )
{
int algo;
gcry_md_hd_t hd;
int i, j, repcount;
char buf_base[1000+15];
size_t bufsize = 1000;
char *buf;
char *largebuf_base;
char *largebuf;
char digest[512/8];
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 400; i++)
if (in_fips_mode && i == GCRY_MD_MD5)
; /* Don't use MD5 in fips mode. */
else if ( !gcry_md_test_algo (i) )
md_bench (gcry_md_algo_name (i));
return;
}
buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment);
algo = gcry_md_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
exit (1);
}
err = gcry_md_open (&hd, algo, 0);
if (err)
{
fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
exit (1);
}
for (i=0; i < bufsize; i++)
buf[i] = i;
printf ("%-12s", gcry_md_algo_name (algo));
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000; i++)
gcry_md_write (hd, buf, bufsize);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_md_reset (hd);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 10000; i++)
gcry_md_write (hd, buf, bufsize/10);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_md_reset (hd);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000000; i++)
gcry_md_write (hd, buf, 1);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 1000; i++)
for (j=0; j < bufsize; j++)
gcry_md_putc (hd, buf[j]);
gcry_md_final (hd);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_md_close (hd);
/* Now 100 hash operations on 10000 bytes using the fast function.
We initialize the buffer so that all memory pages are committed
and we have repeatable values. */
if (gcry_md_get_algo_dlen (algo) > sizeof digest)
die ("digest buffer too short\n");
if (gcry_md_get_algo_dlen (algo))
{
largebuf_base = malloc (10000+15);
if (!largebuf_base)
die ("out of core\n");
largebuf = (largebuf_base
+ ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment));
for (i=0; i < 10000; i++)
largebuf[i] = i;
start_timer ();
for (repcount=0; repcount < hash_repetitions; repcount++)
for (i=0; i < 100; i++)
gcry_md_hash_buffer (algo, digest, largebuf, 10000);
stop_timer ();
printf (" %s", elapsed_time (1));
free (largebuf_base);
}
putchar ('\n');
fflush (stdout);
}
static void
mac_bench ( const char *algoname )
{
int algo;
gcry_mac_hd_t hd;
int step, pos, j, i, repcount;
char buf_base[1000+15];
size_t bufsize = 1000;
char *buf;
char mac[3][512];
char key[512];
unsigned int maclen, keylen;
size_t macoutlen;
gcry_error_t err = GPG_ERR_NO_ERROR;
if (!algoname)
{
for (i=1; i < 600; i++)
if (in_fips_mode && i == GCRY_MAC_HMAC_MD5)
; /* Don't use MD5 in fips mode. */
else if ( !gcry_mac_test_algo (i) )
mac_bench (gcry_mac_algo_name (i));
return;
}
buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment);
algo = gcry_mac_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
exit (1);
}
maclen = gcry_mac_get_algo_maclen (algo);
if (maclen > sizeof(mac))
maclen = sizeof(mac);
keylen = gcry_mac_get_algo_keylen (algo);
if (keylen == 0)
keylen = 32;
if (keylen > sizeof(key))
keylen = sizeof(key);
for (i=0; i < keylen; i++)
key[i] = (keylen - i) ^ 0x54;
err = gcry_mac_open (&hd, algo, 0, NULL);
if (err)
{
fprintf (stderr, PGM ": error opening mac algorithm `%s': %s\n", algoname,
gpg_strerror (err));
exit (1);
}
err = gcry_mac_setkey (hd, key, keylen);
if (err)
{
fprintf (stderr, PGM ": error setting key for mac algorithm `%s': %s\n",
algoname, gpg_strerror (err));
exit (1);
}
for (i=0; i < bufsize; i++)
buf[i] = i;
if (algo >= GCRY_MAC_POLY1305_AES && algo <= GCRY_MAC_POLY1305_SEED)
{
static const char iv[16] = { 1, 2, 3, 4, };
err = gcry_mac_setiv(hd, iv, sizeof(iv));
if (err)
{
fprintf (stderr, PGM ": error setting nonce for mac algorithm `%s': %s\n",
algoname, gpg_strerror (err));
exit (1);
}
}
printf ("%-20s", gcry_mac_algo_name (algo));
start_timer ();
for (repcount=0; repcount < mac_repetitions; repcount++)
for (i=0; i < 1000; i++)
gcry_mac_write (hd, buf, bufsize);
macoutlen = maclen;
gcry_mac_read (hd, mac[0], &macoutlen);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_mac_reset (hd);
start_timer ();
for (repcount=0; repcount < mac_repetitions; repcount++)
for (i=0; i < 1000; i++)
for (step=bufsize/10, pos=0, j=0; j < 10; j++, pos+=step)
gcry_mac_write (hd, &buf[pos], step);
macoutlen = maclen;
gcry_mac_read (hd, mac[1], &macoutlen);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_mac_reset (hd);
start_timer ();
for (repcount=0; repcount < mac_repetitions; repcount++)
for (i=0; i < 1000; i++)
for (step=bufsize/100, pos=0, j=0; j < 100; j++, pos+=step)
gcry_mac_write (hd, &buf[pos], step);
macoutlen = maclen;
gcry_mac_read (hd, mac[2], &macoutlen);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_mac_close (hd);
for (i=1; i < 3; i++)
{
if (memcmp(mac[i-1], mac[i], maclen))
{
fprintf (stderr, PGM ": mac mismatch with algorithm `%s'\n",
algoname);
exit(1);
}
}
putchar ('\n');
fflush (stdout);
}
static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen)
{
const int _L = 4;
const int noncelen = 15 - _L;
char nonce[noncelen];
u64 params[3];
gcry_error_t err = GPG_ERR_NO_ERROR;
memset (nonce, 0x33, noncelen);
err = gcry_cipher_setiv (hd, nonce, noncelen);
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
params[0] = buflen; /* encryptedlen */
params[1] = 0; /* aadlen */
params[2] = authlen; /* authtaglen */
err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(params));
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
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 )
{
static int header_printed;
int algo;
gcry_cipher_hd_t hd;
int i;
int keylen, blklen;
char key[128];
char *outbuf, *buf;
char *raw_outbuf, *raw_buf;
size_t allocated_buflen, buflen;
int repetitions;
static const struct {
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, 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, 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, 0xffffffffU,
NULL, 16, 16, 15 },
{ 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++)
if ( !gcry_cipher_test_algo (i) )
cipher_bench (gcry_cipher_algo_name (i));
return;
}
if (huge_buffers)
{
allocated_buflen = 256 * 1024 * 1024;
repetitions = 4;
}
else if (large_buffers)
{
allocated_buflen = 1024 * 100;
repetitions = 10;
}
else
{
allocated_buflen = 1024;
repetitions = 1000;
}
repetitions *= cipher_repetitions;
raw_buf = gcry_xcalloc (allocated_buflen+15, 1);
buf = (raw_buf
+ ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment));
outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15);
outbuf = (raw_outbuf
+ ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment));
if (!header_printed)
{
if (cipher_repetitions != 1)
printf ("Running each test %d times.\n", cipher_repetitions);
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
if (*modes[modeidx].name)
printf (" %-15s", modes[modeidx].name );
putchar ('\n');
printf ("%-12s", "");
for (modeidx=0; modes[modeidx].mode; modeidx++)
if (*modes[modeidx].name)
printf (" ---------------" );
putchar ('\n');
header_printed = 1;
}
algo = gcry_cipher_map_name (algoname);
if (!algo)
{
fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
exit (1);
}
keylen = gcry_cipher_get_algo_keylen (algo);
if (!keylen)
{
fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
algoname);
exit (1);
}
if ( keylen * 2 > sizeof key )
{
fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
algo, keylen );
exit (1);
}
for (i=0; i < keylen * 2; i++)
key[i] = i + (clock () & 0xff);
blklen = gcry_cipher_get_algo_blklen (algo);
if (!blklen)
{
fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
algoname);
exit (1);
}
printf ("%-12s", gcry_cipher_algo_name (algo));
fflush (stdout);
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 (modes[modeidx].mode == GCRY_CIPHER_MODE_POLY1305
&& algo != GCRY_CIPHER_CHACHA20)
continue;
if (modes[modeidx].req_blocksize > 0
&& blklen != modes[modeidx].req_blocksize)
{
printf (" %7s %7s", "-", "-" );
continue;
}
for (i=0; i < sizeof buf; i++)
buf[i] = i;
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
exit (1);
}
if (!cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, modekeylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
buflen = allocated_buflen;
if (modes[modeidx].blocked)
buflen = (buflen / blklen) * blklen;
start_timer ();
for (i=err=0; !err && i < repetitions; i++)
{
if (cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, modekeylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].noncelen)
{
char nonce[100];
size_t noncelen;
noncelen = modes[modeidx].noncelen;
if (noncelen > sizeof nonce)
noncelen = sizeof nonce;
memset (nonce, 42, noncelen);
err = gcry_cipher_setiv (hd, nonce, noncelen);
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].aead_init)
{
(*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
gcry_cipher_final (hd);
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 = cipher_encrypt (hd, outbuf, buflen, buf, buflen,
modes[modeidx].max_inlen);
}
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
if (err)
{
fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
exit (1);
}
if (!cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, modekeylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
start_timer ();
for (i=err=0; !err && i < repetitions; i++)
{
if (cipher_with_keysetup)
{
err = gcry_cipher_setkey (hd, key, modekeylen);
if (err)
{
fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].noncelen)
{
char nonce[100];
size_t noncelen;
noncelen = modes[modeidx].noncelen;
if (noncelen > sizeof nonce)
noncelen = sizeof nonce;
memset (nonce, 42, noncelen);
err = gcry_cipher_setiv (hd, nonce, noncelen);
if (err)
{
fprintf (stderr, "gcry_cipher_setiv failed: %s\n",
gpg_strerror (err));
gcry_cipher_close (hd);
exit (1);
}
}
if (modes[modeidx].aead_init)
{
(*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
gcry_cipher_final (hd);
err = cipher_decrypt (hd, outbuf, buflen, buf, buflen,
modes[modeidx].max_inlen);
if (err)
break;
err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen);
if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
err = 0;
}
else
{
gcry_cipher_final (hd);
err = cipher_decrypt (hd, outbuf, buflen, buf, buflen,
modes[modeidx].max_inlen);
}
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
gcry_cipher_close (hd);
if (err)
{
fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
gpg_strerror (err) );
exit (1);
}
}
putchar ('\n');
gcry_free (raw_buf);
gcry_free (raw_outbuf);
}
static void
rsa_bench (int iterations, int print_header, int no_blinding)
{
gpg_error_t err;
int p_sizes[] = { 1024, 2048, 3072, 4096 };
int testno;
if (print_header)
printf ("Algorithm generate %4d*priv %4d*public\n"
"------------------------------------------------\n",
iterations, iterations );
for (testno=0; testno < DIM (p_sizes); testno++)
{
gcry_sexp_t key_spec, key_pair, pub_key, sec_key;
gcry_mpi_t x;
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int count;
unsigned nbits = p_sizes[testno];
printf ("RSA %3d bit ", nbits);
fflush (stdout);
if (in_fips_mode && !(nbits == 2048 || nbits == 3072))
{
puts ("[skipped in fips mode]");
continue;
}
err = gcry_sexp_build (&key_spec, NULL,
gcry_fips_mode_active ()
? "(genkey (RSA (nbits %d)))"
: "(genkey (RSA (nbits %d)(transient-key)))",
nbits);
if (err)
die ("creating S-expression failed: %s\n", gcry_strerror (err));
start_timer ();
err = gcry_pk_genkey (&key_pair, key_spec);
if (err)
die ("creating %d bit RSA key failed: %s\n",
nbits, gcry_strerror (err));
pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key_pair, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key_pair);
gcry_sexp_release (key_spec);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
x = gcry_mpi_new (nbits);
gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL,
"(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
die ("signing failed (%d): %s\n", count, gpg_strerror (err));
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
start_timer ();
for (count=0; count < iterations; count++)
{
err = gcry_pk_verify (sig, data, pub_key);
if (err)
{
putchar ('\n');
show_sexp ("seckey:\n", sec_key);
show_sexp ("data:\n", data);
show_sexp ("sig:\n", sig);
die ("verify failed (%d): %s\n", count, gpg_strerror (err));
}
}
stop_timer ();
printf (" %s", elapsed_time (1));
if (no_blinding)
{
fflush (stdout);
x = gcry_mpi_new (nbits);
gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL,
"(data (flags no-blinding) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
die ("signing failed (%d): %s\n", count, gpg_strerror (err));
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
}
putchar ('\n');
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
static void
elg_bench (int iterations, int print_header)
{
gpg_error_t err;
gcry_sexp_t pub_key[3], sec_key[3];
int p_sizes[3] = { 1024, 2048, 3072 };
gcry_sexp_t data = NULL;
gcry_sexp_t enc = NULL;
gcry_sexp_t plain = NULL;
int i, j;
err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_elg_key_1024,
strlen (sample_public_elg_key_1024));
if (!err)
err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_elg_key_1024,
strlen (sample_private_elg_key_1024));
if (!err)
err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_elg_key_2048,
strlen (sample_public_elg_key_2048));
if (!err)
err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_elg_key_2048,
strlen (sample_private_elg_key_2048));
if (!err)
err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_elg_key_3072,
strlen (sample_public_elg_key_3072));
if (!err)
err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_elg_key_3072,
strlen (sample_private_elg_key_3072));
if (err)
{
fprintf (stderr, PGM ": converting sample keys failed: %s\n",
gcry_strerror (err));
exit (1);
}
if (print_header)
printf ("Algorithm generate %4d*priv %4d*public\n"
"------------------------------------------------\n",
iterations, iterations );
for (i=0; i < DIM (p_sizes); i++)
{
char timerbuf1[100];
{
gcry_mpi_t x = gcry_mpi_new (p_sizes[i]);
gcry_mpi_randomize (x, p_sizes[i] - 16, GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
}
if (err)
{
fprintf (stderr, PGM ": converting data failed: %s\n",
gcry_strerror (err));
exit (1);
}
printf ("ELG %d bit -", p_sizes[i]);
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
gcry_sexp_release (enc);
err = gcry_pk_encrypt (&enc, data, pub_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": encrypt failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
snprintf (timerbuf1, sizeof timerbuf1, " %s", elapsed_time (1));
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
gcry_sexp_release (plain);
err = gcry_pk_decrypt (&plain, enc, sec_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": decrypt failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
printf (" %s %s\n", elapsed_time (1), timerbuf1);
fflush (stdout);
gcry_sexp_release (plain);
plain = NULL;
gcry_sexp_release (enc);
enc = NULL;
gcry_sexp_release (data);
data = NULL;
}
for (i=0; i < DIM (p_sizes); i++)
{
gcry_sexp_release (sec_key[i]);
gcry_sexp_release (pub_key[i]);
}
}
static void
dsa_bench (int iterations, int print_header)
{
gpg_error_t err;
gcry_sexp_t pub_key[3], sec_key[3];
int p_sizes[3] = { 1024, 2048, 3072 };
int q_sizes[3] = { 160, 224, 256 };
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int i, j;
err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024,
strlen (sample_public_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024,
strlen (sample_private_dsa_key_1024));
if (!err)
err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048,
strlen (sample_public_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048,
strlen (sample_private_dsa_key_2048));
if (!err)
err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072,
strlen (sample_public_dsa_key_3072));
if (!err)
err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072,
strlen (sample_private_dsa_key_3072));
if (err)
{
fprintf (stderr, PGM ": converting sample keys failed: %s\n",
gcry_strerror (err));
exit (1);
}
if (print_header)
printf ("Algorithm generate %4d*priv %4d*public\n"
"------------------------------------------------\n",
iterations, iterations );
for (i=0; i < DIM (q_sizes); i++)
{
gcry_mpi_t x;
x = gcry_mpi_new (q_sizes[i]);
gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM);
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
{
fprintf (stderr, PGM ": converting data failed: %s\n",
gcry_strerror (err));
exit (1);
}
printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]);
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": signing failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
start_timer ();
for (j=0; j < iterations; j++)
{
err = gcry_pk_verify (sig, data, pub_key[i]);
if (err)
{
putchar ('\n');
fprintf (stderr, PGM ": verify failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
stop_timer ();
printf (" %s\n", elapsed_time (1));
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
sig = NULL;
}
for (i=0; i < DIM (q_sizes); i++)
{
gcry_sexp_release (sec_key[i]);
gcry_sexp_release (pub_key[i]);
}
}
static void
ecc_bench (int iterations, int print_header)
{
#if USE_ECC
gpg_error_t err;
const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519",
"gost256", "gost512" };
int testno;
if (print_header)
printf ("Algorithm generate %4d*priv %4d*public\n"
"------------------------------------------------\n",
iterations, iterations );
for (testno=0; testno < DIM (p_sizes); testno++)
{
gcry_sexp_t key_spec, key_pair, pub_key, sec_key;
gcry_mpi_t x;
gcry_sexp_t data;
gcry_sexp_t sig = NULL;
int count;
int p_size;
int is_ed25519;
int is_gost;
is_ed25519 = !strcmp (p_sizes[testno], "Ed25519");
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")))
continue;
if (is_ed25519)
{
p_size = 256;
printf ("EdDSA Ed25519 ");
fflush (stdout);
}
else if (is_gost)
{
p_size = atoi (p_sizes[testno] + 4);
printf ("GOST %3d bit ", p_size);
fflush (stdout);
}
else
{
p_size = atoi (p_sizes[testno]);
printf ("ECDSA %3d bit ", p_size);
}
fflush (stdout);
if (is_ed25519)
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ecdsa (curve \"Ed25519\")"
"(flags eddsa)))");
else if (is_gost)
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ecdsa (curve %s)))",
p_size == 256 ? "GOST2001-test" : "GOST2012-test");
else
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (ECDSA (nbits %d)))", p_size);
if (err)
die ("creating S-expression failed: %s\n", gcry_strerror (err));
start_timer ();
err = gcry_pk_genkey (&key_pair, key_spec);
if (err)
die ("creating %d bit ECC key failed: %s\n",
p_size, gcry_strerror (err));
if (verbose > 2)
show_sexp ("ECC key:\n", key_pair);
pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key_pair, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key_pair);
gcry_sexp_release (key_spec);
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
x = gcry_mpi_new (p_size);
gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM);
if (is_ed25519)
err = gcry_sexp_build (&data, NULL,
"(data (flags eddsa)(hash-algo sha512)"
" (value %m))", x);
else if (is_gost)
err = gcry_sexp_build (&data, NULL, "(data (flags gost) (value %m))", x);
else
err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x);
gcry_mpi_release (x);
if (err)
die ("converting data failed: %s\n", gcry_strerror (err));
start_timer ();
for (count=0; count < iterations; count++)
{
gcry_sexp_release (sig);
err = gcry_pk_sign (&sig, data, sec_key);
if (err)
{
if (verbose)
{
putc ('\n', stderr);
show_sexp ("signing key:\n", sec_key);
show_sexp ("signed data:\n", data);
}
die ("signing failed: %s\n", gpg_strerror (err));
}
}
stop_timer ();
printf (" %s", elapsed_time (1));
fflush (stdout);
start_timer ();
for (count=0; count < iterations; count++)
{
err = gcry_pk_verify (sig, data, pub_key);
if (err)
{
putchar ('\n');
show_sexp ("seckey:\n", sec_key);
show_sexp ("data:\n", data);
show_sexp ("sig:\n", sig);
die ("verify failed: %s\n", gpg_strerror (err));
}
}
stop_timer ();
printf (" %s\n", elapsed_time (1));
fflush (stdout);
gcry_sexp_release (sig);
gcry_sexp_release (data);
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
#endif /*USE_ECC*/
}
static void
do_powm ( const char *n_str, const char *e_str, const char *m_str)
{
gcry_mpi_t e, n, msg, cip;
gcry_error_t err;
int i;
err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0);
if (err) BUG ();
err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0);
if (err) BUG ();
cip = gcry_mpi_new (0);
start_timer ();
for (i=0; i < 1000; i++)
gcry_mpi_powm (cip, msg, e, n);
stop_timer ();
printf (" %s", elapsed_time (1)); fflush (stdout);
/* { */
/* char *buf; */
/* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */
/* BUG (); */
/* printf ("result: %s\n", buf); */
/* gcry_free (buf); */
/* } */
gcry_mpi_release (cip);
gcry_mpi_release (msg);
gcry_mpi_release (n);
gcry_mpi_release (e);
}
static void
mpi_bench (void)
{
printf ("%-10s", "powm"); fflush (stdout);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E4",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
do_powm (
"20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA4071620A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716",
"29",
"B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847"
);
putchar ('\n');
}
static void
prime_bench (void)
{
gpg_error_t err;
int i;
gcry_mpi_t prime;
int old_prog = single_char_progress;
single_char_progress = 1;
if (!with_progress)
printf ("%-10s", "prime");
fflush (stdout);
start_timer ();
for (i=0; i < 10; i++)
{
if (with_progress)
fputs ("primegen ", stdout);
err = gcry_prime_generate (&prime,
1024, 0,
NULL,
NULL, NULL,
GCRY_WEAK_RANDOM,
GCRY_PRIME_FLAG_SECRET);
if (with_progress)
{
fputc ('\n', stdout);
fflush (stdout);
}
if (err)
{
fprintf (stderr, PGM ": error creating prime: %s\n",
gpg_strerror (err));
exit (1);
}
gcry_mpi_release (prime);
}
stop_timer ();
if (with_progress)
printf ("%-10s", "prime");
printf (" %s\n", elapsed_time (1)); fflush (stdout);
single_char_progress = old_prog;
}
int
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;
buffer_alignment = 1;
if (argc)
{ argc--; argv++; }
/* We skip this test if we are running under the test suite (no args
and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */
if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
exit (77);
if (getenv ("GCRYPT_IN_REGRESSION_TEST"))
{
in_regression_test = 1;
pk_count = 10;
}
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
fputs ("usage: benchmark "
"[md|mac|cipher|random|mpi|rsa|dsa|ecc|prime [algonames]]\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, "--use-random-daemon"))
{
use_random_daemon = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--use-secmem"))
{
use_secmem = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--prefer-standard-rng"))
{
/* 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);
argc--; argv++;
}
else if (!strcmp (*argv, "--prefer-fips-rng"))
{
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);
argc--; argv++;
}
else if (!strcmp (*argv, "--no-blinding"))
{
no_blinding = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--large-buffers"))
{
large_buffers = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--huge-buffers"))
{
huge_buffers = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--cipher-repetitions"))
{
argc--; argv++;
if (argc)
{
cipher_repetitions = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--cipher-with-keysetup"))
{
cipher_with_keysetup = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--hash-repetitions"))
{
argc--; argv++;
if (argc)
{
hash_repetitions = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--mac-repetitions"))
{
argc--; argv++;
if (argc)
{
mac_repetitions = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--pk-count"))
{
argc--; argv++;
if (argc)
{
pk_count = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--alignment"))
{
argc--; argv++;
if (argc)
{
buffer_alignment = atoi(*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--disable-hwf"))
{
argc--; argv++;
if (argc)
{
if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
fprintf (stderr, PGM ": unknown hardware feature `%s'"
" - option ignored\n", *argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--fips"))
{
argc--; argv++;
/* This command needs to be called before gcry_check_version. */
xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
}
else if (!strcmp (*argv, "--progress"))
{
argc--; argv++;
with_progress = 1;
}
}
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);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
GCRYPT_VERSION, gcry_check_version (NULL));
exit (1);
}
if (debug)
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);
if (with_progress)
gcry_set_progress_handler (progress_cb, NULL);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (cipher_repetitions < 1)
cipher_repetitions = 1;
if (hash_repetitions < 1)
hash_repetitions = 1;
if (mac_repetitions < 1)
mac_repetitions = 1;
if (in_regression_test)
fputs ("Note: " PGM " running in quick regression test mode.\n", stdout);
if ( !argc )
{
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
md_bench (NULL);
putchar ('\n');
mac_bench (NULL);
putchar ('\n');
cipher_bench (NULL);
putchar ('\n');
rsa_bench (pk_count, 1, no_blinding);
elg_bench (pk_count, 0);
dsa_bench (pk_count, 0);
ecc_bench (pk_count, 0);
putchar ('\n');
mpi_bench ();
putchar ('\n');
random_bench (0);
}
else if ( !strcmp (*argv, "random") || !strcmp (*argv, "strongrandom"))
{
if (argc == 1)
random_bench ((**argv == 's'));
else if (argc == 2)
{
xgcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]);
random_bench ((**argv == 's'));
xgcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
}
else
fputs ("usage: benchmark [strong]random [seedfile]\n", stdout);
}
else if ( !strcmp (*argv, "md"))
{
if (argc == 1)
md_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
md_bench ( *argv );
}
else if ( !strcmp (*argv, "mac"))
{
if (argc == 1)
mac_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
mac_bench ( *argv );
}
else if ( !strcmp (*argv, "cipher"))
{
if (argc == 1)
cipher_bench (NULL);
else
for (argc--, argv++; argc; argc--, argv++)
cipher_bench ( *argv );
}
else if ( !strcmp (*argv, "mpi"))
{
mpi_bench ();
}
else if ( !strcmp (*argv, "pubkey"))
{
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
rsa_bench (pk_count, 1, no_blinding);
elg_bench (pk_count, 0);
dsa_bench (pk_count, 0);
ecc_bench (pk_count, 0);
}
else if ( !strcmp (*argv, "rsa"))
{
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);
elg_bench (pk_count, 1);
}
else if ( !strcmp (*argv, "dsa"))
{
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
dsa_bench (pk_count, 1);
}
else if ( !strcmp (*argv, "ecc"))
{
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
ecc_bench (pk_count, 1);
}
else if ( !strcmp (*argv, "prime"))
{
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
prime_bench ();
}
else
{
fprintf (stderr, PGM ": bad arguments\n");
return 1;
}
if (in_fips_mode && !gcry_fips_mode_active ())
fprintf (stderr, PGM ": FIPS mode is not anymore active\n");
return 0;
}
diff --git a/tests/cavs_driver.pl b/tests/cavs_driver.pl
index bc93feb9..88bc2f72 100755
--- a/tests/cavs_driver.pl
+++ b/tests/cavs_driver.pl
@@ -1,2243 +1,2243 @@
#!/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
+# Cf. https://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
+# Examples from https://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/dsa-rfc6979.c b/tests/dsa-rfc6979.c
index 2cfa94a8..b2d3fe5d 100644
--- a/tests/dsa-rfc6979.c
+++ b/tests/dsa-rfc6979.c
@@ -1,983 +1,983 @@
/* dsa-rfc6979.c - Test for Deterministic DSA
* Copyright (C) 2008 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifndef _GCRYPT_IN_LIBGCRYPT
# include <gcrypt.h>
#endif
#define PGM "dsa-rfc6979"
#include "t-common.h"
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
/* 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 *
data_from_hex (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = gcry_xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
die ("error parsing hex string `%s'\n", string);
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected)
{
gcry_sexp_t l1;
const void *a;
size_t alen;
void *b;
size_t blen;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_data (l1, 1, &alen);
b = data_from_hex (expected, &blen);
if (!a)
fail ("parameter \"%s\" missing in key\n", name);
else if ( alen != blen || memcmp (a, b, alen) )
{
fail ("parameter \"%s\" does not match expected value\n", name);
if (verbose)
{
info ("expected: %s\n", expected);
show_sexp ("sexp: ", sexp);
}
}
gcry_free (b);
gcry_sexp_release (l1);
}
/* These test vectors are from RFC 6979. */
static void
check_dsa_rfc6979 (void)
{
static struct {
const char *name;
const char *key;
} keys[] = {
{
"DSA, 1024 bits",
"(private-key"
" (DSA"
" (p #86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447"
" E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88"
" 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C"
" 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779#)"
" (q #996F967F6C8E388D9E28D01E205FBA957A5698B1#)"
" (g #07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D"
" 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD"
" 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4"
" 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD#)"
" (x #411602CB19A6CCC34494D79D98EF1E7ED5AF25F7#)"
" (y #5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653"
" 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D"
" 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6"
" 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B#)"
" ))"
},
{
"DSA, 2048 bits",
"(private-key"
" (DSA"
" (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48"
" C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F"
" FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5"
" B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2"
" 35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41"
" F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE"
" 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15"
" 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)"
" (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)"
" (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613"
" D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4"
" 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472"
" 085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5"
" AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA"
" 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71"
" BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0"
" DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)"
" (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)"
" (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94"
" 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61"
" 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE"
" CB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB"
" 5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254"
" 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1"
" 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA"
" 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)"
" ))"
},
{
"ECDSA, 192 bits (prime field)",
"(private-key"
" (ecdsa"
" (curve \"NIST P-192\")"
" (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56"
" 3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)"
" (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)"
" ))"
},
{
"ECDSA, 224 bits (prime field)",
"(private-key"
" (ecdsa"
" (curve \"NIST P-224\")"
" (q #04"
" 00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C"
" EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A#)"
" (d #F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1#)"
" ))"
},
{
"ECDSA, 256 bits (prime field)",
"(private-key"
" (ecdsa"
" (curve \"NIST P-256\")"
" (q #04"
" 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
" 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)"
" (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)"
" ))"
},
{
"ECDSA, 384 bits (prime field)",
"(private-key"
" (ecdsa"
" (curve \"NIST P-384\")"
" (q #04"
" EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64"
" DEF8F0EA9055866064A254515480BC13"
" 8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1"
" 288B231C3AE0D4FE7344FD2533264720#)"
" (d #6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8"
" 96D5724E4C70A825F872C9EA60D2EDF5#)"
" ))"
},
{
"ECDSA, 521 bits (prime field)",
"(private-key"
" (ecdsa"
" (curve \"NIST P-521\")"
" (q #04"
" 01894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD"
" 371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F50"
" 23A4"
" 00493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A"
" 28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFD"
" FCF5#)"
" (d #FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75"
" CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B8"
" 3538#)"
" ))"
},
{ NULL }
};
static struct {
const char *keyname;
const char *name;
const char *hashname;
const char *message;
const char *k, *r, *s;
} tests[] = {
{
"DSA, 1024 bits",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B",
"2E1A0C2562B2912CAAF89186FB0F42001585DA55",
"29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5"
},
{
"DSA, 1024 bits",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"562097C06782D60C3037BA7BE104774344687649",
"4BC3B686AEA70145856814A6F1BB53346F02101E",
"410697B92295D994D21EDD2F4ADA85566F6F94C1"
},
{
"DSA, 1024 bits",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"519BA0546D0C39202A7D34D7DFA5E760B318BCFB",
"81F2F5850BE5BC123C43F71A3033E9384611C545",
"4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89"
},
{
"DSA, 1024 bits",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"95897CD7BBB944AA932DBC579C1C09EB6FCFC595",
"07F2108557EE0E3921BC1774F1CA9B410B4CE65A",
"54DF70456C86FAC10FAB47C1949AB83F2C6F7595"
},
{
"DSA, 1024 bits",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B",
"16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B",
"02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C"
},
{
"DSA, 1024 bits",
"With SHA-1, message = \"test\"",
"sha1", "test",
"5C842DF4F9E344EE09F056838B42C7A17F4A6433",
"42AB2052FD43E123F0607F115052A67DCD9C5C77",
"183916B0230D45B9931491D4C6B0BD2FB4AAF088"
},
{
"DSA, 1024 bits",
"With SHA-224, message = \"test\"",
"sha224", "test",
"4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297",
"6868E9964E36C1689F6037F91F28D5F2C30610F2",
"49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F"
},
{
"DSA, 1024 bits",
"With SHA-256, message = \"test\"",
"sha256", "test",
"5A67592E8128E03A417B0484410FB72C0B630E1A",
"22518C127299B0F6FDC9872B282B9E70D0790812",
"6837EC18F150D55DE95B5E29BE7AF5D01E4FE160"
},
{
"DSA, 1024 bits",
"With SHA-384, message = \"test\"",
"sha384", "test",
"220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89",
"854CF929B58D73C3CBFDC421E8D5430CD6DB5E66",
"91D0E0F53E22F898D158380676A871A157CDA622"
},
{
"DSA, 1024 bits",
"With SHA-512, message = \"test\"",
"sha512", "test",
"65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C",
"8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0",
"7C670C7AD72B6C050C109E1790008097125433E8"
},
{
"DSA, 2048 bits",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E",
"3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A",
"D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF"
},
{
"DSA, 2048 bits",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806",
"DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C",
"A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC"
},
{
"DSA, 2048 bits",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52",
"EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809",
"7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53"
},
{
"DSA, 2048 bits",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920",
"B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B",
"19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B"
},
{
"DSA, 2048 bits",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC",
"2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E",
"D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351"
},
{
"DSA, 2048 bits",
"With SHA-1, message = \"test\"",
"sha1", "test",
"6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F",
"C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0",
"414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA"
},
{
"DSA, 2048 bits",
"With SHA-224, message = \"test\"",
"sha224", "test",
"06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670",
"272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3",
"E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806"
},
{
"DSA, 2048 bits",
"With SHA-256, message = \"test\"",
"sha256", "test",
"1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7",
"8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0",
"7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E"
},
{
"DSA, 2048 bits",
"With SHA-384, message = \"test\"",
"sha384", "test",
"206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C",
"239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE",
"6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961"
},
{
"DSA, 2048 bits",
"With SHA-512, message = \"test\"",
"sha512", "test",
"AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA",
"89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307",
"C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021",
"98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF",
"57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8",
"A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5",
"E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496",
"4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55",
"CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"4730005C4FCB01834C063A7B6760096DBE284B8252EF4311",
"DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5",
"C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1",
"4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8",
"3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-1, message = \"test\"",
"sha1", "test",
"D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25",
"0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D",
"EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-224, message = \"test\"",
"sha224", "test",
"F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE",
"6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34",
"B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-256, message = \"test\"",
"sha256", "test",
"5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C",
"3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE",
"5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-384, message = \"test\"",
"sha384", "test",
"5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693",
"B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367",
"7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A"
},
{
"ECDSA, 192 bits (prime field)",
"With SHA-512, message = \"test\"",
"sha512", "test",
"0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527",
"FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739",
"74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC",
"22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC",
"66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D",
"1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E",
"A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC",
"61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA",
"BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40",
"0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953",
"830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14",
"074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397",
"A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-1, message = \"test\"",
"sha1", "test",
"2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253",
"DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C",
"95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-224, message = \"test\"",
"sha224", "test",
"DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524",
"C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019",
"902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-256, message = \"test\"",
"sha256", "test",
"FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904",
"AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6",
"178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-384, message = \"test\"",
"sha384", "test",
"7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D",
"389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4",
"414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB"
},
{
"ECDSA, 224 bits (prime field)",
"With SHA-512, message = \"test\"",
"sha512", "test",
"E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D",
"049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C",
"077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4",
"61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32",
"6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473",
"53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F",
"B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60",
"EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
"F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4",
"0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719",
"4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5",
"8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00",
"2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-1, message = \"test\"",
"sha1", "test",
"8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E",
"0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89",
"01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-224, message = \"test\"",
"sha224", "test",
"669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7",
"C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692",
"C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-256, message = \"test\"",
"sha256", "test",
"D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0",
"F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367",
"019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-384, message = \"test\"",
"sha384", "test",
"16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8",
"83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6",
"8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C"
},
{
"ECDSA, 256 bits (prime field)",
"With SHA-512, message = \"test\"",
"sha512", "test",
"6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F",
"461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04",
"39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB09663"
"0F29E5938D25106C3C340045A2DB01A7",
"EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3"
"7B9BA002899F6FDA3A4A9386790D4EB2",
"A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF"
"26F49CA031D4857570CCB5CA4424A443"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB"
"8083EE4E3C45B06A5899EA56C51B5879",
"42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366"
"450F76EE3DE43F5A125333A6BE060122",
"9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483"
"4C082C03D83028EFBF93A3C23940CA8D"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E"
"375572342863C899F9F2EDF9747A9B60",
"21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33"
"BDE1E888E63355D92FA2B3C36D8FB2CD",
"F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB"
"EFDC63ECCD1AC42EC0CB8668A4FA0AB0"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA"
"2907E3E83BA95368623B8C4686915CF9",
"94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C"
"81A648152E44ACF96E36DD1E80FABE46",
"99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F"
"A329C145786E679E7B82C71A38628AC8"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331"
"A4E966532593A52980D0E3AAA5E10EC3",
"ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C"
"FE30F35CC900056D7C99CD7882433709",
"512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112"
"DC7CC3EF3446DEFCEB01A45C2667FDD5"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-1, message = \"test\"",
"sha1", "test",
"66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47"
"EC3727F3A3C186C15054492E30698497",
"4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678"
"ACD9D29876DAF46638645F7F404B11C7",
"D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916"
"95BA1C84541327E966FA7B50F7382282"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-224, message = \"test\"",
"sha224", "test",
"18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E"
"3D33BE4DC5EB8886A8ECD093F2935726",
"E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624"
"64A9A817C47FF78B8C11066B24080E72",
"07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614"
"1C53EA5ABEF0D8231077A04540A96B66"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-256, message = \"test\"",
"sha256", "test",
"0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FA"
"A48DD070BA79921A3457ABFF2D630AD7",
"6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559"
"F918EEDAF2293BE5B475CC8F0188636B",
"2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D"
"51AB373F9845C0514EEFB14024787265"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-384, message = \"test\"",
"sha384", "test",
"015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092AD"
"A71F4A459BC0DA98ADB95837DB8312EA",
"8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB"
"0542A7F0812998DA8F1DD3CA3CF023DB",
"DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0"
"6A739F040649A667BF3B828246BAA5A5"
},
{
"ECDSA, 384 bits (prime field)",
"With SHA-512, message = \"test\"",
"sha512", "test",
"3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE"
"0E2CC8A136036DC4B9C00E6888F66B6C",
"A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0"
"6FB6495CD21B4B6E340FC236584FB277",
"976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463"
"4A2092CD3792E0159AD9CEE37659C736"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-1, message = \"sample\"",
"sha1", "sample",
"0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB"
"42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D"
"0F9",
"343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910"
"FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D"
"75D",
"E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D"
"5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5"
"D16"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-224, message = \"sample\"",
"sha224", "sample",
"121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0"
"493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B9211"
"3F3",
"01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3"
"0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E"
"D2E",
"50CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B"
"A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B"
"41F"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-256, message = \"sample\"",
"sha256", "sample",
"0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C3257576"
"1793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E"
"1A0",
"01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659"
"D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E"
"1A7",
"4A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916"
"E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E"
"CFC"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-384, message = \"sample\"",
"sha384", "sample",
"1546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FF"
"AD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4"
"211",
"01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4"
"B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67"
"451",
"01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5"
"FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65"
"D61"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-512, message = \"sample\"",
"sha512", "sample",
"1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F1019"
"8B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBF"
"FD3",
"C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1"
"74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37"
"7FA",
"617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2"
"82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A"
"67A"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-1, message = \"test\"",
"sha1", "test",
"0BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DD"
"BA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B"
"222",
"013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0"
"693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0"
"367",
"01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90"
"F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679"
"7FF"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-224, message = \"test\"",
"sha224", "test",
"040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A011369"
"87E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F"
"706",
"01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086"
"BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1"
"7FB",
"0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5"
"BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51"
"9A4"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-256, message = \"test\"",
"sha256", "test",
"01DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E84384"
"1AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909"
"258",
"0E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104"
"2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656"
"AA8",
"CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9"
"FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694"
"E86"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-384, message = \"test\"",
"sha384", "test",
"1F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5D"
"CEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0"
"C88",
"014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C"
"89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755"
"78C",
"0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E"
"D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B"
"979"
},
{
"ECDSA, 521 bits (prime field)",
"With SHA-512, message = \"test\"",
"sha512", "test",
"16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1"
"B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC"
"56D",
"013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10"
"CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E"
"E6D",
"01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78"
"A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D"
"CE3"
},
{ NULL }
};
gpg_error_t err;
int tno, i, hashalgo;
gcry_sexp_t seckey, data, sig;
unsigned char digest[64];
int digestlen;
for (tno = 0; tests[tno].keyname; tno++)
{
if (verbose)
info ("Test %d: %s. %s.\n", tno, tests[tno].keyname, tests[tno].name);
{
for (i=0; keys[i].name; i++)
if (!strcmp (tests[tno].keyname, keys[i].name))
break;
if (!keys[i].name)
die ("Key '%s' used by test '%s' not found\n",
tests[tno].keyname, tests[tno].name);
err = gcry_sexp_new (&seckey, keys[i].key, 0, 1);
if (err)
die ("reading key failed: %s\n", gpg_strerror (err));
}
hashalgo = gcry_md_map_name (tests[tno].hashname);
if (!hashalgo)
die ("hash with name '%s' is not supported\n", tests[tno].hashname);
digestlen = gcry_md_get_algo_dlen (hashalgo);
if (digestlen > sizeof digest)
die ("internal error: digest does not fit into our buffer\n");
gcry_md_hash_buffer (hashalgo, digest,
tests[tno].message, strlen (tests[tno].message));
err = gcry_sexp_build (&data, NULL,
"(data "
" (flags rfc6979)"
" (hash %s %b))",
tests[tno].hashname, digestlen, digest);
if (err)
die ("building data sexp failed: %s\n", gpg_strerror (err));
err = gcry_pk_sign (&sig, data, seckey);
if (err)
fail ("signing failed: %s\n", gpg_strerror (err));
extract_cmp_data (sig, "r", tests[tno].r);
extract_cmp_data (sig, "s", tests[tno].s);
err = gcry_pk_verify (sig, data, seckey);
if (err)
fail ("verification failed: %s\n", gpg_strerror (err));
gcry_sexp_release (sig);
gcry_sexp_release (data);
gcry_sexp_release (seckey);
}
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
{
verbose = 2;
debug = 1;
}
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);
if (debug)
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);
check_dsa_rfc6979 ();
return error_count ? 1 : 0;
}
diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c
index b5f0cf0b..6d5cc088 100644
--- a/tests/fips186-dsa.c
+++ b/tests/fips186-dsa.c
@@ -1,429 +1,429 @@
/* fips186-dsa.c - FIPS 186 DSA tests
* 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
#else
# include <gcrypt.h>
#endif
#define PGM "fips186-dsa"
#include "t-common.h"
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
static gcry_mpi_t
mpi_from_string (const char *string)
{
gpg_error_t err;
gcry_mpi_t a;
err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, string, 0, NULL);
if (err)
die ("error converting string to mpi: %s\n", gpg_strerror (err));
return a;
}
/* 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 *
data_from_hex (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = gcry_xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
die ("error parsing hex string `%s'\n", string);
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected)
{
gcry_sexp_t l1;
gcry_mpi_t a, b;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
b = mpi_from_string (expected);
if (!a)
fail ("parameter \"%s\" missing in key\n", name);
else if ( gcry_mpi_cmp (a, b) )
fail ("parameter \"%s\" does not match expected value\n", name);
gcry_mpi_release (b);
gcry_mpi_release (a);
gcry_sexp_release (l1);
}
static void
extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected)
{
gcry_sexp_t l1;
const void *a;
size_t alen;
void *b;
size_t blen;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_data (l1, 1, &alen);
b = data_from_hex (expected, &blen);
if (!a)
fail ("parameter \"%s\" missing in key\n", name);
else if ( alen != blen || memcmp (a, b, alen) )
fail ("parameter \"%s\" does not match expected value\n", name);
gcry_free (b);
gcry_sexp_release (l1);
}
static void
extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected)
{
gcry_sexp_t l1;
char *a;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_string (l1, 1);
if (!a)
fail ("parameter \"%s\" missing in key\n", name);
else if ( strtoul (a, NULL, 10) != expected )
fail ("parameter \"%s\" does not match expected value\n", name);
gcry_free (a);
gcry_sexp_release (l1);
}
static void
check_dsa_gen_186_2 (void)
{
static struct {
int nbits;
const char *p, *q, *g;
const char *seed;
int counter;
const char *h;
} tbl[] = {
/* These tests are from FIPS 186-2, B.3.1. */
{
1024,
"d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
"4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7"
"74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0"
"5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69",
"9c916d121de9a03f71fb21bc2e1c0d116f065a4f",
"8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab"
"0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad"
"b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e"
"ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44",
"0cb1990c1fd3626055d7a0096f8fa99807399871",
98,
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000002"
},
{
1024,
"f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f"
"8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb"
"0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be"
"3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9",
"f8751166cf4f6f3b07c081fd2a9071f23ca1988d",
"1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62"
"4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a"
"665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c"
"4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33",
"34b3520d45d240a8861b82c8b61ffa16e67b5cce",
622,
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000002",
},
{
1024,
"c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7"
"b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4"
"55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc"
"1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad",
"d32b29f065c1394a30490b6fcbf812a32a8634ab",
"06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1"
"ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714"
"c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231"
"80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2",
"b6ec750da2f824cb42c5f7e28c81350d97f75125",
185,
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000002",
},
{
1024,
"b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b"
"ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f"
"d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b"
"c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5",
"de822c03445b77cec4ad3a6fb0ca39ff97059ddf",
"65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371"
"681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b"
"848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69"
"1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748",
"cd2221dd73815a75224e9fde7faf52829b81ac7a",
62,
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000002",
},
{
1024,
"898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803"
"ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891"
"354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9"
"8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227",
"c6d786643d2acfc6b8d576863fda8cfbfbd5e03f",
"2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d"
"af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d"
"5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb"
"e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb",
"73483e697599871af983a281e3afa22e0ed86b68",
272,
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000002",
},
/* These tests are generated by the OpenSSL FIPS version. */
{
1024,
"A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C"
"A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255"
"EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033"
"11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9",
"C643946CEA8748E12D430C48DB038F9165814389",
"59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16"
"892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC"
"B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7"
"44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225",
"02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd",
50,
"02"
},
{
1024,
"9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987"
"6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3"
"D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450"
"04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5",
"AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7",
"74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701"
"95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E"
"039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A"
"C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498",
"6481a12a50384888ee84b61024f7c9c685d6ac96",
289,
"02"
},
{
1024,
"B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828"
"1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63"
"5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503"
"B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF",
"EA649C04911FAB5A41440287A517EF752A40354B",
"88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162"
"01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194"
"93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C"
"858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696",
"5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a",
626,
"02"
},
{
1024,
"F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C"
"F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D"
"5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977"
"CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD",
"A40D9EE456AED4C8A653FDB47B6629C0B843FE8F",
"DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE"
"700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614"
"F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7"
"2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67",
"8a9a57706f69f4f566252cdf6d5cbfdf2020150b",
397,
"02"
},
{
1024,
"D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068"
"29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934"
"96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A"
"093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B",
"D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5",
"468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC"
"58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5"
"7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159"
"928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839",
"30b3599944a914a330a3f49d11ec88f555422aef",
678,
"02"
}
};
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-2 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)(use-fips186-2)"
"(derive-parms(seed %b))))",
tbl[tno].nbits, (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)
{
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_mpi (sec_key, "g", tbl[tno].g);
extract_cmp_data (seed_values, "seed", tbl[tno].seed);
extract_cmp_int (seed_values, "counter", tbl[tno].counter);
extract_cmp_mpi (seed_values, "h", tbl[tno].h);
gcry_sexp_release (seed_values);
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
gcry_sexp_release (key);
}
}
static void
check_dsa_gen_186_3 (void)
{
/* FIXME: Needs to be implemented. */
if (verbose)
info ("generating FIPS 186-3 test keys - skipped\n");
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
{
verbose = 2;
debug = 1;
}
xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (debug)
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);
check_dsa_gen_186_2 ();
check_dsa_gen_186_3 ();
return error_count ? 1 : 0;
}
diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index 71554e23..b9c89df5 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -1,2865 +1,2865 @@
/* fipsdrv.c - A driver to help with FIPS CAVS tests.
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/>.
+ License along with this program; if not, see <https://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>
#ifdef HAVE_W32_SYSTEM
# include <fcntl.h> /* We need setmode(). */
#else
# include <signal.h>
#endif
#include <assert.h>
#include <unistd.h>
#ifndef _GCRYPT_IN_LIBGCRYPT
# include <gcrypt.h>
# define PACKAGE_BUGREPORT "devnull@example.org"
# define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]"
#endif
#include "../src/gcrypt-testapi.h"
#define PGM "fipsdrv"
#include "t-common.h"
/* Binary input flag. */
static int binary_input;
/* Binary output flag. */
static int binary_output;
/* Base64 output flag. */
static int base64_output;
/* We need to know whether we are in loop_mode. */
static int loop_mode;
/* If true some functions are modified to print the output in the CAVS
response file format. */
static int standalone_mode;
/* ASN.1 classes. */
enum
{
UNIVERSAL = 0,
APPLICATION = 1,
ASNCONTEXT = 2,
PRIVATE = 3
};
/* ASN.1 tags. */
enum
{
TAG_NONE = 0,
TAG_BOOLEAN = 1,
TAG_INTEGER = 2,
TAG_BIT_STRING = 3,
TAG_OCTET_STRING = 4,
TAG_NULL = 5,
TAG_OBJECT_ID = 6,
TAG_OBJECT_DESCRIPTOR = 7,
TAG_EXTERNAL = 8,
TAG_REAL = 9,
TAG_ENUMERATED = 10,
TAG_EMBEDDED_PDV = 11,
TAG_UTF8_STRING = 12,
TAG_REALTIVE_OID = 13,
TAG_SEQUENCE = 16,
TAG_SET = 17,
TAG_NUMERIC_STRING = 18,
TAG_PRINTABLE_STRING = 19,
TAG_TELETEX_STRING = 20,
TAG_VIDEOTEX_STRING = 21,
TAG_IA5_STRING = 22,
TAG_UTC_TIME = 23,
TAG_GENERALIZED_TIME = 24,
TAG_GRAPHIC_STRING = 25,
TAG_VISIBLE_STRING = 26,
TAG_GENERAL_STRING = 27,
TAG_UNIVERSAL_STRING = 28,
TAG_CHARACTER_STRING = 29,
TAG_BMP_STRING = 30
};
/* ASN.1 Parser object. */
struct tag_info
{
int class; /* Object class. */
unsigned long tag; /* The tag of the object. */
unsigned long length; /* Length of the values. */
int nhdr; /* Length of the header (TL). */
unsigned int ndef:1; /* The object has an indefinite length. */
unsigned int cons:1; /* This is a constructed object. */
};
static void
showhex (const char *prefix, const void *buffer, size_t length)
{
const unsigned char *p = buffer;
if (prefix)
fprintf (stderr, PGM ": %s: ", prefix);
while (length-- )
fprintf (stderr, "%02X", *p++);
if (prefix)
putc ('\n', stderr);
}
/* static void */
/* show_sexp (const char *prefix, gcry_sexp_t a) */
/* { */
/* char *buf; */
/* size_t size; */
/* if (prefix) */
/* fputs (prefix, stderr); */
/* size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); */
/* buf = gcry_xmalloc (size); */
/* gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); */
/* fprintf (stderr, "%.*s", (int)size, buf); */
/* gcry_free (buf); */
/* } */
/* 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;
}
/* 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 = gcry_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 char *
read_textline (FILE *fp)
{
char line[256];
char *p;
int any = 0;
/* Read line but skip over initial empty lines. */
do
{
do
{
if (!fgets (line, sizeof line, fp))
{
if (feof (fp))
return NULL;
die ("error reading input line: %s\n", strerror (errno));
}
p = strchr (line, '\n');
if (p)
*p = 0;
p = line + (*line? (strlen (line)-1):0);
for ( ;p > line; p--)
if (my_isascii (*p) && isspace (*p))
*p = 0;
}
while (!any && !*line);
any = 1;
}
while (*line == '#'); /* Always skip comment lines. */
if (verbose > 1)
fprintf (stderr, PGM ": received line: %s\n", line);
return gcry_xstrdup (line);
}
static char *
read_hexline (FILE *fp, size_t *retlen)
{
char *line, *p;
line = read_textline (fp);
if (!line)
return NULL;
p = hex2buffer (line, retlen);
if (!p)
die ("error decoding hex string on input\n");
gcry_free (line);
return p;
}
static void
skip_to_empty_line (FILE *fp)
{
char line[256];
char *p;
do
{
if (!fgets (line, sizeof line, fp))
{
if (feof (fp))
return;
die ("error reading input line: %s\n", strerror (errno));
}
p = strchr (line, '\n');
if (p)
*p =0;
}
while (*line);
}
/* Read a file from stream FP into a newly allocated buffer and return
that buffer. The valid length of the buffer is stored at R_LENGTH.
Returns NULL on failure. If decode is set, the file is assumed to
be hex encoded and the decoded content is returned. */
static void *
read_file (FILE *fp, int decode, size_t *r_length)
{
char *buffer;
size_t buflen;
size_t nread, bufsize = 0;
*r_length = 0;
#define NCHUNK 8192
#ifdef HAVE_DOSISH_SYSTEM
setmode (fileno(fp), O_BINARY);
#endif
buffer = NULL;
buflen = 0;
do
{
bufsize += NCHUNK;
if (!buffer)
buffer = gcry_xmalloc (bufsize);
else
buffer = gcry_xrealloc (buffer, bufsize);
nread = fread (buffer + buflen, 1, NCHUNK, fp);
if (nread < NCHUNK && ferror (fp))
{
gcry_free (buffer);
return NULL;
}
buflen += nread;
}
while (nread == NCHUNK);
#undef NCHUNK
if (decode)
{
const char *s;
char *p;
for (s=buffer,p=buffer,nread=0; nread+1 < buflen; s += 2, nread +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
{
gcry_free (buffer);
return NULL; /* Invalid hex digits. */
}
*(unsigned char*)p++ = xtoi_2 (s);
}
if (nread != buflen)
{
gcry_free (buffer);
return NULL; /* Odd number of hex digits. */
}
buflen = p - buffer;
}
*r_length = buflen;
return buffer;
}
/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Returns
the new length of the buffer. Dies on error. */
static size_t
base64_decode (char *buffer, size_t length)
{
static unsigned char const asctobin[128] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
};
int idx = 0;
unsigned char val = 0;
int c = 0;
char *d, *s;
int lfseen = 1;
/* Find BEGIN line. */
for (s=buffer; length; length--, s++)
{
if (lfseen && *s == '-' && length > 11 && !memcmp (s, "-----BEGIN ", 11))
{
for (; length && *s != '\n'; length--, s++)
;
break;
}
lfseen = (*s == '\n');
}
/* Decode until pad character or END line. */
for (d=buffer; length; length--, s++)
{
if (lfseen && *s == '-' && length > 9 && !memcmp (s, "-----END ", 9))
break;
if ((lfseen = (*s == '\n')) || *s == ' ' || *s == '\r' || *s == '\t')
continue;
if (*s == '=')
{
/* Pad character: stop */
if (idx == 1)
*d++ = val;
break;
}
if ( (*s & 0x80) || (c = asctobin[*(unsigned char *)s]) == 0xff)
die ("invalid base64 character %02X at pos %d detected\n",
*(unsigned char*)s, (int)(s-buffer));
switch (idx)
{
case 0:
val = c << 2;
break;
case 1:
val |= (c>>4)&3;
*d++ = val;
val = (c<<4)&0xf0;
break;
case 2:
val |= (c>>2)&15;
*d++ = val;
val = (c<<6)&0xc0;
break;
case 3:
val |= c&0x3f;
*d++ = val;
break;
}
idx = (idx+1) % 4;
}
return d - buffer;
}
/* Parse the buffer at the address BUFFER which consists of the number
of octets as stored at BUFLEN. Return the tag and the length part
from the TLV triplet. Update BUFFER and BUFLEN on success. Checks
that the encoded length does not exhaust the length of the provided
buffer. */
static int
parse_tag (unsigned char const **buffer, size_t *buflen, struct tag_info *ti)
{
int c;
unsigned long tag;
const unsigned char *buf = *buffer;
size_t length = *buflen;
ti->length = 0;
ti->ndef = 0;
ti->nhdr = 0;
/* Get the tag */
if (!length)
return -1; /* Premature EOF. */
c = *buf++; length--;
ti->nhdr++;
ti->class = (c & 0xc0) >> 6;
ti->cons = !!(c & 0x20);
tag = (c & 0x1f);
if (tag == 0x1f)
{
tag = 0;
do
{
tag <<= 7;
if (!length)
return -1; /* Premature EOF. */
c = *buf++; length--;
ti->nhdr++;
tag |= (c & 0x7f);
}
while ( (c & 0x80) );
}
ti->tag = tag;
/* Get the length */
if (!length)
return -1; /* Premature EOF. */
c = *buf++; length--;
ti->nhdr++;
if ( !(c & 0x80) )
ti->length = c;
else if (c == 0x80)
ti->ndef = 1;
else if (c == 0xff)
return -1; /* Forbidden length value. */
else
{
unsigned long len = 0;
int count = c & 0x7f;
for (; count; count--)
{
len <<= 8;
if (!length)
return -1; /* Premature EOF. */
c = *buf++; length--;
ti->nhdr++;
len |= (c & 0xff);
}
ti->length = len;
}
if (ti->class == UNIVERSAL && !ti->tag)
ti->length = 0;
if (ti->length > length)
return -1; /* Data larger than buffer. */
*buffer = buf;
*buflen = length;
return 0;
}
/* Read the file FNAME assuming it is a PEM encoded private key file
and return an S-expression. With SHOW set, the key parameters are
printed. */
static gcry_sexp_t
read_private_key_file (const char *fname, int show)
{
gcry_error_t err;
FILE *fp;
char *buffer;
size_t buflen;
const unsigned char *der;
size_t derlen;
struct tag_info ti;
gcry_mpi_t keyparms[8];
int n_keyparms = 8;
int idx;
gcry_sexp_t s_key;
fp = fopen (fname, binary_input?"rb":"r");
if (!fp)
die ("can't open `%s': %s\n", fname, strerror (errno));
buffer = read_file (fp, 0, &buflen);
if (!buffer)
die ("error reading `%s'\n", fname);
fclose (fp);
buflen = base64_decode (buffer, buflen);
/* Parse the ASN.1 structure. */
der = (const unsigned char*)buffer;
derlen = buflen;
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef)
goto bad_asn1;
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
goto bad_asn1;
if (ti.length != 1 || *der)
goto bad_asn1; /* The value of the first integer is no 0. */
der += ti.length; derlen -= ti.length;
for (idx=0; idx < n_keyparms; idx++)
{
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
goto bad_asn1;
if (show)
{
char prefix[2];
prefix[0] = idx < 8? "nedpq12u"[idx] : '?';
prefix[1] = 0;
showhex (prefix, der, ti.length);
}
err = gcry_mpi_scan (keyparms+idx, GCRYMPI_FMT_USG, der, ti.length,NULL);
if (err)
die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err));
der += ti.length; derlen -= ti.length;
}
if (idx != n_keyparms)
die ("not enough RSA key parameters\n");
gcry_free (buffer);
/* Convert from OpenSSL parameter ordering to the OpenPGP order. */
/* First check that p < q; if not swap p and q and recompute u. */
if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0)
{
gcry_mpi_swap (keyparms[3], keyparms[4]);
gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]);
}
/* Build the S-expression. */
err = gcry_sexp_build (&s_key, NULL,
"(private-key(rsa(n%m)(e%m)"
/**/ "(d%m)(p%m)(q%m)(u%m)))",
keyparms[0], keyparms[1], keyparms[2],
keyparms[3], keyparms[4], keyparms[7] );
if (err)
die ("error building S-expression: %s\n", gpg_strerror (err));
for (idx=0; idx < n_keyparms; idx++)
gcry_mpi_release (keyparms[idx]);
return s_key;
bad_asn1:
die ("invalid ASN.1 structure in `%s'\n", fname);
return NULL; /*NOTREACHED*/
}
/* Read the file FNAME assuming it is a PEM encoded public key file
and return an S-expression. With SHOW set, the key parameters are
printed. */
static gcry_sexp_t
read_public_key_file (const char *fname, int show)
{
gcry_error_t err;
FILE *fp;
char *buffer;
size_t buflen;
const unsigned char *der;
size_t derlen;
struct tag_info ti;
gcry_mpi_t keyparms[2];
int n_keyparms = 2;
int idx;
gcry_sexp_t s_key;
fp = fopen (fname, binary_input?"rb":"r");
if (!fp)
die ("can't open `%s': %s\n", fname, strerror (errno));
buffer = read_file (fp, 0, &buflen);
if (!buffer)
die ("error reading `%s'\n", fname);
fclose (fp);
buflen = base64_decode (buffer, buflen);
/* Parse the ASN.1 structure. */
der = (const unsigned char*)buffer;
derlen = buflen;
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef)
goto bad_asn1;
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef)
goto bad_asn1;
/* We skip the description of the key parameters and assume it is RSA. */
der += ti.length; derlen -= ti.length;
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_BIT_STRING || ti.class || ti.cons || ti.ndef)
goto bad_asn1;
if (ti.length < 1 || *der)
goto bad_asn1; /* The number of unused bits needs to be 0. */
der += 1; derlen -= 1;
/* Parse the BIT string. */
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_SEQUENCE || ti.class || !ti.cons || ti.ndef)
goto bad_asn1;
for (idx=0; idx < n_keyparms; idx++)
{
if ( parse_tag (&der, &derlen, &ti)
|| ti.tag != TAG_INTEGER || ti.class || ti.cons || ti.ndef)
goto bad_asn1;
if (show)
{
char prefix[2];
prefix[0] = idx < 2? "ne"[idx] : '?';
prefix[1] = 0;
showhex (prefix, der, ti.length);
}
err = gcry_mpi_scan (keyparms+idx, GCRYMPI_FMT_USG, der, ti.length,NULL);
if (err)
die ("error scanning RSA parameter %d: %s\n", idx, gpg_strerror (err));
der += ti.length; derlen -= ti.length;
}
if (idx != n_keyparms)
die ("not enough RSA key parameters\n");
gcry_free (buffer);
/* Build the S-expression. */
err = gcry_sexp_build (&s_key, NULL,
"(public-key(rsa(n%m)(e%m)))",
keyparms[0], keyparms[1] );
if (err)
die ("error building S-expression: %s\n", gpg_strerror (err));
for (idx=0; idx < n_keyparms; idx++)
gcry_mpi_release (keyparms[idx]);
return s_key;
bad_asn1:
die ("invalid ASN.1 structure in `%s'\n", fname);
return NULL; /*NOTREACHED*/
}
/* Read the file FNAME assuming it is a binary signature result and
return an an S-expression suitable for gcry_pk_verify. */
static gcry_sexp_t
read_sig_file (const char *fname)
{
gcry_error_t err;
FILE *fp;
char *buffer;
size_t buflen;
gcry_mpi_t tmpmpi;
gcry_sexp_t s_sig;
fp = fopen (fname, "rb");
if (!fp)
die ("can't open `%s': %s\n", fname, strerror (errno));
buffer = read_file (fp, 0, &buflen);
if (!buffer)
die ("error reading `%s'\n", fname);
fclose (fp);
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, buffer, buflen, NULL);
if (!err)
err = gcry_sexp_build (&s_sig, NULL,
"(sig-val(rsa(s %m)))", tmpmpi);
if (err)
die ("error building S-expression: %s\n", gpg_strerror (err));
gcry_mpi_release (tmpmpi);
gcry_free (buffer);
return s_sig;
}
/* Read an S-expression from FNAME. */
static gcry_sexp_t
read_sexp_from_file (const char *fname)
{
gcry_error_t err;
FILE *fp;
char *buffer;
size_t buflen;
gcry_sexp_t sexp;
fp = fopen (fname, "rb");
if (!fp)
die ("can't open `%s': %s\n", fname, strerror (errno));
buffer = read_file (fp, 0, &buflen);
if (!buffer)
die ("error reading `%s'\n", fname);
fclose (fp);
if (!buflen)
die ("error: file `%s' is empty\n", fname);
err = gcry_sexp_create (&sexp, buffer, buflen, 1, gcry_free);
if (err)
die ("error parsing `%s': %s\n", fname, gpg_strerror (err));
return sexp;
}
static void
print_buffer (const void *buffer, size_t length)
{
int writerr = 0;
if (base64_output)
{
static const unsigned char bintoasc[64+1] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
const unsigned char *p;
unsigned char inbuf[4];
char outbuf[4];
int idx, quads;
idx = quads = 0;
for (p = buffer; length; p++, length--)
{
inbuf[idx++] = *p;
if (idx > 2)
{
outbuf[0] = bintoasc[(*inbuf>>2)&077];
outbuf[1] = bintoasc[(((*inbuf<<4)&060)
|((inbuf[1] >> 4)&017))&077];
outbuf[2] = bintoasc[(((inbuf[1]<<2)&074)
|((inbuf[2]>>6)&03))&077];
outbuf[3] = bintoasc[inbuf[2]&077];
if (fwrite (outbuf, 4, 1, stdout) != 1)
writerr = 1;
idx = 0;
if (++quads >= (64/4))
{
if (fwrite ("\n", 1, 1, stdout) != 1)
writerr = 1;
quads = 0;
}
}
}
if (idx)
{
outbuf[0] = bintoasc[(*inbuf>>2)&077];
if (idx == 1)
{
outbuf[1] = bintoasc[((*inbuf<<4)&060)&077];
outbuf[2] = outbuf[3] = '=';
}
else
{
outbuf[1] = bintoasc[(((*inbuf<<4)&060)
|((inbuf[1]>>4)&017))&077];
outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077];
outbuf[3] = '=';
}
if (fwrite (outbuf, 4, 1, stdout) != 1)
writerr = 1;
quads++;
}
if (quads && fwrite ("\n", 1, 1, stdout) != 1)
writerr = 1;
}
else if (binary_output)
{
if (fwrite (buffer, length, 1, stdout) != 1)
writerr++;
}
else
{
const unsigned char *p = buffer;
if (verbose > 1)
showhex ("sent line", buffer, length);
while (length-- && !ferror (stdout) )
printf ("%02X", *p++);
if (ferror (stdout))
writerr++;
}
if (!writerr && fflush (stdout) == EOF)
writerr++;
if (writerr)
{
#ifndef HAVE_W32_SYSTEM
if (loop_mode && errno == EPIPE)
loop_mode = 0;
else
#endif
die ("writing output failed: %s\n", strerror (errno));
}
}
/* Print an MPI on a line. */
static void
print_mpi_line (gcry_mpi_t a, int no_lz)
{
unsigned char *buf, *p;
gcry_error_t err;
int writerr = 0;
err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a);
if (err)
die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err));
p = buf;
if (no_lz && p[0] == '0' && p[1] == '0' && p[2])
p += 2;
printf ("%s\n", p);
if (ferror (stdout))
writerr++;
if (!writerr && fflush (stdout) == EOF)
writerr++;
if (writerr)
die ("writing output failed: %s\n", strerror (errno));
gcry_free (buf);
}
/* Print some data on hex format on a line. */
static void
print_data_line (const void *data, size_t datalen)
{
const unsigned char *p = data;
int writerr = 0;
while (data && datalen-- && !ferror (stdout) )
printf ("%02X", *p++);
putchar ('\n');
if (ferror (stdout))
writerr++;
if (!writerr && fflush (stdout) == EOF)
writerr++;
if (writerr)
die ("writing output failed: %s\n", strerror (errno));
}
/* Print the S-expression A to the stream FP. */
static void
print_sexp (gcry_sexp_t a, FILE *fp)
{
char *buf;
size_t size;
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
if (fwrite (buf, size, 1, fp) != 1)
die ("error writing to stream: %s\n", strerror (errno));
gcry_free (buf);
}
static gcry_error_t
init_external_rng_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 (PRIV_CTL_INIT_EXTRNG_TEST,
r_context, flags,
key, keylen,
seed, seedlen,
dt, dtlen);
}
static gcry_error_t
run_external_rng_test (void *context, void *buffer, size_t buflen)
{
return gcry_control (PRIV_CTL_RUN_EXTRNG_TEST, context, buffer, buflen);
}
static void
deinit_external_rng_test (void *context)
{
xgcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context);
}
/* Given an OpenSSL cipher name NAME, return the Libgcrypt algirithm
identified and store the libgcrypt mode at R_MODE. Returns 0 on
error. */
static int
map_openssl_cipher_name (const char *name, int *r_mode)
{
static struct {
const char *name;
int algo;
int mode;
} table[] =
{
{ "bf-cbc", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
{ "bf", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC },
{ "bf-cfb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB },
{ "bf-ecb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB },
{ "bf-ofb", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB },
{ "cast-cbc", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
{ "cast", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
{ "cast5-cbc", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC },
{ "cast5-cfb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CFB },
{ "cast5-ecb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_ECB },
{ "cast5-ofb", GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_OFB },
{ "des-cbc", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC },
{ "des", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC },
{ "des-cfb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CFB },
{ "des-ofb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_OFB },
{ "des-ecb", GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB },
{ "des-ede3-cbc", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC },
{ "des-ede3", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB },
{ "des3", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC },
{ "des-ede3-cfb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CFB },
{ "des-ede3-ofb", GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_OFB },
{ "rc4", GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM },
{ "aes-128-cbc", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC },
{ "aes-128", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC },
{ "aes-128-cfb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CFB },
{ "aes-128-ecb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB },
{ "aes-128-ofb", GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_OFB },
{ "aes-192-cbc", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC },
{ "aes-192", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC },
{ "aes-192-cfb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB },
{ "aes-192-ecb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB },
{ "aes-192-ofb", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB },
{ "aes-256-cbc", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC },
{ "aes-256", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC },
{ "aes-256-cfb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB },
{ "aes-256-ecb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB },
{ "aes-256-ofb", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB },
{ NULL, 0 , 0 }
};
int idx;
for (idx=0; table[idx].name; idx++)
if (!strcmp (name, table[idx].name))
{
*r_mode = table[idx].mode;
return table[idx].algo;
}
*r_mode = 0;
return 0;
}
/* Run an encrypt or decryption operations. If DATA is NULL the
function reads its input in chunks of size DATALEN from fp and
processes it and writes it out until EOF. */
static void
run_encrypt_decrypt (int encrypt_mode,
int cipher_algo, int cipher_mode,
const void *iv_buffer, size_t iv_buflen,
const void *key_buffer, size_t key_buflen,
const void *data, size_t datalen, FILE *fp)
{
gpg_error_t err;
gcry_cipher_hd_t hd;
void *outbuf;
size_t outbuflen;
void *inbuf;
size_t inbuflen;
size_t blocklen;
err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0);
if (err)
die ("gcry_cipher_open failed for algo %d, mode %d: %s\n",
cipher_algo, cipher_mode, gpg_strerror (err));
blocklen = gcry_cipher_get_algo_blklen (cipher_algo);
assert (blocklen);
gcry_cipher_ctl (hd, PRIV_CIPHERCTL_DISABLE_WEAK_KEY, NULL, 0);
err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
if (err)
die ("gcry_cipher_setkey failed with keylen %u: %s\n",
(unsigned int)key_buflen, gpg_strerror (err));
if (iv_buffer)
{
err = gcry_cipher_setiv (hd, iv_buffer, iv_buflen);
if (err)
die ("gcry_cipher_setiv failed with ivlen %u: %s\n",
(unsigned int)iv_buflen, gpg_strerror (err));
}
inbuf = data? NULL : gcry_xmalloc (datalen);
outbuflen = datalen;
outbuf = gcry_xmalloc (outbuflen < blocklen? blocklen:outbuflen);
do
{
if (inbuf)
{
int nread = fread (inbuf, 1, datalen, fp);
if (nread < (int)datalen && ferror (fp))
die ("error reading input\n");
data = inbuf;
inbuflen = nread;
}
else
inbuflen = datalen;
if (encrypt_mode)
err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, inbuflen);
else
err = gcry_cipher_decrypt (hd, outbuf, outbuflen, data, inbuflen);
if (err)
die ("gcry_cipher_%scrypt failed: %s\n",
encrypt_mode? "en":"de", gpg_strerror (err));
print_buffer (outbuf, outbuflen);
}
while (inbuf);
gcry_cipher_close (hd);
gcry_free (outbuf);
gcry_free (inbuf);
}
static void
get_current_iv (gcry_cipher_hd_t hd, void *buffer, size_t buflen)
{
unsigned char tmp[17];
if (gcry_cipher_ctl (hd, PRIV_CIPHERCTL_GET_INPUT_VECTOR, tmp, sizeof tmp))
die ("error getting current input vector\n");
if (buflen > *tmp)
die ("buffer too short to store the current input vector\n");
memcpy (buffer, tmp+1, *tmp);
}
/* Run the inner loop of the CAVS monte carlo test. */
static void
run_cipher_mct_loop (int encrypt_mode, int cipher_algo, int cipher_mode,
const void *iv_buffer, size_t iv_buflen,
const void *key_buffer, size_t key_buflen,
const void *data, size_t datalen, int iterations)
{
gpg_error_t err;
gcry_cipher_hd_t hd;
size_t blocklen;
int count;
char input[16];
char output[16];
char last_output[16];
char last_last_output[16];
char last_iv[16];
err = gcry_cipher_open (&hd, cipher_algo, cipher_mode, 0);
if (err)
die ("gcry_cipher_open failed for algo %d, mode %d: %s\n",
cipher_algo, cipher_mode, gpg_strerror (err));
blocklen = gcry_cipher_get_algo_blklen (cipher_algo);
if (!blocklen || blocklen > sizeof output)
die ("invalid block length %d\n", (int)blocklen);
gcry_cipher_ctl (hd, PRIV_CIPHERCTL_DISABLE_WEAK_KEY, NULL, 0);
err = gcry_cipher_setkey (hd, key_buffer, key_buflen);
if (err)
die ("gcry_cipher_setkey failed with keylen %u: %s\n",
(unsigned int)key_buflen, gpg_strerror (err));
if (iv_buffer)
{
err = gcry_cipher_setiv (hd, iv_buffer, iv_buflen);
if (err)
die ("gcry_cipher_setiv failed with ivlen %u: %s\n",
(unsigned int)iv_buflen, gpg_strerror (err));
}
if (datalen != blocklen)
die ("length of input (%u) does not match block length (%u)\n",
(unsigned int)datalen, (unsigned int)blocklen);
memcpy (input, data, datalen);
memset (output, 0, sizeof output);
for (count=0; count < iterations; count++)
{
memcpy (last_last_output, last_output, sizeof last_output);
memcpy (last_output, output, sizeof output);
get_current_iv (hd, last_iv, blocklen);
if (encrypt_mode)
err = gcry_cipher_encrypt (hd, output, blocklen, input, blocklen);
else
err = gcry_cipher_decrypt (hd, output, blocklen, input, blocklen);
if (err)
die ("gcry_cipher_%scrypt failed: %s\n",
encrypt_mode? "en":"de", gpg_strerror (err));
if (encrypt_mode && (cipher_mode == GCRY_CIPHER_MODE_CFB
|| cipher_mode == GCRY_CIPHER_MODE_CBC))
memcpy (input, last_iv, blocklen);
else if (cipher_mode == GCRY_CIPHER_MODE_OFB)
memcpy (input, last_iv, blocklen);
else if (!encrypt_mode && cipher_mode == GCRY_CIPHER_MODE_CFB)
{
/* Reconstruct the output vector. */
int i;
for (i=0; i < blocklen; i++)
input[i] ^= output[i];
}
else
memcpy (input, output, blocklen);
}
print_buffer (output, blocklen);
putchar ('\n');
print_buffer (last_output, blocklen);
putchar ('\n');
print_buffer (last_last_output, blocklen);
putchar ('\n');
get_current_iv (hd, last_iv, blocklen);
print_buffer (last_iv, blocklen); /* Last output vector. */
putchar ('\n');
print_buffer (input, blocklen); /* Next input text. */
putchar ('\n');
if (verbose > 1)
showhex ("sent line", "", 0);
putchar ('\n');
fflush (stdout);
gcry_cipher_close (hd);
}
/* Run a digest operation. */
static void
run_digest (int digest_algo, const void *data, size_t datalen)
{
gpg_error_t err;
gcry_md_hd_t hd;
const unsigned char *digest;
unsigned int digestlen;
err = gcry_md_open (&hd, digest_algo, 0);
if (err)
die ("gcry_md_open failed for algo %d: %s\n",
digest_algo, gpg_strerror (err));
gcry_md_write (hd, data, datalen);
digest = gcry_md_read (hd, digest_algo);
digestlen = gcry_md_get_algo_dlen (digest_algo);
print_buffer (digest, digestlen);
gcry_md_close (hd);
}
/* Run a HMAC operation. */
static void
run_hmac (int digest_algo, const void *key, size_t keylen,
const void *data, size_t datalen)
{
gpg_error_t err;
gcry_md_hd_t hd;
const unsigned char *digest;
unsigned int digestlen;
err = gcry_md_open (&hd, digest_algo, GCRY_MD_FLAG_HMAC);
if (err)
die ("gcry_md_open failed for HMAC algo %d: %s\n",
digest_algo, gpg_strerror (err));
gcry_md_setkey (hd, key, keylen);
if (err)
die ("gcry_md_setkey failed for HMAC algo %d: %s\n",
digest_algo, gpg_strerror (err));
gcry_md_write (hd, data, datalen);
digest = gcry_md_read (hd, digest_algo);
digestlen = gcry_md_get_algo_dlen (digest_algo);
print_buffer (digest, digestlen);
gcry_md_close (hd);
}
/* Derive an RSA key using the S-expression in (DATA,DATALEN). This
S-expression is used directly as input to gcry_pk_genkey. The
result is printed to stdout with one parameter per line in hex
format and in this order: p, q, n, d. */
static void
run_rsa_derive (const void *data, size_t datalen)
{
gpg_error_t err;
gcry_sexp_t s_keyspec, s_key, s_top, l1;
gcry_mpi_t mpi;
const char *parmlist;
int idx;
if (!datalen)
err = gpg_error (GPG_ERR_NO_DATA);
else
err = gcry_sexp_new (&s_keyspec, data, datalen, 1);
if (err)
die ("gcry_sexp_new failed for RSA key derive: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&s_key, s_keyspec);
if (err)
die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
gcry_sexp_release (s_keyspec);
/* P and Q might have been swapped but we need to to return them in
the proper order. Build the parameter list accordingly. */
parmlist = "pqnd";
s_top = gcry_sexp_find_token (s_key, "misc-key-info", 0);
if (s_top)
{
l1 = gcry_sexp_find_token (s_top, "p-q-swapped", 0);
if (l1)
parmlist = "qpnd";
gcry_sexp_release (l1);
gcry_sexp_release (s_top);
}
/* Parse and print the parameters. */
l1 = gcry_sexp_find_token (s_key, "private-key", 0);
s_top = gcry_sexp_find_token (l1, "rsa", 0);
gcry_sexp_release (l1);
if (!s_top)
die ("private-key part not found in result\n");
for (idx=0; parmlist[idx]; idx++)
{
l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1);
mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l1);
if (!mpi)
die ("parameter %c missing in private-key\n", parmlist[idx]);
print_mpi_line (mpi, 1);
gcry_mpi_release (mpi);
}
gcry_sexp_release (s_top);
gcry_sexp_release (s_key);
}
/* Generate RSA key using the S-expression in (DATA,DATALEN). This
S-expression is used directly as input to gcry_pk_genkey. The
result is printed to stdout with one parameter per line in hex
format and in this order: e, p, q, n, d. */
static void
run_rsa_keygen (const void *data, size_t datalen, int test)
{
gpg_error_t err;
gcry_sexp_t s_keyspec, s_key, s_top, l1;
gcry_mpi_t mpi;
const char *parmlist;
int idx;
if (!datalen)
err = gpg_error (GPG_ERR_NO_DATA);
else
err = gcry_sexp_new (&s_keyspec, data, datalen, 1);
if (err)
die ("gcry_sexp_new failed for RSA key generation: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&s_key, s_keyspec);
gcry_sexp_release (s_keyspec);
if (test) {
if (err)
printf("F\n");
else {
gcry_sexp_release (s_key);
printf("P\n");
}
return;
}
if (err)
die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
parmlist = "epqnd";
/* Parse and print the parameters. */
l1 = gcry_sexp_find_token (s_key, "private-key", 0);
s_top = gcry_sexp_find_token (l1, "rsa", 0);
gcry_sexp_release (l1);
if (!s_top)
die ("private-key part not found in result\n");
for (idx=0; parmlist[idx]; idx++)
{
l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1);
mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l1);
if (!mpi)
die ("parameter %c missing in private-key\n", parmlist[idx]);
print_mpi_line (mpi, 1);
gcry_mpi_release (mpi);
}
gcry_sexp_release (s_top);
gcry_sexp_release (s_key);
}
static size_t
compute_tag_length (size_t n)
{
int needed = 0;
if (n < 128)
needed += 2; /* Tag and one length byte. */
else if (n < 256)
needed += 3; /* Tag, number of length bytes, 1 length byte. */
else if (n < 65536)
needed += 4; /* Tag, number of length bytes, 2 length bytes. */
else
die ("DER object too long to encode\n");
return needed;
}
static unsigned char *
store_tag_length (unsigned char *p, int tag, size_t n)
{
if (tag == TAG_SEQUENCE)
tag |= 0x20; /* constructed */
*p++ = tag;
if (n < 128)
*p++ = n;
else if (n < 256)
{
*p++ = 0x81;
*p++ = n;
}
else if (n < 65536)
{
*p++ = 0x82;
*p++ = n >> 8;
*p++ = n;
}
return p;
}
/* Generate an RSA key of size KEYSIZE using the public exponent
PUBEXP and print it to stdout in the OpenSSL format. The format
is:
SEQUENCE {
INTEGER (0) -- Unknown constant.
INTEGER -- n
INTEGER -- e
INTEGER -- d
INTEGER -- p
INTEGER -- q (with p < q)
INTEGER -- dmp1 = d mod (p-1)
INTEGER -- dmq1 = d mod (q-1)
INTEGER -- u = p^{-1} mod q
}
*/
static void
run_rsa_gen (int keysize, int pubexp)
{
gpg_error_t err;
gcry_sexp_t keyspec, key, l1;
const char keyelems[] = "nedpq..u";
gcry_mpi_t keyparms[8];
size_t keyparmslen[8];
int idx;
size_t derlen, needed, n;
unsigned char *derbuf, *der;
err = gcry_sexp_build (&keyspec, NULL,
"(genkey (rsa (nbits %d)(rsa-use-e %d)))",
keysize, pubexp);
if (err)
die ("gcry_sexp_build failed for RSA key generation: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&key, keyspec);
if (err)
die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
gcry_sexp_release (keyspec);
l1 = gcry_sexp_find_token (key, "private-key", 0);
if (!l1)
die ("private key not found in genkey result\n");
gcry_sexp_release (key);
key = l1;
l1 = gcry_sexp_find_token (key, "rsa", 0);
if (!l1)
die ("returned private key not formed as expected\n");
gcry_sexp_release (key);
key = l1;
/* Extract the parameters from the S-expression and store them in a
well defined order in KEYPARMS. */
for (idx=0; idx < DIM(keyparms); idx++)
{
if (keyelems[idx] == '.')
{
keyparms[idx] = gcry_mpi_new (0);
continue;
}
l1 = gcry_sexp_find_token (key, keyelems+idx, 1);
if (!l1)
die ("no %c parameter in returned private key\n", keyelems[idx]);
keyparms[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
if (!keyparms[idx])
die ("no value for %c parameter in returned private key\n",
keyelems[idx]);
gcry_sexp_release (l1);
}
gcry_sexp_release (key);
/* Check that p < q; if not swap p and q and recompute u. */
if (gcry_mpi_cmp (keyparms[3], keyparms[4]) > 0)
{
gcry_mpi_swap (keyparms[3], keyparms[4]);
gcry_mpi_invm (keyparms[7], keyparms[3], keyparms[4]);
}
/* Compute the additional parameters. */
gcry_mpi_sub_ui (keyparms[5], keyparms[3], 1);
gcry_mpi_mod (keyparms[5], keyparms[2], keyparms[5]);
gcry_mpi_sub_ui (keyparms[6], keyparms[4], 1);
gcry_mpi_mod (keyparms[6], keyparms[2], keyparms[6]);
/* Compute the length of the DER encoding. */
needed = compute_tag_length (1) + 1;
for (idx=0; idx < DIM(keyparms); idx++)
{
err = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, keyparms[idx]);
if (err)
die ("error formatting parameter: %s\n", gpg_strerror (err));
keyparmslen[idx] = n;
needed += compute_tag_length (n) + n;
}
/* Store the key parameters. */
derlen = compute_tag_length (needed) + needed;
der = derbuf = gcry_xmalloc (derlen);
der = store_tag_length (der, TAG_SEQUENCE, needed);
der = store_tag_length (der, TAG_INTEGER, 1);
*der++ = 0;
for (idx=0; idx < DIM(keyparms); idx++)
{
der = store_tag_length (der, TAG_INTEGER, keyparmslen[idx]);
err = gcry_mpi_print (GCRYMPI_FMT_STD, der,
keyparmslen[idx], NULL, keyparms[idx]);
if (err)
die ("error formatting parameter: %s\n", gpg_strerror (err));
der += keyparmslen[idx];
}
/* Print the stuff. */
for (idx=0; idx < DIM(keyparms); idx++)
gcry_mpi_release (keyparms[idx]);
assert (der - derbuf == derlen);
if (base64_output)
puts ("-----BEGIN RSA PRIVATE KEY-----");
print_buffer (derbuf, derlen);
if (base64_output)
puts ("-----END RSA PRIVATE KEY-----");
gcry_free (derbuf);
}
/* Sign DATA of length DATALEN using the key taken from the PEM
encoded KEYFILE and the hash algorithm HASHALGO. */
static void
run_rsa_sign (const void *data, size_t datalen,
int hashalgo, int pkcs1, int pss, const char *keyfile)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig, s_tmp;
gcry_mpi_t sig_mpi = NULL;
unsigned char *outbuf;
size_t outlen;
/* showhex ("D", data, datalen); */
if (pkcs1)
{
unsigned char hash[64];
unsigned int hashsize;
hashsize = gcry_md_get_algo_dlen (hashalgo);
if (!hashsize || hashsize > sizeof hash)
die ("digest too long for buffer or unknown hash algorithm\n");
gcry_md_hash_buffer (hashalgo, hash, data, datalen);
err = gcry_sexp_build (&s_data, NULL,
"(data (flags pkcs1)(hash %s %b))",
gcry_md_algo_name (hashalgo),
(int)hashsize, hash);
}
else if (pss)
{
unsigned char hash[64];
unsigned int hashsize;
hashsize = gcry_md_get_algo_dlen (hashalgo);
if (!hashsize || hashsize > sizeof hash)
die ("digest too long for buffer or unknown hash algorithm\n");
gcry_md_hash_buffer (hashalgo, hash, data, datalen);
err = gcry_sexp_build (&s_data, NULL,
"(data (flags pss)(salt-length #00#)(hash %s %b))",
gcry_md_algo_name (hashalgo),
(int)hashsize, hash);
}
else
{
gcry_mpi_t tmp;
err = gcry_mpi_scan (&tmp, GCRYMPI_FMT_USG, data, datalen,NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(value %m))", tmp);
gcry_mpi_release (tmp);
}
}
if (err)
die ("gcry_sexp_build failed for RSA data input: %s\n",
gpg_strerror (err));
s_key = read_private_key_file (keyfile, 0);
err = gcry_pk_sign (&s_sig, s_data, s_key);
if (err)
{
gcry_sexp_release (read_private_key_file (keyfile, 1));
die ("gcry_pk_signed failed (datalen=%d,keyfile=%s): %s\n",
(int)datalen, keyfile, gpg_strerror (err));
}
gcry_sexp_release (s_key);
gcry_sexp_release (s_data);
s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
if (s_tmp)
{
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "rsa", 0);
if (s_tmp)
{
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
if (s_tmp)
{
gcry_sexp_release (s_sig);
s_sig = s_tmp;
sig_mpi = gcry_sexp_nth_mpi (s_sig, 1, GCRYMPI_FMT_USG);
}
}
}
gcry_sexp_release (s_sig);
if (!sig_mpi)
die ("no value in returned S-expression\n");
err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &outbuf, &outlen, sig_mpi);
if (err)
die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err));
gcry_mpi_release (sig_mpi);
print_buffer (outbuf, outlen);
gcry_free (outbuf);
}
/* Verify DATA of length DATALEN using the public key taken from the
PEM encoded KEYFILE and the hash algorithm HASHALGO against the
binary signature in SIGFILE. */
static void
run_rsa_verify (const void *data, size_t datalen, int hashalgo, int pkcs1,
int pss, const char *keyfile, const char *sigfile)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig;
if (pkcs1)
{
unsigned char hash[64];
unsigned int hashsize;
hashsize = gcry_md_get_algo_dlen (hashalgo);
if (!hashsize || hashsize > sizeof hash)
die ("digest too long for buffer or unknown hash algorithm\n");
gcry_md_hash_buffer (hashalgo, hash, data, datalen);
err = gcry_sexp_build (&s_data, NULL,
"(data (flags pkcs1)(hash %s %b))",
gcry_md_algo_name (hashalgo),
(int)hashsize, hash);
}
else if (pss)
{
unsigned char hash[64];
unsigned int hashsize;
hashsize = gcry_md_get_algo_dlen (hashalgo);
if (!hashsize || hashsize > sizeof hash)
die ("digest too long for buffer or unknown hash algorithm\n");
gcry_md_hash_buffer (hashalgo, hash, data, datalen);
err = gcry_sexp_build (&s_data, NULL,
"(data (flags pss)(salt-length #00#)(hash %s %b))",
gcry_md_algo_name (hashalgo),
(int)hashsize, hash);
}
else
{
gcry_mpi_t tmp;
err = gcry_mpi_scan (&tmp, GCRYMPI_FMT_USG, data, datalen,NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(value %m))", tmp);
gcry_mpi_release (tmp);
}
}
if (err)
die ("gcry_sexp_build failed for RSA data input: %s\n",
gpg_strerror (err));
s_key = read_public_key_file (keyfile, 0);
s_sig = read_sig_file (sigfile);
err = gcry_pk_verify (s_sig, s_data, s_key);
if (!err)
puts ("GOOD signature");
else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
puts ("BAD signature");
else
printf ("ERROR (%s)\n", gpg_strerror (err));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_key);
gcry_sexp_release (s_data);
}
/* Generate a DSA key of size KEYSIZE and return the complete
S-expression. */
static gcry_sexp_t
dsa_gen (int keysize)
{
gpg_error_t err;
gcry_sexp_t keyspec, key;
err = gcry_sexp_build (&keyspec, NULL,
"(genkey (dsa (nbits %d)(use-fips186-2)))",
keysize);
if (err)
die ("gcry_sexp_build failed for DSA key generation: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&key, keyspec);
if (err)
die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
gcry_sexp_release (keyspec);
return key;
}
/* Generate a DSA key of size KEYSIZE and return the complete
S-expression. */
static gcry_sexp_t
dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
{
gpg_error_t err;
gcry_sexp_t keyspec, key;
err = gcry_sexp_build (&keyspec, NULL,
"(genkey"
" (dsa"
" (nbits %d)"
" (use-fips186-2)"
" (derive-parms"
" (seed %b))))",
keysize, (int)seedlen, seed);
if (err)
die ("gcry_sexp_build failed for DSA key generation: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&key, keyspec);
if (err)
die ("gcry_pk_genkey failed for DSA: %s\n", gpg_strerror (err));
gcry_sexp_release (keyspec);
return key;
}
/* Generate an ECDSA key on the specified curve and return the complete
S-expression. */
static gcry_sexp_t
ecdsa_gen_key (const char *curve)
{
gpg_error_t err;
gcry_sexp_t keyspec, key;
err = gcry_sexp_build (&keyspec, NULL,
"(genkey"
" (ecc"
" (use-fips186)"
" (curve %s)))",
curve);
if (err)
die ("gcry_sexp_build failed for ECDSA key generation: %s\n",
gpg_strerror (err));
err = gcry_pk_genkey (&key, keyspec);
if (err)
die ("gcry_pk_genkey failed for ECDSA: %s\n", gpg_strerror (err));
gcry_sexp_release (keyspec);
return key;
}
/* Print the domain parameter as well as the derive information. KEY
is the complete key as returned by dsa_gen. We print to stdout
with one parameter per line in hex format using this order: p, q,
g, seed, counter, h. */
static void
print_dsa_domain_parameters (gcry_sexp_t key)
{
gcry_sexp_t l1, l2;
gcry_mpi_t mpi;
int idx;
const void *data;
size_t datalen;
char *string;
l1 = gcry_sexp_find_token (key, "public-key", 0);
if (!l1)
die ("public key not found in genkey result\n");
l2 = gcry_sexp_find_token (l1, "dsa", 0);
if (!l2)
die ("returned public key not formed as expected\n");
gcry_sexp_release (l1);
l1 = l2;
/* 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);
if (!l2)
die ("no %c parameter in returned public key\n", "pqg"[idx]);
mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!mpi)
die ("no value for %c parameter in returned public key\n","pqg"[idx]);
gcry_sexp_release (l2);
if (standalone_mode)
printf ("%c = ", "PQG"[idx]);
print_mpi_line (mpi, 1);
gcry_mpi_release (mpi);
}
gcry_sexp_release (l1);
/* Extract the seed values. */
l1 = gcry_sexp_find_token (key, "misc-key-info", 0);
if (!l1)
die ("misc-key-info not found in genkey result\n");
l2 = gcry_sexp_find_token (l1, "seed-values", 0);
if (!l2)
die ("no seed-values in returned key\n");
gcry_sexp_release (l1);
l1 = l2;
l2 = gcry_sexp_find_token (l1, "seed", 0);
if (!l2)
die ("no seed value in returned key\n");
data = gcry_sexp_nth_data (l2, 1, &datalen);
if (!data)
die ("no seed value in returned key\n");
if (standalone_mode)
printf ("Seed = ");
print_data_line (data, datalen);
gcry_sexp_release (l2);
l2 = gcry_sexp_find_token (l1, "counter", 0);
if (!l2)
die ("no counter value in returned key\n");
string = gcry_sexp_nth_string (l2, 1);
if (!string)
die ("no counter value in returned key\n");
if (standalone_mode)
printf ("c = %ld\n", strtoul (string, NULL, 10));
else
printf ("%lX\n", strtoul (string, NULL, 10));
gcry_free (string);
gcry_sexp_release (l2);
l2 = gcry_sexp_find_token (l1, "h", 0);
if (!l2)
die ("no n value in returned key\n");
mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!mpi)
die ("no h value in returned key\n");
if (standalone_mode)
printf ("H = ");
print_mpi_line (mpi, 1);
gcry_mpi_release (mpi);
gcry_sexp_release (l2);
gcry_sexp_release (l1);
}
/* Print public key Q (in octet-string format) and private key d.
KEY is the complete key as returned by ecdsa_gen_key.
with one parameter per line in hex format using this order: d, Q. */
static void
print_ecdsa_dq (gcry_sexp_t key)
{
gcry_sexp_t l1, l2;
gcry_mpi_t mpi;
int idx;
l1 = gcry_sexp_find_token (key, "private-key", 0);
if (!l1)
die ("private key not found in genkey result\n");
l2 = gcry_sexp_find_token (l1, "ecc", 0);
if (!l2)
die ("returned private key not formed as expected\n");
gcry_sexp_release (l1);
l1 = l2;
/* 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);
if (!l2)
die ("no %c parameter in returned public key\n", "dq"[idx]);
mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
if (!mpi)
die ("no value for %c parameter in returned private key\n","dq"[idx]);
gcry_sexp_release (l2);
if (standalone_mode)
printf ("%c = ", "dQ"[idx]);
print_mpi_line (mpi, 1);
gcry_mpi_release (mpi);
}
gcry_sexp_release (l1);
}
/* Generate DSA domain parameters for a modulus size of KEYSIZE. The
result is printed to stdout with one parameter per line in hex
format and in this order: p, q, g, seed, counter, h. If SEED is
not NULL this seed value will be used for the generation. */
static void
run_dsa_pqg_gen (int keysize, const void *seed, size_t seedlen)
{
gcry_sexp_t key;
if (seed)
key = dsa_gen_with_seed (keysize, seed, seedlen);
else
key = dsa_gen (keysize);
print_dsa_domain_parameters (key);
gcry_sexp_release (key);
}
/* Generate a DSA key of size of KEYSIZE and write the private key to
FILENAME. Also write the parameters to stdout in the same way as
run_dsa_pqg_gen. */
static void
run_dsa_gen (int keysize, const char *filename)
{
gcry_sexp_t key, private_key;
FILE *fp;
key = dsa_gen (keysize);
private_key = gcry_sexp_find_token (key, "private-key", 0);
if (!private_key)
die ("private key not found in genkey result\n");
print_dsa_domain_parameters (key);
fp = fopen (filename, "wb");
if (!fp)
die ("can't create `%s': %s\n", filename, strerror (errno));
print_sexp (private_key, fp);
fclose (fp);
gcry_sexp_release (private_key);
gcry_sexp_release (key);
}
/* Sign DATA of length DATALEN using the key taken from the S-expression
encoded KEYFILE. */
static void
run_dsa_sign (const void *data, size_t datalen, const char *keyfile)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig, s_tmp, s_tmp2;
char hash[20];
gcry_mpi_t tmpmpi;
gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(value %m))", tmpmpi);
gcry_mpi_release (tmpmpi);
}
if (err)
die ("gcry_sexp_build failed for DSA data input: %s\n",
gpg_strerror (err));
s_key = read_sexp_from_file (keyfile);
err = gcry_pk_sign (&s_sig, s_data, s_key);
if (err)
{
gcry_sexp_release (read_private_key_file (keyfile, 1));
die ("gcry_pk_signed failed (datalen=%d,keyfile=%s): %s\n",
(int)datalen, keyfile, gpg_strerror (err));
}
gcry_sexp_release (s_data);
/* We need to return the Y parameter first. */
s_tmp = gcry_sexp_find_token (s_key, "private-key", 0);
if (!s_tmp)
die ("private key part not found in provided key\n");
s_tmp2 = gcry_sexp_find_token (s_tmp, "dsa", 0);
if (!s_tmp2)
die ("private key part is not a DSA key\n");
gcry_sexp_release (s_tmp);
s_tmp = gcry_sexp_find_token (s_tmp2, "y", 0);
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
if (!tmpmpi)
die ("no y parameter in DSA key\n");
print_mpi_line (tmpmpi, 1);
gcry_mpi_release (tmpmpi);
gcry_sexp_release (s_tmp);
gcry_sexp_release (s_key);
/* Now return the actual signature. */
s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
if (!s_tmp)
die ("no sig-val element in returned S-expression\n");
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "dsa", 0);
if (!s_tmp)
die ("no dsa element in returned S-expression\n");
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "r", 0);
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
if (!tmpmpi)
die ("no r parameter in returned S-expression\n");
print_mpi_line (tmpmpi, 1);
gcry_mpi_release (tmpmpi);
gcry_sexp_release (s_tmp);
s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
if (!tmpmpi)
die ("no s parameter in returned S-expression\n");
print_mpi_line (tmpmpi, 1);
gcry_mpi_release (tmpmpi);
gcry_sexp_release (s_tmp);
gcry_sexp_release (s_sig);
}
/* Verify DATA of length DATALEN using the public key taken from the
S-expression in KEYFILE against the S-expression formatted
signature in SIGFILE. */
static void
run_dsa_verify (const void *data, size_t datalen,
const char *keyfile, const char *sigfile)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig;
char hash[20];
gcry_mpi_t tmpmpi;
gcry_md_hash_buffer (GCRY_MD_SHA1, hash, data, datalen);
/* Note that we can't simply use %b with HASH to build the
S-expression, because that might yield a negative value. */
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, 20, NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(value %m))", tmpmpi);
gcry_mpi_release (tmpmpi);
}
if (err)
die ("gcry_sexp_build failed for DSA data input: %s\n",
gpg_strerror (err));
s_key = read_sexp_from_file (keyfile);
s_sig = read_sexp_from_file (sigfile);
err = gcry_pk_verify (s_sig, s_data, s_key);
if (!err)
puts ("GOOD signature");
else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
puts ("BAD signature");
else
printf ("ERROR (%s)\n", gpg_strerror (err));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_key);
gcry_sexp_release (s_data);
}
/* Sign DATA of length DATALEN using the key taken from the S-expression
encoded KEYFILE. */
static void
run_ecdsa_sign (const void *data, size_t datalen,
const char *keyfile, const int algo)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig, s_tmp;
char hash[128];
gcry_mpi_t tmpmpi;
s_key = read_sexp_from_file (keyfile);
gcry_md_hash_buffer (algo, hash, data, datalen);
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
gcry_md_get_algo_dlen(algo), NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(hash %s %M))",
gcry_md_algo_name(algo), tmpmpi);
gcry_mpi_release (tmpmpi);
}
if (err)
die ("gcry_sexp_build failed for ECDSA data input: %s\n",
gpg_strerror (err));
err = gcry_pk_sign (&s_sig, s_data, s_key);
if (err)
{
die ("gcry_pk_signed failed: %s\n", gpg_strerror (err));
}
gcry_sexp_release (s_data);
gcry_sexp_release (s_key);
/* Now return the actual signature. */
s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
if (!s_tmp)
die ("no sig-val element in returned S-expression\n");
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "ecdsa", 0);
if (!s_tmp)
die ("no ecdsa element in returned S-expression\n");
gcry_sexp_release (s_sig);
s_sig = s_tmp;
s_tmp = gcry_sexp_find_token (s_sig, "r", 0);
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
if (!tmpmpi)
die ("no r parameter in returned S-expression\n");
print_mpi_line (tmpmpi, 1);
gcry_mpi_release (tmpmpi);
gcry_sexp_release (s_tmp);
s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
if (!tmpmpi)
die ("no s parameter in returned S-expression\n");
print_mpi_line (tmpmpi, 1);
gcry_mpi_release (tmpmpi);
gcry_sexp_release (s_tmp);
gcry_sexp_release (s_sig);
}
/* Verify DATA of length DATALEN using the public key taken from the
S-expression in KEYFILE against the S-expression formatted
signature in SIGFILE. */
static void
run_ecdsa_verify (const void *data, size_t datalen,
const char *keyfile, const int algo, const char *sigfile)
{
gpg_error_t err;
gcry_sexp_t s_data, s_key, s_sig;
char hash[128];
gcry_mpi_t tmpmpi;
s_key = read_sexp_from_file (keyfile);
gcry_md_hash_buffer (algo, hash, data, datalen);
/* Note that we can't simply use %b with HASH to build the
S-expression, because that might yield a negative value. */
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
gcry_md_get_algo_dlen(algo), NULL);
if (!err)
{
err = gcry_sexp_build (&s_data, NULL,
"(data (flags raw)(hash %s %M))",
gcry_md_algo_name(algo), tmpmpi);
gcry_mpi_release (tmpmpi);
}
if (err)
die ("gcry_sexp_build failed for DSA data input: %s\n",
gpg_strerror (err));
s_sig = read_sexp_from_file (sigfile);
err = gcry_pk_verify (s_sig, s_data, s_key);
if (!err)
puts ("GOOD signature");
else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
puts ("BAD signature");
else
printf ("ERROR (%s)\n", gpg_strerror (err));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_key);
gcry_sexp_release (s_data);
}
/* Generate an ECDSA key with specified domain parameters
and print the d and Q values, in the standard octet-string format. */
static void
run_ecdsa_gen_key (const char *curve)
{
gcry_sexp_t key;
key = ecdsa_gen_key (curve);
print_ecdsa_dq (key);
gcry_sexp_release (key);
}
static void
usage (int show_help)
{
if (!show_help)
{
fputs ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n", stderr);
exit (2);
}
fputs
("Usage: " PGM " [OPTIONS] MODE [FILE]\n"
"Run a crypto operation using hex encoded input and output.\n"
"MODE:\n"
" encrypt, decrypt, digest, random, hmac-sha,\n"
" rsa-{derive,gen,sign,verify},\n"
" dsa-{pqg-gen,gen,sign,verify}, ecdsa-{gen-key,sign,verify}\n"
"OPTIONS:\n"
" --verbose Print additional information\n"
" --binary Input and output is in binary form\n"
" --no-fips Do not force FIPS mode\n"
" --key KEY Use the hex encoded KEY\n"
" --iv IV Use the hex encoded IV\n"
" --dt DT Use the hex encoded DT for the RNG\n"
" --algo NAME Use algorithm NAME\n"
" --curve NAME Select ECC curve spec NAME\n"
" --keysize N Use a keysize of N bits\n"
" --signature NAME Take signature from file NAME\n"
" --chunk N Read in chunks of N bytes (implies --binary)\n"
" --pkcs1 Use PKCS#1 encoding\n"
" --pss Use PSS encoding with a zero length salt\n"
" --mct-server Run a monte carlo test server\n"
" --loop Enable random loop mode\n"
" --progress Print pogress indicators\n"
" --help Print this text\n"
"With no FILE, or when FILE is -, read standard input.\n"
"Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
exit (0);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
gpg_error_t err;
int no_fips = 0;
int progress = 0;
int use_pkcs1 = 0;
int use_pss = 0;
const char *mode_string;
const char *curve_string = NULL;
const char *key_string = NULL;
const char *iv_string = NULL;
const char *dt_string = NULL;
const char *algo_string = NULL;
const char *keysize_string = NULL;
const char *signature_string = NULL;
FILE *input;
void *data;
size_t datalen;
size_t chunksize = 0;
int mct_server = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
usage (1);
}
else if (!strcmp (*argv, "--version"))
{
fputs (PGM " (Libgcrypt) " PACKAGE_VERSION "\n", stdout);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--binary"))
{
binary_input = binary_output = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--no-fips"))
{
no_fips++;
argc--; argv++;
}
else if (!strcmp (*argv, "--loop"))
{
loop_mode = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--progress"))
{
progress = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--key"))
{
argc--; argv++;
if (!argc)
usage (0);
key_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--iv"))
{
argc--; argv++;
if (!argc)
usage (0);
iv_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--dt"))
{
argc--; argv++;
if (!argc)
usage (0);
dt_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--algo"))
{
argc--; argv++;
if (!argc)
usage (0);
algo_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--keysize"))
{
argc--; argv++;
if (!argc)
usage (0);
keysize_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--signature"))
{
argc--; argv++;
if (!argc)
usage (0);
signature_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--chunk"))
{
argc--; argv++;
if (!argc)
usage (0);
chunksize = atoi (*argv);
binary_input = binary_output = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--curve"))
{
argc--; argv++;
if (!argc)
usage (0);
curve_string = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--pkcs1"))
{
use_pkcs1 = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--pss"))
{
use_pss = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--mct-server"))
{
mct_server = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--standalone"))
{
standalone_mode = 1;
argc--; argv++;
}
}
if (!argc || argc > 2)
usage (0);
mode_string = *argv;
if (use_pkcs1 && use_pss)
die ("Only one of --pkcs or --pss may be given\n");
if (!strcmp (mode_string, "rsa-derive"))
binary_input = 1;
if (argc == 2 && strcmp (argv[1], "-"))
{
input = fopen (argv[1], binary_input? "rb":"r");
if (!input)
die ("can't open `%s': %s\n", argv[1], strerror (errno));
}
else
input = stdin;
#ifndef HAVE_W32_SYSTEM
if (loop_mode)
signal (SIGPIPE, SIG_IGN);
#endif
if (verbose)
fprintf (stderr, PGM ": started (mode=%s)\n", mode_string);
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 ("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);
/* Most operations need some input data. */
if (!chunksize
&& !mct_server
&& strcmp (mode_string, "random")
&& strcmp (mode_string, "rsa-gen")
&& strcmp (mode_string, "rsa-keygen")
&& strcmp (mode_string, "rsa-keygen-kat")
&& strcmp (mode_string, "dsa-gen")
&& strcmp (mode_string, "ecdsa-gen-key") )
{
data = read_file (input, !binary_input, &datalen);
if (!data)
die ("error reading%s input\n", binary_input?"":" and decoding");
if (verbose)
fprintf (stderr, PGM ": %u bytes of input data\n",
(unsigned int)datalen);
}
else
{
data = NULL;
datalen = 0;
}
if (!strcmp (mode_string, "encrypt") || !strcmp (mode_string, "decrypt"))
{
int cipher_algo, cipher_mode;
void *iv_buffer = NULL;
void *key_buffer = NULL;
size_t iv_buflen, key_buflen;
if (!algo_string)
die ("option --algo is required in this mode\n");
cipher_algo = map_openssl_cipher_name (algo_string, &cipher_mode);
if (!cipher_algo)
die ("cipher algorithm `%s' is not supported\n", algo_string);
if (mct_server)
{
int iterations;
for (;;)
{
gcry_free (key_buffer); key_buffer = NULL;
gcry_free (iv_buffer); iv_buffer = NULL;
gcry_free (data); data = NULL;
if (!(key_buffer = read_textline (input)))
{
if (feof (input))
break;
die ("no version info in input\n");
}
if (atoi (key_buffer) != 1)
die ("unsupported input version %s\n",
(const char*)key_buffer);
gcry_free (key_buffer);
if (!(key_buffer = read_textline (input)))
die ("no iteration count in input\n");
iterations = atoi (key_buffer);
gcry_free (key_buffer);
if (!(key_buffer = read_hexline (input, &key_buflen)))
die ("no key in input\n");
if (!(iv_buffer = read_hexline (input, &iv_buflen)))
die ("no IV in input\n");
if (!(data = read_hexline (input, &datalen)))
die ("no data in input\n");
skip_to_empty_line (input);
run_cipher_mct_loop ((*mode_string == 'e'),
cipher_algo, cipher_mode,
iv_buffer, iv_buflen,
key_buffer, key_buflen,
data, datalen, iterations);
}
}
else
{
if (cipher_mode != GCRY_CIPHER_MODE_ECB)
{
if (!iv_string)
die ("option --iv is required in this mode\n");
iv_buffer = hex2buffer (iv_string, &iv_buflen);
if (!iv_buffer)
die ("invalid value for IV\n");
}
else
{
iv_buffer = NULL;
iv_buflen = 0;
}
if (!key_string)
die ("option --key is required in this mode\n");
key_buffer = hex2buffer (key_string, &key_buflen);
if (!key_buffer)
die ("invalid value for KEY\n");
run_encrypt_decrypt ((*mode_string == 'e'),
cipher_algo, cipher_mode,
iv_buffer, iv_buflen,
key_buffer, key_buflen,
data, data? datalen:chunksize, input);
}
gcry_free (key_buffer);
gcry_free (iv_buffer);
}
else if (!strcmp (mode_string, "digest"))
{
int algo;
if (!algo_string)
die ("option --algo is required in this mode\n");
algo = gcry_md_map_name (algo_string);
if (!algo)
die ("digest algorithm `%s' is not supported\n", algo_string);
if (!data)
die ("no data available (do not use --chunk)\n");
run_digest (algo, data, datalen);
}
else if (!strcmp (mode_string, "random"))
{
void *context;
unsigned char key[16];
unsigned char seed[16];
unsigned char dt[16];
unsigned char buffer[16];
size_t count = 0;
if (!key_string || hex2bin (key_string, key, 16) < 0 )
die ("value for --key are not 32 hex digits\n");
if (!iv_string || hex2bin (iv_string, seed, 16) < 0 )
die ("value for --iv are not 32 hex digits\n");
if (!dt_string || hex2bin (dt_string, dt, 16) < 0 )
die ("value for --dt are not 32 hex digits\n");
/* The flag value 1 disables the dup check, so that the RNG
returns all generated data. */
err = init_external_rng_test (&context, 1, key, 16, seed, 16, dt, 16);
if (err)
die ("init external RNG test failed: %s\n", gpg_strerror (err));
do
{
err = run_external_rng_test (context, buffer, sizeof buffer);
if (err)
die ("running external RNG test failed: %s\n", gpg_strerror (err));
print_buffer (buffer, sizeof buffer);
if (progress)
{
if (!(++count % 1000))
fprintf (stderr, PGM ": %lu random bytes so far\n",
(unsigned long int)(count * sizeof buffer));
}
}
while (loop_mode);
if (progress)
fprintf (stderr, PGM ": %lu random bytes\n",
(unsigned long int)(count * sizeof buffer));
deinit_external_rng_test (context);
}
else if (!strcmp (mode_string, "hmac-sha"))
{
int algo;
void *key_buffer;
size_t key_buflen;
if (!data)
die ("no data available (do not use --chunk)\n");
if (!algo_string)
die ("option --algo is required in this mode\n");
switch (atoi (algo_string))
{
case 1: algo = GCRY_MD_SHA1; break;
case 224: algo = GCRY_MD_SHA224; break;
case 256: algo = GCRY_MD_SHA256; break;
case 384: algo = GCRY_MD_SHA384; break;
case 512: algo = GCRY_MD_SHA512; break;
default: algo = 0; break;
}
if (!algo)
die ("no digest algorithm found for hmac type `%s'\n", algo_string);
if (!key_string)
die ("option --key is required in this mode\n");
key_buffer = hex2buffer (key_string, &key_buflen);
if (!key_buffer)
die ("invalid value for KEY\n");
run_hmac (algo, key_buffer, key_buflen, data, datalen);
gcry_free (key_buffer);
}
else if (!strcmp (mode_string, "rsa-derive"))
{
if (!data)
die ("no data available (do not use --chunk)\n");
run_rsa_derive (data, datalen);
}
else if (!strcmp (mode_string, "rsa-keygen"))
{
data = read_file (input, 0, &datalen);
if (!data)
die ("no data available (do not use --chunk)\n");
run_rsa_keygen (data, datalen, 0);
}
else if (!strcmp (mode_string, "rsa-keygen-kat"))
{
data = read_file (input, 0, &datalen);
if (!data)
die ("no data available (do not use --chunk)\n");
run_rsa_keygen (data, datalen, 1);
}
else if (!strcmp (mode_string, "rsa-gen"))
{
int keysize;
if (!binary_output)
base64_output = 1;
keysize = keysize_string? atoi (keysize_string) : 0;
if (keysize < 128 || keysize > 16384)
die ("invalid keysize specified; needs to be 128 .. 16384\n");
run_rsa_gen (keysize, 65537);
}
else if (!strcmp (mode_string, "rsa-sign"))
{
int algo;
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!algo_string)
die ("option --algo is required in this mode\n");
algo = gcry_md_map_name (algo_string);
if (!algo)
die ("digest algorithm `%s' is not supported\n", algo_string);
if (!data)
die ("no data available (do not use --chunk)\n");
run_rsa_sign (data, datalen, algo, use_pkcs1, use_pss, key_string);
}
else if (!strcmp (mode_string, "rsa-verify"))
{
int algo;
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!algo_string)
die ("option --algo is required in this mode\n");
algo = gcry_md_map_name (algo_string);
if (!algo)
die ("digest algorithm `%s' is not supported\n", algo_string);
if (!data)
die ("no data available (do not use --chunk)\n");
if (!signature_string)
die ("option --signature is required in this mode\n");
if (access (signature_string, R_OK))
die ("option --signature needs to specify an existing file\n");
run_rsa_verify (data, datalen, algo, use_pkcs1, use_pss, key_string,
signature_string);
}
else if (!strcmp (mode_string, "dsa-pqg-gen"))
{
int keysize;
keysize = keysize_string? atoi (keysize_string) : 0;
if (keysize < 1024 || keysize > 3072)
die ("invalid keysize specified; needs to be 1024 .. 3072\n");
run_dsa_pqg_gen (keysize, datalen? data:NULL, datalen);
}
else if (!strcmp (mode_string, "dsa-gen"))
{
int keysize;
keysize = keysize_string? atoi (keysize_string) : 0;
if (keysize < 1024 || keysize > 3072)
die ("invalid keysize specified; needs to be 1024 .. 3072\n");
if (!key_string)
die ("option --key is required in this mode\n");
run_dsa_gen (keysize, key_string);
}
else if (!strcmp (mode_string, "dsa-sign"))
{
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!data)
die ("no data available (do not use --chunk)\n");
run_dsa_sign (data, datalen, key_string);
}
else if (!strcmp (mode_string, "dsa-verify"))
{
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!data)
die ("no data available (do not use --chunk)\n");
if (!signature_string)
die ("option --signature is required in this mode\n");
if (access (signature_string, R_OK))
die ("option --signature needs to specify an existing file\n");
run_dsa_verify (data, datalen, key_string, signature_string);
}
else if (!strcmp (mode_string, "ecdsa-gen-key"))
{
if (!curve_string)
die ("option --curve containing name of the specified curve is required in this mode\n");
run_ecdsa_gen_key (curve_string);
}
else if (!strcmp (mode_string, "ecdsa-sign"))
{
int algo;
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!algo_string)
die ("use --algo to specify the digest algorithm\n");
algo = gcry_md_map_name (algo_string);
if (!algo)
die ("digest algorithm `%s' is not supported\n", algo_string);
if (!data)
die ("no data available (do not use --chunk)\n");
run_ecdsa_sign (data, datalen, key_string, algo);
}
else if (!strcmp (mode_string, "ecdsa-verify"))
{
int algo;
if (!key_string)
die ("option --key is required in this mode\n");
if (access (key_string, R_OK))
die ("option --key needs to specify an existing keyfile\n");
if (!algo_string)
die ("use --algo to specify the digest algorithm\n");
algo = gcry_md_map_name (algo_string);
if (!algo)
die ("digest algorithm `%s' is not supported\n", algo_string);
if (!data)
die ("no data available (do not use --chunk)\n");
if (!signature_string)
die ("option --signature is required in this mode\n");
if (access (signature_string, R_OK))
die ("option --signature needs to specify an existing file\n");
run_ecdsa_verify (data, datalen, key_string, algo, signature_string);
}
else
usage (0);
gcry_free (data);
/* Because Libgcrypt does not enforce FIPS mode in all cases we let
the process die if Libgcrypt is not anymore in FIPS mode after
the actual operation. */
if (!no_fips && !gcry_fips_mode_active ())
die ("FIPS mode is not anymore active\n");
if (verbose)
fputs (PGM ": ready\n", stderr);
return 0;
}
diff --git a/tests/fipsrngdrv.c b/tests/fipsrngdrv.c
index d6023c7f..a795934d 100644
--- a/tests/fipsrngdrv.c
+++ b/tests/fipsrngdrv.c
@@ -1,271 +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/>.
+ License along with this program; if not, see <https://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;
}
diff --git a/tests/gchash.c b/tests/gchash.c
index 83dc7b55..ae9ec8fb 100644
--- a/tests/gchash.c
+++ b/tests/gchash.c
@@ -1,123 +1,123 @@
/* gchash.c - Calculate hash values
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# undef _GCRYPT_IN_LIBGCRYPT
# include "gcrypt.h"
#else
# include <gcrypt.h>
#endif
#define PGM "gchash"
#include "t-common.h"
void
init_gcrypt (void)
{
if (!gcry_check_version (GCRYPT_VERSION)) {
fputs ("libgcrypt version mismatch\n", stderr);
exit (2);
}
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_RESUME_SECMEM_WARN);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
}
int
main (int argc, char **argv)
{
gcry_md_hd_t hd;
gcry_error_t err;
int algo;
init_gcrypt();
if (argc < 2 || (argv[1] && !strcmp(argv[1], "--help")))
{
fprintf (stderr, "Usage: %s <digest> <file>...\n", argv[0]);
return 1;
}
algo = gcry_md_map_name (argv[1]);
if (algo == GCRY_MD_NONE)
{
fprintf (stderr, "Unknown algorithm '%s'\n", argv[1]);
return 1;
}
err = gcry_md_open(&hd, algo, 0);
if (err)
{
fprintf (stderr, "LibGCrypt error %s/%s\n",
gcry_strsource (err),
gcry_strerror (err));
exit (1);
}
for (argv += 2; *argv; argv++)
{
FILE *fp;
unsigned char buf[1024];
size_t size;
int i;
unsigned char *h;
if (!strcmp (*argv, "-"))
fp = stdin;
else
fp = fopen (*argv, "r");
if (fp == NULL)
{
perror ("fopen");
return 1;
}
while (!feof (fp))
{
size = fread (buf, 1, sizeof(buf), fp);
gcry_md_write (hd, buf, size);
}
h = gcry_md_read(hd, 0);
for (i = 0; i < gcry_md_get_algo_dlen (algo); i++)
printf("%02x", h[i]);
printf(" %s\n", *argv);
gcry_md_reset(hd);
}
gcry_md_close(hd);
return 0;
}
diff --git a/tests/genhashdata.c b/tests/genhashdata.c
index 138a534b..eac9b0dd 100644
--- a/tests/genhashdata.c
+++ b/tests/genhashdata.c
@@ -1,160 +1,160 @@
/* genhashdata.c - Create data for hash tests
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Results:
$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha1sum;done
92fc51850c7b750e6e774b75f294f6979d4059f0 -
4bddeeb4c08683f02d4944d93dbcb02ebab50134 -
71b923afde1c8c040884c723a2e3335b333e64c6 -
2d99f9b5b86e9c9c937104f4242bd6b8bc0927ef -
a60dabe8d749f798b7ec3a684cc3eab487451482 -
$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha224sum;done
b5672b54d2480a5688a2dc727a1ad4db7a81ef31ce8999e0bbaeffdc -
814ea7159473e6ffc1c64b90026a542e13ac6980f7f3ca3c4582a9b8 -
9ec0e1829455db8650ec7a8b06912196f97a7358bc3a73c79911cd4e -
e578d5d523320876565bbbc892511a485427caee6dd754d57e3e58c2 -
ff0464df248cd298b63765bc4f87f21e25c93c657fdf3656d3c878e5 -
$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha256sum;done
87a9828d3de78d55d252341db2a622908c4e0ceaee9961ecf9768700fc799ec8 -
823bf95f64ef04a4a77579c38760b1d401b56bf3a8e664bdf56ca15afb468a03 -
2d0723878cb2c3d5c59dfad910cdb857f4430a6ba2a7d687938d7a20e63dde47 -
5a2e21b1e79cd866acf53a2a18ca76bd4e02c4b01bf4627354171824c812d95f -
34444808af8e9d995e67f9e155ed94bf55f195a51dc1d8a989e6bcf95511c8a2 -
$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha512sum;done
e01bf8140874bf240e8426cb2bcbc377cbed2e6037334116637149e1cd8cd462 \
96828b71f32b9f002771d4cb51172ce578b73b7939221e4df655ecd08601e655 -
4917ff94514b1757705c289fdc3e7d6ffcce5771b20ae237ebc03d2ec9eb435f \
b7ce9f0e27272be8cced77a5edae1a01a0ad62b0a44169d88bbee45474a17734 -
1e28e8b3c79f2f47da11f3c0b7da4e7981e7d932db6d17d528a31e191922edda \
8fc4bb2df10ea876232db5a1c606bc41886e8b2c570a3e721221f60c8c7dc4ab -
027d3324dd1cf127770ceb53681f4c70937c9bca4e3acd5fd76cb266c7d4527d \
58140290a1822e8d60c4d3ae9725fb923183230d6dfd2d7d73c0d74a4757f34a -
49920704ea9d6ee19f0742d6c868110fa3eda8ac09f026e9ef22cc731af53020 \
de40eedef66cb1afd94c61e285fa9327e01336e804903740a9145ab1f065c2d5 -
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define PGM "genhashdata"
#include "t-common.h"
int
main (int argc, char **argv)
{
int last_argc = -1;
int gigs = 0;
int bytes = 0;
char pattern[1024];
int i, g;
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"
" --gigs N Emit N GiB of test bytes\n"
" --bytes DIFF Stop DIFF bytes earlier or later\n",
stdout);
exit (0);
}
else if (!strcmp (*argv, "--gigs"))
{
argc--; argv++;
if (argc)
{
gigs = atoi (*argv);
argc--; argv++;
}
}
else if (!strcmp (*argv, "--bytes"))
{
argc--; argv++;
if (argc)
{
bytes = atoi (*argv);
argc--; argv++;
}
}
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s'", *argv);
}
if (gigs < 0 || gigs > 1024*1024)
die ("value for --gigs must be in the range 0 to %d", 1024*1024);
if (bytes < -1024 || bytes > 1024)
die ("value for --bytes must be in the range -1024 to 1024");
if (sizeof pattern != 1024)
die ("internal error");
if (argc > 1)
die ("arguments are not expected");
memset (pattern, 'a', sizeof pattern);
for (g=0; g < gigs; g++)
{
if (g + 1 == gigs && bytes < 0)
{
for (i = 0; i < 1024*1023; i++)
if (fwrite (pattern, sizeof pattern, 1, stdout) != 1)
die ("writing to stdout failed: %s", strerror (errno));
for (i = 0; i < 1023; i++)
if (fwrite (pattern, sizeof pattern, 1, stdout) != 1)
die ("writing to stdout failed: %s", strerror (errno));
if (fwrite (pattern, sizeof pattern + bytes, 1, stdout) != 1)
die ("writing to stdout failed: %s", strerror (errno));
}
else
{
for (i = 0; i < 1024*1024; i++)
if (fwrite (pattern, sizeof pattern, 1, stdout) != 1)
die ("writing to stdout failed: %s", strerror (errno));
}
}
if (bytes > 0)
if (fwrite (pattern, bytes, 1, stdout) != 1)
die ("writing to stdout failed: %s", strerror (errno));
if (fflush (stdout))
die ("writing to stdout failed: %s", strerror (errno));
return 0;
}
diff --git a/tests/hashtest.c b/tests/hashtest.c
index 33945949..f382f3bb 100644
--- a/tests/hashtest.c
+++ b/tests/hashtest.c
@@ -1,451 +1,451 @@
/* hashtest.c - Check the hash functions
* Copyright (C) 2013 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/>.
+ * 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 "../src/gcrypt-int.h"
#include "stopwatch.h"
#define PGM "hashtest"
#include "t-common.h"
static int missing_test_vectors;
static struct {
int algo;
int gigs;
int bytes;
const char *hex;
} testvectors[] = {
{ GCRY_MD_SHA1, 256, -64, "92fc51850c7b750e6e774b75f294f6979d4059f0" },
{ GCRY_MD_SHA1, 256, -1, "4bddeeb4c08683f02d4944d93dbcb02ebab50134" },
{ GCRY_MD_SHA1, 256, -0, "71b923afde1c8c040884c723a2e3335b333e64c6" },
{ GCRY_MD_SHA1, 256, 1, "2d99f9b5b86e9c9c937104f4242bd6b8bc0927ef" },
{ GCRY_MD_SHA1, 256, 64, "a60dabe8d749f798b7ec3a684cc3eab487451482" },
{ GCRY_MD_SHA224, 256, -64,
"b5672b54d2480a5688a2dc727a1ad4db7a81ef31ce8999e0bbaeffdc" },
{ GCRY_MD_SHA224, 256, -1,
"814ea7159473e6ffc1c64b90026a542e13ac6980f7f3ca3c4582a9b8" },
{ GCRY_MD_SHA224, 256, 0,
"9ec0e1829455db8650ec7a8b06912196f97a7358bc3a73c79911cd4e" },
{ GCRY_MD_SHA224, 256, 1,
"e578d5d523320876565bbbc892511a485427caee6dd754d57e3e58c2" },
{ GCRY_MD_SHA224, 256, 64,
"ff0464df248cd298b63765bc4f87f21e25c93c657fdf3656d3c878e5" },
{ GCRY_MD_SHA256, 256, -64,
"87a9828d3de78d55d252341db2a622908c4e0ceaee9961ecf9768700fc799ec8" },
{ GCRY_MD_SHA256, 256, -1,
"823bf95f64ef04a4a77579c38760b1d401b56bf3a8e664bdf56ca15afb468a03" },
{ GCRY_MD_SHA256, 256, 0,
"2d0723878cb2c3d5c59dfad910cdb857f4430a6ba2a7d687938d7a20e63dde47" },
{ GCRY_MD_SHA256, 256, 1,
"5a2e21b1e79cd866acf53a2a18ca76bd4e02c4b01bf4627354171824c812d95f" },
{ GCRY_MD_SHA256, 256, 64,
"34444808af8e9d995e67f9e155ed94bf55f195a51dc1d8a989e6bcf95511c8a2" },
{ GCRY_MD_SHA512, 256, -64,
"e01bf8140874bf240e8426cb2bcbc377cbed2e6037334116637149e1cd8cd462"
"96828b71f32b9f002771d4cb51172ce578b73b7939221e4df655ecd08601e655" },
{ GCRY_MD_SHA512, 256, -1,
"4917ff94514b1757705c289fdc3e7d6ffcce5771b20ae237ebc03d2ec9eb435f"
"b7ce9f0e27272be8cced77a5edae1a01a0ad62b0a44169d88bbee45474a17734" },
{ GCRY_MD_SHA512, 256, 0,
"1e28e8b3c79f2f47da11f3c0b7da4e7981e7d932db6d17d528a31e191922edda"
"8fc4bb2df10ea876232db5a1c606bc41886e8b2c570a3e721221f60c8c7dc4ab" },
{ GCRY_MD_SHA512, 256, 1,
"027d3324dd1cf127770ceb53681f4c70937c9bca4e3acd5fd76cb266c7d4527d"
"58140290a1822e8d60c4d3ae9725fb923183230d6dfd2d7d73c0d74a4757f34a" },
{ GCRY_MD_SHA512, 256, 64,
"49920704ea9d6ee19f0742d6c868110fa3eda8ac09f026e9ef22cc731af53020"
"de40eedef66cb1afd94c61e285fa9327e01336e804903740a9145ab1f065c2d5" },
{ GCRY_MD_SHA3_512, 256, -64,
"c6e082b3db996dbe5f2c5709818a7f325ef4febd883d7e9c545c06bfa7225198"
"1ecf40103788913cd5a5bdf13246b952ded6651043684b24197eb23544882a97" },
{ GCRY_MD_SHA3_512, 256, -1,
"d7bf28e8216bf7d3d0d3969e34078e94b98598e17b6f21f256379389e4eba8ee"
"74eb288774797263fec00bdfd357d132cea9e408be36b982f5a60ab56ad01613" },
{ GCRY_MD_SHA3_512, 256, +0,
"c1270852ba7b1e1a3eaa777969b8a65be28c3894537c61eb8cd22b1df6af703d"
"b59939f6adadeb64317faece8167d4817e73daf73e28a5ccd26bebee0a35c322" },
{ GCRY_MD_SHA3_512, 256, +1,
"8bdfeb3a1a9a1cdcef21172cbc5bb3b87c0d8f7111df0aaf7f1bc03ad4775bd6"
"a03e0a875c4e7d02d2230c213562c6a57be28d92eaf6e4bea4bc24690454c8ef" },
{ GCRY_MD_SHA3_512, 256, +64,
"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 }
};
static void
showhex (const void *buffer, size_t buflen, const char *format, ...)
{
va_list arg_ptr;
const unsigned char *s;
fprintf (stderr, "%s: ", PGM);
va_start (arg_ptr, format);
vfprintf (stderr, format, arg_ptr);
va_end (arg_ptr);
for (s=buffer; buflen; buflen--, s++)
fprintf (stderr, "%02x", *s);
putc ('\n', stderr);
}
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
run_selftest (int algo)
{
gpg_error_t err;
size_t n;
n = 1;
err = gcry_md_algo_info (algo, GCRYCTL_SELFTEST, NULL, &n);
if (err && gpg_err_code (err) != GPG_ERR_NOT_IMPLEMENTED)
fail ("extended selftest for %s (%d) failed: %s",
gcry_md_algo_name (algo), algo, gpg_strerror (err));
else if (err && verbose)
info ("extended selftest for %s (%d) not implemented",
gcry_md_algo_name (algo), algo);
else if (verbose)
info ("extended selftest for %s (%d) passed",
gcry_md_algo_name (algo), algo);
}
/* Compare DIGEST of length DIGESTLEN generated using ALGO and GIGS
plus BYTES with the test vector and print an error message if the
don't match. Return 0 on match. */
static int
cmp_digest (const unsigned char *digest, size_t digestlen,
int algo, int gigs, int bytes)
{
int idx;
unsigned char *tv_digest;
size_t tv_digestlen = 0;
for (idx=0; testvectors[idx].algo; idx++)
{
if (testvectors[idx].algo == algo
&& testvectors[idx].gigs == gigs
&& testvectors[idx].bytes == bytes)
break;
}
if (!testvectors[idx].algo)
{
info ("%d GiB %+3d %-10s warning: %s",
gigs, bytes, gcry_md_algo_name (algo), "no test vector");
missing_test_vectors++;
return 1;
}
tv_digest = hex2buffer (testvectors[idx].hex, &tv_digestlen);
if (tv_digestlen != digestlen) /* Ooops. */
{
fail ("%d GiB %+3d %-10s error: %s",
gigs, bytes, gcry_md_algo_name (algo), "digest length mismatch");
xfree (tv_digest);
return 1;
}
if (memcmp (tv_digest, digest, tv_digestlen))
{
fail ("%d GiB %+3d %-10s error: %s",
gigs, bytes, gcry_md_algo_name (algo), "mismatch");
xfree (tv_digest);
return 1;
}
xfree (tv_digest);
return 0;
}
static void
run_longtest (int algo, int gigs)
{
gpg_error_t err;
gcry_md_hd_t hd;
gcry_md_hd_t hd_pre = NULL;
gcry_md_hd_t hd_pre2 = NULL;
gcry_md_hd_t hd_post = NULL;
gcry_md_hd_t hd_post2 = NULL;
char pattern[1024];
int i, g;
const unsigned char *digest;
unsigned int digestlen;
memset (pattern, 'a', sizeof pattern);
err = gcry_md_open (&hd, algo, 0);
if (err)
{
fail ("gcry_md_open failed for %s (%d): %s",
gcry_md_algo_name (algo), algo, gpg_strerror (err));
return;
}
digestlen = gcry_md_get_algo_dlen (algo);
for (g=0; g < gigs; g++)
{
if (g == gigs - 1)
{
for (i = 0; i < 1024*1023; i++)
gcry_md_write (hd, pattern, sizeof pattern);
for (i = 0; i < 1023; i++)
gcry_md_write (hd, pattern, sizeof pattern);
err = gcry_md_copy (&hd_pre, hd);
if (!err)
err = gcry_md_copy (&hd_pre2, hd);
if (err)
die ("gcry_md_copy failed for %s (%d): %s",
gcry_md_algo_name (algo), algo, gpg_strerror (err));
gcry_md_write (hd, pattern, sizeof pattern);
}
else
{
for (i = 0; i < 1024*1024; i++)
gcry_md_write (hd, pattern, sizeof pattern);
}
if (g && !(g % 16))
show_note ("%d GiB so far hashed with %s", g, gcry_md_algo_name (algo));
}
if (g >= 16)
show_note ("%d GiB hashed with %s", g, gcry_md_algo_name (algo));
err = gcry_md_copy (&hd_post, hd);
if (err)
die ("gcry_md_copy failed for %s (%d): %s",
gcry_md_algo_name (algo), algo, gpg_strerror (err));
err = gcry_md_copy (&hd_post2, hd);
if (err)
die ("gcry_md_copy failed for %s (%d): %s",
gcry_md_algo_name (algo), algo, gpg_strerror (err));
gcry_md_write (hd_pre2, pattern, sizeof pattern - 64);
gcry_md_write (hd_pre, pattern, sizeof pattern - 1);
gcry_md_write (hd_post, pattern, 1);
gcry_md_write (hd_post2, pattern, 64);
digest = gcry_md_read (hd_pre2, algo);
if (cmp_digest (digest, digestlen, algo, gigs, -64) || verbose)
showhex (digest, digestlen, "%d GiB %+3d %-10s ",
gigs, -64, gcry_md_algo_name (algo));
digest = gcry_md_read (hd_pre, algo);
if (cmp_digest (digest, digestlen, algo, gigs, -1) || verbose)
showhex (digest, digestlen, "%d GiB %+3d %-10s ",
gigs, -1, gcry_md_algo_name (algo));
digest = gcry_md_read (hd, algo);
if (cmp_digest (digest, digestlen, algo, gigs, 0) || verbose)
showhex (digest, digestlen, "%d GiB %+3d %-10s ",
gigs, 0, gcry_md_algo_name (algo));
digest = gcry_md_read (hd_post, algo);
if (cmp_digest (digest, digestlen, algo, gigs, 1) || verbose)
showhex (digest, digestlen, "%d GiB %+3d %-10s ",
gigs, 1, gcry_md_algo_name (algo));
digest = gcry_md_read (hd_post2, algo);
if (cmp_digest (digest, digestlen, algo, gigs, 64) || verbose)
showhex (digest, digestlen, "%d GiB %+3d %-10s ",
gigs, 64, gcry_md_algo_name (algo));
gcry_md_close (hd);
gcry_md_close (hd_pre);
gcry_md_close (hd_pre2);
gcry_md_close (hd_post);
gcry_md_close (hd_post2);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int gigs = 0;
int algo = 0;
int idx;
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] [algos]\n"
"Options:\n"
" --verbose print timings etc.\n"
" --debug flyswatter\n"
" --gigs N Run a test on N GiB\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, "--gigs"))
{
argc--; argv++;
if (argc)
{
gigs = atoi (*argv);
argc--; argv++;
}
}
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s'", *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);
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);
/* A quick check that all given algorithms are valid. */
for (idx=0; idx < argc; idx++)
{
algo = gcry_md_map_name (argv[idx]);
if (!algo)
fail ("invalid algorithm '%s'", argv[idx]);
}
if (error_count)
exit (1);
/* Start checking. */
start_timer ();
if (!argc)
{
for (algo=1; algo < 400; algo++)
if (!gcry_md_test_algo (algo))
{
if (!gigs)
run_selftest (algo);
else
run_longtest (algo, gigs);
}
}
else
{
for (idx=0; idx < argc; idx++)
{
algo = gcry_md_map_name (argv[idx]);
if (!algo)
die ("invalid algorithm '%s'", argv[idx]);
if (!gigs)
run_selftest (algo);
else
run_longtest (algo, gigs);
}
}
stop_timer ();
if (missing_test_vectors)
fail ("Some test vectors are missing");
if (verbose)
info ("All tests completed in %s. Errors: %d\n",
elapsed_time (1), error_count);
return !!error_count;
}
diff --git a/tests/keygen.c b/tests/keygen.c
index 6b6a60a4..192e7b11 100644
--- a/tests/keygen.c
+++ b/tests/keygen.c
@@ -1,787 +1,787 @@
/* keygen.c - key generation regression tests
* Copyright (C) 2003, 2005, 2012 Free Software Foundation, Inc.
* Copyright (C) 2013, 2015 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/>.
+ * License along with this program; if not, see <https://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 "../src/gcrypt-int.h"
#define PGM "keygen"
#include "t-common.h"
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);
}
static void
show_mpi (const char *prefix, gcry_mpi_t a)
{
char *buf;
void *bufaddr = &buf;
gcry_error_t rc;
fprintf (stderr, "%s: ", PGM);
if (prefix)
fputs (prefix, stderr);
rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
if (rc)
fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (rc));
else
{
fprintf (stderr, "%s\n", buf);
gcry_free (buf);
}
}
static void
check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e)
{
gcry_sexp_t skey, pkey, list;
pkey = gcry_sexp_find_token (key, "public-key", 0);
if (!pkey)
fail ("public part missing in return value\n");
else
{
gcry_mpi_t e = NULL;
list = gcry_sexp_find_token (pkey, "e", 0);
if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) )
fail ("public exponent not found\n");
else if (!expected_e)
{
if (verbose)
show_mpi ("public exponent: ", e);
}
else if ( gcry_mpi_cmp_ui (e, expected_e))
{
show_mpi ("public exponent: ", e);
fail ("public exponent is not %lu\n", expected_e);
}
gcry_sexp_release (list);
gcry_mpi_release (e);
gcry_sexp_release (pkey);
}
skey = gcry_sexp_find_token (key, "private-key", 0);
if (!skey)
fail ("private part missing in return value\n");
else
{
int rc = gcry_pk_testkey (skey);
if (rc)
fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
gcry_sexp_release (skey);
}
}
static void
check_rsa_keys (void)
{
gcry_sexp_t keyparm, key;
int rc;
if (verbose)
info ("creating 2048 bit RSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (rsa\n"
" (nbits 4:2048)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating RSA key: %s\n", gpg_strerror (rc));
if (verbose)
info ("creating 1024 bit RSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (rsa\n"
" (nbits 4:1024)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
gcry_sexp_release (key);
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
fail ("error generating RSA key: %s\n", gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating 1024 bit RSA key must not work!");
if (!rc)
{
if (verbose > 1)
show_sexp ("1024 bit RSA key:\n", key);
check_generated_rsa_key (key, 65537);
}
gcry_sexp_release (key);
if (verbose)
info ("creating 2048 bit RSA key with e=65539\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (rsa\n"
" (nbits 4:2048)\n"
" (rsa-use-e 5:65539)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
fail ("error generating RSA key: %s\n", gpg_strerror (rc));
if (!rc)
check_generated_rsa_key (key, 65539);
gcry_sexp_release (key);
if (verbose)
info ("creating 512 bit RSA key with e=257\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (rsa\n"
" (nbits 3:512)\n"
" (rsa-use-e 3:257)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
fail ("error generating RSA key: %s\n", gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating 512 bit RSA key must not work!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
if (!rc)
check_generated_rsa_key (key, 257);
gcry_sexp_release (key);
if (verbose)
info ("creating 512 bit RSA key with default e\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (rsa\n"
" (nbits 3:512)\n"
" (rsa-use-e 1:0)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
fail ("error generating RSA key: %s\n", gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating 512 bit RSA key must not work!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
if (!rc)
check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
gcry_sexp_release (key);
}
static void
check_elg_keys (void)
{
gcry_sexp_t keyparm, key;
int rc;
if (verbose)
info ("creating 1024 bit Elgamal key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (elg\n"
" (nbits 4:1024)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
if (verbose > 1)
show_sexp ("1024 bit Elgamal key:\n", key);
gcry_sexp_release (key);
}
static void
check_dsa_keys (void)
{
gcry_sexp_t keyparm, key;
int rc;
int i;
/* Check that DSA generation works and that it can grok the qbits
argument. */
if (verbose)
info ("creating 5 1024 bit DSA keys\n");
for (i=0; i < 5; i++)
{
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (dsa\n"
" (nbits 4:1024)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
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!");
if (!i && verbose > 1)
show_sexp ("1024 bit DSA key:\n", key);
gcry_sexp_release (key);
}
if (verbose)
info ("creating 1536 bit DSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (dsa\n"
" (nbits 4:1536)\n"
" (qbits 3:224)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
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!");
if (verbose > 1)
show_sexp ("1536 bit DSA key:\n", key);
gcry_sexp_release (key);
if (verbose)
info ("creating 3072 bit DSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (dsa\n"
" (nbits 4:3072)\n"
" (qbits 3:256)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating DSA key: %s\n", gpg_strerror (rc));
if (verbose > 1)
show_sexp ("3072 bit DSA key:\n", key);
gcry_sexp_release (key);
if (verbose)
info ("creating 2048/256 bit DSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (dsa\n"
" (nbits 4:2048)\n"
" (qbits 3:256)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating DSA key: %s\n", gpg_strerror (rc));
if (verbose > 1)
show_sexp ("2048 bit DSA key:\n", key);
gcry_sexp_release (key);
if (verbose)
info ("creating 2048/224 bit DSA key\n");
rc = gcry_sexp_new (&keyparm,
"(genkey\n"
" (dsa\n"
" (nbits 4:2048)\n"
" (qbits 3:224)\n"
" ))", 0, 1);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating DSA key: %s\n", gpg_strerror (rc));
if (verbose > 1)
show_sexp ("2048 bit DSA key:\n", key);
gcry_sexp_release (key);
}
static void
check_generated_ecc_key (gcry_sexp_t key)
{
gcry_sexp_t skey, pkey;
pkey = gcry_sexp_find_token (key, "public-key", 0);
if (!pkey)
fail ("public part missing in return value\n");
else
{
/* Fixme: Check more stuff. */
gcry_sexp_release (pkey);
}
skey = gcry_sexp_find_token (key, "private-key", 0);
if (!skey)
fail ("private part missing in return value\n");
else
{
int rc = gcry_pk_testkey (skey);
if (rc)
fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
gcry_sexp_release (skey);
}
/* Finally check that gcry_pk_testkey also works on the entire
S-expression. */
{
int rc = gcry_pk_testkey (key);
if (rc)
fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
}
}
static void
check_ecc_keys (void)
{
const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
"Ed25519", NULL };
int testno;
gcry_sexp_t keyparm, key;
int rc;
for (testno=0; curves[testno]; testno++)
{
if (verbose)
info ("creating ECC key using curve %s\n", curves[testno]);
if (!strcmp (curves[testno], "Ed25519"))
{
/* Ed25519 isn't allowed in fips mode */
if (in_fips_mode)
continue;
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve %s)(flags param eddsa)))",
curves[testno]);
}
else
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve %s)(flags param)))",
curves[testno]);
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating ECC key using curve %s: %s\n",
curves[testno], gpg_strerror (rc));
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
gcry_sexp_release (key);
}
if (verbose)
info ("creating ECC key using curve Ed25519 for ECDSA\n");
rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating Ed25519 key must not work!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
if (!rc)
{
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
}
gcry_sexp_release (key);
if (verbose)
info ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve Ed25519)(flags nocomp)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
die ("error generating ECC key using curve Ed25519 for ECDSA"
" (nocomp): %s\n",
gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating Ed25519 key must not work in FIPS mode!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
gcry_sexp_release (key);
if (verbose)
info ("creating ECC key using curve NIST P-384 for ECDSA\n");
/* Must be specified as nistp384 (one word), because ecc_generate
* uses _gcry_sexp_nth_string which takes the first word of the name
* and thus libgcrypt can't find it later in its curves table. */
rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating ECC key using curve NIST P-384 for ECDSA: %s\n",
gpg_strerror (rc));
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
gcry_sexp_release (key);
if (verbose)
info ("creating ECC key using curve NIST P-384 for ECDSA (nocomp)\n");
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve nistp384)(flags nocomp)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc)
die ("error generating ECC key using curve NIST P-384 for ECDSA"
" (nocomp): %s\n",
gpg_strerror (rc));
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
gcry_sexp_release (key);
if (verbose)
info ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n");
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve Ed25519)(flags transient-key)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
die ("error generating ECC key using curve Ed25519 for ECDSA"
" (transient-key): %s\n",
gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating Ed25519 key must not work in FIPS mode!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
if (!rc)
{
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
}
gcry_sexp_release (key);
if (verbose)
info ("creating ECC key using curve Ed25519 for ECDSA "
"(transient-key no-keytest)\n");
rc = gcry_sexp_build (&keyparm, NULL,
"(genkey(ecc(curve Ed25519)"
"(flags transient-key no-keytest)))");
if (rc)
die ("error creating S-expression: %s\n", gpg_strerror (rc));
rc = gcry_pk_genkey (&key, keyparm);
gcry_sexp_release (keyparm);
if (rc && !in_fips_mode)
die ("error generating ECC key using curve Ed25519 for ECDSA"
" (transient-key no-keytest): %s\n",
gpg_strerror (rc));
else if (!rc && in_fips_mode)
fail ("generating Ed25519 key must not work in FIPS mode!");
if (verbose && rc && in_fips_mode)
info ("... correctly rejected key creation in FIPS mode (%s)\n",
gpg_strerror (rc));
if (!rc)
{
if (verbose > 1)
show_sexp ("ECC key:\n", key);
check_generated_ecc_key (key);
}
gcry_sexp_release (key);
}
static void
check_nonce (void)
{
char a[32], b[32];
int i,j;
int oops=0;
if (verbose)
info ("checking gcry_create_nonce\n");
gcry_create_nonce (a, sizeof a);
for (i=0; i < 10; i++)
{
gcry_create_nonce (b, sizeof b);
if (!memcmp (a, b, sizeof a))
die ("identical nonce found\n");
}
for (i=0; i < 10; i++)
{
gcry_create_nonce (a, sizeof a);
if (!memcmp (a, b, sizeof a))
die ("identical nonce found\n");
}
again:
for (i=1,j=0; i < sizeof a; i++)
if (a[0] == a[i])
j++;
if (j+1 == sizeof (a))
{
if (oops)
die ("impossible nonce found\n");
oops++;
gcry_create_nonce (a, sizeof a);
goto again;
}
}
static void
progress_cb (void *cb_data, const char *what, int printchar,
int current, int total)
{
(void)cb_data;
(void)what;
(void)current;
(void)total;
if (printchar == '\n')
fputs ( "<LF>", stdout);
else
putchar (printchar);
fflush (stdout);
}
static void
usage (int mode)
{
fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
"Options:\n"
" --verbose be verbose\n"
" --debug flyswatter\n"
" --fips run in FIPS mode\n"
" --no-quick To not use the quick RNG hack\n"
" --progress print progress indicators\n",
mode? stderr : stdout);
if (mode)
exit (1);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int opt_fips = 0;
int with_progress = 0;
int no_quick = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
usage (0);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--; argv++;
}
else if (!strcmp (*argv, "--fips"))
{
argc--; argv++;
opt_fips = 1;
}
else if (!strcmp (*argv, "--progress"))
{
argc--; argv++;
with_progress = 1;
}
else if (!strcmp (*argv, "--no-quick"))
{
argc--; argv++;
no_quick = 1;
}
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s'", *argv);
else
break;
}
xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
if (opt_fips)
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_INITIALIZATION_FINISHED, 0);
if (debug)
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);
if (with_progress)
gcry_set_progress_handler (progress_cb, NULL);
if ( gcry_fips_mode_active () )
in_fips_mode = 1;
if (opt_fips && !in_fips_mode)
die ("failed to switch into FIPS mode\n");
if (!argc)
{
check_rsa_keys ();
check_elg_keys ();
check_dsa_keys ();
check_ecc_keys ();
check_nonce ();
}
else
{
for (; argc; argc--, argv++)
if (!strcmp (*argv, "rsa"))
check_rsa_keys ();
else if (!strcmp (*argv, "elg"))
check_elg_keys ();
else if (!strcmp (*argv, "dsa"))
check_dsa_keys ();
else if (!strcmp (*argv, "ecc"))
check_ecc_keys ();
else if (!strcmp (*argv, "nonce"))
check_nonce ();
else
usage (1);
}
return error_count? 1:0;
}
diff --git a/tests/mpitests.c b/tests/mpitests.c
index 9b4a66c2..86ef6099 100644
--- a/tests/mpitests.c
+++ b/tests/mpitests.c
@@ -1,610 +1,610 @@
/* mpitests.c - basic mpi tests
* Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
#else
# include <gcrypt.h>
#endif
#define PGM "mpitests"
#include "t-common.h"
/* Set up some test patterns */
/* 48 bytes with value 1: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */
unsigned char ones[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
};
/* 48 bytes with value 2: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */
unsigned char twos[] = {
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
};
/* 48 bytes with value 3: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */
unsigned char threes[] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
};
/* 48 bytes with value 0x80: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */
unsigned char eighties[] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
};
/* 48 bytes with value 0xff: this results in 8 limbs for 64bit limbs, 16limb for 32 bit limbs */
unsigned char manyff[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static int
test_const_and_immutable (void)
{
gcry_mpi_t one, second_one;
one = gcry_mpi_set_ui (NULL, 1);
if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE)
|| gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST))
die ("immutable or const flag initially set\n");
second_one = gcry_mpi_copy (one);
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE))
die ("immutable flag set after copy\n");
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST))
die ("const flag set after copy\n");
gcry_mpi_release (second_one);
gcry_mpi_set_flag (one, GCRYMPI_FLAG_IMMUTABLE);
if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE))
die ("failed to set immutable flag\n");
if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST))
die ("const flag unexpectly set\n");
second_one = gcry_mpi_copy (one);
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE))
die ("immutable flag not cleared after copy\n");
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST))
die ("const flag unexpectly set after copy\n");
gcry_mpi_release (second_one);
gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE);
if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE))
die ("failed to clear immutable flag\n");
if (gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST))
die ("const flag unexpectly set\n");
gcry_mpi_set_flag (one, GCRYMPI_FLAG_CONST);
if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST))
die ("failed to set const flag\n");
if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE))
die ("failed to set immutable flag with const flag\n");
second_one = gcry_mpi_copy (one);
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE))
die ("immutable flag not cleared after copy\n");
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST))
die ("const flag not cleared after copy\n");
gcry_mpi_release (second_one);
gcry_mpi_clear_flag (one, GCRYMPI_FLAG_IMMUTABLE);
if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_IMMUTABLE))
die ("clearing immutable flag not ignored for a constant MPI\n");
if (!gcry_mpi_get_flag (one, GCRYMPI_FLAG_CONST))
die ("const flag unexpectly cleared\n");
second_one = gcry_mpi_set (NULL, GCRYMPI_CONST_ONE);
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE))
die ("immutable flag not cleared by mpi_set (NULL,x)\n");
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST))
die ("const flag not cleared by mpi_set (NULL,x)\n");
gcry_mpi_release (second_one);
second_one = gcry_mpi_set_ui (NULL, 42);
gcry_mpi_set (second_one, GCRYMPI_CONST_ONE);
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_IMMUTABLE))
die ("immutable flag not cleared after mpi_set (a,x)\n");
if (gcry_mpi_get_flag (second_one, GCRYMPI_FLAG_CONST))
die ("const flag not cleared mpi_set (a,x)\n");
gcry_mpi_release (second_one);
/* Due to the the constant flag the release below should be a NOP
and will leak memory. */
gcry_mpi_release (one);
return 1;
}
static void
test_opaque (void)
{
gcry_mpi_t a;
char *p;
unsigned int nbits;
p = gcry_xstrdup ("This is a test buffer");
a = gcry_mpi_set_opaque (NULL, p, 21*8+1); /* (a non byte aligned length) */
if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
die ("opaque flag not set\n");
p = gcry_mpi_get_opaque (a, &nbits);
if (!p)
die ("gcry_mpi_get_opaque returned NULL\n");
if (nbits != 21*8+1)
die ("gcry_mpi_get_opaque returned a changed bit size\n");
if (strcmp (p, "This is a test buffer"))
die ("gcry_mpi_get_opaque returned a changed buffer\n");
if (debug)
gcry_log_debugmpi ("mpi", a);
gcry_mpi_release (a);
p = gcry_xstrdup ("This is a test buffer");
a = gcry_mpi_set_opaque_copy (NULL, p, 21*8+1);
gcry_free (p);
if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
die ("opaque flag not set\n");
p = gcry_mpi_get_opaque (a, &nbits);
if (!p)
die ("gcry_mpi_get_opaque returned NULL\n");
if (nbits != 21*8+1)
die ("gcry_mpi_get_opaque returned a changed bit size\n");
if (strcmp (p, "This is a test buffer"))
die ("gcry_mpi_get_opaque returned a changed buffer\n");
if (debug)
gcry_log_debugmpi ("mpi", a);
gcry_mpi_release (a);
}
static void
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);
/* We use a short buffer but a give a too large length to simulate a
* programming error. In case this test fails (i.e. die() is
* called) the scan function may have access data outside of BUFFER
* which may result in a segv but we ignore that to avoid actually
* allocating such a long buffer. */
err = gcry_mpi_scan (&a, GCRYMPI_FMT_USG, buffer, 16*1024*1024 +1, NULL);
if (gpg_err_code (err) != GPG_ERR_INV_OBJ)
die ("gcry_mpi_scan does not detect its generic input limit\n");
/* Now test the PGP limit. The scan code check the two length bytes
* from the buffer and thus it is sufficient to fake them. */
buffer[0] = (16385 >> 8);
buffer[1] = (16385 & 0xff);
err = gcry_mpi_scan (&a, GCRYMPI_FMT_PGP, buffer, sizeof buffer, NULL);
if (gpg_err_code (err) != GPG_ERR_INV_OBJ)
die ("gcry_mpi_scan does not detect the PGP input limit\n");
buffer[0] = (16384 >> 8);
buffer[1] = (16384 & 0xff);
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);
}
static void
test_cmp (void)
{
gpg_error_t rc;
gcry_mpi_t zero, zero2;
gcry_mpi_t one;
gcry_mpi_t two;
gcry_mpi_t all_ones;
gcry_mpi_t opa1, opa2;
gcry_mpi_t opa1s, opa2s;
gcry_mpi_t opa0, opa02;
zero = gcry_mpi_new (0);
zero2= gcry_mpi_set_ui (NULL, 0);
one = gcry_mpi_set_ui (NULL, 1);
two = gcry_mpi_set_ui (NULL, 2);
rc = gcry_mpi_scan (&all_ones, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL);
if (rc)
die ("scanning number failed at line %d", __LINE__);
opa0 = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("a"), 0);
opa02 = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("b"), 0);
opa1 = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("aaaaaaaaaaaaaaaa"), 16*8);
opa1s = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("a"), 1*8);
opa2 = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("bbbbbbbbbbbbbbbb"), 16*8);
opa2s = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("b"), 1*8);
/* Single limb test with cmp_ui */
if (gcry_mpi_cmp_ui (zero, 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (!(gcry_mpi_cmp_ui (zero, 1) < 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (!(gcry_mpi_cmp_ui (zero, (-1)) < 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (gcry_mpi_cmp_ui (two, 2))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (!(gcry_mpi_cmp_ui (two, 3) < 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (!(gcry_mpi_cmp_ui (two, 1) > 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
/* Multi limb tests with cmp_ui. */
if (!(gcry_mpi_cmp_ui (all_ones, 0) > 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
if (!(gcry_mpi_cmp_ui (all_ones, (-1)) > 0))
fail ("mpi_cmp_ui failed at line %d", __LINE__);
/* Single limb test with cmp */
if (gcry_mpi_cmp (zero, zero2))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (zero, one) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (one, zero) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
gcry_mpi_neg (one, one);
if (!(gcry_mpi_cmp (zero, one) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (one, zero) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (one, two) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
gcry_mpi_neg (one, one);
if (!(gcry_mpi_cmp (one, two) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (two, one) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (one, all_ones) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
/* Tests with opaque values. */
if (!(gcry_mpi_cmp (opa1, one) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (one, opa1) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa0, opa02) == 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa1s, opa1) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa2, opa1s) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa1, opa2) < 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa2, opa1) > 0))
fail ("mpi_cmp failed at line %d", __LINE__);
if (!(gcry_mpi_cmp (opa1, opa1) == 0))
fail ("mpi_cmp failed at line %d", __LINE__);
gcry_mpi_release(opa2s);
gcry_mpi_release(opa2);
gcry_mpi_release(opa1s);
gcry_mpi_release(opa1);
gcry_mpi_release(opa02);
gcry_mpi_release(opa0);
gcry_mpi_release(all_ones);
gcry_mpi_release(two);
gcry_mpi_release(one);
gcry_mpi_release(zero2);
gcry_mpi_release(zero);
}
static int
test_add (void)
{
gcry_mpi_t one;
gcry_mpi_t two;
gcry_mpi_t ff;
gcry_mpi_t result;
unsigned char* pc;
gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL);
gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL);
gcry_mpi_scan(&ff, GCRYMPI_FMT_USG, manyff, sizeof(manyff), NULL);
result = gcry_mpi_new(0);
gcry_mpi_add(result, one, two);
gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
if (debug)
gcry_log_debug ("Result of one plus two:\n%s\n", pc);
gcry_free(pc);
gcry_mpi_add(result, ff, one);
gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
if (debug)
gcry_log_debug ("Result of ff plus one:\n%s\n", pc);
gcry_free(pc);
gcry_mpi_release(one);
gcry_mpi_release(two);
gcry_mpi_release(ff);
gcry_mpi_release(result);
return 1;
}
static int
test_sub (void)
{
gcry_mpi_t one;
gcry_mpi_t two;
gcry_mpi_t result;
unsigned 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);
if (debug)
gcry_log_debug ("Result of two minus one:\n%s\n", pc);
gcry_free(pc);
gcry_mpi_release(one);
gcry_mpi_release(two);
gcry_mpi_release(result);
return 1;
}
static int
test_mul (void)
{
gcry_mpi_t two;
gcry_mpi_t three;
gcry_mpi_t result;
unsigned 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);
if (debug)
gcry_log_debug ("Result of two mul three:\n%s\n", pc);
gcry_free(pc);
gcry_mpi_release(two);
gcry_mpi_release(three);
gcry_mpi_release(result);
return 1;
}
/* What we test here is that we don't overwrite our args and that
using the same mpi for several args works. */
static int
test_powm (void)
{
int b_int = 17;
int e_int = 3;
int m_int = 19;
gcry_mpi_t base = gcry_mpi_set_ui (NULL, b_int);
gcry_mpi_t exp = gcry_mpi_set_ui (NULL, e_int);
gcry_mpi_t mod = gcry_mpi_set_ui (NULL, m_int);
gcry_mpi_t res = gcry_mpi_new (0);
gcry_mpi_powm (res, base, exp, mod);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (exp, e_int))
die ("test_powm_ui failed for exp at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (mod, m_int))
die ("test_powm failed for mod at %d\n", __LINE__);
/* Check using base for the result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui (exp, e_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (base, base, exp, mod);
if (gcry_mpi_cmp (res, base))
die ("test_powm failed at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (exp, e_int))
die ("test_powm_ui failed for exp at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (mod, m_int))
die ("test_powm failed for mod at %d\n", __LINE__);
/* Check using exp for the result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui (exp, e_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (exp, base, exp, mod);
if (gcry_mpi_cmp (res, exp))
die ("test_powm failed at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (mod, m_int))
die ("test_powm failed for mod at %d\n", __LINE__);
/* Check using mod for the result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui (exp, e_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (mod, base, exp, mod);
if (gcry_mpi_cmp (res, mod))
die ("test_powm failed at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (exp, e_int))
die ("test_powm_ui failed for exp at %d\n", __LINE__);
/* Now check base ^ base mod mod. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (res, base, base, mod);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (mod, m_int))
die ("test_powm failed for mod at %d\n", __LINE__);
/* Check base ^ base mod mod with base as result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (base, base, base, mod);
if (gcry_mpi_cmp (res, base))
die ("test_powm failed at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (mod, m_int))
die ("test_powm failed for mod at %d\n", __LINE__);
/* Check base ^ base mod mod with mod as result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (mod, base, base, mod);
if (gcry_mpi_cmp (res, mod))
die ("test_powm failed at %d\n", __LINE__);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
/* Now check base ^ base mod base. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_powm (res, base, base, base);
if (gcry_mpi_cmp_ui (base, b_int))
die ("test_powm failed for base at %d\n", __LINE__);
/* Check base ^ base mod base with base as result. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_powm (base, base, base, base);
if (gcry_mpi_cmp (res, base))
die ("test_powm failed at %d\n", __LINE__);
/* Check for a case: base is negative and expo is even. */
gcry_mpi_set_ui (base, b_int);
gcry_mpi_neg (base, base);
gcry_mpi_set_ui (exp, e_int * 2);
gcry_mpi_set_ui(mod, m_int);
gcry_mpi_powm (res, base, exp, mod);
/* Result should be positive and it's 7 = (-17)^6 mod 19. */
if (gcry_mpi_is_neg (res) || gcry_mpi_cmp_ui (res, 7))
{
if (verbose)
{
fprintf (stderr, "is_neg: %d\n", gcry_mpi_is_neg (res));
fprintf (stderr, "mpi: ");
gcry_mpi_dump (res);
putc ('\n', stderr);
}
die ("test_powm failed for negative base at %d\n", __LINE__);
}
gcry_mpi_release (base);
gcry_mpi_release (exp);
gcry_mpi_release (mod);
gcry_mpi_release (res);
/* Fixme: We should add the rest of the cases of course. */
return 1;
}
int
main (int argc, char* argv[])
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
verbose = debug = 1;
if (!gcry_check_version (GCRYPT_VERSION))
{
fputs ("version mismatch\n", stderr);
exit (1);
}
xgcry_control(GCRYCTL_DISABLE_SECMEM);
test_const_and_immutable ();
test_opaque ();
test_maxsize ();
test_cmp ();
test_add ();
test_sub ();
test_mul ();
test_powm ();
return !!error_count;
}
diff --git a/tests/pkbench.c b/tests/pkbench.c
index e458b429..f8f5cf23 100644
--- a/tests/pkbench.c
+++ b/tests/pkbench.c
@@ -1,485 +1,485 @@
/* pkbench.c - Pubkey menchmarking
* Copyright (C) 2004, 2005, 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#ifndef HAVE_W32_SYSTEM
# include <sys/times.h>
#endif /*HAVE_W32_SYSTEM*/
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#define PGM "pkbench"
#include "t-common.h"
typedef struct context
{
gcry_sexp_t key_secret;
gcry_sexp_t key_public;
gcry_sexp_t data;
gcry_sexp_t data_encrypted;
gcry_sexp_t data_signed;
} *context_t;
typedef int (*work_t) (context_t context, unsigned int final);
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
static void *
read_file (const char *fname, size_t *r_length)
{
FILE *fp;
struct stat st;
char *buf;
size_t buflen;
fp = fopen (fname, "rb");
if (!fp)
{
fail ("can't open `%s': %s\n", fname, strerror (errno));
return NULL;
}
if (fstat (fileno(fp), &st))
{
fail ("can't stat `%s': %s\n", fname, strerror (errno));
fclose (fp);
return NULL;
}
buflen = st.st_size;
buf = gcry_xmalloc (buflen+1);
if (fread (buf, buflen, 1, fp) != 1)
{
fail ("error reading `%s': %s\n", fname, strerror (errno));
fclose (fp);
gcry_free (buf);
return NULL;
}
fclose (fp);
if (r_length)
*r_length = buflen;
return buf;
}
static void
benchmark (work_t worker, context_t context)
{
clock_t timer_start, timer_stop;
unsigned int loop = 10;
unsigned int i = 0;
struct tms timer;
int ret = 0;
#ifdef HAVE_W32_SYSTEM
timer_start = clock ();
#else
times (&timer);
timer_start = timer.tms_utime;
#endif
for (i = 0; i < loop; i++)
{
ret = (*worker) (context, (i + 1) == loop);
if (! ret)
break;
}
#ifdef HAVE_W32_SYSTEM
timer_stop = clock ();
#else
times (&timer);
timer_stop = timer.tms_utime;
#endif
if (ret)
printf ("%.0f ms\n",
(((double) ((timer_stop - timer_start) / loop)) / CLOCKS_PER_SEC)
* 10000000);
else
printf ("[skipped]\n");
}
static int
work_encrypt (context_t context, unsigned int final)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
gcry_sexp_t data_encrypted = NULL;
int ret = 1;
err = gcry_pk_encrypt (&data_encrypted,
context->data, context->key_public);
if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
{
err = GPG_ERR_NO_ERROR;
ret = 0;
}
else
{
assert (! err);
if (final)
context->data_encrypted = data_encrypted;
else
gcry_sexp_release (data_encrypted);
}
return ret;
}
static int
work_decrypt (context_t context, unsigned int final)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
int ret = 1;
if (! context->data_encrypted)
ret = 0;
else
{
gcry_sexp_t data_decrypted = NULL;
err = gcry_pk_decrypt (&data_decrypted,
context->data_encrypted,
context->key_secret);
assert (! err);
if (final)
{
gcry_sexp_release (context->data_encrypted);
context->data_encrypted = NULL;
}
gcry_sexp_release (data_decrypted);
}
return ret;
}
static int
work_sign (context_t context, unsigned int final)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
gcry_sexp_t data_signed = NULL;
int ret = 1;
err = gcry_pk_sign (&data_signed,
context->data, context->key_secret);
if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
{
err = GPG_ERR_NO_ERROR;
ret = 0;
}
else if (err)
{
fail ("pk_sign failed: %s\n", gpg_strerror (err));
ret = 0;
}
else
{
if (final)
context->data_signed = data_signed;
else
gcry_sexp_release (data_signed);
}
return ret;
}
static int
work_verify (context_t context, unsigned int final)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
int ret = 1;
if (!context->data_signed)
return 0;
err = gcry_pk_verify (context->data_signed,
context->data,
context->key_public);
if (err)
{
show_sexp ("data_signed:\n", context->data_signed);
show_sexp ("data:\n", context->data);
fail ("pk_verify failed: %s\n", gpg_strerror (err));
ret = 0;
}
else if (final)
{
gcry_sexp_release (context->data_signed);
context->data_signed = NULL;
}
return ret;
}
static void
process_key_pair (context_t context)
{
struct
{
work_t worker;
const char *identifier;
} worker_functions[] = { { work_encrypt, "encrypt" },
{ work_decrypt, "decrypt" },
{ work_sign, "sign" },
{ work_verify, "verify" } };
unsigned int i = 0;
for (i = 0; i < (sizeof (worker_functions) / sizeof (*worker_functions)); i++)
{
printf ("%s: ", worker_functions[i].identifier);
benchmark (worker_functions[i].worker, context);
}
}
static void
context_init (context_t context, gcry_sexp_t key_secret, gcry_sexp_t key_public)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
unsigned int key_size = 0;
gcry_mpi_t data = NULL;
gcry_sexp_t data_sexp = NULL;
key_size = gcry_pk_get_nbits (key_secret);
assert (key_size);
data = gcry_mpi_new (key_size);
assert (data);
gcry_mpi_randomize (data, key_size, GCRY_STRONG_RANDOM);
gcry_mpi_clear_bit (data, key_size - 1);
err = gcry_sexp_build (&data_sexp, NULL,
"(data (flags raw) (value %m))",
data);
assert (! err);
gcry_mpi_release (data);
context->key_secret = key_secret;
context->key_public = key_public;
context->data = data_sexp;
context->data_encrypted = NULL;
context->data_signed = NULL;
}
static void
context_destroy (context_t context)
{
gcry_sexp_release (context->key_secret);
gcry_sexp_release (context->key_public);
gcry_sexp_release (context->data);
}
static void
process_key_pair_file (const char *key_pair_file)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
void *key_pair_buffer = NULL;
gcry_sexp_t key_pair_sexp = NULL;
gcry_sexp_t key_secret_sexp = NULL;
gcry_sexp_t key_public_sexp = NULL;
struct context context = { NULL };
size_t file_length;
key_pair_buffer = read_file (key_pair_file, &file_length);
if (!key_pair_buffer)
die ("failed to open `%s'\n", key_pair_file);
err = gcry_sexp_sscan (&key_pair_sexp, NULL,
key_pair_buffer, file_length);
if (err)
die ("gcry_sexp_sscan failed\n");
key_secret_sexp = gcry_sexp_find_token (key_pair_sexp, "private-key", 0);
assert (key_secret_sexp);
key_public_sexp = gcry_sexp_find_token (key_pair_sexp, "public-key", 0);
assert (key_public_sexp);
gcry_sexp_release (key_pair_sexp);
context_init (&context, key_secret_sexp, key_public_sexp);
printf ("Key file: %s\n", key_pair_file);
process_key_pair (&context);
printf ("\n");
context_destroy (&context);
gcry_free (key_pair_buffer);
}
static void
generate_key (const char *algorithm, const char *key_size)
{
gcry_error_t err = GPG_ERR_NO_ERROR;
size_t key_pair_buffer_size = 0;
char *key_pair_buffer = NULL;
gcry_sexp_t key_spec = NULL;
gcry_sexp_t key_pair = NULL;
if (isdigit ((unsigned int)*key_size))
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (%s (nbits %s)))",
algorithm, key_size);
else
err = gcry_sexp_build (&key_spec, NULL,
"(genkey (%s (curve %s)))",
algorithm, key_size);
if (err)
die ("sexp_build failed: %s\n", gpg_strerror (err));
err = gcry_pk_genkey (&key_pair, key_spec);
if (err)
{
show_sexp ("request:\n", key_spec);
die ("pk_genkey failed: %s\n", gpg_strerror (err));
}
key_pair_buffer_size = gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED,
NULL, 0);
key_pair_buffer = gcry_xmalloc (key_pair_buffer_size);
gcry_sexp_sprint (key_pair, GCRYSEXP_FMT_ADVANCED,
key_pair_buffer, key_pair_buffer_size);
printf ("%.*s", (int)key_pair_buffer_size, key_pair_buffer);
gcry_free (key_pair_buffer);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int genkey_mode = 0;
int fips_mode = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
puts ("Usage: " PGM " [OPTIONS] [FILES]\n"
"Various public key tests:\n\n"
" Default is to process all given key files\n\n"
" --genkey ALGONAME SIZE Generate a public key\n"
"\n"
" --verbose enable extra informational output\n"
" --debug enable additional debug output\n"
" --help display this help and exit\n\n");
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = debug = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--genkey"))
{
genkey_mode = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--fips"))
{
fips_mode = 1;
argc--; argv++;
}
}
xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
if (fips_mode)
xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
xgcry_control (GCRYCTL_DISABLE_SECMEM);
if (!gcry_check_version (GCRYPT_VERSION))
{
fprintf (stderr, PGM ": version mismatch\n");
exit (1);
}
if (genkey_mode)
{
/* No valuable keys are create, so we can speed up our RNG. */
xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
}
if (debug)
xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (genkey_mode && argc == 2)
{
generate_key (argv[0], argv[1]);
}
else if (!genkey_mode && argc)
{
int i;
for (i = 0; i < argc; i++)
process_key_pair_file (argv[i]);
}
else
{
fprintf (stderr, "usage: " PGM
" [OPTIONS] [FILES] (try --help for more information)\n");
exit (1);
}
return error_count ? 1 : 0;
}
diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c
index b52bff81..1c191322 100644
--- a/tests/pkcs1v2.c
+++ b/tests/pkcs1v2.c
@@ -1,676 +1,676 @@
/* pkcs1v2.c - Test OAEP and PSS padding
* Copyright (C) 2011 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
#else
# include <gcrypt.h>
#endif
#define PGM "pkcs1v2"
#include "t-common.h"
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
/* 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 *
data_from_hex (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = gcry_xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
die ("error parsing hex string `%s'\n", string);
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static int
extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected,
const char *description)
{
gcry_sexp_t l1;
const void *a;
size_t alen;
void *b;
size_t blen;
int rc = 0;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_data (l1, 1, &alen);
b = data_from_hex (expected, &blen);
if (!a)
{
info ("%s: parameter \"%s\" missing in key\n", description, name);
rc = 1;
}
else if ( alen != blen || memcmp (a, b, alen) )
{
info ("%s: parameter \"%s\" does not match expected value\n",
description, name);
rc = 1;
}
gcry_free (b);
gcry_sexp_release (l1);
return rc;
}
/* Check against the OAEP test vectors from
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip . */
static void
check_oaep (void)
{
#include "pkcs1v2-oaep.h"
gpg_error_t err;
int tno, mno;
for (tno = 0; tno < DIM (tbl); tno++)
{
void *rsa_n, *rsa_e, *rsa_d;
size_t rsa_n_len, rsa_e_len, rsa_d_len;
gcry_sexp_t sec_key, pub_key;
if (verbose > 1)
info ("(%s)\n", tbl[tno].desc);
rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
err = gcry_sexp_build (&sec_key, NULL,
"(private-key (rsa (n %b)(e %b)(d %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e,
(int)rsa_d_len, rsa_d);
if (err)
die ("constructing private key failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&pub_key, NULL,
"(public-key (rsa (n %b)(e %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e);
if (err)
die ("constructing public key failed: %s\n", gpg_strerror (err));
gcry_free (rsa_n);
gcry_free (rsa_e);
gcry_free (rsa_d);
for (mno = 0; mno < DIM (tbl[0].m); mno++)
{
void *mesg, *seed, *encr;
size_t mesg_len, seed_len, encr_len;
gcry_sexp_t plain, ciph;
if (verbose)
info ("running test: %s\n", tbl[tno].m[mno].desc);
mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
err = gcry_sexp_build (&plain, NULL,
"(data (flags oaep)(hash-algo sha1)"
"(value %b)(random-override %b))",
(int)mesg_len, mesg,
(int)seed_len, seed);
if (err)
die ("constructing plain data failed: %s\n", gpg_strerror (err));
gcry_free (mesg);
gcry_free (seed);
err = gcry_pk_encrypt (&ciph, plain, pub_key);
if (err)
{
show_sexp ("plain:\n", ciph);
fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr,
tbl[tno].m[mno].desc))
{
show_sexp ("encrypt result:\n", ciph);
fail ("mismatch in gcry_pk_encrypt\n");
}
gcry_sexp_release (ciph);
ciph = NULL;
}
gcry_sexp_release (plain);
plain = NULL;
/* Now test the decryption. */
seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len);
err = gcry_sexp_build (&ciph, NULL,
"(enc-val (flags oaep)(hash-algo sha1)"
"(random-override %b)"
"(rsa (a %b)))",
(int)seed_len, seed,
(int)encr_len, encr);
if (err)
die ("constructing cipher data failed: %s\n", gpg_strerror (err));
gcry_free (encr);
gcry_free (seed);
err = gcry_pk_decrypt (&plain, ciph, sec_key);
if (err)
{
show_sexp ("ciph:\n", ciph);
fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg,
tbl[tno].m[mno].desc))
{
show_sexp ("decrypt result:\n", plain);
fail ("mismatch in gcry_pk_decrypt\n");
}
gcry_sexp_release (plain);
plain = NULL;
}
gcry_sexp_release (ciph);
ciph = NULL;
}
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
/* Check against the PSS test vectors from
ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2-vec.zip . */
static void
check_pss (void)
{
#include "pkcs1v2-pss.h"
gpg_error_t err;
int tno, mno;
for (tno = 0; tno < DIM (tbl); tno++)
{
void *rsa_n, *rsa_e, *rsa_d;
size_t rsa_n_len, rsa_e_len, rsa_d_len;
gcry_sexp_t sec_key, pub_key;
if (verbose > 1)
info ("(%s)\n", tbl[tno].desc);
rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
err = gcry_sexp_build (&sec_key, NULL,
"(private-key (rsa (n %b)(e %b)(d %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e,
(int)rsa_d_len, rsa_d);
if (err)
die ("constructing private key failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&pub_key, NULL,
"(public-key (rsa (n %b)(e %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e);
if (err)
die ("constructing public key failed: %s\n", gpg_strerror (err));
gcry_free (rsa_n);
gcry_free (rsa_e);
gcry_free (rsa_d);
for (mno = 0; mno < DIM (tbl[0].m); mno++)
{
void *mesg, *salt, *sign;
size_t mesg_len, salt_len, sign_len;
gcry_sexp_t sigtmpl, sig;
char mhash[20];
if (verbose)
info ("running test: %s\n", tbl[tno].m[mno].desc);
mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
salt = data_from_hex (tbl[tno].m[mno].salt, &salt_len);
gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len);
err = gcry_sexp_build (&sigtmpl, NULL,
"(data (flags pss)"
"(hash sha1 %b)"
"(random-override %b))",
20, mhash,
(int)salt_len, salt);
if (err)
die ("constructing sig template failed: %s\n", gpg_strerror (err));
gcry_free (mesg);
gcry_free (salt);
err = gcry_pk_sign (&sig, sigtmpl, sec_key);
if (err)
{
show_sexp ("sigtmpl:\n", sigtmpl);
fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign,
tbl[tno].m[mno].desc))
{
show_sexp ("sign result:\n", sig);
fail ("mismatch in gcry_pk_sign\n");
}
gcry_sexp_release (sig);
sig = NULL;
}
gcry_sexp_release (sigtmpl);
sigtmpl = NULL;
/* Now test the verification. */
salt = data_from_hex (tbl[tno].m[mno].salt, &salt_len);
sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len);
err = gcry_sexp_build (&sig, NULL,
"(sig-val(rsa(s %b)))",
(int)sign_len, sign);
if (err)
die ("constructing verify data failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&sigtmpl, NULL,
"(data (flags pss)"
"(hash sha1 %b)"
"(random-override %b))",
20, mhash,
(int)salt_len, salt);
if (err)
die ("constructing verify tmpl failed: %s\n", gpg_strerror (err));
gcry_free (sign);
gcry_free (salt);
err = gcry_pk_verify (sig, sigtmpl, pub_key);
if (err)
{
show_sexp ("sig:\n", sig);
show_sexp ("sigtmpl:\n", sigtmpl);
fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err));
}
gcry_sexp_release (sig);
sig = NULL;
gcry_sexp_release (sigtmpl);
sigtmpl = NULL;
}
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
/* Check against PKCS#1 v1.5 encryption test vectors as found at
ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt . */
static void
check_v15crypt (void)
{
#include "pkcs1v2-v15c.h"
gpg_error_t err;
int tno, mno;
for (tno = 0; tno < DIM (tbl); tno++)
{
void *rsa_n, *rsa_e, *rsa_d;
size_t rsa_n_len, rsa_e_len, rsa_d_len;
gcry_sexp_t sec_key, pub_key;
if (verbose > 1)
info ("(%s)\n", tbl[tno].desc);
rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
err = gcry_sexp_build (&sec_key, NULL,
"(private-key (rsa (n %b)(e %b)(d %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e,
(int)rsa_d_len, rsa_d);
if (err)
die ("constructing private key failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&pub_key, NULL,
"(public-key (rsa (n %b)(e %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e);
if (err)
die ("constructing public key failed: %s\n", gpg_strerror (err));
gcry_free (rsa_n);
gcry_free (rsa_e);
gcry_free (rsa_d);
for (mno = 0; mno < DIM (tbl[0].m); mno++)
{
void *mesg, *seed, *encr;
size_t mesg_len, seed_len, encr_len;
gcry_sexp_t plain, ciph;
if (verbose)
info ("running test: %s\n", tbl[tno].m[mno].desc);
mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
err = gcry_sexp_build (&plain, NULL,
"(data (flags pkcs1)(hash-algo sha1)"
"(value %b)(random-override %b))",
(int)mesg_len, mesg,
(int)seed_len, seed);
if (err)
die ("constructing plain data failed: %s\n", gpg_strerror (err));
gcry_free (mesg);
gcry_free (seed);
err = gcry_pk_encrypt (&ciph, plain, pub_key);
if (err)
{
show_sexp ("plain:\n", ciph);
fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr,
tbl[tno].m[mno].desc))
{
show_sexp ("encrypt result:\n", ciph);
fail ("mismatch in gcry_pk_encrypt\n");
}
gcry_sexp_release (ciph);
ciph = NULL;
}
gcry_sexp_release (plain);
plain = NULL;
/* Now test the decryption. */
seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len);
err = gcry_sexp_build (&ciph, NULL,
"(enc-val (flags pkcs1)(hash-algo sha1)"
"(random-override %b)"
"(rsa (a %b)))",
(int)seed_len, seed,
(int)encr_len, encr);
if (err)
die ("constructing cipher data failed: %s\n", gpg_strerror (err));
gcry_free (encr);
gcry_free (seed);
err = gcry_pk_decrypt (&plain, ciph, sec_key);
if (err)
{
show_sexp ("ciph:\n", ciph);
fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg,
tbl[tno].m[mno].desc))
{
show_sexp ("decrypt result:\n", plain);
fail ("mismatch in gcry_pk_decrypt\n");
}
gcry_sexp_release (plain);
plain = NULL;
}
gcry_sexp_release (ciph);
ciph = NULL;
}
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
/* Check against PKCS#1 v1.5 signature test vectors as found at
ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt . */
static void
check_v15sign (void)
{
#include "pkcs1v2-v15s.h"
gpg_error_t err;
int tno, mno;
for (tno = 0; tno < DIM (tbl); tno++)
{
void *rsa_n, *rsa_e, *rsa_d;
size_t rsa_n_len, rsa_e_len, rsa_d_len;
gcry_sexp_t sec_key, pub_key;
if (verbose > 1)
info ("(%s)\n", tbl[tno].desc);
rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
err = gcry_sexp_build (&sec_key, NULL,
"(private-key (rsa (n %b)(e %b)(d %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e,
(int)rsa_d_len, rsa_d);
if (err)
die ("constructing private key failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&pub_key, NULL,
"(public-key (rsa (n %b)(e %b)))",
(int)rsa_n_len, rsa_n,
(int)rsa_e_len, rsa_e);
if (err)
die ("constructing public key failed: %s\n", gpg_strerror (err));
gcry_free (rsa_n);
gcry_free (rsa_e);
gcry_free (rsa_d);
for (mno = 0; mno < DIM (tbl[0].m); mno++)
{
void *mesg, *sign;
size_t mesg_len, sign_len;
gcry_sexp_t sigtmpl, sig;
char mhash[20];
if (verbose)
info ("running test: %s\n", tbl[tno].m[mno].desc);
mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len);
err = gcry_sexp_build (&sigtmpl, NULL,
"(data (flags pkcs1)"
"(hash sha1 %b))",
20, mhash);
if (err)
die ("constructing sig template failed: %s\n", gpg_strerror (err));
gcry_free (mesg);
err = gcry_pk_sign (&sig, sigtmpl, sec_key);
if (err)
{
show_sexp ("sigtmpl:\n", sigtmpl);
fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err));
}
else
{
if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign,
tbl[tno].m[mno].desc))
{
show_sexp ("sign result:\n", sig);
fail ("mismatch in gcry_pk_sign\n");
}
gcry_sexp_release (sig);
sig = NULL;
}
gcry_sexp_release (sigtmpl);
sigtmpl = NULL;
/* Now test the verification. */
sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len);
err = gcry_sexp_build (&sig, NULL,
"(sig-val(rsa(s %b)))",
(int)sign_len, sign);
if (err)
die ("constructing verify data failed: %s\n", gpg_strerror (err));
err = gcry_sexp_build (&sigtmpl, NULL,
"(data (flags pkcs1)"
"(hash sha1 %b))",
20, mhash);
if (err)
die ("constructing verify tmpl failed: %s\n", gpg_strerror (err));
gcry_free (sign);
err = gcry_pk_verify (sig, sigtmpl, pub_key);
if (err)
{
show_sexp ("sig:\n", sig);
show_sexp ("sigtmpl:\n", sigtmpl);
fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err));
}
gcry_sexp_release (sig);
sig = NULL;
gcry_sexp_release (sigtmpl);
sigtmpl = NULL;
}
gcry_sexp_release (sec_key);
gcry_sexp_release (pub_key);
}
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int run_oaep = 0;
int run_pss = 0;
int run_v15c = 0;
int run_v15s = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = 2;
debug = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--die"))
{
die_on_error = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--oaep"))
{
run_oaep = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--pss"))
{
run_pss = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--v15c"))
{
run_v15c = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--v15s"))
{
run_v15s = 1;
argc--; 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);
if (debug)
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);
if (run_oaep)
check_oaep ();
if (run_pss)
check_pss ();
if (run_v15c)
check_v15crypt ();
if (run_v15s)
check_v15sign ();
if (verbose)
fprintf (stderr, "\nAll tests completed. Errors: %i\n", error_count);
return error_count ? 1 : 0;
}
diff --git a/tests/pubkey.c b/tests/pubkey.c
index fbb7bbb5..0a4bc292 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -1,1202 +1,1202 @@
/* pubkey.c - Public key encryption/decryption tests
* 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, see <http://www.gnu.org/licenses/>.
+ * 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 <stdlib.h>
#include <string.h>
#define PGM "pubkey"
#include "t-common.h"
/* 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"
" (e #010001#)\n"
" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
"7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
"C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
"C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
"fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n"
" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
"35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n"
" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
"ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n"
" )\n"
")\n";
/* The same key as above but without p, q and u to test the non CRT case. */
static const char sample_private_key_1_1[] =
"(private-key\n"
" (openpgp-rsa\n"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
"2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
"ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
"891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
" (e #010001#)\n"
" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
"7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
"C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
"C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
" )\n"
")\n";
/* The same key as above but just without q to test the non CRT case. This
should fail. */
static const char sample_private_key_1_2[] =
"(private-key\n"
" (openpgp-rsa\n"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
"2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
"ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
"891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
" (e #010001#)\n"
" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
"7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
"C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
"C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
"fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n"
" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
"ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n"
" )\n"
")\n";
static const char sample_public_key_1[] =
"(public-key\n"
" (rsa\n"
" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
"2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
"ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
"891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
" (e #010001#)\n"
" )\n"
")\n";
static void
show_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
/* from ../cipher/pubkey-util.c */
static gpg_err_code_t
_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
{
char buf[50];
const char *s;
size_t n;
*r_nbits = 0;
list = gcry_sexp_find_token (list, "nbits", 0);
if (!list)
return 0; /* No NBITS found. */
s = gcry_sexp_nth_data (list, 1, &n);
if (!s || n >= DIM (buf) - 1 )
{
/* NBITS given without a cdr. */
gcry_sexp_release (list);
return GPG_ERR_INV_OBJ;
}
memcpy (buf, s, n);
buf[n] = 0;
*r_nbits = (unsigned int)strtoul (buf, NULL, 0);
gcry_sexp_release (list);
return 0;
}
/* 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 *
data_from_hex (const char *string, size_t *r_length)
{
const char *s;
unsigned char *buffer;
size_t length;
buffer = gcry_xmalloc (strlen(string)/2+1);
length = 0;
for (s=string; *s; s +=2 )
{
if (!hexdigitp (s) || !hexdigitp (s+1))
die ("error parsing hex string `%s'\n", string);
((unsigned char*)buffer)[length++] = xtoi_2 (s);
}
*r_length = length;
return buffer;
}
static void
extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected)
{
gcry_sexp_t l1;
const void *a;
size_t alen;
void *b;
size_t blen;
l1 = gcry_sexp_find_token (sexp, name, 0);
a = gcry_sexp_nth_data (l1, 1, &alen);
b = data_from_hex (expected, &blen);
if (!a)
fail ("parameter \"%s\" missing in key\n", name);
else if ( alen != blen || memcmp (a, b, alen) )
{
fail ("parameter \"%s\" does not match expected value\n", name);
if (verbose)
{
info ("expected: %s\n", expected);
show_sexp ("sexp: ", sexp);
}
}
gcry_free (b);
gcry_sexp_release (l1);
}
static void
check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey,
gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code)
{
gcry_sexp_t plain1, cipher, l;
gcry_mpi_t x0, x1;
int rc;
int have_flags;
/* Extract data from plaintext. */
l = gcry_sexp_find_token (plain0, "value", 0);
x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l);
/* Encrypt data. */
rc = gcry_pk_encrypt (&cipher, plain0, pkey);
if (rc)
die ("encryption failed: %s\n", gcry_strerror (rc));
l = gcry_sexp_find_token (cipher, "flags", 0);
have_flags = !!l;
gcry_sexp_release (l);
/* Decrypt data. */
rc = gcry_pk_decrypt (&plain1, cipher, skey);
gcry_sexp_release (cipher);
if (rc)
{
if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code)
{
gcry_mpi_release (x0);
return; /* This is the expected failure code. */
}
die ("decryption failed: %s\n", gcry_strerror (rc));
}
/* Extract decrypted data. Note that for compatibility reasons, the
output of gcry_pk_decrypt depends on whether a flags lists (even
if empty) occurs in its input data. Because we passed the output
of encrypt directly to decrypt, such a flag value won't be there
as of today. We check it anyway. */
l = gcry_sexp_find_token (plain1, "value", 0);
if (l)
{
if (!have_flags)
die ("compatibility mode of pk_decrypt broken\n");
gcry_sexp_release (plain1);
x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l);
}
else
{
if (have_flags)
die ("compatibility mode of pk_decrypt broken\n");
x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG);
gcry_sexp_release (plain1);
}
/* Compare. */
if (gcry_mpi_cmp (x0, x1))
die ("data corrupted\n");
gcry_mpi_release (x0);
gcry_mpi_release (x1);
}
static void
check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data,
gpg_err_code_t decrypt_fail_code)
{
gcry_sexp_t plain;
gcry_mpi_t x;
int rc;
/* Create plain text. */
x = gcry_mpi_new (nbits_data);
gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM);
rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x);
if (rc)
die ("converting data for encryption failed: %s\n",
gcry_strerror (rc));
check_keys_crypt (pkey, skey, plain, decrypt_fail_code);
gcry_sexp_release (plain);
gcry_mpi_release (x);
/* Create plain text. */
x = gcry_mpi_new (nbits_data);
gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM);
rc = gcry_sexp_build (&plain, NULL,
"(data (flags raw no-blinding) (value %m))", x);
gcry_mpi_release (x);
if (rc)
die ("converting data for encryption failed: %s\n",
gcry_strerror (rc));
check_keys_crypt (pkey, skey, plain, decrypt_fail_code);
gcry_sexp_release (plain);
}
static void
get_keys_sample (gcry_sexp_t *pkey, gcry_sexp_t *skey, int secret_variant)
{
gcry_sexp_t pub_key, sec_key;
int rc;
static const char *secret;
switch (secret_variant)
{
case 0: secret = sample_private_key_1; break;
case 1: secret = sample_private_key_1_1; break;
case 2: secret = sample_private_key_1_2; break;
default: die ("BUG\n");
}
rc = gcry_sexp_sscan (&pub_key, NULL, sample_public_key_1,
strlen (sample_public_key_1));
if (!rc)
rc = gcry_sexp_sscan (&sec_key, NULL, secret, strlen (secret));
if (rc)
die ("converting sample keys failed: %s\n", gcry_strerror (rc));
*pkey = pub_key;
*skey = sec_key;
}
static void
get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new (&key_spec,
"(genkey (rsa (nbits 4:2048)))", 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 RSA key: %s\n", gcry_strerror (rc));
if (verbose > 1)
show_sexp ("generated RSA key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (! pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (! sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new (&key_spec,
"(genkey (rsa (nbits 4:2048)(use-x931)))", 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 RSA key: %s\n", gcry_strerror (rc));
if (verbose > 1)
show_sexp ("generated RSA (X9.31) key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new
(&key_spec,
(fixed_x
? "(genkey (elg (nbits 4:1024)(xvalue my.not-so-secret.key)))"
: "(genkey (elg (nbits 3:512)))"),
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 Elgamal key: %s\n", gcry_strerror (rc));
if (verbose > 1)
show_sexp ("generated ELG key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new (&key_spec,
transient_key
? "(genkey (dsa (nbits 4:2048)(transient-key)))"
: "(genkey (dsa (nbits 4:2048)))",
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 (verbose > 1)
show_sexp ("generated DSA key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new
(&key_spec, "(genkey (dsa (nbits 4:2048)(use-fips186)))", 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 (verbose > 1)
show_sexp ("generated DSA key (fips 186):\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new
(&key_spec,
"(genkey (dsa (transient-key)(domain"
"(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
"4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7"
"74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0"
"5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)"
"(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)"
"(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab"
"0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad"
"b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e"
"ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)"
")))", 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 (verbose > 1)
show_sexp ("generated DSA key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
#if 0
static void
get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new
(&key_spec,
"(genkey (dsa (transient-key)(use-fips186)(domain"
"(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
"4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7"
"74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0"
"5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)"
"(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)"
"(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab"
"0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad"
"b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e"
"ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)"
")))", 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 (verbose > 1)
show_sexp ("generated DSA key:\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
#endif /*0*/
static void
get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
{
gcry_sexp_t key_spec, key, pub_key, sec_key;
int rc;
rc = gcry_sexp_new
(&key_spec,
"(genkey"
" (dsa"
" (nbits 4:2048)"
" (use-fips186)"
" (transient-key)"
" (derive-parms"
" (seed #0cb1990c1fd3626055d7a0096f8fa99807399871#))))",
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 (verbose > 1)
show_sexp ("generated DSA key (fips 186 with seed):\n", key);
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key\n");
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key\n");
gcry_sexp_release (key);
*pkey = pub_key;
*skey = sec_key;
}
static void
check_run (void)
{
gpg_error_t err;
gcry_sexp_t pkey, skey;
int variant;
for (variant=0; variant < 3; variant++)
{
if (verbose)
fprintf (stderr, "Checking sample key (%d).\n", variant);
get_keys_sample (&pkey, &skey, variant);
/* Check gcry_pk_testkey which requires all elements. */
err = gcry_pk_testkey (skey);
if ((variant == 0 && err)
|| (variant > 0 && gpg_err_code (err) != GPG_ERR_NO_OBJ))
die ("gcry_pk_testkey failed: %s\n", gpg_strerror (err));
/* Run the usual check but expect an error from variant 2. */
check_keys (pkey, skey, 800, variant == 2? GPG_ERR_NO_OBJ : 0);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
}
if (verbose)
fprintf (stderr, "Checking generated RSA key.\n");
get_keys_new (&pkey, &skey);
check_keys (pkey, skey, 800, 0);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
if (verbose)
fprintf (stderr, "Checking generated RSA key (X9.31).\n");
get_keys_x931_new (&pkey, &skey);
check_keys (pkey, skey, 800, 0);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
if (verbose)
fprintf (stderr, "Checking generated Elgamal key.\n");
get_elg_key_new (&pkey, &skey, 0);
check_keys (pkey, skey, 400, 0);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
if (verbose)
fprintf (stderr, "Checking passphrase generated Elgamal key.\n");
get_elg_key_new (&pkey, &skey, 1);
check_keys (pkey, skey, 800, 0);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
if (verbose)
fprintf (stderr, "Generating DSA key.\n");
get_dsa_key_new (&pkey, &skey, 0);
/* Fixme: Add a check function for DSA keys. */
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
if (!gcry_fips_mode_active ())
{
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);
}
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. */
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
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. */
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
/* We need new test vectors for get_dsa_key_fips186_with_domain_new. */
if (verbose)
fprintf (stderr, "Generating DSA key with given domain (FIPS 186)"
" - skipped.\n");
/* get_dsa_key_fips186_with_domain_new (&pkey, &skey); */
/* /\* Fixme: Add a check function for DSA keys. *\/ */
/* gcry_sexp_release (pkey); */
/* gcry_sexp_release (skey); */
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. */
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
}
static gcry_mpi_t
key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name)
{
gcry_sexp_t l1, l2;
gcry_mpi_t result;
l1 = gcry_sexp_find_token (sexp, topname, 0);
if (!l1)
return NULL;
l2 = gcry_sexp_find_token (l1, name, 0);
if (!l2)
{
gcry_sexp_release (l1);
return NULL;
}
result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
gcry_sexp_release (l1);
return result;
}
static void
check_x931_derived_key (int what)
{
static struct {
const char *param;
const char *expected_d;
} testtable[] = {
{ /* First example from X9.31 (D.1.1). */
"(genkey\n"
" (rsa\n"
" (nbits 4:1024)\n"
" (rsa-use-e 1:3)\n"
" (derive-parms\n"
" (Xp1 #1A1916DDB29B4EB7EB6732E128#)\n"
" (Xp2 #192E8AAC41C576C822D93EA433#)\n"
" (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D\n"
" 769D6D76646C7A792E16EBD89FE6FC5B605A6493\n"
" 39DFC925A86A4C6D150B71B9EEA02D68885F5009\n"
" B98BD984#)\n"
" (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)\n"
" (Xq2 #134E4CAA16D2350A21D775C404#)\n"
" (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D\n"
" 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325\n"
" 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34\n"
" 321DE34A#))))\n",
"1CCDA20BCFFB8D517EE9666866621B11822C7950D55F4BB5BEE37989A7D173"
"12E326718BE0D79546EAAE87A56623B919B1715FFBD7F16028FC4007741961"
"C88C5D7B4DAAAC8D36A98C9EFBB26C8A4A0E6BC15B358E528A1AC9D0F042BE"
"B93BCA16B541B33F80C933A3B769285C462ED5677BFE89DF07BED5C127FD13"
"241D3C4B"
},
{ /* Second example from X9.31 (D.2.1). */
"(genkey\n"
" (rsa\n"
" (nbits 4:1536)\n"
" (rsa-use-e 1:3)\n"
" (derive-parms\n"
" (Xp1 #18272558B61316348297EACA74#)\n"
" (Xp2 #1E970E8C6C97CEF91F05B0FA80#)\n"
" (Xp #F7E943C7EF2169E930DCF23FE389EF7507EE8265\n"
" 0D42F4A0D3A3CEFABE367999BB30EE680B2FE064\n"
" 60F707F46005F8AA7CBFCDDC4814BBE7F0F8BC09\n"
" 318C8E51A48D134296E40D0BBDD282DCCBDDEE1D\n"
" EC86F0B1C96EAFF5CDA70F9AEB6EE31E#)\n"
" (Xq1 #11FDDA6E8128DC1629F75192BA#)\n"
" (Xq2 #18AB178ECA907D72472F65E480#)\n"
" (Xq #C47560011412D6E13E3E7D007B5C05DBF5FF0D0F\n"
" CFF1FA2070D16C7ABA93EDFB35D8700567E5913D\n"
" B734E3FBD15862EBC59FA0425DFA131E549136E8\n"
" E52397A8ABE4705EC4877D4F82C4AAC651B33DA6\n"
" EA14B9D5F2A263DC65626E4D6CEAC767#))))\n",
"1FB56069985F18C4519694FB71055721A01F14422DC901C35B03A64D4A5BD1"
"259D573305F5B056AC931B82EDB084E39A0FD1D1A86CC5B147A264F7EF4EB2"
"0ED1E7FAAE5CAE4C30D5328B7F74C3CAA72C88B70DED8EDE207B8629DA2383"
"B78C3CE1CA3F9F218D78C938B35763AF2A8714664CC57F5CECE2413841F5E9"
"EDEC43B728E25A41BF3E1EF8D9EEE163286C9F8BF0F219D3B322C3E4B0389C"
"2E8BB28DC04C47DA2BF38823731266D2CF6CC3FC181738157624EF051874D0"
"BBCCB9F65C83"
/* Note that this example in X9.31 gives this value for D:
"7ED581A6617C6311465A53EDC4155C86807C5108B724070D6C0E9935296F44"
"96755CCC17D6C15AB24C6E0BB6C2138E683F4746A1B316C51E8993DFBD3AC8"
"3B479FEAB972B930C354CA2DFDD30F2A9CB222DC37B63B7881EE18A7688E0E"
"DE30F38728FE7C8635E324E2CD5D8EBCAA1C51993315FD73B38904E107D7A7"
"B7B10EDCA3896906FCF87BE367BB858CA1B27E2FC3C8674ECC8B0F92C0E270"
"BA2ECA3701311F68AFCE208DCC499B4B3DB30FF0605CE055D893BC1461D342"
"EF32E7D9720B"
This is a bug in X9.31, obviously introduced by using
d = e^{-1} mod (p-1)(q-1)
instead of using the universal exponent as required by 4.1.3:
d = e^{-1} mod lcm(p-1,q-1)
The examples in X9.31 seem to be pretty buggy, see
cipher/primegen.c for another bug. Not only that I had to
spend 100 USD for the 66 pages of the document, it also took
me several hours to figure out that the bugs are in the
document and not in my code.
*/
},
{ /* First example from NIST RSAVS (B.1.1). */
"(genkey\n"
" (rsa\n"
" (nbits 4:1024)\n"
" (rsa-use-e 1:3)\n"
" (derive-parms\n"
" (Xp1 #1ed3d6368e101dab9124c92ac8#)\n"
" (Xp2 #16e5457b8844967ce83cab8c11#)\n"
" (Xp #b79f2c2493b4b76f329903d7555b7f5f06aaa5ea\n"
" ab262da1dcda8194720672a4e02229a0c71f60ae\n"
" c4f0d2ed8d49ef583ca7d5eeea907c10801c302a\n"
" cab44595#)\n"
" (Xq1 #1a5d9e3fa34fb479bedea412f6#)\n"
" (Xq2 #1f9cca85f185341516d92e82fd#)\n"
" (Xq #c8387fd38fa33ddcea6a9de1b2d55410663502db\n"
" c225655a9310cceac9f4cf1bce653ec916d45788\n"
" f8113c46bc0fa42bf5e8d0c41120c1612e2ea8bb\n"
" 2f389eda#))))\n",
"17ef7ad4fd96011b62d76dfb2261b4b3270ca8e07bc501be954f8719ef586b"
"f237e8f693dd16c23e7adecc40279dc6877c62ab541df5849883a5254fccfd"
"4072a657b7f4663953930346febd6bbd82f9a499038402cbf97fd5f068083a"
"c81ad0335c4aab0da19cfebe060a1bac7482738efafea078e21df785e56ea0"
"dc7e8feb"
},
{ /* Second example from NIST RSAVS (B.1.1). */
"(genkey\n"
" (rsa\n"
" (nbits 4:1536)\n"
" (rsa-use-e 1:3)\n"
" (derive-parms\n"
" (Xp1 #1e64c1af460dff8842c22b64d0#)\n"
" (Xp2 #1e948edcedba84039c81f2ac0c#)\n"
" (Xp #c8c67df894c882045ede26a9008ab09ea0672077\n"
" d7bc71d412511cd93981ddde8f91b967da404056\n"
" c39f105f7f239abdaff92923859920f6299e82b9\n"
" 5bd5b8c959948f4a034d81613d6235a3953b49ce\n"
" 26974eb7bb1f14843841281b363b9cdb#)\n"
" (Xq1 #1f3df0f017ddd05611a97b6adb#)\n"
" (Xq2 #143edd7b22d828913abf24ca4d#)\n"
" (Xq #f15147d0e7c04a1e3f37adde802cdc610999bf7a\n"
" b0088434aaeda0c0ab3910b14d2ce56cb66bffd9\n"
" 7552195fae8b061077e03920814d8b9cfb5a3958\n"
" b3a82c2a7fc97e55db543948d3396289245336ec\n"
" 9e3cb308cc655aebd766340da8921383#))))\n",
"1f8b19f3f5f2ac9fc599f110cad403dcd9bdf5f7f00fb2790e78e820398184"
"1f3fb3dd230fb223d898f45719d9b2d3525587ff2b8bcc7425e40550a5b536"
"1c8e9c1d26e83fbd9c33c64029c0e878b829d55def12912b73d94fd758c461"
"0f473e230c41b5e4c86e27c5a5029d82c811c88525d0269b95bd2ff272994a"
"dbd80f2c2ecf69065feb8abd8b445b9c6d306b1585d7d3d7576d49842bc7e2"
"8b4a2f88f4a47e71c3edd35fdf83f547ea5c2b532975c551ed5268f748b2c4"
"2ccf8a84835b"
}
};
gpg_error_t err;
gcry_sexp_t key_spec = NULL, key = NULL, pub_key = NULL, sec_key = NULL;
gcry_mpi_t d_expected = NULL, d_have = NULL;
if (what < 0 && what >= sizeof testtable)
die ("invalid WHAT value\n");
err = gcry_sexp_new (&key_spec, testtable[what].param, 0, 1);
if (err)
die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err));
{
unsigned nbits;
err = _gcry_pk_util_get_nbits(key_spec, &nbits);
if (err)
die ("nbits not found\n");
if (gcry_fips_mode_active() && nbits < 2048)
{
info("RSA key test with %d bits skipped in fips mode\n", nbits);
goto leave;
}
}
err = gcry_pk_genkey (&key, key_spec);
gcry_sexp_release (key_spec);
if (err)
{
fail ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err));
goto leave;
}
pub_key = gcry_sexp_find_token (key, "public-key", 0);
if (!pub_key)
die ("public part missing in key [%d]\n", what);
sec_key = gcry_sexp_find_token (key, "private-key", 0);
if (!sec_key)
die ("private part missing in key [%d]\n", what);
err = gcry_mpi_scan
(&d_expected, GCRYMPI_FMT_HEX, testtable[what].expected_d, 0, NULL);
if (err)
die ("error converting string [%d]\n", what);
if (verbose > 1)
show_sexp ("generated key:\n", key);
d_have = key_param_from_sexp (sec_key, "rsa", "d");
if (!d_have)
die ("parameter d not found in RSA secret key [%d]\n", what);
if (gcry_mpi_cmp (d_expected, d_have))
{
show_sexp (NULL, sec_key);
die ("parameter d does match expected value [%d]\n", what);
}
leave:
gcry_mpi_release (d_expected);
gcry_mpi_release (d_have);
gcry_sexp_release (key);
gcry_sexp_release (pub_key);
gcry_sexp_release (sec_key);
}
static void
check_ecc_sample_key (void)
{
static const char ecc_private_key[] =
"(private-key\n"
" (ecdsa\n"
" (curve \"NIST P-256\")\n"
" (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781"
"B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)\n"
" (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)"
"))";
static const char ecc_private_key_wo_q[] =
"(private-key\n"
" (ecdsa\n"
" (curve \"NIST P-256\")\n"
" (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)"
"))";
static const char ecc_public_key[] =
"(public-key\n"
" (ecdsa\n"
" (curve \"NIST P-256\")\n"
" (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781"
"B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)"
"))";
static const char hash_string[] =
"(data (flags raw)\n"
" (value #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))";
static const char hash2_string[] =
"(data (flags raw)\n"
" (hash sha1 #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "00112233445566778899AABBCCDDEEFF#))";
/* hash2, but longer than curve length, so it will be truncated */
static const char hash3_string[] =
"(data (flags raw)\n"
" (hash sha1 #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "000102030405060708090A0B0C0D0E0F"
/* */ "00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))";
gpg_error_t err;
gcry_sexp_t key, hash, hash2, hash3, sig, sig2;
if (verbose)
fprintf (stderr, "Checking sample ECC key.\n");
if ((err = gcry_sexp_new (&hash, hash_string, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_sexp_new (&hash2, hash2_string, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_sexp_new (&hash3, hash3_string, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_sign (&sig, hash, key)))
die ("gcry_pk_sign failed: %s", gpg_strerror (err));
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify failed: %s", gpg_strerror (err));
/* Verify hash truncation */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_sign (&sig2, hash2, key)))
die ("gcry_pk_sign failed: %s", gpg_strerror (err));
gcry_sexp_release (sig);
if ((err = gcry_pk_sign (&sig, hash3, key)))
die ("gcry_pk_sign failed: %s", gpg_strerror (err));
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash2, key)))
die ("gcry_pk_verify failed: %s", gpg_strerror (err));
if ((err = gcry_pk_verify (sig2, hash3, key)))
die ("gcry_pk_verify failed: %s", gpg_strerror (err));
/* Now try signing without the Q parameter. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
gcry_sexp_release (sig);
if ((err = gcry_pk_sign (&sig, hash, key)))
die ("gcry_pk_sign without Q failed: %s", gpg_strerror (err));
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify signed without Q failed: %s", gpg_strerror (err));
gcry_sexp_release (sig);
gcry_sexp_release (sig2);
gcry_sexp_release (key);
gcry_sexp_release (hash);
gcry_sexp_release (hash2);
gcry_sexp_release (hash3);
}
static void
check_ed25519ecdsa_sample_key (void)
{
static const char ecc_private_key[] =
"(private-key\n"
" (ecc\n"
" (curve \"Ed25519\")\n"
" (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321"
" 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)"
" (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)"
"))";
static const char ecc_private_key_wo_q[] =
"(private-key\n"
" (ecc\n"
" (curve \"Ed25519\")\n"
" (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)"
"))";
static const char ecc_public_key[] =
"(public-key\n"
" (ecc\n"
" (curve \"Ed25519\")\n"
" (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321"
" 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)"
"))";
static const char ecc_public_key_comp[] =
"(public-key\n"
" (ecc\n"
" (curve \"Ed25519\")\n"
" (q #047b57c2c1d3ded93332b52d588dd45863478b658387413a718779c0dd1a6d95#)"
"))";
static const char hash_string[] =
"(data (flags rfc6979)\n"
" (hash sha256 #00112233445566778899AABBCCDDEEFF"
/* */ "000102030405060708090A0B0C0D0E0F#))";
gpg_error_t err;
gcry_sexp_t key, hash, sig;
if (verbose)
fprintf (stderr, "Checking sample Ed25519/ECDSA key.\n");
/* Sign. */
if ((err = gcry_sexp_new (&hash, hash_string, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_sign (&sig, hash, key)))
die ("gcry_pk_sign failed: %s", gpg_strerror (err));
/* Verify. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify failed: %s", gpg_strerror (err));
/* Verify again using a compressed public key. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify failed (comp): %s", gpg_strerror (err));
/* Sign without a Q parameter. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
gcry_sexp_release (sig);
if ((err = gcry_pk_sign (&sig, hash, key)))
die ("gcry_pk_sign w/o Q failed: %s", gpg_strerror (err));
/* Verify. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify signed w/o Q failed: %s", gpg_strerror (err));
/* Verify again using a compressed public key. */
gcry_sexp_release (key);
if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1)))
die ("line %d: %s", __LINE__, gpg_strerror (err));
if ((err = gcry_pk_verify (sig, hash, key)))
die ("gcry_pk_verify signed w/o Q failed (comp): %s", gpg_strerror (err));
extract_cmp_data (sig, "r", ("a63123a783ef29b8276e08987daca4"
"655d0179e22199bf63691fd88eb64e15"));
extract_cmp_data (sig, "s", ("0d9b45c696ab90b96b08812b485df185"
"623ddaf5d02fa65ca5056cb6bd0f16f1"));
gcry_sexp_release (sig);
gcry_sexp_release (key);
gcry_sexp_release (hash);
}
int
main (int argc, char **argv)
{
int i;
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
{
verbose = 2;
debug = 1;
}
xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
if (debug)
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);
for (i=0; i < 2; i++)
check_run ();
for (i=0; i < 4; i++)
check_x931_derived_key (i);
check_ecc_sample_key ();
if (!gcry_fips_mode_active ())
check_ed25519ecdsa_sample_key ();
return !!error_count;
}
diff --git a/tests/rsacvt.c b/tests/rsacvt.c
index 3d832640..52d713a3 100644
--- a/tests/rsacvt.c
+++ b/tests/rsacvt.c
@@ -1,399 +1,399 @@
/* rsacvt.c - A debug tool to convert RSA formats.
Copyright (C) 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/>.
+ License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
/* Input data format:
=======
# A hash denotes a comment line
e861b700e17e8afe68[...]f1
f7a7ca5367c661f8e6[...]61
10001
# After an empty line another input block may follow.
7861b700e17e8afe68[...]f3
e7a7ca5367c661f8e6[...]71
3
=========
*/
#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>
#ifdef HAVE_W32_SYSTEM
# include <fcntl.h> /* We need setmode(). */
#else
# include <signal.h>
#endif
#include <assert.h>
#include <unistd.h>
#ifdef _GCRYPT_IN_LIBGCRYPT
# include "../src/gcrypt-int.h"
#else
# include <gcrypt.h>
# define PACKAGE_BUGREPORT "devnull@example.org"
# define PACKAGE_VERSION "[build on " __DATE__ " " __TIME__ "]"
#endif
#define PGM "rsacvt"
#include "t-common.h"
/* Prefix output with labels. */
static int with_labels;
/* Do not suppress leading zeroes. */
static int keep_lz;
/* Create parameters as specified by OpenPGP (rfc4880). That is we
don't store dmp1 and dmp1 but d and make sure that p is less than q. */
static int openpgp_mode;
static char *
read_textline (FILE *fp)
{
char line[4096];
char *p;
int any = 0;
/* Read line but skip over initial empty lines. */
do
{
do
{
if (!fgets (line, sizeof line, fp))
{
if (feof (fp))
return NULL;
die ("error reading input line: %s\n", strerror (errno));
}
p = strchr (line, '\n');
if (p)
*p = 0;
p = line + (*line? (strlen (line)-1):0);
for ( ;p > line; p--)
if (my_isascii (*p) && isspace (*p))
*p = 0;
}
while (!any && !*line);
any = 1;
}
while (*line == '#'); /* Always skip comment lines. */
if (verbose > 1)
fprintf (stderr, PGM ": received line: %s\n", line);
return gcry_xstrdup (line);
}
static gcry_mpi_t
read_hexmpi_line (FILE *fp, int *got_eof)
{
gpg_error_t err;
gcry_mpi_t a;
char *line;
*got_eof = 0;
line = read_textline (fp);
if (!line)
{
*got_eof = 1;
return NULL;
}
err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
gcry_free (line);
if (err)
a = NULL;
return a;
}
static int
skip_to_empty_line (FILE *fp)
{
char line[256];
char *p;
do
{
if (!fgets (line, sizeof line, fp))
{
if (feof (fp))
return -1;
die ("error reading input line: %s\n", strerror (errno));
}
p = strchr (line, '\n');
if (p)
*p =0;
}
while (*line);
return 0;
}
/* Print an MPI on a line. */
static void
print_mpi_line (const char *label, gcry_mpi_t a)
{
unsigned char *buf, *p;
gcry_error_t err;
int writerr = 0;
if (with_labels && label)
printf ("%s = ", label);
err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a);
if (err)
die ("gcry_mpi_aprint failed: %s\n", gpg_strerror (err));
p = buf;
if (!keep_lz && p[0] == '0' && p[1] == '0' && p[2])
p += 2;
printf ("%s\n", p);
if (ferror (stdout))
writerr++;
if (!writerr && fflush (stdout) == EOF)
writerr++;
if (writerr)
die ("writing output failed: %s\n", strerror (errno));
gcry_free (buf);
}
/* Compute and print missing RSA parameters. */
static void
compute_missing (gcry_mpi_t rsa_p, gcry_mpi_t rsa_q, gcry_mpi_t rsa_e)
{
gcry_mpi_t rsa_n, rsa_d, rsa_pm1, rsa_qm1, rsa_u;
gcry_mpi_t phi, tmp_g, tmp_f;
rsa_n = gcry_mpi_new (0);
rsa_d = gcry_mpi_new (0);
rsa_pm1 = gcry_mpi_new (0);
rsa_qm1 = gcry_mpi_new (0);
rsa_u = gcry_mpi_new (0);
phi = gcry_mpi_new (0);
tmp_f = gcry_mpi_new (0);
tmp_g = gcry_mpi_new (0);
/* Check that p < q; if not swap p and q. */
if (openpgp_mode && gcry_mpi_cmp (rsa_p, rsa_q) > 0)
{
fprintf (stderr, PGM ": swapping p and q\n");
gcry_mpi_swap (rsa_p, rsa_q);
}
gcry_mpi_mul (rsa_n, rsa_p, rsa_q);
/* Compute the Euler totient: phi = (p-1)(q-1) */
gcry_mpi_sub_ui (rsa_pm1, rsa_p, 1);
gcry_mpi_sub_ui (rsa_qm1, rsa_q, 1);
gcry_mpi_mul (phi, rsa_pm1, rsa_qm1);
if (!gcry_mpi_gcd (tmp_g, rsa_e, phi))
die ("parameter 'e' does match 'p' and 'q'\n");
/* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
gcry_mpi_gcd (tmp_g, rsa_pm1, rsa_qm1);
gcry_mpi_div (tmp_f, NULL, phi, tmp_g, -1);
/* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */
gcry_mpi_invm (rsa_d, rsa_e, tmp_f);
/* Compute the CRT helpers: d mod (p-1), d mod (q-1) */
gcry_mpi_mod (rsa_pm1, rsa_d, rsa_pm1);
gcry_mpi_mod (rsa_qm1, rsa_d, rsa_qm1);
/* Compute the CRT value: OpenPGP: u = p^{-1} mod q
Standard: iqmp = q^{-1} mod p */
if (openpgp_mode)
gcry_mpi_invm (rsa_u, rsa_p, rsa_q);
else
gcry_mpi_invm (rsa_u, rsa_q, rsa_p);
gcry_mpi_release (phi);
gcry_mpi_release (tmp_f);
gcry_mpi_release (tmp_g);
/* Print everything. */
print_mpi_line ("n", rsa_n);
print_mpi_line ("e", rsa_e);
if (openpgp_mode)
print_mpi_line ("d", rsa_d);
print_mpi_line ("p", rsa_p);
print_mpi_line ("q", rsa_q);
if (openpgp_mode)
print_mpi_line ("u", rsa_u);
else
{
print_mpi_line ("dmp1", rsa_pm1);
print_mpi_line ("dmq1", rsa_qm1);
print_mpi_line ("iqmp", rsa_u);
}
gcry_mpi_release (rsa_n);
gcry_mpi_release (rsa_d);
gcry_mpi_release (rsa_pm1);
gcry_mpi_release (rsa_qm1);
gcry_mpi_release (rsa_u);
}
static void
usage (int show_help)
{
if (!show_help)
{
fputs ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n", stderr);
exit (2);
}
fputs
("Usage: " PGM " [OPTIONS] [FILE]\n"
"Take RSA parameters p, n, e and compute missing parameters.\n"
"OPTIONS:\n"
" --openpgp Compute as specified by RFC4880\n"
" --labels Prefix output with labels\n"
" --keep-lz Keep all leading zeroes in the output\n"
" --verbose Print additional information\n"
" --version Print version information\n"
" --help Print this text\n"
"With no FILE, or if FILE is -, read standard input.\n"
"Report bugs to " PACKAGE_BUGREPORT ".\n" , stdout);
exit (0);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
FILE *input;
gcry_mpi_t rsa_p, rsa_q, rsa_e;
int got_eof;
int any = 0;
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
usage (1);
}
else if (!strcmp (*argv, "--version"))
{
fputs (PGM " (Libgcrypt) " PACKAGE_VERSION "\n", stdout);
printf ("libgcrypt %s\n", gcry_check_version (NULL));
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--labels"))
{
with_labels = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--keep-lz"))
{
keep_lz = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--openpgp"))
{
openpgp_mode = 1;
argc--; argv++;
}
}
if (argc > 1)
usage (0);
#if !defined (HAVE_W32_SYSTEM) && !defined (_WIN32)
signal (SIGPIPE, SIG_IGN);
#endif
if (argc == 1 && strcmp (argv[0], "-"))
{
input = fopen (argv[0], "r");
if (!input)
die ("can't open `%s': %s\n", argv[0], strerror (errno));
}
else
input = stdin;
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);
do
{
rsa_p = read_hexmpi_line (input, &got_eof);
if (!rsa_p && got_eof)
break;
if (!rsa_p)
die ("RSA parameter 'p' missing or not properly hex encoded\n");
rsa_q = read_hexmpi_line (input, &got_eof);
if (!rsa_q)
die ("RSA parameter 'q' missing or not properly hex encoded\n");
rsa_e = read_hexmpi_line (input, &got_eof);
if (!rsa_e)
die ("RSA parameter 'e' missing or not properly hex encoded\n");
got_eof = skip_to_empty_line (input);
if (any)
putchar ('\n');
compute_missing (rsa_p, rsa_q, rsa_e);
gcry_mpi_release (rsa_p);
gcry_mpi_release (rsa_q);
gcry_mpi_release (rsa_e);
any = 1;
}
while (!got_eof);
return 0;
}
diff --git a/tests/stopwatch.h b/tests/stopwatch.h
index 696e3005..c5259d04 100644
--- a/tests/stopwatch.h
+++ b/tests/stopwatch.h
@@ -1,113 +1,113 @@
/* stopwatch.h - Helper code for timing
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <time.h>
#ifdef _WIN32
# include <winsock2.h>
# include <windows.h>
#else
# include <sys/times.h>
#endif
#ifdef _WIN32
struct
{
FILETIME creation_time, exit_time, kernel_time, user_time;
} started_at, stopped_at;
#else
static clock_t started_at, stopped_at;
#endif
static void
start_timer (void)
{
#ifdef _WIN32
#ifdef __MINGW32CE__
GetThreadTimes (GetCurrentThread (),
&started_at.creation_time, &started_at.exit_time,
&started_at.kernel_time, &started_at.user_time);
#else
GetProcessTimes (GetCurrentProcess (),
&started_at.creation_time, &started_at.exit_time,
&started_at.kernel_time, &started_at.user_time);
#endif
stopped_at = started_at;
#else
struct tms tmp;
times (&tmp);
started_at = stopped_at = tmp.tms_utime;
#endif
}
static void
stop_timer (void)
{
#ifdef _WIN32
#ifdef __MINGW32CE__
GetThreadTimes (GetCurrentThread (),
&stopped_at.creation_time, &stopped_at.exit_time,
&stopped_at.kernel_time, &stopped_at.user_time);
#else
GetProcessTimes (GetCurrentProcess (),
&stopped_at.creation_time, &stopped_at.exit_time,
&stopped_at.kernel_time, &stopped_at.user_time);
#endif
#else
struct tms tmp;
times (&tmp);
stopped_at = tmp.tms_utime;
#endif
}
static const char *
elapsed_time (unsigned int divisor)
{
static char buf[50];
#if _WIN32
unsigned long long t1, t2, t;
t1 = (((unsigned long long)started_at.kernel_time.dwHighDateTime << 32)
+ started_at.kernel_time.dwLowDateTime);
t1 += (((unsigned long long)started_at.user_time.dwHighDateTime << 32)
+ started_at.user_time.dwLowDateTime);
t2 = (((unsigned long long)stopped_at.kernel_time.dwHighDateTime << 32)
+ stopped_at.kernel_time.dwLowDateTime);
t2 += (((unsigned long long)stopped_at.user_time.dwHighDateTime << 32)
+ stopped_at.user_time.dwLowDateTime);
t = ((t2 - t1)/divisor)/10000;
if (divisor != 1)
snprintf (buf, sizeof buf, "%5.1fms", (double)t );
else
snprintf (buf, sizeof buf, "%5.0fms", (double)t );
#else
if (divisor != 1)
snprintf (buf, sizeof buf, "%5.1fms",
((((double) (stopped_at - started_at)/(double)divisor)
/CLOCKS_PER_SEC)*10000000));
else
snprintf (buf, sizeof buf, "%5.0fms",
(((double) (stopped_at - started_at)/CLOCKS_PER_SEC)*10000000));
#endif
return buf;
}
diff --git a/tests/t-common.h b/tests/t-common.h
index 2040f099..99b96175 100644
--- a/tests/t-common.h
+++ b/tests/t-common.h
@@ -1,198 +1,198 @@
/* t-common.h - Common code for the tests.
* Copyright (C) 2013 g10 Code GmbH
*
* This file is part of libgpg-error.
*
* libgpg-error 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.
*
* libgpg-error 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include "../src/gcrypt.h"
#ifndef PGM
# error Macro PGM not defined.
#endif
#ifndef _GCRYPT_CONFIG_H_INCLUDED
# error config.h not included
#endif
/* 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 xmalloc(a) gcry_xmalloc ((a))
#define xcalloc(a,b) gcry_xcalloc ((a),(b))
#define xstrdup(a) gcry_xstrdup ((a))
#define xfree(a) gcry_free ((a))
#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))
#define xmalloc(a) gcry_xmalloc ((a))
#define xcalloc(a,b) gcry_xcalloc ((a),(b))
#define xstrdup(a) gcry_xstrdup ((a))
#define xfree(a) gcry_free ((a))
#define pass() do { ; } while (0)
/* Standard global variables. */
static const char *wherestr;
static int verbose;
static int debug;
static int error_count;
static int die_on_error;
/* 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);
#endif /*GPGRT_ATTR_NORETURN*/
/* 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);
if (wherestr)
fprintf (stderr, "%s: ", wherestr);
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
fail (const char *format, ...)
{
va_list arg_ptr;
fflush (stdout);
#ifdef HAVE_FLOCKFILE
flockfile (stderr);
#endif
fprintf (stderr, "%s: ", PGM);
if (wherestr)
fprintf (stderr, "%s: ", wherestr);
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++;
if (error_count >= 50)
die ("stopped after 50 errors.");
}
static void
info (const char *format, ...)
{
va_list arg_ptr;
if (!verbose)
return;
#ifdef HAVE_FLOCKFILE
flockfile (stderr);
#endif
fprintf (stderr, "%s: ", PGM);
if (wherestr)
fprintf (stderr, "%s: ", wherestr);
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
}
/* Convenience macro for initializing gcrypt with error checking. */
#define xgcry_control(cmd...) \
do { \
gcry_error_t err__ = gcry_control (cmd); \
if (err__) \
die ("line %d: gcry_control (%s) failed: %s", \
__LINE__, #cmd, gcry_strerror (err__)); \
} while (0)
/* Split a string into colon delimited fields A pointer to each field
* is stored in ARRAY. Stop splitting at ARRAYSIZE fields. The
* function modifies STRING. The number of parsed fields is returned.
* Note that leading and trailing spaces are not removed from the fields.
* Example:
*
* char *fields[2];
* if (split_fields (string, fields, DIM (fields)) < 2)
* return // Not enough args.
* foo (fields[0]);
* foo (fields[1]);
*/
#ifdef NEED_EXTRA_TEST_SUPPORT
static int
split_fields_colon (char *string, char **array, int arraysize)
{
int n = 0;
char *p, *pend;
p = string;
do
{
if (n == arraysize)
break;
array[n++] = p;
pend = strchr (p, ':');
if (!pend)
break;
*pend++ = 0;
p = pend;
}
while (*p);
return n;
}
#endif /*NEED_EXTRA_TEST_SUPPORT*/
diff --git a/tests/t-convert.c b/tests/t-convert.c
index 121039c7..913fb257 100644
--- a/tests/t-convert.c
+++ b/tests/t-convert.c
@@ -1,534 +1,534 @@
/* t-convert.c - Tests for mpi print and scna functions
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#define PGM "t-convert"
#include "t-common.h"
static void
showhex (const char *prefix, const void *buffer, size_t buflen)
{
const unsigned char *s;
if (!verbose)
return;
fprintf (stderr, "%s: %s ", PGM, prefix);
for (s= buffer; buflen; buflen--, s++)
fprintf (stderr, "%02x", *s);
putc ('\n', stderr);
}
/* Allocate a bit string consisting of '0' and '1' from the MPI A. Do
not return any leading zero bits. Caller needs to gcry_free the
result. */
static char *
mpi2bitstr_nlz (gcry_mpi_t a)
{
char *p, *buf;
size_t length = gcry_mpi_get_nbits (a);
if (!length)
{
buf = p = xmalloc (3);
*p++ = ' ';
*p++ = '0';
}
else
{
buf = p = xmalloc (length + 1 + 1);
*p++ = gcry_mpi_is_neg (a)? '-':' ';
while (length-- > 1)
*p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
*p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
}
*p = 0;
return buf;
}
static void
showmpi (const char *prefix, gcry_mpi_t a)
{
char *bitstr;
if (!verbose)
return;
bitstr = mpi2bitstr_nlz (a);
fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
xfree (bitstr);
}
/* Check that mpi_print does not return a negative zero. */
static void
negative_zero (void)
{
gpg_error_t err;
gcry_mpi_t a;
char *buf;
void *bufaddr = &buf;
struct { const char *name; enum gcry_mpi_format format; } fmts[] =
{
{ "STD", GCRYMPI_FMT_STD },
{ "PGP", GCRYMPI_FMT_PGP },
{ "SSH", GCRYMPI_FMT_SSH },
{ "HEX", GCRYMPI_FMT_HEX },
{ "USG", GCRYMPI_FMT_USG },
{ NULL, 0 }
};
int i;
if (debug)
info ("negative zero printing\n");
a = gcry_mpi_new (0);
for (i=0; fmts[i].name; i++)
{
err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
if (err)
fail ("error printing a zero as %s: %s\n",
fmts[i].name,gpg_strerror (err) );
else
gcry_free (buf);
}
/* With the current version of libgcrypt the next two statements
should set a to -0. */
gcry_mpi_sub_ui (a, a, 1);
gcry_mpi_add_ui (a, a, 1);
for (i=0; fmts[i].name; i++)
{
err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
if (err)
fail ("error printing a negative zero as %s: %s\n",
fmts[i].name,gpg_strerror (err) );
else
gcry_free (buf);
}
gcry_mpi_release (a);
}
static void
check_formats (void)
{
static struct {
int value;
struct {
const char *hex;
size_t stdlen;
const char *std;
size_t sshlen;
const char *ssh;
size_t usglen;
const char *usg;
size_t pgplen;
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" }
}
};
gpg_error_t err;
gcry_mpi_t a, b;
char *buf;
void *bufaddr = &buf;
int idx;
size_t buflen;
a = gcry_mpi_new (0);
for (idx=0; idx < DIM(data); idx++)
{
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);
}
else
gcry_mpi_set_ui (a, data[idx].value);
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));
else
{
if (strcmp (buf, data[idx].a.hex))
{
fail ("error printing value %d as %s: %s\n",
data[idx].value, "HEX", "wrong result");
info ("expected: '%s'\n", data[idx].a.hex);
info (" got: '%s'\n", buf);
}
gcry_free (buf);
}
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));
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");
showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
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));
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");
showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
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));
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");
showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, bufaddr, &buflen, a);
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");
}
else if (err)
fail ("error printing value %d as %s: %s\n",
data[idx].value, "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");
showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
showhex (" got:", buf, buflen);
}
gcry_free (buf);
}
}
/* Now for the other direction. */
for (idx=0; idx < DIM(data); idx++)
{
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);
}
else
gcry_mpi_set_ui (a, data[idx].value);
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));
else
{
if (gcry_mpi_cmp (a, b))
{
fail ("error scanning value %d from %s: %s\n",
data[idx].value, "HEX", "wrong result");
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
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));
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",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
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));
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",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
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));
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",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
/* Negative values are not supported by PGP, thus we don't have
an samples. */
if (!gcry_mpi_is_neg (a))
{
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));
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",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
}
gcry_mpi_release (b);
}
}
}
gcry_mpi_release (a);
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
verbose = debug = 1;
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
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);
negative_zero ();
check_formats ();
info ("All tests completed. Errors: %d\n", error_count);
return error_count ? 1 : 0;
}
diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c
index 8c4a53eb..c78383bf 100644
--- a/tests/t-cv25519.c
+++ b/tests/t-cv25519.c
@@ -1,571 +1,571 @@
/* t-cv25519.c - Check the cv25519 crypto
* Copyright (C) 2016 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/>.
+ * 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-cv25519"
#include "t-common.h"
#define N_TESTS 18
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 X25519 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 X25519 (K, U).
*
* It calls gcry_pk_decrypt 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)
{
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 != 32)
{
fail ("error building s-exp for test %d, %s: %s",
testno, "k", "invalid hex string");
goto leave;
}
reverse_buffer (buffer, buflen);
if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
{
fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err));
goto leave;
}
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;
}
xfree (buffer);
if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32)
{
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 \"Curve25519\")"
" (flags djb-tweak)"
" (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;
if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk)))
fail ("gcry_pk_encrypt failed 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;
/* To skip the prefix 0x40, for-loop start with i=1 */
r0 = r = xmalloc (2*(res_len)+1);
if (!r0)
{
fail ("memory allocation for test %d", testno);
goto leave;
}
for (i=1; 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 iterative X25519 computation through lower layer MPI routines.
*
* Input: K (as hex string), ITER, R (as hex string)
*
* where R is expected result of iterating X25519 by ITER times.
*
*/
static void
test_it (int testno, const char *k_str, int iter, const char *result_str)
{
gcry_ctx_t ctx;
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, "Curve25519");
Q = gcry_mpi_point_new (0);
if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
{
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 decodeScalar25519 thing.
*/
mpi_kk = gcry_mpi_set (mpi_kk, mpi_k);
gcry_mpi_set_bit (mpi_kk, 254);
gcry_mpi_clear_bit (mpi_kk, 255);
gcry_mpi_clear_bit (mpi_kk, 0);
gcry_mpi_clear_bit (mpi_kk, 1);
gcry_mpi_clear_bit (mpi_kk, 2);
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[32];
char *r, *r0;
gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k);
reverse_buffer (res, 32);
r0 = r = xmalloc (65);
if (!r0)
{
fail ("memory allocation for test %d", testno);
goto leave;
}
for (i=0; i < 32; i++, r += 2)
snprintf (r, 3, "%02x", res[i]);
if (strcmp (result_str, r0))
{
fail ("curv25519 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 Curve25519.
*/
#define G_X "0900000000000000000000000000000000000000000000000000000000000000"
/*
* 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_cv25519 (void)
{
int ntests;
info ("Checking Curve25519.\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,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
"c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552");
ntests++;
test_cv (2,
"4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
"e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
"95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957");
ntests++;
/*
* Additional test. Value is from second type test.
*/
test_cv (3,
G_X,
G_X,
"422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079");
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,
"422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079");
ntests++;
test_it (5,
G_X,
1000,
"684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51");
ntests++;
/*
* Last test is from: 6. Diffie-Hellman, 6.1. Curve25519
*/
test_dh (6,
/* Alice's private key, a */
"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
/* Alice's public key, X25519(a, 9) */
"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
/* Bob's private key, b */
"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
/* Bob's public key, X25519(b, 9) */
"de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
/* Their shared secret, K */
"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
ntests++;
/* Seven tests which results 0. */
test_cv (7,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (8,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"0100000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (9,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (10,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (11,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (12,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
test_cv (13,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"0000000000000000000000000000000000000000000000000000000000000000");
ntests++;
/* Five tests which resulted 0 if decodeUCoordinate didn't change MSB. */
test_cv (14,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
"7ce548bc4919008436244d2da7a9906528fe3a6d278047654bd32d8acde9707b");
ntests++;
test_cv (15,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
"e17902e989a034acdf7248260e2c94cdaf2fe1e72aaac7024a128058b6189939");
ntests++;
test_cv (16,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ea6e6ddf0685c31e152d5818441ac9ac8db1a01f3d6cb5041b07443a901e7145");
ntests++;
test_cv (17,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"845ddce7b3a9b3ee01a2f1fd4282ad293310f7a232cbc5459fb35d94bccc9d05");
ntests++;
test_cv (18,
"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
"dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"6989e2cb1cea159acf121b0af6bf77493189c9bd32c2dac71669b540f9488247");
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);
start_timer ();
check_cv25519 ();
stop_timer ();
info ("All tests completed in %s. Errors: %d\n",
elapsed_time (1), error_count);
return !!error_count;
}
diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c
index 73628a81..b6f313cf 100644
--- a/tests/t-ed25519.c
+++ b/tests/t-ed25519.c
@@ -1,497 +1,497 @@
/* t-ed25519.c - Check the Ed25519 crypto
* Copyright (C) 2013 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/>.
+ * 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-ed25519"
#include "t-common.h"
#define N_TESTS 1026
static int sign_with_pk;
static int no_verify;
static int custom_data_file;
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, const char *sk, const char *pk,
const char *msg, 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\n", testno);
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 \"Ed25519\")"
" (flags eddsa)"
" (q %b)"
" (d %b)))",
(int)buflen2, buffer2,
(int)buflen, buffer);
else
err = gcry_sexp_build (&s_sk, NULL,
"(private-key"
" (ecc"
" (curve \"Ed25519\")"
" (flags eddsa)"
" (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 \"Ed25519\")"
" (flags eddsa)"
" (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 ((err = gcry_sexp_build (&s_msg, NULL,
"(data"
" (flags eddsa)"
" (hash-algo sha512)"
" (value %b))", (int)buflen, buffer)))
{
fail ("error building s-exp for test %d, %s: %s",
testno, "msg", gpg_strerror (err));
goto leave;
}
if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk)))
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_ed25519 (const char *fname)
{
FILE *fp;
int lineno, ntests;
char *line;
int testno;
char *sk, *pk, *msg, *sig;
info ("Checking Ed25519.\n");
fp = fopen (fname, "r");
if (!fp)
die ("error opening '%s': %s\n", fname, strerror (errno));
testno = 0;
sk = pk = msg = sig = NULL;
lineno = ntests = 0;
while ((line = read_textline (fp, &lineno)))
{
if (!strncmp (line, "TST:", 4))
testno = atoi (line+4);
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, "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, sk, pk, msg, sig);
ntests++;
if (!(ntests % 256))
show_note ("%d of %d tests done\n", ntests, N_TESTS);
xfree (pk); pk = NULL;
xfree (sk); sk = NULL;
xfree (msg); msg = NULL;
xfree (sig); sig = NULL;
}
}
xfree (pk);
xfree (sk);
xfree (msg);
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-ed25519.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);
/* Ed25519 isn't supported in fips mode */
if (gcry_fips_mode_active())
return 77;
start_timer ();
check_ed25519 (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-ed25519.inp b/tests/t-ed25519.inp
index e13566f8..b40c85fe 100644
--- a/tests/t-ed25519.inp
+++ b/tests/t-ed25519.inp
@@ -1,6172 +1,6172 @@
# t-ed25519.inp - 1024 test data sets
# This has been taken from
-# http://ed25519.cr.yp.to/python/sign.input
+# https://ed25519.cr.yp.to/python/sign.input
# which distributed them as public domain.
# For our use converted using this script:
# awk -F: 'BEGIN {n=1} { print "TST: " n; n++; \
# print "SK: " substr($1,0,64); print "PK: " $2;\
# print "MSG: " $3; print "SIG: " substr($4,0,128); print ""}'
#
# The PK appended to the SK and the MSG appended to the SIG have been
# stripped. A few additional tests have been added to the 1024
# original tests.
TST: 1
SK: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
PK: d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a
MSG:
SIG: e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b
TST: 2
SK: 4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb
PK: 3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c
MSG: 72
SIG: 92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00
TST: 3
SK: c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7
PK: fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025
MSG: af82
SIG: 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a
TST: 4
SK: 0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9
PK: e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057
MSG: cbc77b
SIG: d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00c
TST: 5
SK: 6df9340c138cc188b5fe4464ebaa3f7fc206a2d55c3434707e74c9fc04e20ebb
PK: c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7
MSG: 5f4c8989
SIG: 124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c07
TST: 6
SK: b780381a65edf8b78f6945e8dbec7941ac049fd4c61040cf0c324357975a293c
PK: e253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01
MSG: 18b6bec097
SIG: b2fc46ad47af464478c199e1f8be169f1be6327c7f9a0a6689371ca94caf04064a01b22aff1520abd58951341603faed768cf78ce97ae7b038abfe456aa17c09
TST: 7
SK: 78ae9effe6f245e924a7be63041146ebc670dbd3060cba67fbc6216febc44546
PK: fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d
MSG: 89010d855972
SIG: 6ed629fc1d9ce9e1468755ff636d5a3f40a5d9c91afd93b79d241830f7e5fa29854b8f20cc6eecbb248dbd8d16d14e99752194e4904d09c74d639518839d2300
TST: 8
SK: 691865bfc82a1e4b574eecde4c7519093faf0cf867380234e3664645c61c5f79
PK: 98a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63
MSG: b4a8f381e70e7a
SIG: 6e0af2fe55ae377a6b7a7278edfb419bd321e06d0df5e27037db8812e7e3529810fa5552f6c0020985ca17a0e02e036d7b222a24f99b77b75fdd16cb05568107
TST: 9
SK: 3b26516fb3dc88eb181b9ed73f0bcd52bcd6b4c788e4bcaf46057fd078bee073
PK: f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863
MSG: 4284abc51bb67235
SIG: d6addec5afb0528ac17bb178d3e7f2887f9adbb1ad16e110545ef3bc57f9de2314a5c8388f723b8907be0f3ac90c6259bbe885ecc17645df3db7d488f805fa08
TST: 10
SK: edc6f5fbdd1cee4d101c063530a30490b221be68c036f5b07d0f953b745df192
PK: c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd
MSG: 672bf8965d04bc5146
SIG: 2c76a04af2391c147082e33faacdbe56642a1e134bd388620b852b901a6bc16ff6c9cc9404c41dea12ed281da067a1513866f9d964f8bdd24953856c50042901
TST: 11
SK: 4e7d21fb3b1897571a445833be0f9fd41cd62be3aa04040f8934e1fcbdcacd45
PK: 31b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff
MSG: 33d7a786aded8c1bf691
SIG: 28e4598c415ae9de01f03f9f3fab4e919e8bf537dd2b0cdf6e79b9e6559c9409d9151a4c40f083193937627c369488259e99da5a9f0a87497fa6696a5dd6ce08
TST: 12
SK: a980f892db13c99a3e8971e965b2ff3d41eafd54093bc9f34d1fd22d84115bb6
PK: 44b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f
MSG: 3486f68848a65a0eb5507d
SIG: 77d389e599630d934076329583cd4105a649a9292abc44cd28c40000c8e2f5ac7660a81c85b72af8452d7d25c070861dae91601c7803d656531650dd4e5c4100
TST: 13
SK: 5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef9
PK: 6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257
MSG: 5a8d9d0a22357e6655f9c785
SIG: 0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e
TST: 14
SK: 940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800
PK: a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd
MSG: b87d3813e03f58cf19fd0b6395
SIG: d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0c
TST: 15
SK: 9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738
PK: cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291
MSG: 55c7fa434f5ed8cdec2b7aeac173
SIG: 6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf06
TST: 16
SK: d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300
PK: fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5
MSG: 0a688e79be24f866286d4646b5d81c
SIG: f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f35503951fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b00
TST: 17
SK: 0a47d10452ae2febec518a1c7c362890c3fc1a49d34b03b6467d35c904a8362d
PK: 34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b
MSG: c942fa7ac6b23ab7ff612fdc8e68ef39
SIG: 2a3d27dc40d0a8127949a3b7f908b3688f63b7f14f651aacd715940bdbe27a0809aac142f47ab0e1e44fa490ba87ce5392f33a891539caf1ef4c367cae54500c
TST: 18
SK: f8148f7506b775ef46fdc8e8c756516812d47d6cfbfa318c27c9a22641e56f17
PK: 0445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372
MSG: 7368724a5b0efb57d28d97622dbde725af
SIG: 3653ccb21219202b8436fb41a32ba2618c4a133431e6e63463ceb3b6106c4d56e1d2ba165ba76eaad3dc39bffb130f1de3d8e6427db5b71938db4e272bc3e20b
TST: 19
SK: 77f88691c4eff23ebb7364947092951a5ff3f10785b417e918823a552dab7c75
PK: 74d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b
MSG: bd8e05033f3a8bcdcbf4beceb70901c82e31
SIG: fbe929d743a03c17910575492f3092ee2a2bf14a60a3fcacec74a58c7334510fc262db582791322d6c8c41f1700adb80027ecabc14270b703444ae3ee7623e0a
TST: 20
SK: ab6f7aee6a0837b334ba5eb1b2ad7fcecfab7e323cab187fe2e0a95d80eff132
PK: 5b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c
MSG: 8171456f8b907189b1d779e26bc5afbb08c67a
SIG: 73bca64e9dd0db88138eedfafcea8f5436cfb74bfb0e7733cf349baa0c49775c56d5934e1d38e36f39b7c5beb0a836510c45126f8ec4b6810519905b0ca07c09
TST: 21
SK: 8d135de7c8411bbdbd1b31e5dc678f2ac7109e792b60f38cd24936e8a898c32d
PK: 1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f
MSG: 8ba6a4c9a15a244a9c26bb2a59b1026f21348b49
SIG: a1adc2bc6a2d980662677e7fdff6424de7dba50f5795ca90fdf3e96e256f3285cac71d3360482e993d0294ba4ec7440c61affdf35fe83e6e04263937db93f105
TST: 22
SK: 0e765d720e705f9366c1ab8c3fa84c9a44370c06969f803296884b2846a652a4
PK: 7fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8
MSG: 1d566a6232bbaab3e6d8804bb518a498ed0f904986
SIG: bb61cf84de61862207c6a455258bc4db4e15eea0317ff88718b882a06b5cf6ec6fd20c5a269e5d5c805bafbcc579e2590af414c7c227273c102a10070cdfe80f
TST: 23
SK: db36e326d676c2d19cc8fe0c14b709202ecfc761d27089eb6ea4b1bb021ecfa7
PK: 48359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85
MSG: 1b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4
SIG: b6dcd09989dfbac54322a3ce87876e1d62134da998c79d24b50bd7a6a797d86a0e14dc9d7491d6c14a673c652cfbec9f962a38c945da3b2f0879d0b68a921300
TST: 24
SK: c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77
PK: fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c
MSG: 507c94c8820d2a5793cbf3442b3d71936f35fe3afef316
SIG: 7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c
TST: 25
SK: 4e62627fc221142478aee7f00781f817f662e3b75db29bb14ab47cf8e84104d6
PK: b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107
MSG: d3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5
SIG: 836afa764d9c48aa4770a4388b654e97b3c16f082967febca27f2fc47ddfd9244b03cfc729698acf5109704346b60b230f255430089ddc56912399d1122de70a
TST: 26
SK: 6b83d7da8908c3e7205b39864b56e5f3e17196a3fc9c2f5805aad0f5554c142d
PK: d0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6
MSG: 6ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c
SIG: 16e462a29a6dd498685a3718b3eed00cc1598601ee47820486032d6b9acc9bf89f57684e08d8c0f05589cda2882a05dc4c63f9d0431d6552710812433003bc08
TST: 27
SK: 19a91fe23a4e9e33ecc474878f57c64cf154b394203487a7035e1ad9cd697b0d
PK: 2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23
MSG: 82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c
SIG: 881f5b8c5a030df0f75b6634b070dd27bd1ee3c08738ae349338b3ee6469bbf9760b13578a237d5182535ede121283027a90b5f865d63a6537dca07b44049a0f
TST: 28
SK: 1d5b8cb6215c18141666baeefcf5d69dad5bea9a3493dddaa357a4397a13d4de
PK: 94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835
MSG: a9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0
SIG: 3acd39bec8c3cd2b44299722b5850a0400c1443590fd4861d59aae7496acb3df73fc3fdf7969ae5f50ba47dddc435246e5fd376f6b891cd4c2caf5d614b6170c
TST: 29
SK: 6a91b3227c472299089bdce9356e726a40efd840f11002708b7ee55b64105ac2
PK: 9d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e
MSG: 5cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc
SIG: f5875423781b66216cb5e8998de5d9ffc29d1d67107054ace3374503a9c3ef811577f269de81296744bd706f1ac478caf09b54cdf871b3f802bd57f9a6cb9101
TST: 30
SK: 93eaa854d791f05372ce72b94fc6503b2ff8ae6819e6a21afe825e27ada9e4fb
PK: 16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5
MSG: 32fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5
SIG: d834197c1a3080614e0a5fa0aaaa808824f21c38d692e6ffbd200f7dfb3c8f44402a7382180b98ad0afc8eec1a02acecf3cb7fde627b9f18111f260ab1db9a07
TST: 31
SK: 941cac69fb7b1815c57bb987c4d6c2ad2c35d5f9a3182a79d4ba13eab253a8ad
PK: 23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b
MSG: bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa
SIG: 0f8fad1e6bde771b4f5420eac75c378bae6db5ac6650cd2bc210c1823b432b48e016b10595458ffab92f7a8989b293ceb8dfed6c243a2038fc06652aaaf16f02
TST: 32
SK: 1acdbb793b0384934627470d795c3d1dd4d79cea59ef983f295b9b59179cbb28
PK: 3f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a
MSG: 7cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56
SIG: be71ef4806cb041d885effd9e6b0fbb73d65d7cdec47a89c8a994892f4e55a568c4cc78d61f901e80dbb628b86a23ccd594e712b57fa94c2d67ec26634878507
TST: 33
SK: 8ed7a797b9cea8a8370d419136bcdf683b759d2e3c6947f17e13e2485aa9d420
PK: b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9
MSG: a750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3
SIG: 04266c033b91c1322ceb3446c901ffcf3cc40c4034e887c9597ca1893ba7330becbbd8b48142ef35c012c6ba51a66df9308cb6268ad6b1e4b03e70102495790b
TST: 34
SK: f2ab396fe8906e3e5633e99cabcd5b09df0859b516230b1e0450b580b65f616c
PK: 8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b
MSG: 5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187
SIG: a06a23d982d81ab883aae230adbc368a6a9977f003cebb00d4c2e4018490191a84d3a282fdbfb2fc88046e62de43e15fb575336b3c8b77d19ce6a009ce51f50c
TST: 35
SK: 550a41c013f79bab8f06e43ad1836d51312736a9713806fafe6645219eaa1f9d
PK: af6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0
MSG: 8bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27
SIG: 16dc1e2b9fa909eefdc277ba16ebe207b8da5e91143cde78c5047a89f681c33c4e4e3428d5c928095903a811ec002d52a39ed7f8b3fe1927200c6dd0b9ab3e04
TST: 36
SK: 19ac3e272438c72ddf7b881964867cb3b31ff4c793bb7ea154613c1db068cb7e
PK: f85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f
MSG: 95872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645
SIG: ea855d781cbea4682e350173cb89e8619ccfddb97cdce16f9a2f6f6892f46dbe68e04b12b8d88689a7a31670cdff409af98a93b49a34537b6aa009d2eb8b4701
TST: 37
SK: ca267de96c93c238fafb1279812059ab93ac03059657fd994f8fa5a09239c821
PK: 017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26
MSG: e05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531
SIG: ac957f82335aa7141e96b59d63e3ccee95c3a2c47d026540c2af42dc9533d5fd81827d1679ad187aeaf37834915e75b147a9286806c8017516ba43dd051a5e0c
TST: 38
SK: 3dff5e899475e7e91dd261322fab09980c52970de1da6e2e201660cc4fce7032
PK: f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b
MSG: 938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382
SIG: 5efe7a92ff9623089b3e3b78f352115366e26ba3fb1a416209bc029e9cadccd9f4affa333555a8f3a35a9d0f7c34b292cae77ec96fa3adfcaadee2d9ced8f805
TST: 39
SK: 9a6b847864e70cfe8ba6ab22fa0ca308c0cc8bec7141fbcaa3b81f5d1e1cfcfc
PK: 34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930
MSG: 838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da
SIG: 2ab255169c489c54c732232e37c87349d486b1eba20509dbabe7fed329ef08fd75ba1cd145e67b2ea26cb5cc51cab343eeb085fe1fd7b0ec4c6afcd9b979f905
TST: 40
SK: 575be07afca5d063c238cd9b8028772cc49cda34471432a2e166e096e2219efc
PK: 94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0
MSG: 33e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e
SIG: 58271d44236f3b98c58fd7ae0d2f49ef2b6e3affdb225aa3ba555f0e11cc53c23ad19baf24346590d05d7d5390582082cf94d39cad6530ab93d13efb39279506
TST: 41
SK: 15ffb45514d43444d61fcb105e30e135fd268523dda20b82758b179423110441
PK: 1772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8
MSG: da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e
SIG: 6828cd7624e793b8a4ceb96d3c2a975bf773e5ff6645f353614058621e58835289e7f31f42dfe6af6d736f2644511e320c0fa698582a79778d18730ed3e8cb08
TST: 42
SK: fe0568642943b2e1afbfd1f10fe8df87a4236bea40dce742072cb21886eec1fa
PK: 299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61
MSG: c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d
SIG: d59e6dfcc6d7e3e2c58dec81e985d245e681acf6594a23c59214f7bed8015d813c7682b60b3583440311e72a8665ba2c96dec23ce826e160127e18132b030404
TST: 43
SK: 5ecb16c2df27c8cf58e436a9d3affbd58e9538a92659a0f97c4c4f994635a8ca
PK: da768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d
MSG: 56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9
SIG: 1c723a20c6772426a670e4d5c4a97c6ebe9147f71bb0a415631e44406e290322e4ca977d348fe7856a8edc235d0fe95f7ed91aefddf28a77e2c7dbfd8f552f0a
TST: 44
SK: d599d637b3c30a82a9984e2f758497d144de6f06b9fba04dd40fd949039d7c84
PK: 6791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f
MSG: a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e
SIG: ebf10d9ac7c96108140e7def6fe9533d727646ff5b3af273c1df95762a66f32b65a09634d013f54b5dd6011f91bc336ca8b355ce33f8cfbec2535a4c427f8205
TST: 45
SK: 30ab8232fa7018f0ce6c39bd8f782fe2e159758bb0f2f4386c7f28cfd2c85898
PK: ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37
MSG: 63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc
SIG: 9af885344cc7239498f712df80bc01b80638291ed4a1d28baa5545017a72e2f65649ccf9603da6eb5bfab9f5543a6ca4a7af3866153c76bf66bf95def615b00c
TST: 46
SK: 0ddcdc872c7b748d40efe96c2881ae189d87f56148ed8af3ebbbc80324e38bdd
PK: 588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85
MSG: 65641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12
SIG: c179c09456e235fe24105afa6e8ec04637f8f943817cd098ba95387f9653b2add181a31447d92d1a1ddf1ceb0db62118de9dffb7dcd2424057cbdff5d41d0403
TST: 47
SK: 89f0d68299ba0a5a83f248ae0c169f8e3849a9b47bd4549884305c9912b46603
PK: aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832
MSG: 4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05
SIG: 2c691fa8d487ce20d5d2fa41559116e0bbf4397cf5240e152556183541d66cf753582401a4388d390339dbef4d384743caa346f55f8daba68ba7b9131a8a6e0b
TST: 48
SK: 0a3c1844e2db070fb24e3c95cb1cc6714ef84e2ccd2b9dd2f1460ebf7ecf13b1
PK: 72e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01
MSG: 4c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957
SIG: 87f7fdf46095201e877a588fe3e5aaf476bd63138d8a878b89d6ac60631b3458b9d41a3c61a588e1db8d29a5968981b018776c588780922f5aa732ba6379dd05
TST: 49
SK: c8d7a8818b98dfdb20839c871cb5c48e9e9470ca3ad35ba2613a5d3199c8ab23
PK: 90d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f
MSG: 783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff
SIG: fa2e994421aef1d5856674813d05cbd2cf84ef5eb424af6ecd0dc6fdbdc2fe605fe985883312ecf34f59bfb2f1c9149e5b9cc9ecda05b2731130f3ed28ddae0b
TST: 50
SK: b482703612d0c586f76cfcb21cfd2103c957251504a8c0ac4c86c9c6f3e429ff
PK: fd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad
MSG: 29d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b
SIG: 58832bdeb26feafc31b46277cf3fb5d7a17dfb7ccd9b1f58ecbe6feb979666828f239ba4d75219260ecac0acf40f0e5e2590f4caa16bbbcd8a155d347967a607
TST: 51
SK: 84e50dd9a0f197e3893c38dbd91fafc344c1776d3a400e2f0f0ee7aa829eb8a2
PK: 2c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea
MSG: f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123
SIG: 69e6a4491a63837316e86a5f4ba7cd0d731ecc58f1d0a264c67c89befdd8d3829d8de13b33cc0bf513931715c7809657e2bfb960e5c764c971d733746093e500
TST: 52
SK: b322d46577a2a991a4d1698287832a39c487ef776b4bff037a05c7f1812bdeec
PK: eb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f
MSG: 19f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5
SIG: c7b55137317ca21e33489ff6a9bfab97c855dc6f85684a70a9125a261b56d5e6f149c5774d734f2d8debfc77b721896a8267c23768e9badb910eef83ec258802
TST: 53
SK: 960cab5034b9838d098d2dcbf4364bec16d388f6376d73a6273b70f82bbc98c0
PK: 5e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a
MSG: f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308
SIG: 27d4c3a1811ef9d4360b3bdd133c2ccc30d02c2f248215776cb07ee4177f9b13fc42dd70a6c2fed8f225c7663c7f182e7ee8eccff20dc7b0e1d5834ec5b1ea01
TST: 54
SK: eb77b2638f23eebc82efe45ee9e5a0326637401e663ed029699b21e6443fb48e
PK: 9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc
MSG: 99e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab
SIG: 18dc56d7bd9acd4f4daa78540b4ac8ff7aa9815f45a0bba370731a14eaabe96df8b5f37dbf8eae4cb15a64b244651e59d6a3d6761d9e3c50f2d0cbb09c05ec06
TST: 55
SK: b625aa89d3f7308715427b6c39bbac58effd3a0fb7316f7a22b99ee5922f2dc9
PK: 65a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e
MSG: e07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a
SIG: 01bb901d83b8b682d3614af46a807ba2691358feb775325d3423f549ff0aa5757e4e1a74e9c70f9721d8f354b319d4f4a1d91445c870fd0ffb94fed64664730d
TST: 56
SK: b1c9f8bd03fe82e78f5c0fb06450f27dacdf716434db268275df3e1dc177af42
PK: 7fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf
MSG: 331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2
SIG: 4b229951ef262f16978f7914bc672e7226c5f8379d2778c5a2dc0a2650869f7acfbd0bcd30fdb0619bb44fc1ae5939b87cc318133009c20395b6c7eb98107701
TST: 57
SK: 6d8cdb2e075f3a2f86137214cb236ceb89a6728bb4a200806bf3557fb78fac69
PK: 57a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda
MSG: 7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf
SIG: a6cbc947f9c87d1455cf1a708528c090f11ecee4855d1dbaadf47454a4de55fa4ce84b36d73a5b5f8f59298ccf21992df492ef34163d87753b7e9d32f2c3660b
TST: 58
SK: 47adc6d6bf571ee9570ca0f75b604ac43e303e4ab339ca9b53cacc5be45b2ccb
PK: a3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be
MSG: ce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739
SIG: 4e8c318343c306adbba60c92b75cb0569b9219d8a86e5d57752ed235fc109a43c2cf4e942cacf297279fbb28675347e08027722a4eb7395e00a17495d32edf0b
TST: 59
SK: 3c19b50b0fe47961719c381d0d8da9b9869d312f13e3298b97fb22f0af29cbbe
PK: 0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612
MSG: 8ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f
SIG: efbd41f26a5d62685516f882b6ec74e0d5a71830d203c231248f26e99a9c6578ec900d68cdb8fa7216ad0d24f9ecbc9ffa655351666582f626645395a31fa704
TST: 60
SK: 34e1e9d539107eb86b393a5ccea1496d35bc7d5e9a8c5159d957e4e5852b3eb0
PK: 0ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76
MSG: a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0
SIG: 32d22904d3e7012d6f5a441b0b4228064a5cf95b723a66b048a087ecd55920c31c204c3f2006891a85dd1932e3f1d614cfd633b5e63291c6d8166f3011431e09
TST: 61
SK: 49dd473ede6aa3c866824a40ada4996c239a20d84c9365e4f0a4554f8031b9cf
PK: 788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501
MSG: 3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c
SIG: d2fde02791e720852507faa7c3789040d9ef86646321f313ac557f4002491542dd67d05c6990cdb0d495501fbc5d5188bfbb84dc1bf6098bee0603a47fc2690f
TST: 62
SK: 331c64da482b6b551373c36481a02d8136ecadbb01ab114b4470bf41607ac571
PK: 52a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521
MSG: 20e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3
SIG: 22c99aa946ead39ac7997562810c01c20b46bd610645bd2d56dcdcbaacc5452c74fbf4b8b1813b0e94c30d808ce5498e61d4f7ccbb4cc5f04dfc6140825a9600
TST: 63
SK: 5c0b96f2af8712122cf743c8f8dc77b6cd5570a7de13297bb3dde1886213cce2
PK: 0510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1
MSG: 54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575
SIG: 06e5d8436ac7705b3a90f1631cdd38ec1a3fa49778a9b9f2fa5ebea4e7d560ada7dd26ff42fafa8ba420323742761aca6904940dc21bbef63ff72daab45d430b
TST: 64
SK: de84f2435f78dedb87da18194ff6a336f08111150def901c1ac418146eb7b54a
PK: d3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2
MSG: 205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab
SIG: 471ebc973cfdaceec07279307368b73be35bc6f8d8312b70150567369096706dc471126c3576f9f0eb550df5ac6a525181110029dd1fc11174d1aaced48d630f
TST: 65
SK: ba4d6e67b2ce67a1e44326494044f37a442f3b81725bc1f9341462718b55ee20
PK: f73fa076f84b6db675a5fda5ad67e351a41e8e7f29add16809ca010387e9c6cc
MSG: 4bafdac9099d4057ed6dd08bcaee8756e9a40f2cb9598020eb95019528409bbea38b384a59f119f57297bfb2fa142fc7bb1d90dbddde772bcde48c5670d5fa13
SIG: 57b9d2a711207f837421bae7dd48eaa18eab1a9a70a0f1305806fee17b458f3a0964b302d1834d3e0ac9e8496f000b77f0083b41f8a957e632fbc7840eee6a06
TST: 66
SK: 0d131c45aea6f3a4e1b9a2cf60c55104587efaa846b222bf0a7b74ce7a3f63b6
PK: 3c6729dbe93b499c4e614a2f21beb729438d498e1ac8d14cbad9717a5dbd97cd
MSG: b4291d08b88fb2f7b8f99d0dce40079fcbab718bbd8f4e8eabc3c1428b6a071fb2a3c8eba1cacccfa871b365c708bef2685bc13e6b80bc14a5f249170ffc56d014
SIG: a9c5ee86fb06d9e46b379c32dda7c92c9c13db274dc24116fbdd878696045488cc75a52fff67d1a5113d06e333ac67ff664b3f2a405fa1d14dd5bbb97409b606
TST: 67
SK: a75e3b6b4170e444781be4eeac3e0fdaa4b4356f705486bcb071a325ae071fba
PK: 993d38a7d72f0aee15ff6f4fdc37ca7724fd1373a3766b275dbc77e647980e0a
MSG: 4037866f6548b01cc6bcf3a940e3945aa2d188b4b7f182aa77ec4d6b0428ab5b84d85df192a5a38ada089d76fa26bf67736a7041a5eb8f0c5719eb396693c45160f8
SIG: a5db4d3d3329abe3697959e6b5947ea8601b03ef8e1d6fe202144931272ca0a09b5eb0f390572ea7ef03c6131e9de5f16bf0b034244f7e104ff5311bbf663a0d
TST: 68
SK: bcbcf561ecc05a41c7d7e55e696d32ce39b4d03c1f5f3f3a8927fe5e62e844b2
PK: 4ddf53fad6a7a9ed30f3afecca136fd7843b72c243090891ae4021a32cadff1a
MSG: 6f6716b6784740980aebc3248807e31c1286ac7b681c00b66c88ff7a336d441fa5c3eb256d20cf6d1ac92ccfe4be6dcc41b1aff846d360c243001cabdfbf1a9b240455
SIG: 9ff15115f6661f3211d7a40764967629ba6a5263951bdc3c6a4c90d070f7be00024b80d83b6bc27587fcff5f5ccc0eb3cde1497cf56895147a063f61f08adf0b
TST: 69
SK: 210532805fa9cc9be916d213cac374e3cd6fc2602a544d0c1ce29d30105d69ab
PK: 10699e499be99e2b11b98f6f86b67cdc4ccf69f3c53ce094875647d2d0d0ecc5
MSG: 9fc4d28cfd25e6c0c5e724e19ca39d71e53bf4aa2796c54c3351f108fc70f2611a62e0ab90af6ade5216788e9eb2a873059b1e79d7d59debd68f2d4d80ffe31bf74b928c
SIG: 4c2d31d5bbc42e026dc1e079ecc4dd072c5d2cce65e3db8d8a1dd9057faa0371727f727231a0f060fa27097533b6db3b8f6252f2793d75662caadf5f0fcc710e
TST: 70
SK: 185d64b69479e0ba0a5844a10ad84125ba11c4b40d63eda2c57afc7e019c8e0c
PK: a5764f6398a5ae2266a38f9714533c4bbd8d07826f63e204cbac374b0acef1bd
MSG: 4a0824fe70d4315413d0a0cafbf4f5fe117d5e07e1c3a4effb9d0ae91490234878ccf6792a91f68c6a520de16071f08abe35dc5ea428f1957b663371ce24c609dd55b8f493
SIG: 43e0387da5ba09a190f6e7b2680578d889769bcc445e5ef571b492871c155c5b9f620bfacfbf2df1fd87444604b71b2e237baaa7ee2093ede4a601edf883e307
TST: 71
SK: cfa9d9164b3c4f6f722635d2066cd7ea5e5533d2c74f8add669c371faa476426
PK: 41169a66f9a63f285782a6c2db81cc3f70b3ada21a68c84745c88a74c3b0a2de
MSG: 757621b1675db7cacef7f2782587ff3af51a3ef2f4bcf9279c4ce94002e1f00424bf0eb621982cc85cb4d171e564a0c2f6e3567a1aae2cddb7e9b25f47dc20a51050542969ca
SIG: 01d7c9b5701af71e2f4877ffc9b7b5305f52816d4458e37e41c7719fac1d76a01fff3f50fe1a5875ccc3fb70001c947a33fc8b207de13572ccdb8ba98933ab01
TST: 72
SK: 1acb4a256c2f8993ca24de1e0014606d668b5e756032d269f1d24d351c8eea4a
PK: cbbdcd8cbc885ab43a057e5f9579f1161954159e7b562ea26cd9a43c88d3f96d
MSG: c46a6d61aa0aed1c1d8547a70b89b7196475d5a4870881b1ecd0f0cb9c745f8a2adc8024e2dc55b53aa5d383a81aabc1a47e8d07d00b7f0b56ceddbfb1f424bb5c02184678a666
SIG: 05aa76f7fe51892303d78914715995e7d768ff7714ce270f175e56af17ae018d3fa939f5f620de82bcd1549687b205c7871203e624238c4e309fab7f92fbaa05
TST: 73
SK: ace3c46424823622979fc3a84a7da69c1d527d8312e8fb018375bd3a96c29c18
PK: 937cf34136d9e1cce0de11b12c70cbfb7455448421e92c82e7c40934bff8c676
MSG: a9f137bc9021bf105aee25be21cd9ee5b3547cf10cc5f98476fb588bd70e2d6d6b0834e842e4ee94303cf96b09c1715381b36e14a491b80f895ea421b8ec2b1d3c187e02935c5526
SIG: feb8896dd3fe6001ffea171b37b788a69f7f850193a63406f56376dd263d099aef80ece67e2c43f40eca462c6b71e79406b18db74ae5d49844e3b132bc2a1307
TST: 74
SK: 88f681934e33c35c07dc6e5a832942ae3d59903ccde2f76ccb7587cea7ec41b6
PK: 6a4e8aa5adb63d22fd7b14a26fdb03b7c8aa6ccd5a196f2c54b0465adb5092e1
MSG: 6e8bac1f853b81fef94707e18cc61c6f0a9cbc2a41d078dcc83fc0229c7f8dbe6dbdd90854b1f1ae2b9f2b120b86a8786b4e78ce23ab86baaf88754af0f3d88881dae0bc5261bfd038
SIG: 45b27bf1b9eac06b62b686f6d546563b2dfe5b175dbef32bf78c35a16c958a9d4f26d291de9bb2066c0a286113cc09172d40a36d4cbd951708860226eb30cd05
TST: 75
SK: 48050a6e0158f6ad253412e4497cff62d5ee555edffe59e4dc401522813295ce
PK: 975e010abb9a3e56659137b0506057f283982f886ca172c7bc2c500ed9bd26c1
MSG: ed6eec29fb7049dff707f0a4426ebc8f5b350e95870b9d6198c8139e9c3e1e409937d1a858a0dea482a5cb1a854ed3b5a9397acb63bff6b64039ef2eb1159e99858310bbbd86125c3e0e
SIG: 7216ab60c35168187d0fce4753c86e80058d540b76bf95843a5898841060a99a44de6f439625a3f6365f59c377bf45909bbfef5c50b25f3194e5fbd34ea5e706
TST: 76
SK: 18d13d0c00e8e3386a5cfb30a9e79fe88b1861ed2d1201eb170038e194770403
PK: a4afc833401876090d9b880c41267d68cbbeeaa38afb20884e27328f3b7f535e
MSG: 910f6c272dd97931ac47310d244cadb43251365e02ba9f6a5b3c3226be9d7d3a74a2ba4906e8e71a4bf3d3556ebdfc666cd6b12f20c4a00834b88fbb244575199286b0b9344cf334aff007
SIG: 033988154c5d79d2510be83e778015dfe2fb85b8111f7ec139918b5400e3d656ee80a9f5c9072b5b467a5cc5a57cc8ad1062b5bff10862d9d369dde2cc966701
TST: 77
SK: 4adc8c28646a93a817293a14d29b48e2c6d712a68993547a5c5e4d1452acbc3a
PK: 7f40473628f23fc0dff0021afd487740d4916a9122e6c97d36433e5ebf04f88c
MSG: 09fb5501f1688f80a0ab9e22d778ae130acaf74d7f5185b4da198c6b9edac4302e2b753e578766e17d4056dc40d95cf4ca8bcc6565795e97d68bcda79fa77c493397716356164caab5d19cfd
SIG: 6d3b4e90ec408311f9b15b9253d3d95c5d152620c260d56302555a8804a5104ba5e8d29ee108e764a64219297298ab7674bbca784dee28773b34e185a386c208
TST: 78
SK: f26e1c84697a4908151b447dcf6c7c7a38b04081db9e7c7738e6fec900bed0c1
PK: a86e1422c1235ff8e1aa083470d5e42288cb007ab50e795dd0b4ff87394966c4
MSG: 54ed47606a1487c2f900cefb6e899dbaf6c31cc88ebe3558b83b93f6d422c31e888e48e520eeaedd7e554a9cd40c2c519d533b6144cee484c389e976b1e4022b50e7dbb87ead7e541a2004daf7
SIG: 44f3344b9566c9dfd22d6198e1cbf95d9e28f2982fc7f166ab25dda30c46f768c558e0394fb9ab3e1d4db4cf487c17641a13f3f48939e0c64827a75103c57406
TST: 79
SK: cc0c33f3a86f5a17d30c186ce0f3b740bafa5fe3c7090f143541e2b2c1e534bc
PK: 967a71c7cf9b82cc78cbe109104d8b438a8d1fd71d260d029046a9a4526866ff
MSG: 1944e5e155d75e0d0be92e1be14cec370ad13791f2bfd40f271214e94fcf213c71bc20d7ce0c7584421ac4efc451883cc3f4956f21f73a4216720438bc38ff2cfdf3709905a50a9d94b1d9e7932b
SIG: e277b3dd655c33ff75fa920af1fcc859401e6c7a6ef4c6bfbfac5069638f19ca115baf13c09c82af793facb6abd0cd58e8481b08c1b68ad7a2665c4a614a2806
TST: 80
SK: f0bc979375a7073068dba7f6c094db6598b4e45df7d549583c22fded8048fa2e
PK: b42b6c57a78f1d90090a7181ab2ae09f426cbc2be96eb2cf27abc70d7d32a4b3
MSG: 27ab3049b5c6351f6cfe38b13a059f5037257ee3d65d6079656856edc876ea081fd8a9480466f8839478088466f51ecbfaf2d65def25f0c4dd8d08588202812232f57945df8a6fa161ed8c0343b583
SIG: 19dbc3027f9fae707deb76f588f9fd07aa8eae29bd4e1d04c2c984388286b3b122248a6c03ed67eca35df4db3dc1e4237f267892518497d9552a21de19b5140f
TST: 81
SK: 3022975f298c0ad5ddbe90954f20e63ae0c0d2704cf13c221f5b3720af4dba32
PK: b845bce38e26ab027b8247463d437a71bbddca2a2381d81fad4c297df9140bd5
MSG: 9aa19a595d989378cdc06891887ef5f9c246e5f83c0b658710673e4e7db760c76354c4f5d1e90db04a23b4fb434c69384593d010e312b11d299c9f97482de887cecfe82ea723bca79a1bd64d03ef19ee
SIG: ae14a860fad0051b3eb72b3721a82f7b9546b2867261e2b7b638979e2561bdeb89b600768f82450a66c8b0481283fa21cb6c53bde350effb68a7d1114bfdb203
TST: 82
SK: 0f710b6c481f71449589753312ef64932b4652ebe0e07597f7da1c4f3dcffb80
PK: 6973ff2932ccddfc1d16c4c0da50c8b29fe6452d1ee84d52064ebf3d628d403e
MSG: 85d85744ad55e9ef9a65ca91e85c8a4f80e4c58f8e4e9354e833986098b7d9fe9fdc0dedb0d75d2539fba00034fc0c2e84344d1edaa09d4f63d5546d67803dd6b54ddcc0b1d3f2582dd75289e31de42e69
SIG: 02a8d26aee11420fb4f09d1163e14b867df7c6f6c8f8dc7a78034659f0401cad0aa90397efdd0704b798db1936503026e2a1adc297e27974d4be312a3753f804
TST: 83
SK: 7a05f121f60112dd16fee8c91bc2a11479f4b67ee33456042c8de167fc588017
PK: b3b05be989cea7197505d4b54335e5e1d77a4b52ba7282604bbc1cf6c4e87a6c
MSG: d9c59e8cc4ede537be2122ab492a5b915a9b0a114b2ade356fc0457ef98722d5f567b86211e28369d14168ec4a3c804076e154adc70a668cf64a20d13cf190d115cd688d036e46938251df4964dc3517b10c
SIG: d30ce8a322b450a2fb1afd329cec8559ccf112bd83965f9ec4736270a0914e061196bf5209778c9f8ccf39c4668bbf0e1363f81afe45dd74e80d5875ddbf6f01
TST: 84
SK: bf381f8dfb5d0c6d64e416ac23e0d0fcb86ebb899b1d146abd911b92a7808eb6
PK: 863fad8d1f1bc630a15f6fe8ecefe6b4497b60b21ae8830da46742045fef156f
MSG: 8654f2f5c6dcd2cfcbb6ed8d2bc5fb5fec53e3effb0de65aac507fa56c897732395aa09946d3b6586a92edd6dc99315e1ba74c6a0247c4ba7760b948eb3c0932d9fe1f0e9fea6eb61a548a9ab48ffdf1547329
SIG: 99b75378738fcac8067669e8509b5d2607e1ef76af9004e13fe5d3932df60b168216f58565340fa4d638055a89044ee7d45e2bd082a53382289a34700648980e
TST: 85
SK: 36983241a0a8e60ce02a61b3fafab15a7313a5a270d015b9c9ec070dc42deeda
PK: 6647984d42b9a5b3b1afa3b7f8f49d4c2b05e38984e99cea8fd68235d2ae4627
MSG: cebb9e404451818253c0392a4554ee7323c5d5b8b226775700b806ed5b91337916ea7ecbc3d4103fc65e5372ae7e5f9ba2d8f5aee24ccf6e631ae20c4af9b5f728cdf89e8189def1a5b3d35347aa203525ea1d2e
SIG: ee37df8af422f91f85dfe43efe79f62378068ccdbaf3916eecbc3adfed0508bdebaf5ce06b3bc279f78087f0db8db3c6823edfb32c12217830be723d8872b30c
TST: 86
SK: d06899f93a408dacb41c969718346f1e289bb5ea65e283ff79c705a074517c35
PK: 46bf2a08a076c47d7f11b733f8141c355363ed85d7def26ba6a0ce15ac5f2be8
MSG: 0864c39ac4fda8eb9048597bd40be0401021fd2dd3a3390a8facce984b260a13fa2c7cfc00d192fadf134a0ad5a181ee89eff0c795eaa0fbfe2f3b26115d07168db42ed21a51303b1958e4a42dc065b22ce48f17a6
SIG: 6f89de92a66bc5f4144339124950bdf588144cb372f6736245351c9476becc59a258f9a933ffff2bef4b46cd1057395225799fd09dede6823db0e325dbc8140d
TST: 87
SK: eebca7966970ee9f2cc4d74c6f1d8e0ebff7c45aebad349fb9f86df628dfff0e
PK: 89101e0309f767e64ae9c98c4a5d8d2328fb3ef262d082f49b64ca209e1990f6
MSG: 0fac790adb9f59e5cb0ddcb2b667172f2a21034d93bcaddf188606fa9e776db33a8fcc6bd7f5567883fc0de351aa9afaa36d2075b1ba853bada849b8661d5c8154e7b0afea656dd15e01a9c5ba21589b02f8fc5481c2
SIG: 7d447ee5328c9fe7f11936cc42998754a56cd1d2a6951af4fee7c4a8eb319d4923707c793c55d79067f822d5b16bb5776e38dffabc67237a916a81a63339b003
TST: 88
SK: 3820b6b15939d0afe18c9cb3d9a2a08f167dd458eb6c7e3f1558b0c6db4c6890
PK: 80b85c6559fea8b400e1999cc5bfed507ad7fc294cd9ba0ce2dd2584a91089b0
MSG: 3e5ad92d44b40e8614d8087c9c743de0c0861a07f1f5146d71cac2f3740024e841cc2d46027cf5d261d3ee7c1875b39551017b5fb1468114fc3e098a899cdbd558b39f098e156b6e9801ebcdd65fed56dbfcaf2c8c787b
SIG: 823ee2c0c8d87faa0ec0141e9ce08b51e57c839792d1fbd97a967207fd415849ebfb5dadb5a1dc2c0a8b7fc63fc354857b8c90c44720e13f45cd01e7aa23140c
TST: 89
SK: 0d20fa4a37ff30c4dcc3e44ea7ac501137e5807e9781330ac310982cc3d39dbd
PK: 67bb0a01bc8617b491eff1a326c1c70f7d0c5b95a5ad48241aedce1c6f0883cf
MSG: 35e0f4b4a517f9c7aa4514f03e6d65f19b27c62cc069f6bf07dd6378bd6afe2b766560006cbd5730a00919ed11191fb0c8dac56e153fc1cea4bdce5046cccb717759a4083e1c16f740763264cc804de0d0e1a4b5a23067af
SIG: deab12ed82ba94b469ca98b66fa20444b4b7881c4f0f853409c9a1504a5b2b6d7860f26ada6bf73459b9cdb573c8017121338efa60f4148086d7a3a8ed59bb07
TST: 90
SK: bee161881d819b370d240d509ba46b06fb828e20310d9f6b309780703e98927b
PK: 10854380de89162bfb9f7835a2716a3a6e0265671b250b389d01c3bcc03736b8
MSG: 5a6fe599b6b09b05c0ba6a622df3a92b3d376d24d04ea85ebe767bc2ec4d14e83e6937dc0b914b4809fdb607906841a6fd1dcdf61aaea8f9bb81b2ccaa32df412989ae53646680a71a211c8440eab0f1aec5e4fc00e6a2c96d
SIG: b07d072eb3831fae8a06effa9201797496dce126b8e11fef2fa07f664dc5cf3d4bf9c38a8b3c09fb5f14fa2deb219e7d852fdd27c7ba32d309942f2746dfe404
TST: 91
SK: 70150e9516164a3d7b7e8b6f255b65cac9f07459b32d11bb94b3d277208abc99
PK: 2328bec8e40351047882e8b43bc1ab085386fa47987e46ea87608814c5da713c
MSG: 77be8eceaab431a13c2a28d0d1556489d8c392fd7ae41157f7caf082cb54e45f08626be0076be844d38fde901a5eab0e8832d69dac22fb8507fb8ec4faf7c88fd26da308461afe385987972b5e760a34a5e18b9a82b4aaa529b7
SIG: eda3f5033ea7953a0d583c6457522e84ad78445304d48e577d4d69e8641febe15248d8d90ce0944a8f801d39099bc77494bac4ce2a20b38369c6adfb71e03d0f
TST: 92
SK: 3f87fcfdb421422a9c5fb98268313c15128c78844ef9eb3b3713fa77b6718903
PK: 533ec59228374bd03a4699e3a8896b86182fcf8fc3085fdb8f5c4671524d6fe0
MSG: c00fed2d689468bcbacccd446e8d8f299e2a86925e62e59709afaf4857469ff1e006d00fa3e18a3615f8f06b6ebdff785dde58851d2c239038a0c344dce985bd1fc8deb4779ae5f8932e2f9ed5990b6472dbe4e6fef6917657e0b5
SIG: f6519d7edb6134111974033f03b8d89e9c76caec8965a8e17cd45fff19de2615d73eccdb4a6664a8f0e23adf98988e96251bf26eb7a4ccaac1079f0a772f9b05
TST: 93
SK: 44ceef044ff998d4abeaaf374eb41d086718b63097b1e35f89634c14897132ea
PK: e83c86677d03ed3a5e8c95f41f0b325ff4333702f2ff6936f57ff30aa31485c7
MSG: 8d3e2dec4644c7b51633b13e6375ca42ff9138465f43d7800c7313199f67c9cf1b520b1820bd630ecf1c992e2767b38eb5bbc441a4ab8d317db441db35a0fe3abe7a9e4541881c2d7b1a2612306959815d1da41267d9649dd4494ace
SIG: 554552d6b790d421d06b0a67f8e002ad7a1ed01c06cf00cbeaec2a268bda29f1183f0ceafc625fa5fdb847dc86fae1a20406e459d4a0177cb515220a568e0800
TST: 94
SK: 98ef2a44d4c8476dff05aa78dcf9c6dc086cb2f622a06745d60cbf223faaba66
PK: 42fdb1daa39f0159119beec1bedf6f0394b26a2a29bd1fde081eccdadecc226a
MSG: c8b5fcfc3c18c7d95957b668e91c731d50c7fcea4f9575bbf784625870e238df546e2cb1a19d2808dd5b230d3871fdec16100ee1fbf9b722fa3744a750a3b396b05f9c21b8c0f61ead57a78c5ecf72b579cfe88a3f404c8acf524f9ab9
SIG: ab5e8724a3e6ff76058cfb214d574e04d05574ecdd4ffe8c07c7af396e882687c5d79ef1e62fbb4c5f1bd06b9bd897826edde0d111d918e8ef961ff2a00d7700
TST: 95
SK: 93a8c792a239c931917c114824a0174f8bc4ebbf98af8c7e321e0f5bea4015ec
PK: 9b2eaa8a9c2c25ff4f6e13bb12bae5d06fda0eb1105fafae5880ff168740bb74
MSG: 901bf4e041caf16e04f2ffde8d6fe97e93d0900f6bc0fc09a9a0179d137b4b7788e57eb92766a9c634f35adb5c2988af1e86208f461998f59cfec99204b484fbcad3951e7ee4405523705d9739b44307db03f713fda78db421ef3121b3ba
SIG: cfe32c4435d911d772dc0727e78d689d0164c5069597cb441b22c1d26236479f1afd7089121b9ab4f61bbb1fae1ab42f7635a92a53784d7170916b703aa5cc09
TST: 96
SK: 7001fa0c4404c28aa5b5fcff30a961f21a22f5b85a9e382e07aea8a8924d0ec1
PK: daebb63c4d8f40ceba8ec35e3dd946a6b75bc74fcb29ade7b55eee3cc3aea5ca
MSG: 44f48cfb02f08777a57873855f96be4c0291323f2739b275d90757a15472e5750436e0107408fe3026c00625689983f990eba9becbfce403ccd56356ad2741fd21445dfb23d76112e578b3395cf9d960955f1da8f399ca286f21390e25a59a
SIG: 64eac9ce87460618636b41fd2decc1673bfc48c5f479dfacb51e86686407374b1d10bf65d6d7474214d7770c9e5c7f806c80d53d48b720870e5e78f32e3a7e05
TST: 97
SK: 3adce3a3d3fbc977dd4b300a74749f13a3b04a5d73a2cd75a994e3195efebdac
PK: 6ff19b1f18d64851d5c74845c6407f0bf596a52e385e020127e83e54cff5ac19
MSG: fe6c1a31068e332d12aab37d99406568deaa36bdb277cee55304633bd0a267a850e203bb3fabe5110bcc1ca4316698ab1cf00f0b0f1d97ef2180887f0ec0991e8c1111f0c0e1d2b712433ad2b3071bd66e1d81f7fa47bb4bb31ac0f059bb3cb8
SIG: 7dda89f85b40539f5ad8c6de4953f7094a715b63dda30ec7cf65a785ceae5fc688707ee00be682cecbe7ee37d8fc39ee6d83c64409681708a0898a183b288a06
TST: 98
SK: 14803c1f23a47fcdd35e5d146e20ca630cd712c047d5330b652e31857acbc9e8
PK: 36f2d5bd6d8324fa6e9db7f7d854ebe48c0e6299998122e9d44b8adbef54f093
MSG: 555983679d026e5354b4cc055ae1bc14653c7281ec722372f3feb778e841da821b3d0b8ee7a9a9129ea06824be8379fbbdcb0748f423721ccb172a1bafa1d5ae9fc1c51e93d41dd551c3086079b620286c1c40c1223bbcbb76722e92ca21d8410a
SIG: 07a7de6ce97664b3ea0928e1385c3309be08a47cbf4daa9186a1b948c86fbba39c4efcfcb7a0a3866bc94c6788ffe6be0d4972e56d0c3292d1cc6e25447b9904
TST: 99
SK: 1a61154d3472cd96b328ee674beb4fc86763a969fb410494e0678414e31a46a6
PK: 7576d93ac85d0fc61f258c55cf90bd87a635099c0e810ed0b937258d13b42559
MSG: 64c565efbcb8b9528ed47253f3c6a4035db781d6f0976b5e5ba8447d4ed54b04105293ef4c000d8b2e1b5b75e727e5d2a077743b50d183b491764801a2504d16ee6d7d8ac4fe40e6bfc2a8129c7285a5ac691c35e642ed162cf7fbc64516733a23b3
SIG: ada1666c9c3b8284b8a21c4f2618ef0808a646f3f10941e470f738e1785e2de9fdd9c8cb526f945c7a8c6994f151b7d066581b1d755307947c62befc8ab7070f
TST: 100
SK: f215d34fe2d757cff9cf5c05430994de587987ce45cb0459f61ec6c825c62259
PK: 1ed506485b09a6450be7c9337d9fe87ef99c96f8bd11cd631ca160d0fd73067e
MSG: fbed2a7df418ec0e8036312ec239fcee6ef97dc8c2df1f2e14adee287808b788a6072143b851d975c8e8a0299df846b19113e38cee83da71ea8e9bd6f57bdcd3557523f4feb616caa595aea01eb0b3d490b99b525ea4fbb9258bc7fbb0deea8f568cb2
SIG: cbef65b6f3fd580969fc3340cfae4f7c99df1340cce54626183144ef468871634b0a5c0033534108e1c67c0dc99d3014f01084e98c95e1014b309b1dbb2e6704
TST: 101
SK: 8c9f95083075a43fe426d19f1e87719b40043de88eb0ee971f70e10c7694ce4e
PK: e91d167aa3ebc23e70aab45dabe905e416262f910e2a955dd8619efc74c24e85
MSG: b69d70e860f55c427ef2a71df36e05bbc43bb2e06463aa5de34419c6a614eea6695335a87526c1226488d842891d0574df343c9c1e17aed6958ecee87474221eb77a599ecb059344c0d052c0002a66e5a6013185af69a01ba5dbc660d36cae235f67fe0e
SIG: cac555222dafec76a0b47b9d2c586b3b3b9b3b9c8364beb3cae1e8dd7f1ae9dd74f22b8dd4ad2b290f81351a415a99f030f10778be4cda85d1d353331e70f109
TST: 102
SK: d7eb1fba424feed100777eedb4874bf20810ad686b67e31d27ecf610609a33f5
PK: a25acb11a6c825713a085fa754692886a87d07fb9be1a53eb961728bb66c9060
MSG: a1d0f81e3d59089cc2b19e07d2fce43db4cf171faa642f3b0bbde77ae3d53af5c02bf8fc12ffb4e57f7c8a015d6c2d178944fae9f7c8fc969d4b77bea51876ae99d59e94ad2456e0ed72c52cf4e5340da17c44dbff86457a519b6fffe269066290d629fe69
SIG: 2bf719682b07cc5ecc0480f37e9d123ff6f44c26e6958e59f080466f9cd373a16500daf123dc3f1334774bfc9fa84503b16dbf21a815c1ada6ebef4920461702
TST: 103
SK: 4f6aeb35fce14fbcbb9aa8a4f6451bf95b98df047fa8c43f1ead3b404d3f928f
PK: bf66a9edd09481db8444a176c8ce0578d2934f0cdc9734e86fcaac05bf3330f1
MSG: 2dfbb3f59e19ea17d44a5bde4ad227a1a351dda17af840ee0a75da21a5cca89b6d1c567c333e9cc910e2157e05e86ad5d931145064594c47baeea8663a34649c43e90eb95ca10f7d51597b378a722f1f704adf9f22e9f885b89d1f938006a2efcdb42aaff5e3
SIG: 6adb07e364f2a455cb05867abc511acd9d658977f0cacafc92828e7b724f6bbf98bf0bfb29f4e5e6c74738d4fdd816d9252407ae4f3afc574c4f00614824e203
TST: 104
SK: ef4a6762b400975204ccc13abb47344015454906850ff14940cbb83aa22414ae
PK: eaca450996f50cfaf2bd7f9d7fa7087f09ad49664206a80bc2e5bbbb85bb668e
MSG: a4b63eaed5a64a94f2cad212ce2ae71092fd3ea744f5bd89562b2fc2a6c9e4d7aa27add56264a5a55016610be6c19ff7d4989e9504740853012715a79ece9e12c301b3317c7d9b6730db862a4a1d28058e0f8b5ddd9738c7c62ea572cfe59eae08e2b8b6593b58
SIG: 02697d44cad862f1daf5708205f450d408525b10c01ffd06cfee80374f3db16fa9a49c19a9844b345f2f9559ea74aab173baa078c54370a5166700c6dafb780a
TST: 105
SK: 55017e5f61f0c5bafbcde6f849f42a31e5e7a878c1d3f9126fc569fd417ea9f2
PK: 66914f74ed932fc881ff0166683f675a7c28a926fddd6469cdb3f28e6dec42cc
MSG: 2fc84a0998fa6e168a866410bb68105df249a28cfc76604be94fd7dffff2fc1dedd220199465575e8df860190f16aca4084169be16c6ba32eb67042ffd4f230316a26b2624a42f8f90ad57f6916486fa91fd94ed68aded4e632430ef719446979bfaf345409c387f
SIG: b1a5e7c49b8fc6b4331e0416ce7e4ed59edd56300b802e0d72abca4a6fcb876c03bf331579124ae0d3fe43f7898bc87e93fc2da3970fc8638957d18c6613c808
TST: 106
SK: 0553fba866942341217cf278ac57cb21acd09d9916cc6af0ac46941ea139d545
PK: 840c66e57c2d4f52a4a2796d2a53c5709b96a628c2e063fe6efd47f283ef5e82
MSG: c1fae6262a0e98a6b1235fcb62283b7f0a097f9d002416d318fefc60c5a1584f900ad0ab26ccfae0d6d84aa9aa2df16d4c117ea2724676cb866d4870a872fc829a7c2a5d21ba83340adb339a34c5184c7f5ead0f077289b33677ed6a1ba34be1994e25763bd1d9faec
SIG: bc3364c152ee5c808ac340f49ea2cc404e93517121220cce6f7c30a22500e41bcdb6e820480f8fccdd22ff9ad96da532802f431e94240fb83d4bceaa09b92b0d
TST: 107
SK: 7a5ac602de19f3c21040bcddbff42f6aee6f95c1b093868f48e50482dbf4f9c7
PK: fbb6c7531cda21e7d17ea903c4d14be6c68b4ca803a16bd87120f5aaf7dce1d4
MSG: bd1685419279eb81e4cf3c909031f0f09c5ffae7e2ce6ba9d96c2bce87b8ba0dd763231001e532c7ddd62103abf701288e19dd8f5302e8f5d31b64cc339bd8b7a95550c8a116fd486948772bd5af8dfd46001c59767b0d6bdce383a7078992d1022fbcaf90710687b9aa
SIG: 84101dd4b5e8ca3ed98c1e8a06e11d7e424b0d12ca714ee7374b64c29d51a2021cc77ac75389d9b0a646a447623d7d04d1241866b0ca6edd1b7ac015666b700d
TST: 108
SK: 50414cf549bcc55b5b6b75ea3782b2ea7c087b6a0106175e469ca2cc764aeb01
PK: d0f30c12e997f96e7aeecd1bff6a012ec388ebf8f3f4af664804d1638e4c346a
MSG: 75ad77e8c54b0b05fb2d162e7cadb8a7528081b863f76a441b374469413e5714edf54f800496af0157c17e425583414d4361f2134171c0b87c22ce6820a4850ab49d99a9badce9e36110e7f3060118b3590f82b43771e9fbb081afe62227e024d98de6cdec028d7c49490d
SIG: b309800160de43a63a89a0acb8a6050059589b3eaecac20b256fece438042f69415d8a56883ee3836d3134a7fc1de64fa8c8cecc3ce27589f606058820857a0c
TST: 109
SK: 93cb00d8fe9c9777a683631f39ba0f48761482cf1c366bd863cf715101532555
PK: 87e94a1ea5258d61180cb828590ff1418a87d01e702686ba8abc2692c8dc3c91
MSG: 88d8538d31867813d88fef7228d49a7e950d738396f116dda1025f7913547c5d1dc5677a6de4b4a5880507b361780b61b43f7795263db22ff341645f2f5914fd6088c2811211ed4756ac019a6035d66e3170c1d82bfaa30596b396b3260cc1d10d413dd47ebe6daa0c30dc42
SIG: 09824fa2dfbc4d6ef76a9e4145961116769130553b3edffa50d04f39b8b79facbd237acf71354a53a6e5fee754e823b0b290f9619320a13d561269a221639f03
TST: 110
SK: 2b4cae380e95ce694c26ac7957447347f98e31b4bf02d744e131529071e2301d
PK: e6fc705a79c98e115b4e28d3aa1506b74ee74276c5fc1109a7f4d89c6fafb889
MSG: e0b8250e27b7c0291dbc47a6da6f1268987afdf0a1e90be69bcbc4370865217830d5208693be7b7045099a22ea27f952eb3f79a9a0f1b5a87b19367790788d34c219c2e2a6b834020fb4fd149dc56b544fddbb42071a162fc7cb33c146cac05a31b183e9daadc616f3af449b17
SIG: 555e45656ba9cfbf5155d0e52576e5197abbbc9dd233993eec2a1ee7f6a86409c0b71b0a661978ff5e0acdc9463dc449906f474f8e79bb86168bf70741e34b02
TST: 111
SK: b56491e54999bb5a1715ebfa2feb14a545a3a43c2fdfd4be0c95fc11819ad695
PK: cd42bf414f9bfc72ec069882a800557cdf31bc3464fb102c310e6dbd3ae20863
MSG: eb4418ba30683ec7959bdb1ec7b263f83e81f054ddcdbe0a6738ca7763e246935bac419026c22bfbdd1236336cc16107c53513e3ddf34e120846962c3bdd54f5ad5749597208f15a8bb56667baa895f08340db89b85c435e770931928d8abc99262f839aedd9be2aa138c9259adf
SIG: e3be3e71a89852df3cffd72d68207869dd3eceb49b1f029493eccbb932444ebe8c8c6db5f0a5a67e2194408df9841913a5ac1a606896419a668f4f47c56c2b08
TST: 112
SK: 6579c247dd2cd02ba2f7d7a950a330752681e92c0dc62984bbea279ea521c381
PK: 0b087bea1a1b3d15805cb604f4bb8d68edde274faf521fe6df50c55f8ad4a70d
MSG: df7c552ffc89374b9571a6024a8d0471d7eb6be8dfca6f4166b581b65479015a0568129074cc04d6342c758ca18f7987dec536b7033d5f9681504340e20986f027b8cf1f263be76db3525d173422950ea8dceddc585640918aa9d25ca89cba701c2020153873f46108c772cb388d55
SIG: eccaf801ae0a912e21c6b83a5f0e4e88d4b2713459ff93449fc0b21a9f416050113cbae4e814d20c0a798f76d2f9d326ed83959ea02abdc1ab350a467123f709
TST: 113
SK: 18fba60c5026f3c9dd7aedc04209d5260361de400e190aeb60169e05a3367c9f
PK: dfff347f3dd255530bf7fb34d02ba486d112bb46e950e2ef80e517014cc95734
MSG: 34f08a804d7829cc3914f000ce1a3288acce2149c8a02086b9f67afccd83a178b0bcfd4970c056997da7dc3d47562f16663cedc52f82d710850cf4050379efdac23bee17c330a383ad137f788473b2b0723603b6deb1fdbf6c523fc948a0ccc4ff100fb946d874c1f990436ae8c4f3b2
SIG: 4bc011e40f0f59c618f6bbe230b6f7bc2f50e3617c7faab7f4c21cb84f77eba994cb7c2a1bf10b01bb20084497fdf0a6ab5d9bcd22c4a2c5a78f79926825940f
TST: 114
SK: 073cc15b0536285933b2be39253cf4fd696b81610f5dd3adac2e9cbf338ef2f6
PK: 00b551d371544375dac5c4e96cd1f0215207e8e166a1fe49d5b0a51ac18443ec
MSG: c285362bc8ef628f7aedf654231ee51acdf2cf69a886b942bb9bfed8155105d9209ded2af24f169ad5fcd451370f5827a85111c7a52e032c5038617c0c0170e2a6c231dc401d12062edb186036114e38793b79089077581b9783f40007103ef17472491c00e7138aecc5084d3c85010470
SIG: 3aa52a83062a8f28a5d6b7607f484b66cc374896b766123126333c579581316c742806f627b5bc55cad705cc1d4782b044080c8ac840f38c0c50d35e345c7803
TST: 115
SK: fd894a1e8232203b289505d5c68c68791ffc0e54f2a87530fbba5b3a3f2caf00
PK: e95ab565945c7ae5d533df5d0cccc7e9abbc838e20a0b61c930f5d41d81a6fe7
MSG: 2669624a94f2c44a05b7dc3ebf93e58a4bf3a01c273657e7e7878976f6b6ea737fa3f22cc8365b8b220c007d5b642726a408fe2fab69ebb3bd072b349f4dc3377ee7cc752934254215d23989bd3cd02ce999adec9784993f4c19940815f39c9e229247f5205c36cba44e714266369289b4a7
SIG: f51102219e8804be713e556df4e4afa2f8866fe86541a1c2a0934d24c3c9beb280a70dd8d527fe8b7e0b948214d5f2f9638619914b72d55dc198b0229a848708
TST: 116
SK: 18ef464e28f87ffcfa4d3a9c09a22910951b8c719fdacdb56de62c4b406df00c
PK: c5064c9d43ee2da75b06bb09c77267dbd0d39128f1cdc6bfa451a03e93af4a70
MSG: 9c825707d9358365ab9d38f7e728d628aa722a4f1a20a38e47c999fff8fc32417fbe072f96eb6a0e11e4da9b6de9615445280e93c77a3634d3d2c6879856c248f9800f60a0d38dc1cea8b7f31f286cb0374827b4c6ba144a6694f2b908ead68d18340124cb59cf1701863bd4f3efc709f3627a
SIG: d1e7f16e8e597d428adea65591d551b54b667aff2020c464f7f4e53c4773f70433249a3c71b4d11c89c3faa892809227b9f29ef4f7f5d020d4674d4021359405
TST: 117
SK: c911bdf2f9e7cc5fff35c96e15cc12eafd05ab0db31f649f7408acd0cada76e0
PK: de44696cd6bd2cbe9b11a0ef18b88164801a969d5e06ed453eb4008cce9a5725
MSG: 76c471241d17192984b00362696e4d9d4d2b7f839c2064117e50a1598f3a1172b16c55e5396866084752024f3a7eb68bb3ffdb80979a0af6d0f6af26b6f0bc0c0384433bcfd44c75eb654a8a8225cb9c4a7fb3c824c3af6125fd46db287e70492d154632cb8f62432659d958d6281d04a54f5f5f
SIG: d584b5da371ae4f5c9859b25f70dc56c1b7b4e02d1ae6636283b1b7b11217afdcdf65d1b49ca2c8ef17966e9bc65f10c310b77bb5df7aff5ec1b379a2ce55d0d
TST: 118
SK: d3703299c41db36d77dd3a49541f3fb21d0b2bad1f6e074affd96f1c40d0f927
PK: 862c5ef616a5f066fd87758a56ab45056fea4bd33f008be24f7b540e095e148e
MSG: ac92edbe22257bb06d94aa950e62d18ca2ac0a8fc106000d2231f8a13b8d7a209ccd8cc49a6cd68a7f36c02fb8f728d15595167f0ba8cfe95c8a1e435f327513014ac428b75d4f72e7c834dd70e1a448f1847d3498475f74e3d9334dc7dcc4fed72bf6c7fe3b1d4f53d429616f1df44f19733158b6
SIG: df28277121eac44630084cce75917ae9f6bec65af5572dc30719bde661cf696b85b8672dd4983cab30bd05cc3a119d7db9babd522d7b3a6bcf3886ecd25e080f
TST: 119
SK: d411cd33576d0efe9ec413ccdaabd4fcbafec01a3af4b3cbe34f8b05ef8b59ba
PK: e870344df98dd3a8702c4519bf9e8b35a9d189e746f7203dbbf9bbfab22d6f63
MSG: 11d2c2a7f0190988126696431b4bbcd90ab7b56a32da6404ae446aa762a4ddc66094971538eeb85bde0470a510be0d6d85780ee730a9854138728ae6816162268da852858eaed4ec74c7ac62e6e7096dc002df0bdf5fa40da565b41d181a3f0ad0c5e0b976743e315d9db8ed4160abe69c13a2b3f09a
SIG: 83460d15461d6717710bafd6a47a1eaa900a80f2bf8b8aae2468773614ee84bd628c9717476368ef3640cf760acac83ad60232a76963b7d52588b11dc004d70d
TST: 120
SK: e10a2f1380c3e4720e8a8707a9bcb25a0f58270d7059cd7626c7153447edfb87
PK: a3c717acab366a40b51187bbf35b2d15e97cfeacd7349c06ef1c91ac93e90656
MSG: 135212a9cf00d0a05220be7323bfa4a5ba7fc5465514007702121a9c92e46bd473062f00841af83cb7bc4b2cd58dc4d5b151244cc8293e795796835ed36822c6e09893ec991b38ada4b21a06e691afa887db4e9d7b1d2afc65ba8d2f5e6926ff53d2d44d55fa095f3fad62545c714f0f3f59e4bfe91af8
SIG: 094bf6f953ca0eb77df45129b7bf10d192cf6ddeae94ad6202b8eacfbec119e5291578fe64a084ae600fe07efdb8a782610dbdb0b49eb5f2a46c432355552f01
TST: 121
SK: b2e697b3d3efec976ef3369530c792717bdbb428d9ed0c11ec0ea9b2e5f39f82
PK: c4d2e4b3c236d6c9b8c74fa384612c4710d83aa16ad7ef01fbb7421d4fb3f0f6
MSG: 7b436232ac2111a84059510c48362588fcb7383426be5e6f62f372e4f7cca83c81c2357f9b54f4a15291065b6d41aad1ea93cffa776b9acaa58afe2b51644b97af9a3e53f84e40aa6d86051e6914cd039d4170a9a526dd69955ff507c33f74e2176591fb0b3cd7f00ee418f2c258a9981cccee72f01c8430
SIG: 5047fa38197b8328e78dd8a10e966afb7bd3d43608280f1c257d25ca43bc1c06e94a5747ab6215ece54cdeff8c56567d70d2f91f9ec8c260aa1080a6ab5a7a02
TST: 122
SK: 19a679a7a905a1e2b3038e6e418b3da97c3089c7cd351ea07bc8d1af64eacc46
PK: 19f08361f469b4ae1e0ceb94f47a7de7317410a92dd013b16ae0d0532fa4b3ef
MSG: 980c7b4d2939061ac7b9ba441117a19485661781a4083067c55acf93026c082a93cc124f095e1b4f2c3f6c135412a5096228e8a071e8b4b668ba9d9644ea9f4dabfc54a9856c3e965e6363395ab709037dda229baf927cd01f9af5e039afc42f3cec634f5d832d2ab7c7cad3ad7b8cf27ebdac698431ad8236
SIG: 4347b7b4f7c3c4dd315b8384a0b0caeed84bdabe24b2915f12512dfd04770fc996a1bfb729afef9edd611447081a5330617eaea1c1dab1bf13cea8997204910c
TST: 123
SK: f03b8363ee5b0eef7018a49bc02adf731da54ee50a7f03b88a29a2082b189c43
PK: 31287ef5a2e64104ab7790b312f35c7ad4af6beb0d7ceb8a58f36a54ce272c3e
MSG: 24191b5464b35ac7bcf4a375f033efba8943b09b9ff0fc403ca7aae702a3cbf396c5131bc008132cf5f12910d586dc1db9c084574a96babee95642f922371c0382ec0402a26feb142e4146bbd3360c2b36834fe45af5e2868d4d56fdd504cebf0c2d7f5791b4429417c8b65a98e0b15c466c137f410524fce737
SIG: e8fa967e6afadf6a877d87e5f5c52bb634b75a7804199a2bc9d027b63a35654d9ddd06830455641dbfb49edce42e20e7d4104a071c2cbbec23018c297ced9908
TST: 124
SK: 11086b0d11e415ab1ce02aaf8f0621b54430f6fb135c74f40d38e8c64737064b
PK: 7166dfbc691eb8c201114ba0d1a2c7b87f7a1fd8d0b36058b0d7dcabe1ae30da
MSG: 4b5b2936c5e360a38455503721078f8adb404a7ee7ecc14801dc87a67a152b769569fbeac0afa25a2070a1686b900ac1633d499808cdb2e81ce3916d5a3c04d19c5bb2699a662b8aba4af94d390bac7ccc8ec910ed2acdf86ebb71adb601877885eef3c91662fc30738e352cc74353ccf8d8edeefacc042c10a0e5
SIG: e907459d5adcd0d0c36418581f19d0eebda7138ebd9faa0b262201f458c856310bb77f4c7de922495dcfe8b248eda2ad0df6a73f47bbfb894baa7d8869875802
TST: 125
SK: efce7667a8ef91228caed14eb477a345e5e8239234080848760ed0970713fa86
PK: 9193055a84df1eacca28ce2a08c2a07a50f04c024ecf1fe4a47d2efbaf63ed58
MSG: aa1bc80d7bcc1d94a23a57cedf5027482477dc46b86890bc0e5ac29ae6c91bbc43130348797305f75543580a8a069b348a7bd8fc3e015230b7c1940c7f80a82b12900910dbcf0630da03f081d44c7f955d4a1172f56ecc7c5ac646696bffdf4eb6d88bdd9cc3843528b72583abb3bad02e56ef7646eed5139551cdeb
SIG: e5a63124db1696b64140b6e9612fa9587b3eef710109398d44ba0ca63c0ebad06f0a6c8994ea34b3a2af91a89bf41ae614d7727d716fd42f8b92e1ac64fdbf03
TST: 126
SK: 88fccaa96ad884d1165be71dd0c4f5f8f4421c60fbfa498bfee9b967462443bd
PK: c75cb0e0237b45b8656eea9f3d1a9d4acd01a103aa269bb24fd54122fd81f2ac
MSG: 9d0eac98556bfa8672c35705d1d61ac4d0fca19dc0d993015877857d27fd80f74acace666c563485d81e53603a6aef40875fa551cc105f2cc10b39694679cdf4a6b073bc88645fc51a36da179d3d1e3c7722454c5e73577c61aa7d148c4ba50ea46c56a1c3b3b3c470f93100494e08bc5514ac763a85483c42c7cdc27c
SIG: 27d3a197cc9994212063bce8d799e77b6853b7355ebe369bcf1889a418a82caa3a7987a663f621defe86b3ac4ad44faeed16c9116ace28fccf915557fa779903
TST: 127
SK: 670b30626fe367d8b45f43733d6f25b37eccbcb551963f0ac8b666b48041c72d
PK: 65aa4c6d4ba0ab34bc75b39f09527ca6f2425f52415cdffdf2dff273f8ea612c
MSG: d00bcca7e184d10e1f1fe420b50639e1d5deba52a751236e68c59bb4bff9802f5fc165ed42fd6d534670a7c6fb60e4307d947915a248bf2f93465c2cb44d8f453d2c015afbc8ed58818ea51726a25177930e9ea192ef4514f4bb0eb4e0f5d4ae3c46e357c81187f7ed174733fff959c3f9fae6486cfa1356a95699211de5
SIG: 1b6b4377d2b98e0f9d24ae8dfe30e2396e2004380d3431488e5843cf8d2d7a0070ab21f8a3b51ce84d2f4ba209f739f922bebf798096693f5622873d79ae6f04
TST: 128
SK: 813c4daed67a190d68bb635d73af6da74f32fdf7c48cca6e59262946b8e8c71f
PK: a2095457d7697020e2b884d95a96578c2a900a7666ac0dc7bd38f1931d7945d8
MSG: ce54cb0450e689a0dbef785308b3177472fcd6d38203e58a0590b31fa253f9ea590be5368a922de88b63450102684443fb8189e601282003323b89c81e92eaef2b5ddc4a55c53fa3cfad4160248b3c286ff80d31d161b7b8dee713552b56f1507fb72eadfa89054e9d1600ac874c4b0a961004eb6d0d4bfd2ecb9c734f00ba
SIG: b446574ff6a4bd2b572e487c4ab443ca641075168aa4e1092f71f30bdb068ce46a395efee1ee660b9fac26d54109722c15cdb791bfb87fff63c6596ad4f2270c
TST: 129
SK: 8400962bb769f63868cae5a3fec8db6a9c8d3f1c846c8dceeb642b6946efa8e3
PK: 98be21001993a7eb1a1277ff74c15504183d25fdfcc05f0d4dea892f6e301890
MSG: f7e67d982a2ff93ecda4087152b4864c943b1ba7021f5407043ccb4253d348c27b9283acb26c194fd1cbb79e6afc32ff686b55b0b3617218dcf39316b4b66b3c8c0d67267a86db8adf3750801bcf9327d4c25441b96197832b4cde0eac3ff22892a2f0bc17c2c213c02377a333e308ed271658049383b7e2e57b6b8b125512e0
SIG: 0ad71b0025f3d9a50db338414d6d670e7799b7270a8444f6ae7f12ae7eb71bd03ffd3c4f36631f69fdcc4061468ff582ede495243ef1361a3b3295fa813ba205
TST: 130
SK: 6288722035d1ea699bc7cfdf18d89625423180b683fa74639f4f30f15359cc85
PK: e17faa019572861a064e1bc571256dea1468f3a48590a89138aaa85925080cd7
MSG: 8b6caacac51d8949fb86acbcb1b99d859ff67c64147bc1216909dcab07ee6ef09f403863327394689dc34abc778fcb5c1f5091acf5a08f9d842211d1ae2eb40be9bb8d6679077471547a6c71ff77b519d4b7108e32bc46251c60dee8e332b6229316e6d57c22ab826ff1bc33f2b0213807c19280af110fd26ee27468201cff49cb
SIG: 9dec92b6e89adbe8f4e1b5e93ac4fcf957de7d1970a226770ec4eda647c8e3b3dffb2731a39e16e4a0119d3662a937e560522491ec7a1696be04c076b12e3501
TST: 131
SK: 13038a3a65ef32759a9cd903acb554b252de00e7cdb77bbed1970b20680ee17b
PK: b6a308e67f9b46c66499456ab5cd135cb2fe84a32eb045358626604da4122c8f
MSG: ddf00b4033a2a088022dabe93356432f50ddc6c6e1a659dc1a93124a4c2ffffd182765a2f56c43ea0bfd8de8015060889ae6941c3f3e255d4421a1c36201be846a2738a71f120cad598ca8527d70ff8d5a0993b55cb5153517110a41962daff42250158f2096d1ddaf7186e50298cbe51fcb429cbea411293f8a7bd9cf069fa237e4
SIG: 5261558ecc3c98ff36351f42f504cad4a32ffda5a744560960b4c106e4492f02e20478887afee4f770f05597a7e388caceae805ae351e0e45e8e578e6a6ff20c
TST: 132
SK: b9de5b063d3ca3a773f114941b2e4227c07511c0f5c06017b9c8845018f23432
PK: 5295243c8646e096674dda15979b322b9dd0faf27d024a0ed5771334e1179ed2
MSG: 9493cc23896b84096046ae1053afe39499e9424254b366fe143f4da321e2dc9e4784208e12a542d899828dde7eff625a7f12416990c2841ffb095bf94c0c610e5a663918b689031ccd6b519349d04de1c212ca2a9d7abf52e1b4fd467bb665b6919ef8f91617e205565bf56647e5f8d508ea200a84467f8fa122e74bc3b9979f1174e5
SIG: 92ba760d14d1415cfaf218ca847014088ae51ad821113a6f8630356f7ba85c005e2330f1066d0df464806052a4174610050462f3e013d702e7c77185a032580b
TST: 133
SK: 8ff0297cc08842b5e67552ec2843e04353a34d74ef89b8565d97205b74ca133a
PK: 0f7ef98c5ba4af984dfb77bc4e537b2b39e6273bb3e7b95fe1b7e6781952bd4a
MSG: 2bdc3a486c5e4ea62dcfec8a9d4fcf9ea9490dbcc715615d58490a72ce833fa22387ca50a0052508cf0aff1ca727f0fed46ffa7d3c8e23c5bb01d47e90ff06d3858a557d9926481579daf4384aea50e96ec615d2a3bf3c1122f1f24dd6ed98a5de421883589c213998ca5432373e68bbbe89428ca9885d0593d5e6215116b8266386452b
SIG: 0783737f706e6ff36614f850074fca1f485f24fcde2a28af544f37abd69b7a581defd8c771b031e108d19d788c74c5f20bb3f1c21cd92be317bacd8f650b4905
TST: 134
SK: 050d553d282dca3269c83c181768ec067b81c9fe0c94f2a0ebbb0c942d0fcd7c
PK: 63e230b003c53a5672e832ff7f24430be223e497de840233f595a3e200c7127e
MSG: 15e13b8c01004f6aa5b236dbb281677f746d81e548e0aa80f0e414521521d856cd694e7c9152bb5e43776b60f6b560ed1ad3e4b390dbf3e46ef9257443f39c149e0240a02d021e1e3d7d046b26fd004eee7ca16a8059e126c74cb3f2194db47bf60465ecef5c704d2e2c75e2e50060ea2a31cb72b7b3c6b1b5ec72ab38004085281a22fe86
SIG: 3f0e83765b31bbe8e1fb92e9678d6cde571a03ba7f1dcc1128461f708525457f4e0e2353aa2b598c063ff1bffdac916b5a2200655156904b0585577a1628560d
TST: 135
SK: 69497cd7b4e868cfa0328d92bd6052d772b2767395c14595b279851a9cdd31aa
PK: 5d276d626e230d18e7bcd61141cb93c90ef0f79e01321212d838ec71457b1aac
MSG: 53cd080a0c61f1a093d3b3a74571c296303f363b4107edbe880b7aa9dfe44ab5d5dc5f74be9c8d876f04d754653491ab51b135fc953f71287b62ff41b67c742bd3445671a9d4f2dc174ca1b0335f78627a0dd4b30650504178039e7393638510ffe84091b57298d3ac9001c367c1452fbcb33dc54a5dc316fb2a5270764a2ac820a0b63fbdc6
SIG: beafa58340960908e8d86e40329e3a4523fc7be770addb86e34c3772f84cd9fb338d1f3b65bfcdb09f35c6da36d1a3adf8f91f1ffd5782cc830206433a08410d
TST: 136
SK: 2165a486b612bbff529cd00346964a3cb8cdcffa51dc3d524dd5adc5ac936d68
PK: 7ebc839a465e14f5892476e4a13b3988f83b3cd27ef79e193f86fa16f34a1ce1
MSG: b728da7a36167c6085bd2d962cf63959facd95c9ad4542028afba90ec9c6c0760bdae935429c3feb3933e2f00042c672ad2cd7348d92bc33f81751e294ae9171b945b193144ef8acb9a1bd9abf0475ce0d0ac789b200c32e9c9a2736b168369ce5f97b1e8d2e7900e1a759178441f1fc430564ae129bae7857740511a668f32c0a3b077a9d8b19
SIG: 7ec6fba56ba52460a1b4f2738689c1883dda9aaffc8bde17cb6029bdce3a0ebe2fffda55939b70bbd07fdbf6fc5cda87fed8ba58575f894a366e45e5705eea09
TST: 137
SK: 1c64ad63dd147034598e128f7406ec0530746ea1c5b72ecf79e888065486fa1b
PK: baa6bcc1c3d8d3b11ffc1587adddc58bfd96c2b992b6c6f59fcc50ccbcdd0eb9
MSG: 9ebd8e337893bb053ef2b9e3269df54848494f03cd63576b33e64b1080be4be015264a403fb9602bbf90ca19b241a9b66863909b9008ce1b2ffcf236efa4c2668f0f47db9ff5fa157d9cb605412be7dd8b07ea878cccae6bf50f935b86d19e1b648b69e528553a56d8afb78221ad53307b7a4ec8d2fd4861b55dc5dae8e93ef387fbbe0b4ce7f788
SIG: 7477e54158f13b7128c0a110ca6b65f42514fb70cd5cf28a8b1cc6110ea06fcf94290da13f85a11c2351d3bbccbb4c64e0215d6d0f0099e7f27bc94e949b150b
TST: 138
SK: 55abbc5dac4128134dc8c6018a213ed4b60fcc8e90cbd41db2d21eda5373e936
PK: 251afaa2646926b2a371f2a09d5865b98c9a5eb6ca047cd0d8ee36e5e0416974
MSG: 47010e1398ad55fabe371dd8648f768d90df4b965a3b396100b303b40a17518bed6d86b09f734ab7c10b5f3a01b53deec5f8534b70c79f3f29b284fdec486f22f44c22ccd5c6463594415267baa611f70b1b316caa1b68b5e0e99b31c5bb0ce13679a23c31a63999698164cbf37d103ba92490188be59937f123043ec786efe3d411f9b0623a6ad972
SIG: f6a61c2e661a9eb7bde182e38ec99af985f61698a5d7fa430d16e3f1a93709b75522320de48afcc595ab209122ae0ce132cdf4b0391746e7ff341177570c8108
TST: 139
SK: f2dcf4a1a0d46ddb2d72f8fdd80bbec5b7dea5913da4966c2f4d12c261f0bf98
PK: d39570a25ca59f2257f93f96600df4f63e684bf63ae8dffd914e4629c3d5095f
MSG: 3b00e808fca4c11651d853d6b90f952ccf5647e102d4ee0ad7a5d181d5b4258c523cd39e3d9825298d84c8cba09f43dbba119988222c76059caf17b4bf9931c45e617448aeade151181497b24552367e52bc45ac79088806d3368207aafefd3057845dce819d5aaaa77b218e2aed3da76d40c1f07699f8172e4a5c803f7a2aceb9a47a8952e1b2f053f2
SIG: 42882a811dad2d851885e4cbe9044708d91a86f15dfa1d66c3eb304314531f3015208c711b9bdbc5fb233951e569b59d34e415eec4b37ffd374d412c9a360d0c
TST: 140
SK: 2246bfb06155859e10a748ff8f5919ad5d1daab756f01057b790d07474775f4f
PK: fa6349b62dc8c6a2feeef6ffc33ae085c649795c1c9d9898e75c13ae1625db34
MSG: 63ee1c7bbb15cebe1c22532d481682754bdaf58b8bc997ae30a34c9d23c33f1690c346ab0a7365ff62457424b6105f8421eca0ce3c630acfeb9a1cc416390edf4920e22b2367e9fb5d2ab25bee56da03ea55e3f57882d48b89229314d734cb83c79f4e17ee64bae6f7addbe9b525fcd03a91409a2dde907751db8cc97e08d0ea89c4d18718d26d0b897b64
SIG: 2be4915a352f7785483046d8ae9625b8b63257af57c073691256ee076d6e1b972a101f551c705d3f96157c33b56ea049be4af4dc561cbe3c1ec5072d7f134e07
TST: 141
SK: c088a3dd2cb8bd5d684db8538dc22473b6f014f64fe86af168b4bb01b90a1dd0
PK: aad615a9c28759f03d373abe666691dead8b84f9b8b50a67f8f0aa4a701580d1
MSG: 74906ae05a5af8e9968b6feb498569d6345a24f9711befb136e6c3b5ed49339e59a7938b4ba1a118f169b9ace0f7842a26a645f14c0ad22ebbcda93e67e4c348efc3d9ecbb1419e6262d0436a58ea82c2202389065ccf67c4f550e45b5f6a12a6c011b2e0a30101d5c62328bbf99c8c95563a6e33bdd9cce72b1f720139c2fd3e04913146ae5bac5288e0e3e
SIG: 3bb459d1ac575a180c1728d8b8924970492a0c8d2a378c29d1d41785c8379a58e2ba3606785e1c5da29e5527552bc6dc89a2b69c27fe51ed253a9f3b565b2700
TST: 142
SK: 45667d1e7b5910979c4a328317968371c864d564a661c5cce557c9ecc61bab9e
PK: edcdf5e1a170e00c8c687e7e9c18f9893b5fe495cd2977ceb7f446c0149aa9d3
MSG: cd66cec476c87c8dbf47ec91dac48fb5b42db1282a573e0a5cf0b91768986608e1d7ebd05f5251bcf8b47a17093229acefbd44beb21c0c0c928dd3cd3f8966ecce6910331c508ea76baf904d8c21f6c17c2c58d00afd3259b8bf794c146b12b995cddd1c4289c5be3168ebd616b384c281ce1b38a10e1807808853c681a640a009b4d2acd7934f8c6d07578161
SIG: 6de668f1ca6f292814625289a0808020c87c89ac94f5b0508e557bdf8000a5ca808f021c9679b50ee2f320064c95a464a8439379828c3b76cfa766455e128c0b
TST: 143
SK: 24897428ae6546d85b3190ebe3f1f7bf7c712528ac851a588b07d5c8f94eecd1
PK: 5f348fe3ea5b2c023d0af7ede60e55f91aa55199699da15a11c3791d68d710bd
MSG: 5201d9725f1dffa1863fa4d84c301861141acdfb64be1fbfdd5b9386db20ef394099eebcfdfecc62c6268607a84d55c55cd0efdc372ecf3067343e7b0731c2685461e24b953f99949e59ba3e67ed0f0848313793962a292c459814c5e28690ec1f45171f1abab86fdd14568b00caf48581115ee5ea83b000282fbbf0c0b2a1116039a35cfa3f201422207a3d4948
SIG: 1b5e75def49f51d6b2de008c71fc1a909bd42ca813298dce4eeef717815d7a6c078c2f3d9a3fce1ab5b3ad8ef8d45cdf2eb4901c32eea2d5e018dcf2833cad0c
TST: 144
SK: 7b04aca7cf926216cb960a3890786339d0a615967680190123fda3b60c6aeb11
PK: cdbc3e70e4e8fd13d0cce2852a3b9372c3a6160cd6deaba90f9b3022f70c91f9
MSG: 1cb09624b1f14a0260c7f56d8c60b5fe45837114232551ef5966386e0c2b441b75cfdb8df2185785d22cf526fa9df7fd45d9d83881b66c1feee0913e238121eedbb7ab504da0bee8998016684535031991f11bfcd9b95690aad2d19bd6a9de1844ed1362302df4217230b25c0552ce277534c650cae526577f25d8b1fe9f9febca2c814670d4805b21adef852daf94
SIG: 25d2d361751d52b4fe66ea18e4b9866bde3d121a7312fd9e28a1e295e087e3176c94c874a2e81600f24c4654f43d1b67d47b64822648590ce5ce44f3b5ddc502
TST: 145
SK: ea73bf64a1a97877c3c3e7ca4644b71aaa66314c8f1b66bafaebd5edfb888bcd
PK: caac93902e5764ade47294edd51faa14620940c668b5c1c392a6928325d4c3fd
MSG: 362eec68b912852786bb4f9afff9ecf7cb28c9de6b18422a8ca940b0d7e6dcb83aa44be0afb5f1806d43f0e31d71f922f853615a26e287a27f08a04fbce3d45a0c6c311d4b7cb17e425bbeb0a6b410b5d6dbb7ac11df9850a131a691e3b60b0b214ebe044106e982433287595267b031b5d4a09262ded8934fdfdf964d868ef9a2c842f804eafddefcb71d9f16a59bf8
SIG: bd86cb9c70a055279a86a9e64870988b8a7345c3cd2948a0fabcfb38abce3c420b4d5521618e11d2de827d9de569f6bc3be66aad40636cdaa64760ded3b7c209
TST: 146
SK: b8123c116b33bad0dcbc2c4dc06a3d66850dab360cdb5a033c14895c4ee31bfb
PK: bdca151ba32c6bb31531b05fdf86c6d78c8cd1935611d5ff111a0f00635b1885
MSG: 7970f6666634548c848bb52338817b26a4d0ca68df3d28afff207c2d028067a18e4c9543025f5b0228aa691e5088513151a94494e15d1f54210328e0df159b352c30aaa7a844f18a9f4c395dcbb3fb9fcfbed1103e0706fbf9c35fe2666848fa35dc2cf5227ebee89e7d3bcfae2721b25fdec3d3174ea7ce267a55dd61d58201e96bda303cf418edf6e32fb92f5dc1a0b1
SIG: 9cf13eba3dcc37b8fc70ccb2327436b9f08855e726aa7ed82bd5cb7df45fdf9ec1f96afad193f47572d770444b65b74a37cc034fc514cb3f91b2d8ada5b02006
TST: 147
SK: b18e1d0045995ec3d010c387ccfeb984d783af8fbb0f40fa7db126d889f6dadd
PK: 77f48b59caeda77751ed138b0ec667ff50f8768c25d48309a8f386a2bad187fb
MSG: 916c7d1d268fc0e77c1bef238432573c39be577bbea0998936add2b50a653171ce18a542b0b7f96c1691a3be6031522894a8634183eda38798a0c5d5d79fbd01dd04a8646d71873b77b221998a81922d8105f892316369d5224c9983372d2313c6b1f4556ea26ba49d46e8b561e0fc76633ac9766e68e21fba7edca93c4c7460376d7f3ac22ff372c18f613f2ae2e856af40
SIG: 6bd710a368c1249923fc7a1610747403040f0cc30815a00f9ff548a896bbda0b4eb2ca19ebcf917f0f34200a9edbad3901b64ab09cc5ef7b9bcc3c40c0ff7509
TST: 148
SK: 93649c63910b35718e48c590d261c48e4ef8336613f6aa077b462676b3ba8829
PK: 06a685898b855212ebc289915d105a4320d620d85771b8c6b15bf10a1be6e9b8
MSG: 2cd1a951056c9ebae1399b6bd2d82c0ae277856290d06920ac56cac8fb42435101c72aa9c08dd2d12426325562c2f0a49cd821b11b939aafa593b4095c021bcb4827b107b9664d68282888bc4a44af3e3bdc861be6af309044c3daab57b77023dc902d47ebc326f9bdd02dbc02cd540ff81b2ddf7cf679a41193dfe5f8c8ca1aaefc41ef740280d9823e30a354717c8431f5d8
SIG: 6274f2d4f431d5affefa35e7cf584a599017193da99094ca908b75acb608d1bf981857be93a7dafb0fadb3ff0906f48a5ee950456f782c2d605b14095ba0ff0f
TST: 149
SK: 1c15cbeb89362d69476a2aa4a5f3ef2089cf87286349e0dfe0e72d9e3e5a66c7
PK: 13a882a1064182582c211847e19b4dac59722c9ffd34826d96f33113400fac7a
MSG: 091c9b9b116ae83d23d01a6295211785d446b6228dd687ddf79bd0d5a4daa8c79d2cbfc37365f1f285e361738123e34e2bcbfc664ce1253a11d9e4a7982e58cf9468e1017ea14d2cc6d0865d40fde8cb560241e96ac1617c791f0ca7c6410cadf328611b18aef333d8350ac497f0a4ae2d03fdf0e23e426d34f4514780d1474e113583541f3c043672057172618cb2059eaaed56
SIG: 5998b2808adfdeeaebe2c3eac026d3f825f9c7f2af97ca324fbd57aac1bedff78a8ee621d037ee3ad2a712e9a009c58ea3e6f2a828f74b86da275a44a4b1e50b
TST: 150
SK: 11241ffdf34ae8ab875475e94c6cc3291f0b8820dc85e20f32fc53b24ae68978
PK: 09c045e4bd5137314c0ec1d031faf914910c45a4676f5a3cd8f581bcccb03c97
MSG: 3b89deccb7023e4b2b7aff2c3951870af413a9b04dd86ac78b7c8fd887492d8dde49d8fda149edd54781ae2b508030d14416a9a38bed2b9aebbbb20250b3c931acd4e32fbeeec5a26501beab7268d144fce8951a101c4b5178166fbb5927b1dfb1e1ce90d1d123068e3f472c888fdb01fdf70e7f8de9b0adb284b7119f55354316f84ed090030f9c2662061ca48447cc0aef964126
SIG: 72ce9f91be2e66cfc90f952595946ffc90bfce53087d49e5dd7c087f3faa8f18f2356de971e4429d985a99194b4f92ced3ef47cd7114379e0b3267a9f8b1e706
TST: 151
SK: 3bdb162465eaceff98d69c86f70039c517d168aefe6bb101b4f769a86b17c972
PK: d76cb7be74328289fd1c64be747cca5bb30295dfaccd0f2e43f51703fd5d3683
MSG: fbf368feaeba87918b1b8c7b8a26832be6e7fc1cbdb8902519281a0654ec73de0bb07101a9d603f745d4ec2357aee9870cb19a56cb44fbd9c91fc34752612fbd83d6fc1a16bf8a85a215d0148e4af37d298467e5cc486b131352ce092182ce8284159a3812b30bacbff595863811bf9a30a9da494565c3ac1814430018ea0eeed39cdbca27f93140e46949db570bfa2ed4f4073f8833
SIG: 6f1362a402063791f950984f544928e616a4ef79bbeb6854e9615aab9cdbaec483fb9a04bf22de5d97a15bda2d390483c7f61dbee07bb5141fc173b1aa47650d
TST: 152
SK: d5efe51d5cd8e108bd922fc0ea126190a94628ffa53c433a518022792ddc78ef
PK: 426b01cc61ff5e0e724da1d3b297f5325c18c62f64d5eb48d4a5216a8e9a4073
MSG: 9d17bcfe2dfc742f411cb53a94f359c001abf096c741f34af48679f281e7ce6bbd9e87709fc0728a563db2b9cf8ea4fbdcc344c1848e653ce970c6ce29de2ccd520300649adcddfc753971f846aac1ba42ae4528952d94980aa7c6cfa2142907647f894ae974a74d59035a73ef56a10b6612624809520190ace661c3a47095e0322efd781d50d1163598f2da32f31bc9c4f913d1b14861
SIG: 2306f58fcd4cff2222d81b05a475532b8b19dc67e6d78ddb4205a3b7621cc5aef0b393d5d24dd96c88ccbc53a3208da323be4587d5ec067c820f0723aa44e90e
TST: 153
SK: 18af89025ebfa76bd557cfb2dff148245214641fd5bda159f73da04b08e87c88
PK: 0c584459b9ebcccad587b272160bc60b27f4f772b4321de7723afef577edc7b4
MSG: e82f46652ab914af535d8fb720b557ac95018d9f2a3fcce85771bb40ab14cb9a986e096f3afe5bee829dfd8b97335c536ac971a21655af16a2f8fdba183a4e18564c21492956537a419abbbbb02a4bbdc01481f5c6e658ecf3c34f011ad846f5edcd4939195df85e41303fb9a88fdfbd704396f7559a327318b952b3e60ce8ddde56378579232faf950c78e7f0b17c3b8dece36b788a8473
SIG: 26bb0882297c2c08a752d3981145dcde55893a11df77f8aa4c19d0b9ed6e5220ed12e9fac3af13d0f0c71568f4a547d30114a6599a236806c4beee6765284408
TST: 154
SK: 0c93d99815fff8fe22b9e45aa02b3e6445ce1d6bf5a65dce3da107aa1055940e
PK: 4d27a47b0fc80800d84d244eebb1deb4436d97633a83e67125ad52ea01685057
MSG: 11e877de58c134eaf4c9f1b53c3dc451d3c055f16b09622725b279768512fe10a7adb0765b689ec21d5b6efaa19f1b9d36254df0a9367f441b26bdb90b28cbc403e5074082fa1fed58e140dac97aeaf483e2c13f3cc560abffaba05b763feedb51e60698151cf56efdf1d37d6ce0564486210f052e937f2ea26f63efa5d247ff188329bb1aa83ce3f4f35a3d7dec14599e5feb7b6d5fe4296a
SIG: 7dc4467abcf6431adb7ccfe868eac8cd8a615a0ff65f6a9e338375b1aae3c49a126c9eba79426d1641c6b97c3e92c194e5ee4431efa2439fd450f2cd018c8700
TST: 155
SK: 989e99945635192c023cc5186fc25bbaef47240775d15a56195d88cd07c3748e
PK: ca0beafdf731d89301f7723c5bb7e5a1c3ff3eab27c97d711bcd76e42054bee4
MSG: c48414f5c757d03c523ef3f3b8510771b0ff3b4b97de279625d349ec185a29927a66b9593ba19338c2f5e4131f1ac07ea46d2c1b6e4ab5229280b2e2bb9d140d1ef7af7b1692bf2d097b80f811adcfa95d5cbf9eee92a1641c552b4be4a0d734f0afd470b9d7f4e45778951e21fc534f200a128b96adb8373f10cecec2dac2996a062fb3c294315965a9d5d7b077c4b013c64a38429769d23eab
SIG: aef756bfb8a7266e17d15f3f11ee50ed25be420e95a0742271ebd12294e2cb96ead083b8ff0b829d2edeb14da86e402ef25e6d4a5a7958c184ed10c176cb570b
TST: 156
SK: 6bdbbe06d9f4219eea6403a357b25e561992fae0f0f614561dd86d23de415a43
PK: ed52dd1cce32d9b485e0940746421d36b9fde6cdf0211545b634044d4b3cb8f1
MSG: 582ada13d69293e49bbd461032dfea1ca2025b52e013a33a0387fcfc5f7c0b8ec955982607fc901e1b7f636a9d371e1f91fe476bdd44856e275d67efa14238164354c231124c84de8f5b89d5a58ea6744b4d3b3d7906905233cce694a64d696f5a7024fc9033b1ce390899a3b441a48e53c7c9b30ba12e7d61f35f15e658c7cc4407e2f689ea8a55d01bf5dbacb11954754f920f09dbd48409bbb5
SIG: 950206605b0f417c90843e2c8d8e66c828bb10b99b36eeeee8caf2e0e5484d93fe02bf533405f4bb74a50e5585fa0daef4821f0301d01b46321baa31e1f08d03
TST: 157
SK: d761c8c5a9601b9145b7d051249b004107e452e563100c6c788038c9ee8adad7
PK: e6488775d6407efc7b2bca890a7fc62266fc54cdac893343b4f59a196d948898
MSG: 84ead5eabd2fd4b7c79a9a928ab8ee0a16a5fd667a057f8a254663d56daae156d1a49affb2996137b9d8b340e635732f9d2b4c60218442541e72d2b00e1ee7a73c3f67caa499fa9d070b57d076dcde96b0764723c3c659c7a00c1b78b15ccc2223890b51067fc81e23e9458ab0683ba626a53d0c3793a58a9857bb44b3bd85bb6ce53a85694e7f53cc1bd46d50eda37d81f5381b513d1f38339d291b
SIG: 7ab78b64e6db359a2dc8302e1092ed66fa736b536253a1cd90fdb8c10efd78300225e191963599ba549cc859209df0ff61cd069b03d254e6e7d76c798440f907
TST: 158
SK: c5e0c7a7bb8b7ca07bf0a05ea67eff6deebfe3714ee3e1a227f4dc8e242a2fa0
PK: 5135efcd9052bec57a4431caabe82680eec0a33afd59b30203b280ba12be485c
MSG: 3770a6786652c4b78a043edce07f3e204d81997c42afc22331f75a5494a826d7cb69ab4314a473721058a1839981d5b7022d0cd8670377daf3320476d25b9f559561d66ee0a709fe17361e2a52898f5753c4fb43bd0c98b368f512adc09cd927c6622676926d8c2d91a14aca32f226f70036c1c858bcffc2b59f54c1c37bf81eb52ecb3f00da602c94361b52a5afddbfd7e05036e377503050333be512
SIG: 2e7fdeb3484d0a5e8dce94448979496b0642cabc3733a51f8c3c5c51c19ae319018da91091c2385f2f4e9a59edbca2abd0d085ee40d3f0d42061a5a9832a370c
TST: 159
SK: 11bb4748d2547e6196be823c9be7aa18150c204b12ca8d73c1bd46b11a54b475
PK: efeb42da28d764966403dd300d9f9451b258ab1c80df06fe5943153f5301cccb
MSG: f4b765b258ba35b427525c7f10a46f0bccd357ec1ad52a5b139417a9d3894c512d89eb88e681b1f30aac4c115ccf36545e83f37834c82e8300cc1eb289af4375968c29c0ffefb40e156c20c0432669ac8dc0a83c13b1e855a84ad0133c40c82c87ee1e7dd4084d741c80de8a7a9f7759e843a562099c4d7df875352039ff4d3824651386c97759ff7dba52064e6d3112e080819aee8ce723a1a2aa464d8a
SIG: 44c58da49d2365d27029d1eebb3bebf7c032d858aa07e0756b1c26a5412d22691176031341ad37d7bb7843289eb39db491584c1b2a1da2e4a2649c2293826606
TST: 160
SK: 7452a00156d794edebff4adb1f7a7eec26217fef67c3d268352b2b5460a7dc25
PK: 5f4dc338cfbd384b5f1c14c226701446b52b1e3e2a3cba1a40ee2825080d1de6
MSG: 8c4ee2867656e33f5269414d77b42d8e4750dba93c418bacca10938cc3b570c6603d52c2344488607b2f934f6d269fcb2ad966219b1ab11472f42c672ce20592490ec5baf6a2d2fc8a3ee35374b1902fdefc7870b1b626fa46b12b6cee241f601a9b3fe4c50812e573e6752ce2c7644e3367a6a6b77758d8e4934b58af23abae8fecac25edd734030ee7cf39907e3eed8186a19a807103a9fc49d38f4c8460
SIG: a8f9fa24a3dea1022e73f0d88b1c37d06d0f0b20bbff0ecdb4a40c86d7e475617c03570a7419d74ba0f1327096bf19f0d0cf9f51d483112f26922378682f4807
TST: 161
SK: 880ef106733f04e76195eba280b3fadda0f25dcf96a6a99c8ccf842c68afdae5
PK: 70cee33d41c728ce7b141931e6e8524567d7601eb79f67fdcd07b9d682c650f0
MSG: f4f38d077f2b03da821bd36fde673d666e52f4832e1c0dcfeef049328acb7bd71ad2bfc49c123516e196c470df0847b3848a45a2c69bea03e2afa7e58205b63b523814fc8e242f059c69ff7e40f97be8125b70a54fdaf35aeafac79114a7b419e6bb9e70bf07adb559819600dc25e51b4b700d27ca5472a0e7cbbfd14e099faa3a72002da538cbe45d621ef0d5252ba29d83f8b3ec8389c9ceb6c6b2e8d8a20f
SIG: ff6caedd8a468aa07d4c6e7131bbda76182ba958649376e711f44c7bbacba6077bea878ba5949cdeeef05cfd4983b0057d275ea3e18c32659468c30c47ac8f0b
TST: 162
SK: a2d88f37ecc2b2c05dd6cb3159962c5f646a9815b2fb37791fc7b606e2913ed5
PK: 58dd67d7a15d4ca0341a4c869566cad8c4ee16e583a10b4824173b08290d92d1
MSG: d1b87e9e886dfbbdc8ca8ab9010ecf9bbaf23f72ab3cbe769db1d43c2a474a81651c464e9fb92734634641c9485a0239b3110771e7f75e05252e4d8f4c0aa1ba08626d7e96317c20acde2ad99b23bdadfd6f17468eb402ec5eefa57b47caf972b3dd21d89f0e2989ff87d51ed2e2d639c1644e698cbe0221b8e179f3cfb04a20cb2470216a6882fb4ff799e11536cf64219f0c075176bc7cf0f6c5b7925fcd6155
SIG: ccf2400cd673e1effd20161d7b68a5fb87c1e99d3635d78c2da1b509fac33346c069163a6c46c7826a48bbbd03b05e6e2351fa62bf89bf7ccf9a9024bd157d07
TST: 163
SK: 42aafd0ae26df1e7aa0276860d752783af97280439bb23eae46e3f84caac78de
PK: daa2350adb55dba9df7d7af5101998fe515d311c3cba3eeab9138233190c3b4e
MSG: 72131b80ad599b6f5ff698547d16e7499d71275e4e9b30526a5aac0b0c8b14fa4a540cfb1145fc004418bcd318c1a70e6269a3fb69baed86f363f5b8f97f569c20d4f4990e7bb4d0c39921268d636ed0554bd62acfcacd3b8e030217aafac3044c037e0f94da18c6b9a0932c3c5875d3a93fbdadcf67964eec9ec2be69b48f020f6c9874de5f8a5167b5ee024a2c2efd0cdcd2acd8c1f787814141e30b38b163175b
SIG: 116143650b6c133d617859db2429c2913579790b2197d7b7b1b4962b328721032ceeca58b2d56439e233bb84dc525e284ff8df2bde1db4986fafd21b3d7d6a0a
TST: 164
SK: b69c33b11ba67841c3d4e6f9234e35370a28b47662ac560b27c078b66ab1b021
PK: 9df68e9acf67379261744db5d1e377892f2b692ed5a38b37073c04de5d226737
MSG: f9ea126d3ab21961aa2433900a3982b83e0ef86d52d13440afa4817f9b822fb582cc3932bf450d4677c9188181fe7526ad6fe5abc61d0ae759f215013c0b2b41064cb6278ba7e39e2f4c10d6cc9605b3869e169d7da42e88eb857870fe6118bb02bc08c8055f0c189b62f79fb146b4c543aa30cc0cd57f037e9ef7a63711f66e6f2878931702202702614277d513f0850b758549336b30cf40ab8bd460e60e12deed04
SIG: 24368fee5bd848b4c661a3be4f310cfc436e79ec4a78501b81095fe51614231b6ca1ab1269996ad2e98e299781af8e29804b24fe5679ca3ba650c5c4cc58ce01
TST: 165
SK: 7b63613f6dae01cdcd5e6b37686971cd8d8a99542f6329a12854a9d8ff8105ac
PK: 72ec43faf34d8730177d1f0743c74c20bf72c2394b8a7d471ffe2a04ab00811c
MSG: 1816488f1fc83e1ed5911637dd42ba2077657dfe1ae422ad0aee59df9dd56a2763c2dd0ef61a12bb825b0dac1eda5fbb691c5ed58f3fb325050b4563a4042099982fffa5d6ed742d95823da8e1787cf746ef63b3fbb0e88a6c0beae4f7318366936b4917f507336068b194680900a7bf4a6fb69a5c387b97e31bc7f9be53c2a89e3651ce1de41b10e921b206ebf32e5621ef8081616dcd7a2059437efad014bb8e2c8221
SIG: 76f50b2b9c2ad97bfb9499ee41928ac072da5e8bc71d0212550942332b62e70c8bfe1c722542394688decd917aec8f95353e1d72624b70ebed5d17f6c5497702
TST: 166
SK: 3558d3a74395bdcba560e2c45a91960cec6cb3edbcd30e722f7f055210f37b51
PK: 534f43eba403a84f25967c152d93a0175ec8293e6f4375319eadf957401fbbd2
MSG: be75444f9ce6be1d83af622a8c478d510127db56f1de6eb8a5126522b09fdc6ca0862cec0b8b2aafa31c17a2cc477da533d276a1ae4f8e0759d6afa0b17411b5170b52f20547c72f3e88d48cb456fe625b62feb0f81317edf1ec09ece534b9f500d4e1b1bda2db21982aa95094226ee9f5b0a65da83f91121c96b3b4010ae7826c9e80636cba00f70c3c8a279b01b95294cb850f91709f4376662a580b15ac2981afe9f854
SIG: b365b5561a13a54517cf90d88b35eb0967d6d58414b8c1547e693159e01378563654c50fb42323f09dd78ffe28056ddfa54febf44891e8a741b6a1687d728605
TST: 167
SK: a35b92f244063a19bb5e3ed4d699ed2069607116d2bd08113f0d8373613f35b7
PK: 7ec93601864ee4995a4f7abcd3dfc101e9e7f369e63de1ae68a07aa7f075b329
MSG: 65cd36dae0168d69974f95f09dd9a59db799f911e1a15b85a00893b8c9a3d48a2f58ac126bfaa0a606c05d94701d273abf7d68817f2c71b1c541795c4f6095e26c9dff803f032f75663fd1698edd97ff3a0e72e1b7c9948b08bacb5f7de502b2fea67ca2fef190d60eae92d15158da444a49d2e9d5a573e8e177e8bbf7e6c49f907136e71d2a66cb07636d48768ff417c8beccf4323181fefb3124e434049ea45dd5019e40b4
SIG: a23dbe3757e478dbc84d3db3a933b0428cedb6b01b86d8d73f3959878dae6f0588f505cd4d39f2ab4677b64805d629652a22529825c3a91d043749fc71f03706
TST: 168
SK: 72d4a564ca15499b5e4e75d8ac0f28217d32114a0c649a7c8eaadd0cc78c520b
PK: c766bd73837c4faa5215502f1efc90c003f711bbef55170091028a34493408a9
MSG: 6c7e7b62eb244a45d78436e2970dcd6c0f7db82297a86140ea58dd22c2195adbc956d4c4ec05354b21efe24cfcfe10e17622368848180d2c4680cc215e8ceea6cce222161f1e092239253b9746f7887df2425ab5a880bdba98153be786dc838cbeca016b1d06524bd6bfba809a8bb37adab15d42415f86ec0358365ea87b8150b05441d9d49846871485caae6de359736c27189736d8f1765f3e5c5f6b92168396390bee94cfbd
SIG: 8fc4f179330b642dd86ca9362651b83b006d8375ccef811d3c6706f91594651df2769953723046ccb9bfe66a667e0d11fc3ea2d8226234fdd5164765260f7b05
TST: 169
SK: 2e5aaab298e66c2dc1d77ea7421ff895255f9d900db0450d63f9f79c1a7013cf
PK: 0381f3f19045719b9e8ceb562f0e965dc07b09f371a963a281c749c2532f654a
MSG: 3df0e54c711e3132d7ae953deb7b66869ee531ee40b63ce693206cdb2f4bda0a2569e913ac3e6532c5d9648efd4627780fb8a31d107e033f054d19ed8b7c49dc407d2e949de25f99307221d35843f6d5eb7de5cdf41b91dbbf34cb6c9c530021014b56abc44ac2300313615608a7b4a235e99c14cef8050887032209488b9eaeaa82c09405fc75bec94dd42d6ff1b599a63ee5742f3364093ac92cabab3035822aa867ae56dcc99d
SIG: 7c7430305b361a9e35b2780c4d4408071b2130931d39830ec8d313aafbc83a65dae19cb747d9d1c4ce3f359cc824ea8c92f66a42b8614e7848b884ac8aa4ae02
TST: 170
SK: b636a02448003543db864b40b5d8d6dd9ad611624c9b0fc6890c51ea5592c790
PK: 1ef360495968e56e6d3fe740b1c84c4e4490ed682deb4305afd596efb280223b
MSG: 4aa85aac25034f614ed44f7adcdbeeec25fcc2a9eea32ab6a8699506f7a1cad3bc892e9dce934e75b0a8cd14642b778599286cfd8f50a9e4f2edf9f9d6291a2e2979cf1806b93ed8c9a78fae199b2854a03ec406ab3f720835ee263fbbc91cb4ef0758d775fc784c7d5b251ac8937919a9e67be88c9e44cf2ec7f560269aa0f1113d91b84401db15a3c48c7dacff4939ee01babb982fb95625c6c3ad78749060551bfde8cce4fb8a29
SIG: d4ba80300d5cb51353c03f28c44fd0a424ffe1e40d78ed7bb1133e8fe4e187505293b20a391da962c6a8ac0acec9c67226af3b6195dabe39b3662294da3e0e09
TST: 171
SK: 5ca0543c71f568a00eedf50a9520f4c15b526e3fb0da816c29ea3d50b2f62a12
PK: d4a2933ce19454e331b5280100209a6ce8e569f993c2acab51dbe864c5cb2563
MSG: 4ef8496978d28c10abd54a26356ee55921ceb350dd4b742c4161fbeba8a1601f8ad0484b21a8cf5a294fac00ec8a6f59e3362e47bfae1e28a2e6d017c5caa75fb0f48482808037ca21476954d778ff1a0586da3ef69d6cef6d2d8df4ae7a85442a1e46c998cf407a6ad4c5463a43c248f3b6937fdbc845b60c6d85e0563cc16ba9675d364f525f669aaac95f428bb58205099f9e4a6dbbd0151fb65babe123e5393ad64026935cb488aa
SIG: 436823eeff3edce5d8587d68e5473ef3d8dc9465b558b6e8e7cd3137eccc80b4c4e806edf13619d8e717e69f48d7061b68de02c8209be1f7ac26ba8edf606d02
TST: 172
SK: 5f87117da9bbb6091c94da6b230b7d8f6de0ed2a076413b92eacdc43abbc6897
PK: aa786a146226832aa73c434b0edc2d41d2558f820ab8f87e09e6cda91072b9b6
MSG: 2297c40a2e8365bae4c5f0630c50b13bdd9ad9770a5d9a9451d00874b023d25ecd468b96571b2f16dcb1b0d3d756c1f044fcddd1c51f27727a0369c9cf25bd6aa59551b5b07cf8f807d92b159198639704740fe6eda0f26dba7e75d4530b2800f03fb6aa677d84df75d68d4fbb64ad21001e3fc87b609b9c251e8ccb12bbca927447e2054e07688eb8a20521a52249e7b943bed60e6a93c01e3eb621f0460c18a690b6f6b66edc6e8743a6
SIG: 0f19e6ea0c05f38185c01c2d6477995daf5065ba9d80173fa6bb23a774dc88b3aae879d8a62471d2d304cc3dc66278a7abcb0bb0771cd278e11e7b932e9f9b0f
TST: 173
SK: b53a644c92ba2dc7108b16833f09ad5917846437225a773d32d79c97733c0a58
PK: 515818c69c0e0a1706b04143842f3e9e271448fbaf3a899119c32f42566ffd33
MSG: 13036daaee45fcfde0c53e06d05aa9c01ea94a67e86c6c538ccb283b368daf7078d3fbab580c76ecf82b4e9660f068dcbb500b80595017c5be3c448fbd8a17d97c5643197890e167b35345bf65e75b82c8d65229f2f60aae2772581bc99c49d416bc3d78746ef830f1af944f4a6715ab4ffb01591bac2857f1a9c9d1700888780006a31607338f7af7bedf6efe0b57299ac915526fe5e1e101298708c6e61b84220afe95b53f895987456152
SIG: 13d2cbac7976ad27f0bf669ad588efb2c91bab8507d57fb16bfea9caff2b0964e75625c4d808d7bbb78c5b464edffe4949ecfbc8b95ff6fdb1bdca2742068100
TST: 174
SK: d27c9eafcf88151990bb5b2fa8443e709b5fd8d78d233803322dc86d93d93295
PK: 08e0eff529776714686196d817fdf71eb5b6e8326516ef489bfe186ac5c5bf6d
MSG: 77c35bda32a5967d8b302fa7a47583ceab89c9a609a667b753155fa6996f8631d0ebedfe0ac364c77e85ba37311f0de57a0dc2c1e9e400d58b424a322e1d5771e0a9fd9502ad0232ce544f07d8c66e7c3147f8607ac6189bb69066f2fad631185f457f467eba33228ecc40e894a77b571698a9bfac841a54eac5219da99c6a9125c469a22fe81f3b951433896f19ce39b373fd7e5c7b650a5ef2365ae7510b0da5e49d7c07073cf166a98387e8
SIG: c254e371445633137442eefe40ad4a82e69b1ebf48a685a2bc6ffbac126d228487b2e3537c97ef7410342091962e50c0cb85de7b39ceb41ac4078d40f3407106
TST: 175
SK: 70213d3a79c65d6dbba542a3679635003a682af5fa58de6b0d65bfa24184901c
PK: 4402fb92cc1249dd1ae1690f03b3ec4f1e9bdab0de5bfd289f10296830fd403e
MSG: cd6e1cd9c90f566de043d75d7244ecfdb38e8bde2f9a6cd5a4fdac72b5ede6af62d981918c5e610a38789274fa10e527f85fad209b76ca1c281ad5890f9c96d35de522f1ddccb539b8798a0067acdd45b6e344a5d9a97731f545ffa4b17b875c67b48e9d4c4ba72c98a4505583fdbf1e12f22b5a7a494746cc9b6c1b571906c67fcc883a9c15a3806875b659e5816b4276c3190e25cc1ac3de47bf99c49965388f54f3ef8eb569906c6008e5fbbd
SIG: 5b6ce2774d400ecea8a808f5fd0a797ffc6116752376cd7bfa3b2cca3a84d5593f5c03ad3eec1d89532275c47b7ce2a0e9c59cc4028a8a65e5bb9097ea71c208
TST: 176
SK: 5d540b3b14f0c0175c047eaf026c9070659ef13e9d28e0c5c516a428269b14eb
PK: 1d2d4d551a57c6fb2b04181049d4039d575cf80c0bc6ec7033067f27309344de
MSG: e4c9e8706898cad4ac68d73c130efa04a54f8ca25919ea6bfaa54c8c720ced854c5e9509102c7b885aeddffbd1b7f2c5922583677ac9eea9a108c7e83e8871aed5a084f5440b0f391ad7ffc6bab4574af1b96770f4370e8e988e85ecb1a8d6034fc3d7f49f7422023b9dab5d0c16beab5f5d37b0a4d7de197ad87cd4ff8ce78eb12e1daf739d8b47ab380abe9093356db5b59717751a49e1948472fdacc259ffffc8c1dbae592607d4ec71cc6a8f6b
SIG: 32527da755312889935dd5ee91b1bb117a5d377dd23ef5b7e15baffae9a54391a3fd234bdce073e098c58d05bf195b4c3cc63972383ba4b51072971aebcb620d
TST: 177
SK: ca41769caf1717b4e45c93c121dc82a534fbc6ec0986662c3222d71492bd1176
PK: af3f89f6187dbcf9217750c67ef89ed47b039f9eb062ffec9df64ab52b0b45cb
MSG: 9de8476c5813848ab1451537841cc178002181a2182af305b12e5f7c3b1d56b22cf46ae6276d1826ec0a8c9a7d9f68083b7225bbfaefce82b3b64594052a7700f309233a79fffdfccc5c21400c91cc0e418d5141d486b5219901d6dd2447c1f7b7cf5a0879e70e1dd658d0f2ecf31ebeee11a5c74440c63b9d8b45318c3465d7ff03365edd0385edf80d4fded51f0f7533ee4099f19e93bc9d08dadcd13485db239522ffc81e2c051f8796d62e979fcf
SIG: 5cda872f7ed6d7c90218ac10bee8e214f3b34d15d25c39255ec9e6b0177aa3cb7368d11cb8ed6ff5cf0c04281d06bc4272b8bc09c23f6f4cd5a810ddc7b9c103
TST: 178
SK: fedd63ffd4cfbf618894962e121a9025eea318a80a1adf169d6490445d2e02a0
PK: 542f2244bdb7d84b87e628a8e6a12f17bf74a9a6d0ea46c595dbfdc680c04b26
MSG: 2e2ae584641be03dd48f9c618077aeaa18212a4241f0c0194ed23e370d741a3ae11a5fec3b040c16eafa4ac8d18abaa7ce8f286967337189f0495ffdd61995cde31dd8dfc3df5700b57a7a29980e9c823fee85d61451176729e72787c6109b47359b93dfd62e1e5a2d642c057242dae500a94ca1a93bc57be1ade76fe4501c0f6377ed0e9246179aecdd9946b671e8190e1ed23f966e96409b948222d8ea5839de904fc51348073b8f40edbd9b4a4b2275
SIG: ed59d9e23dec3494b0fbc5d10cd02bab86b3eb35abbf9e4d4a926479f134583a44ce72dc4122aca377a4072b7156462b74e8df46b686698636836ef203179c07
TST: 179
SK: 38f2184eaa553656ee2902706bcec4acb5af25157ca0f6a2d48de85285fa3bc0
PK: 7ff03fb4c82e9c15d659df424b3e73ed1d78006f3e0b79eb64d98c13aec6ba37
MSG: c2df77c9e479f61983b6c7483ef93fb85a103b213923926523065ebff2257e85427e05cdc27582ef6c16be353a3b250372d6370eecb6c8962917eb656f2641690189d172a111051557abc2494e32cab65ed0633affe92408b55c4ed8af65e2c5e7aab887a3cc8d28c52e9e1336d0b7bb3fe2cd843e7fa1680342f8a4aafa02c4ab252f08c3d46d5f00fd01484263ee635284f6db26d6298de5b0dd238da40a8d2a93376da0302783a0e3be23d9e7f990d25b
SIG: 4a6413c2c87f2b3856a8decbce493adeae0c69c94134707fb0f18f3049fd3e3d051abdb9d4bee253c6107c02d57ad7cc9f3101db660afac2b7981938e9564f01
TST: 180
SK: 8bfca48462d2536f74b84f6af59f5d8582ff8f7ec28745d672e72eb72e79d3e9
PK: 9d10d275c3d3fe459f7fe2901bce389191cc8483c0f51140d9c62b08fade81bb
MSG: 81ee4cb9c45da691dacd7dd09aff59737267bb55c3ade1ba32c17b7d0d2d0c6079c39d5fd5b29ba5f9c1762097709843eee5612bd20bc8185bf64d5c934184e13624e6f877a2a5dda15c0df62afbb97057cc91cac9a18406a0e0109cc39b2e3f812e227a4062d5ef81c92c22a7dc797c845d71eb6ea9e42ec8417fba90a96d2bb1439418330b4bb2f99c6d63d304a0e506dca9653e5de0dd56e309db1a76a0faabab163774f000088cef3d1b7a6cf661d2e1d9
SIG: 44d77e439ef6ca5eb940c60ff8732ddc16269ea023bb2613bd447eba7fd69851226c4819ce8d44985a49f3f41ac7af33c47ffe5f89304a3256e445f8d686e307
TST: 181
SK: d7480d4272bcb1557b1bbee04915c126a52ca6d6a8bb5314a0e1a52b59bfc99c
PK: 99c839d36d8f5b8652618ed7b0fe9ec3d94efff4c453c540631476a5979bbbe0
MSG: 615cc19f942017365ba8bfa256ceccc85ee289a1c34bb1442acc0716c7fc2caeb76a9de19adec106371e47a30d2e1239ce1f7dca25526d604bdd647659d942bcbac368911349c3b946a97da10a42dbcf3c73416d2e6ba22bd29d9f705672e9e338944cef01ad21f009742e07bcd888ca31e1ee953e8c1b1fd954b7dcf1a0b1d5a069065a66cb721adc020f4efe1abdd16742746939285780d753137ae0140bb410fb6ce33676c27aeec593a88cbc73afd9f40511
SIG: e04dc8442d352173e931818e290858de85688a4649ea3e3c3ae74edaa54ad01b64622ad8a090b6ad60adfd01881882828d39078bb5b2714fd3ea8397a342fd04
TST: 182
SK: 3c2d3650735b41ef9006bb45e4be2e0aa5cde851aeac421ee9c1b492d87aa18a
PK: 3e46ddce298844fcafa00a1b47eaf3de70596df1bbee3c809d1be7dd94080e34
MSG: 1425d8d218da1a10a80b6a9c3c2750efe41657984abd5100f451ba949db01046b7126be8402334ed57528bac05622553a86b726722695a8fb331d8565417c4ff0f251a320ad06dedbb750def35d521c3c4cd571a45ada8450653d5e81fe0beb53aaae787b3eb653c2381ed55aaf2590ee5ed8b6626f1c4b0430a54f39658624e6635fefc98fee8fc3e1cc7ff3dd420de9da11a62fcae0e0cb454fc6f7df03954291d26202f1b188b657b3bae07389449b75e67422f
SIG: 3f2af01ad5377ac39040d41a41e36e7b93fa7235b841791f432ecd7f91a3b21ab7196c883ad5a7db446f6c06672460f3f63ef863d9432be9caeabb79e87e2208
TST: 183
SK: 74965996268cdc4c09220bd31ce07b217a03826ee981fa89f3a2359ced095ef1
PK: 4096d027c1c5ee4cbfc04b9d534174029fdb50cf5610d3021ef933b4caf33985
MSG: 45b2f064615bf774fce97f51c464685d7b3e4fefff9231240a719b3b0621cd4ad83305675cd6eaaebff791000b0b1fa31d82d8181b7fe57c5e00cec56ff9022e9ce8db66356e408e3ee262fe627789e65535ef1a63e8fec933be3dee34d2facdb8928cc456abf2f3e8cab47eff1ca42e8b0e48d2c73e7bcc5de3f1056fc523dfef6b0023f32889ed394eeda032abf6bcaadaa7f3ee74118760ab6d91df528bdc5807972c85fa7cb56e387d7332e779e52d0dd7db0cfb
SIG: 8c6628344317a63aca6f78cfaea965b3aa5522ce914195141c08870a1b8dacf34b79c7abc693cd9e5ebe1a2e86f0332d2048db3cbdef01687962d6df249e3800
TST: 184
SK: 0abf069c08b2691c3a26f79dc8ed05cb71d220ff78f3a5c5780ae9da18e45643
PK: 9ef3b5cc016cc82dbdda705766aa448bd61fa1aaf1170efe9149daa9fe64a1ae
MSG: 0d055291b2e861eae19ea0fb2069d8c9eef4f1347f3576d78411ae7c0b1c1caf31fde736dc8accacb662df76b620b62ce90b9f92c83309128621d057cf845805949088e938ddbc3d41c5e5541fec8298687ad2f79acda01aa215d25821436eac9d268716d4cd6050260cb4ef6aada4835e073a845821ff211ae2baadceb6e57f06f88345edbf93bfdf54fb74123b57c0fb4a79608d8db6740889e15733507799f7a1fd3017bcd77b28a2bb6c91ecd154e9c5a5ffa0eb62
SIG: c7566fb3b4d8def667e040f276d3ed98d36dff460126a75b4cc2100386bb01c642f6d8de7e649be6e0818b08d77ce60f4ee5e7717a50884bdee02034ecf1cd0c
TST: 185
SK: f3fd5ec5e230b6dad1ac3d3aebadc7863ff89de2a1317f424d15989a3efb0afd
PK: f99e5d5eeeaed1205cfb5c2cc4e5e9f6b4e7f64129f860104ca6244eb9feb564
MSG: 71f28973ed3df05945fa0bdb23e9beca651d3ee6bf9fa45ffdc6061e42fa2e8d76235f0e9e2daa65e52631fc3bead33da055bb492e4758e598a030a33b3c40b34371459b233ccc043cccc3a3cbce549e20e0b2b43305b64aec661aadba6556b17d76e3bbed62c4a4eac4f88603996752d2363c8d4a2789d128f6e959945c68c30146d194ccb6839ec65344601652c18b0074e2bc7668311697d960c7066597924d704d02a0193fafbfdf571ee0dfe414dc2f52896912bc32
SIG: 44b0124663adb0c73aed49f73403461fcb19111b0ba17aa996566f477e37d524b0e1f107612fc52a7c767b181fbf4d629bddc08f30584dec6124c5d39d423102
TST: 186
SK: 738f1310a4e08f917a0a5c1fbaf4ef72f95ee62fcded50868a3daf98856a448d
PK: 42272c2c8b08470ee5dd8af8849c01b7508d3a3c65b0330e695c841d5dccb2f5
MSG: f0e7ef6782d04c6943b19eb66ff6226b736e3b0940c09bb126bfc4c4ca7a5e7016c286b7bfd73aa6a79a96031bc81cb5da68cec71a6a0d39780cbe6a0cd4774d3aa06a881610444a8c9d19102294e5f635187aa6f48d11912c7094b38833028d570cb110db60625bb1bdc37affa25ea3c8f8dbfc2514f4365c62b2989a66d27c80384e74ae5fba8c1c2af9c72c4971e64fa6a1dc2517b31ea57ccb0815a7fe2da0f146caa08431d25d151662d9d26e95229d0c62823664123c
SIG: ce1e3577b6a21016b9dd0b517baa0ccb107bc199b8bbaef68f950c8ed58013c853b4d338eedc675079ab1390462ffefa6a959b043f8b5651c6ca375ce0b4a403
TST: 187
SK: 8841d22aded69c131ef5ee0a10ab0a9b77cb754ede8d257a5372726e2b499c6e
PK: 715ecca63681bc6e9e31d18848902f4d96feaf43b95d008642903b1763bc9fb8
MSG: 087ca6be2a950c024b3e7467fe00a7d364555d5dc6770f5ebd260642525bd3c0f965db36d7b229a57421eec64e4d991cdde59123034470553f4eb0be81ad2936c8ca26bcab4e5d79040e29798728601684a468323cf3baae4d948d0a1fd905effe16dc44642088df53f6388bc480edf4aa207d0ed161eda345712b4c00cb05fcf635ec2588785bfb8a27cdc28996a1db3e6787023393c075d83c9038fed7899c55fec307de3249c14bda49e8b895860942c36d640bb893779142
SIG: bb2bab7003f1311be9b8c883fc4fd528adfd51a9c99db3dca8da0fca958da19a10eb22332667b1a0065d3dbc0d06269a1259b6a890484aa2143a52695f145b0a
TST: 188
SK: c02135e7b65aac72f63c32bf5bef5b68c7f3b8ed56208e59e4752070e9d07095
PK: dcf600f244037a75203ae11ac316e8dbe9986f0dce23473939334bf5cea48b0d
MSG: 86d9491350d2566e708ed356185d610c73465b2a5c7012919958af2cf76af995230d360de400b7137170dd0835f10fcbec224ee4e42c7d1cebb7f580fea8ed6223163bacdd1923a572cbb6dc26ca8b17ade68c6d2808c4ca1eca28eae9a145f68d4079d8d59d140e958228e7e99520e342dbd7457a9159740f48bdc27b93bdabeba465cbf0c8df5ef2c0f9386eebe656f5d749d5f9147f525266910d7b80396a90be5cc188a9a945f93e753fc99bafa18ee0a6dff79bf8484898ef
SIG: dd5cbae479eb5e229574c21ec3bed911113a57a1916d3313457515d55cc5b6e6ebc52c93f821d13988dbba8df5096d55ff9c39e7f9d561cb58930c96a7a5d60b
TST: 189
SK: 154a47eba1b8c38362ea61faeb0c0ad7e61e412a3cba4688af0db2a487208b1c
PK: 16de2c894a50cbd4ca90419a4ca64942cb14bd335c5d3f4a53e239c280bda725
MSG: bf607e8b6e14d9c8acd96815af0c035ac73c4104c93786ccc1c9f859395dd781900320ebf356aa991cdc9f503fcee9f83675888a7d592002d2a54a573a96994b3fa865538c617ed8ad1ff62018288a674f449be0aab5222f74c4fd475ed6a8dfb27f45287b22b2b6c3bd15179f267d157d7d8a4159679be85b25c2bb2ba850aaed9ae3ae571be4f75836329cf36f412c1c80f1413b7661eab4a8e11b6024244fc62323ff02e38aceb1737bd474bf1e98015dbc788b027bbe217cf4e7
SIG: f4b6eb1a8d950e887fd2f30f70a23b41871495bfa5b8a4ad3996cd9bf51eb742e07f4c4d2da4b01ab087367a50e2b65b3cef514e40d837540b8c89966485910f
TST: 190
SK: d3028431ce2eef73bd940ab84ca29f13fb26436aa25e1b7bf26cb33f17fdf817
PK: 63df203e2860bac4d352e722c1c91fe3776e1cbcae8553a4f19890260bf0e457
MSG: 086335d61275d168eaac0540477f50d4b15f9e50b9be693921ed54a9941bc40643cda62e1d805d0250a81146bd5fe2d39e81444d21e2b21b031c111306cacbf52717f6fb4cd3416f1215f8dddcedd2f0096b0fcfa0a6cc2cde7a2bab7f1e32790b5361df3671424cc722f231bf71895bcdcb7b22ee074e8fb4a9678504e735366c172f07637b7a93149bb21f38883378a1db273fc23239e35337f9ce566d8ddf3b3133cad7f2ce81edb503ce1d27c5a657160b78dca9aeaea379be9c85
SIG: ce9729a96c3ed28943b27839c73382ecd572960c1f9e90c5eff9dd499ff48f17d25edd1268effe41ee6a81ce48d84de513df9c41442621b2f5491e346be18c04
TST: 191
SK: ee8985dc27504440a8758d4c53e4225215797a00cd8631d59bd93bc66f373d5e
PK: cd647bb065693d486589156a9fa261437534dc86f46f72d0a800399a7af010f7
MSG: f2220485addfebce02a833aca33381d1df917ed609950ed24f85e3b02b2b994b4d939784e332f41064c8b4a2630ab36961742aa1cffdcb08c144eeaedeafd48b5dbe96bf24350e14fd68286bc08eeaef8bc6ad9e195d1484afcd30afa8ced4848126d56c81b43c27a5dbbdec1a50c11062ce21c61d860c25a862fbb75c3bd51c8dc07636668669bbf751eacaccb3b51d2c0d4140316cfce2eb18d2908cecd5a188679bc5f5de290f548e7ebc57d41b589a24ce88ee48d97e8d0c7c769960
SIG: 5bd60ad5e9bad9932ca9c75f231a76889ae7a8b864b91d1fcba5c5d4bfa1d92838adb974842a0710779b3e3094044909e92c7cf046ce519f4c68e8f19ec03c02
TST: 192
SK: 80dfe2bf7387bad4654eb076f8dae9595163e40127f5df492dad7df04c7221c4
PK: d1783ceeb9cf8e4d07764c473fa4061b8274397103f2076d703249d758b8fbd5
MSG: aa09d784bb09dc999931ebb4c00e424cefeca104818d8eaf0661f09728ad025ef47393210571f17404e9aa6d8cbd5fd88cd7dfb8e2e8a108c05de206f3408234a3b463dbe71a07d05587324524b7326ee79d3348ddbed7871b86fcb488031dc9ea93f6b8d7fda6239348a562444faf1e72d31af35443e9df53e762f3e56b48668f9784b3368ab278a48ef4546a26cfad0d0a5161698f26ee8d34fc2b3d6dfb93b009ac296f6afe487ee335eac9f02cfcae5fcbd1a16ba4e71be1b112562fc2
SIG: 27279e3cdcb03ef557a5defc2f6c58128a6dc3f8b0385958014e709c1f61b0ae6b403576f0e454d5e4c64c173138ee4bbd5fe7b60d06c5abe23fe99ee3b46a00
TST: 193
SK: da1f868542cd7cce7a5ca3fa3c24081b4d2344b21a157f0264a347132d19659d
PK: cb3a25a53f272ea813804468d6500e96a1eaf822705b7790a8ac3e98cc4e524b
MSG: c6987ef380d5d0e74196443aaa3a32356cbc02636c5a4b6d62a8114b2111bc1abddd9e44b3672c18b58d4ef591af4562e020049f8e1274688e1f8e5296d2f9252e7fc84cd1d0c58e98f0f160530aa22c871eef652e71974ce91b4a65fc25fd09fa1b6c32086e98ec708d9abcb1d9cc8e1a089ed8db2206ee9570236ad69b3de6821862fd2c70cd83a32a68b0486229553d928de48d03a104e87381964abea76683976d527c84163a12eee0a55986cf1431e9c86cba8182ca94689bacd165fbce
SIG: 75c517ade4f08d7746305743d1a776c3c55eb5eedfdfcb5eb1d5634a1bdaf7a4b8d24187d6c8850e3ced6567a03c4c59389a4cf47114ce5473160f230546e60d
TST: 194
SK: f13daec0ef33ddd133c7d244d10fd27ddb23705280ff5f1815f0f656d836fe84
PK: 2dc7f1367de672c51e005c74f876f982593996873acba079292734c209c2b111
MSG: ec02ff1804b2b309af3158b66272a14a3aad83c41a719846f7088ca9792af575c78913c432759f0b9a748bdc5568496e41658cc1cdb8da6c91d07c3ec2f4af504249b996aa00c0071cdfa793f82d0ec5d267262f518fc029b88e20b6201fb9e05abd3f9524c5da2fa8978ff2efd48120cf00822d1bee90df816125d8edc0cfb5de66d16be63896a412a62b031b7118ac13fe2c9faa6b1a3342f9ccf7884166cf489a84de26b5ce5b21856a3af289bc6622c0aab9f2142d393f5d4b236779dbb066
SIG: db771833f7fdbacdab2b5cc80eed50afdf13783b7fe5e903d5dbb4c2e535316a6eef4c34f004d2b9a4e2700bd6e2acdd564c3c80cc68a303f5fb091cb4340f0a
TST: 195
SK: 42dc16c57fb6f128945fa101e05bbf548ef7d97726b692fe404069cc57ccefa0
PK: 0a1ba5df523996f954b34ddcfabad3f3dee21a5fa7a4ce322d216bd8ccaf438c
MSG: f2714c23a3a6fc11ad15c980b7350fc84217877661188055ff750d82c49c5fef7bc8e6aac574a1b79a3f26d16969c0f406eeab3e9e12850a55709745e30dffa62a69dfb2b64b3c1bd2bc3586e26d4eea714d2a7b71cf79fb8ffbf2aaad00ca3e4f2b6f503cc1fef2eab3656fb44f8d62a8db8ab58f394693949eea57fafecf005f6ebf1287dba4d2d623c02ea171f567e526add20709ebcab962f83d98ef668ebd01ef20488b3665e3a446fbfb13d34050942c749bb2dffc766367fd452e68e5b0c6
SIG: c75977e83bcfe9df7292a860ed972555b5c24416fd4b7ee3285388fa5b1447608e4a347813cfe093512a7651e422e9867db7b97c0b0867f0b8c7b7f4f02c310d
TST: 196
SK: 90b455c6bb9cec83e137357065339d030525d0ea7f5b923a2d5972c3c12aa37b
PK: 5cef038c16bfa4b4c923a0fe70cd7f25c8bc837fdf5a7efb9d95f21b96be925a
MSG: c62cfdb9d21eee6be47f30727aaee51f0703789a431d32228533350217a93a18900669c95956f3f2ae90dc745a71e18340d058d16b4c6fe33b64af8dad973fe5dc02e8520705c7a8bb3ccbe1838c6c249337f9b6a4c0e1f8a4e5d103196fa79998923d0422e9d079a72cc2a8f86d659031a607d4cca0b947b3abeeeef64c28da420d05de665a5510fe55f77598ecad7faa0ac284800b53829394c4ae90be66678ff04ab46da265ae06402d8c83cad84d61a051de0260559888e779f74b72a5d71c132f
SIG: c9345eec2c4a0aec732386494a69a3fce8b8a1be366bbed1659f131fe97cc037fb1b7c1b68b0f3023945d20090a0cd2c1553a47faec4d66fd816ce121168f309
TST: 197
SK: dc185c2ba0b378dfe5dda510c32feff535ca2e8a02434b326e0158bc878e8848
PK: 33d6cc05a434e419280d5864a1af209a2c676814b70f72f8141ac7e0573ee63e
MSG: e276b11912cca5a84bba650c172aef3a4d5f91ac722913bb891a3ab0424ab07ea709cb8bba3a3d11f82f51c2af0162a82f7219ce27b35a30507d536a930817e40f85a22a5a432b94d192c3c8911777cfdb7fe937a67502770d6d75753d3ae88229e08f1ed23b4328d862ac61863c063ea9848f8ab96a0213d7b936c48fe754836c98487859d199b3d940392716a1d569e6c0cb1ba918932cf88525e256c8abb11aaf0b454655d5db55713cebba287ae202651ac872bfc80feaa7e00d47c0be38e658f7c5
SIG: f1e44514d2ecbcc8d1a7e84bf584ce731835e9894f88974f098d456b60718f575ef4d8062f2182504250cf83bb2af2a79b1f58a6a97bd98da467132d7bec2f05
TST: 198
SK: 90721c43bc366f24bf4e8c993e138024682f1029dba35abeb0d60c7fa710021c
PK: 7c63a2f13b7b220a0bb752e3800753b8b6b32669378ce131bb77a9a8d230e9ae
MSG: 651c9617cac958c7edd4a5f3fedfb83dc971abfbb69a31e898cca8472ef068034a6d2376ee0e72d0a9bfee275796c3795adac8ebe1d12b66ec268f6b75fa3941154f99e223faf2cbab5b92e2b3ba7b79be7700ef9dba69253cce5356b0c4e74703cfcafdb5546850b46232675c90c02d5e426d33d60cebf0c7930182379dbb007f536163c8ddbbd3157bb2da62340133f00ae2682ec6baa6416b5a01521cc10e04695295f2e5b94c05f00383ffe954830797f6df823172532f98165fe314ab325929af8385
SIG: d2064a6d6c99c6c3f152d2d435f24e34b5459b082ef11e944a77ff54ddf9862737ecb2ac8d54207d36c51ad41f36490a111ba80e126bfecb09def6accbdf880e
TST: 199
SK: 9cec246758e412e7378b4579eafe9fac5a25d5405f9270b5d7e543414ec3d5da
PK: 975a9e6a152caebb2f9dd0deb76dd922b6dc77055dda03fbae9e7c685d073aa1
MSG: 17ec9bd47add6ccfbd787af0d9013e9cc979aaf850e09426d3b28edfd71296eb31ff8b21c5fe7be050f536324c3ec48850e0b508a36bb4cb7e754b327183a1b394d88a7941d1ce8dac62a5d8291874d78485e51f29ed05865a206e52ecb12c5d107d4ff96f25d3c5d181d2c4ba6463600db1cca32857fcf597cbdfb2fda2708a8aba281b43c3d28c4a4e7983361509f61a1074e6f0ad6101c7b567ee4078e9839c47f46531b729ff0efeef7c9d1a8d833d9c0f42812a34187c3a778c165c09d6459c9c7ceaa2
SIG: 9bad1e3b1279ef658f4d071644c63ae2b7a780357e9dc426f1650ec0634dfc520f8eda9dc8f10aa7324c5942d2347ff8802bd90e95fcec313352cdae64f32a04
TST: 200
SK: d1403f63202e080525843bde255eeb6b6783c1caae9d6ed00ba60805bed1941f
PK: 238aea3ad6d6f27783e70516bbfcca4770366b50ed0fe6a4e966b53af121a721
MSG: c4f17d442fba4ca0df8dc1d0628d7d7f36b60b5758d7c13b80b8f97a62124d96a23b279565495a8accab5997115b13a4ba220a73957eb7930520acbbfb6f54cf68726b6450c6ffa9470b055ea262914e2bc612633f1ac3d0618a23dff188a733d76bcbcc460f52ab61e19938f9c8caaa792c208d1f6c754728905fda51d881a347a53da744d3baadc0a76c474c558680269095f9084a74471d5c09ffc29141b5bfaf4954dfacbca663d037b17ebf9559882233e5ca5a8bf75cca4fc9c5a4109f32e145f3853b17
SIG: 8e60e73c063816795e29f5d64ece1159f1b5d5021a6f8f655e261a4d0026f5b94ff2923250499d995298480512e4126276aa4a226d015a95827b3ce692e23302
TST: 201
SK: bdf6bdc31ab0b5313784483abeca6ea5e9cdc68f81b21f350d09c3907bb9b6a1
PK: 03627712b755e5069fb9ab8f9e899724029a7f268af9398821eeec9360c9285b
MSG: 90a66aafa5642a98e79f0d88147080167b11e4466518f195cddd8940d12ee4918d31a6d4cb77d0bf5af29983bbe5085610a79daf0c75a78ccbcffbbdab2189c394ae24e265bd8c55fd3f4098e1b175577549518e7a4dcf7452086dd1278dd58ea4c0aa690e917951ef39fcff60cbfa1e90910bab5374928d4722f702bf5ad6028ffda6541fa5ba1a3779ec78b0a95fe3850c748b6c8f42f330ec79541a52a1cf57db72df4f92ce7f748aeef1af33bc5ae0a82c89dff216f23aec168a7dbb510aa632daabcc971b3f
SIG: 38fac603ed246f833f1c0fd4585698b0a71305eff0d14a0049b3cef073bd036dd451b3dabadaaeaea2aeaf83d395746f4e86866ada971cbe482edb0419332f0e
TST: 202
SK: 57b3b14ace1cd0cd603e6328bd219ee7d9d094487fa668f28aeec02b43c909a7
PK: 24e6b6395f97ea0e237186d469b71923d2113adf403beeeb4a2d27909aaf3eda
MSG: b2e0dedd802eed996dbd5836bf8688b0d1201bf5442ff9bbd351aeefe1a0c21fea2b5c9fe5edee47e921099b05aedaa80367c1ce08821d783a5b64cf059c0f4335083986a5a6ecff8c84fd40e0ba5dd5e5d2f01112a84ce5cf8e0db78beb182d9139c0b0f3e0060a3fa73869e96423f170df9af1cb9c35566d87dff542223f6d439bdb54729d366aff637b0f36a5d14b15d612bd03076cc4d04c1f25b3ba84e0d1fe474e5718d1a17d5a488465662ee4c3f664b4c9274b649d78cea4e85243f3713239048a908ce3e1
SIG: fc79fdc6d090887a61e43c6b9187b657d2e4d9cbafd6e7caeb7ebdea842825b78fb949d2c49a0cf38b6c73296d82c8ddeb1fe2d40aaddd7964da68acf8c66f0e
TST: 203
SK: 018a2c3deea50ab506751f9c2adaadfd9e2192121609931684eb265e193e7f89
PK: af410bdddefc644ef12c9899ff71b9e1d0dfa3d69d8c2cd676c1916b34591cfd
MSG: cf7813efac12ad1c7c7322ccbe54aa0e9a8ba4fd4345b06e4ce7a35c8b1cd5e3f7f0688533849ba2cf4c75b6f20926a1194a72df0e1b1b34456a2133112d006722fe811d5e40c4121159ded88990c0ac2bfd34f35af4f07cc402e9a381a675d03fec7ec438c4ad9d929aec8f242def023c993c9e8ba18c7428e88fde68a4711e506d7969f63c8e0bc83ff0de4e1336106c05e09d5922400e8a81bf54885667899785882b70f20dd8fb1e75f5855b765a256da4341bf23ea0ffa18aadda381816946001045669c8d04df0
SIG: 7a44e6a31932dee6dc2d8394e29a6551d13e6c6ffdfa218fa5b998668d8439db5e05379fbfa0da5b563ed966435ae2c54e3ad16e1a9fca1f5a157a080704ab03
TST: 204
SK: bea445e9b6d3f21235912cd6c42ec0577297ca20a10357880c2b846dd8e2cc77
PK: 024174966221699ea4b0a37e517ff9b16598ae4d4e83bfa3ca50bc616841f595
MSG: 4743c7c099ab815927b3674d0054b6de59af2811abc2cf7fde08f62929185adc238fadd5e75ae3ba0036ff565a79405b424f6552331e2789d9709ac1ecbd839aa1e91c854817597958cc4bd91d07377507c2c8d3c006cfeb6c0a6c5a50eee115e21153dd198ea0a3aff62b7075d5a461788783f050e659c572963d7a59e5afaa2b9c501f43c6ac08ab4797c4566d22b93cdf65a99a2a1d638e79f72b5f4631fe5e9e5f968f6db7a1880df51d8febc14942672f8ea6fc3a72814a44d66d148420a69000f68c330de5b80fc6
SIG: 6964b9c5903e74e99328acef036558eecd3369150a52e2cbad4bbb97d461b3dfc6b3e8455813a4f4bdca46302e02e683ecea1820171c538e54c3de6c954aa407
TST: 205
SK: 6447540ed7be0a11c2a8de793d83c6e244983db18d78ec9d75f1729c92e0fdf1
PK: 391212c8edc4d334a5bec860ef0f5ebb5ec44e8bb51c0f6741998959b2b379fc
MSG: a4381c7638c48799e9b5c43f67fc3aa3cbb5ec4234f37e70ccccced1627a57683d1e53f4e0883d8b462bf83f1308630368c89b491533ddb8c9a5b9e8155002fdd581a9a5be0e430b9086a6beac4720210f87b14e862d97e5cc69286786a7586723f231ef0e3e1b932dbba3a18a0cb221cb07f80e6a8e1300056c13e702b23bfb3250ec7cc864d5c7ec5786240709c56024ea6be5f7b15a4fa5555e39a744a1dc557df5b948db220b3d5745746691dacb4421641cdcc12e7ec0450293f19ec57b09cff135847aabe446a61332
SIG: 3ab5f88e2f7276b5b6583dffba5639993a905dbf9b88ceeaaaae3335800e4a5f10f83da6d6225a8dbe99ae80075009dd508786b3975113db478e14ba101bee0f
TST: 206
SK: 0c587a811add88b994458c3c808ac4e3a83afab26d4cff5c961b9df0b5c83344
PK: 06783b0cdcc5028c5638bd748f0bc76f7e94d1aa2015ca948738a3500460aca0
MSG: f56dc6b76076325b2126ed11d1f09decef9d15c31d0e90cdb1a27e089cc56329f6ec3f665eb6739ec5678b3f37ee1fb37deb9e240092b7a88fd25525acd55e294eb1046f9b1b69a847eb9ceb7b1593b9f6978ef618c15de4e059ecc3bfda3297a19c2df202adf72155cf21eabd03948df15198e8a68b0884f93ad5e36eb0983cca30e45a8b4b5fb8136fdea8a3341dd7877540a557debf7530cc33aeeef6271c3f0af6d09787e815f2f1dd25ce4d2fd09ffa9f53081b469c500da4d44180c04eb1869329cbf2d823187e831c24
SIG: 33b4f4274f20008a721d1e8d054a2b4e95327e38bb07b33c4bee7e1ce020a442fb2627eda3b7ac93cd3ab0b12b99935a1a9233111604da4acffb5315b907120b
TST: 207
SK: 66cf401a2142fcf4a8018046cf4140bca18d76ef6266e7a024757df172a5d653
PK: 67d48dfd23743cc2ca40e4dfd6b8cc5d84be82dd2b1120cc476e6af6f25ecc98
MSG: daa8efb3fd41f12fbc55bd60464157a26d718632d882aedb6bf98e47dd2337879e0b46452e062e6dfbff3e7bca7289e4ef6b3f41d4b03bdc2c842afe97f3029883ed45f6054dde9690649abb2b8dc28f5fe8cecf80fc1ea411bfc40bbf4fd20b218cf47ea8ee118d4d5aefa5c1bfa08a8fb1b30d6de0977cd15e50292c501f2e71ce2740ff828b8432da5a594bab5223760b64792ed3a69dd75e2829234943656513df1a17a2a067a9a8eaa64e19569f46939d34b99271ae50a47d7dbca3620c81255b0e1fd1f3cec851f1b11b35
SIG: d6b0e80e60bc1b29ab8f74808fc460847795ccb887bac0ecaa8e135297a85097712b24b0a1fbaf7a67c5d530a47d0643fc8702c059d215fb112dbe475e5bca0d
TST: 208
SK: 5dbf885aa598e895571f5f65090b72323e9d70b0f58110687afbbc383afedcac
PK: fa17eba76e3bc3ea6dab3a5b120dc5ecb9ae6f00138f7d36dda9268bc4722174
MSG: 1e0b6cf15ce03337179c02d65408df5be9200c3782b6004af94ea4decb257999d6fdff301d11d00c98c372fac0d026cb56dfefe3def7eb99ac68d6968e17124d8446f53e8d2d3dd890d37a23c7e0b83a484b3c93bddf6c118e0281959d27bd87d37e843d5785f4a40771398494e6c4322fbb675c1d479321032148f7fe52564ddf7ae7ac269d0cd2e552fec589aeae0fb93fe3eeaef0856096cf4f6b3497e7235cc8494d810a0b46c5eac87f187e505bb7764f8045c9541983f7b025698009a23d9df0bd1a473cbee4cf5e9488ecbc
SIG: e1429dab2e42cd035b7fc602efd6baf94706f16eaf2f8b5fed329239e875605fb172f5dd9ae2bc2eb42eb474567e292f5206e82e694bca0d6d433b867634cb0d
TST: 209
SK: 84b3aedd4797a565c351de7dfa0700b9ff7c4d7291c8808d8a8ae505cdd22590
PK: d7ad72caa7c22209ec4678d11d5590a6cb28a07117fe5aef57b50751583201a5
MSG: 532567ffa53b5c0fcd29c39499d2e78ecd20e63123499240e775088b394dc65c8baaa0fe8f6aa7e70181f9e10add8b4a8beb0b2ec38a43309f100cd4be91c6f48e79dc0aee93a15c9403773b354a8d42ed48d8f276230fa6de5ada501ee0a653b4458f0ecf6d5b3c33e2141c662f6ea055f741e54586917d2e0c4eb2b56621f9665fef3246f0bd800b533e3bc615c4021f8d0e2ad233a11e7736c493acc31faee76a097dc40db9efc22446eacf1cc18f51fd10236a2f942d0a53c3ce209108b5938c0a9e536b89ef0ad6b405a10f22c3
SIG: 9220f0edaaaee1b876350dbe9266061767b86296c351d4cac99d07cd612c6efb24f8f9b0b975f95c42c5b6afedc892f87efedd39d5160294c27658bdcf42850b
TST: 210
SK: 6950bfcf480b98ea18a2d5ae5ba6e7668f4c283ff2711357740ffe32cf25819a
PK: 8e4c6f233f7b86321c9d6799bac28aafcd2503d7aa0a7bded8722727fbbcaeb8
MSG: a401b922aba57ee0c6ac1c8f1b48296a8562eef137526893886a08306e2203667788618b939864467a31f16edce152a42c25546b640ea8bed189a4f89886a37f106911eae1f50081bf795e70c6504437d2a80cb839479ecbb87c129bcc5fe31d716ef978c206d7f08a793466594f4d75e215bb6374596f8e7d00eea724780943e89bd3863c951bbd24efee23c97c2c797c7fafbf8f2c8b43f37a5f881129a09573fa7a034a285e80dc4ba4bc9564a4dcedeb33167e0b30c5a00b9a109a2231cfa0012b29b2b3450b892eccef0808e503f8
SIG: 94de5df7a25ecd70205d40bc9499fc7cd7136568060a419a93be6e318664bb6dfce60e2d4e633f7ec148fe4f834ed277c1fec4c4e2a86f44c4589c817888db00
TST: 211
SK: 61b260f5b848b271ef48e5a56d297432d89f2ab85bd538fa668870d0560220e5
PK: 6086fe8735f399f1af2e395e0fdfb5629ebcb04b6ed4a54a9e47052c6e8191d4
MSG: 2826295d79945f675476bc4d45ef800d80b1f0398e4be60e3de4571ed108df989f032de6c2345d9948d677927ea0b8cf1a5ca36fd5f23c25dc0d2ab5bd565a54af46fd97d338d770e3a7b47efb54c07a1664707771eb4e37d9d70ba779251dcdcd3bf6d1248adec53f787259c4d594d5fd4ced8e3db7621d4965d48298178124931a3d0cd269b2d53b7cd261b96d370c5d9693c8ad133ed58945ee3540e10625d924aeba9bdafc656100aab276fa996b1db477bf85ea559081d5b4c7307dc1595654aca82f7b6d2ddaf7357c15a4d7d8b908
SIG: 9828fec8ff5cf85a98f450770b5bdb4b80daca44379d8f53c91c348e22df64ac48f2b6e2a7b3b642bc8193a194316229e69447ed241cd423d83b6fe7b2d44b00
TST: 212
SK: 936dc1cef6a310747f350088055a39aa762d9a4b52c8c8e4c682794380c2725c
PK: 03b31800412df4d56f1532c05828c0b72528a67a781bef4c06c1fb6ff2ce324b
MSG: eb58fe86c4ef349c29ae6fb04f10850e38c6823dbe64a09a5bf1e0ce600d394efa6fb96ed6a8f2c9d4bec05e6a5ebd5a1bf4d0c51db934e57b79e5c6a879d975197dbb10475f65c7f8a8c6a77a420384b5062a2740f1401740ee0f5e043aad7a2a2b4260c5d907f705edaf65b0e375dfc7b00bd660db6147f2ebe870a0ee18dc2ba3c92b0b76fae2b90932cdb6c149e46f3feecf4c26f0441f3a9e006678aecff8ccaecaeda73a18a68ac988b62e83a9bb5188aede38df77a9a164abbdd9d58e52a6caf7222389f198e85fbf966236dcdbd4c1
SIG: 3f994b8ef528f6421c6a6a22e977ade5cee887263de38b719acd12d469bfd8c3f68e7ac07d2fae80a2092778df0b463537ad3a0551997a3d5b51f832d9c8230b
TST: 213
SK: f89eed09dec551361fa46f375973d4fbfa5c5c12f1b5e5abf45cfa05ff31a340
PK: 3e0efdca3919fa10d4a849cef1de428851bd08efd248594fd89cdeb9deee43b0
MSG: 4cf9773da05fd322fc147be900ef5cf256c88afdad4b08c230dfc8981fb69f476f7d45ef7c9006bc10032ba53436ac22843e0d76289cf68f9818fa64031d4b40955059aa69110915889f5e22732a1343912581ab3b11a3bae7a471359508596575f888160beef966e5708f0e3147eacfcec1caa3ef240c5e0a14c186546c8eeb64658350b1affc0cfd2ac213af670afca7bbc9dddd28a465b586e69c388cd73478d68efb322bdf86d9213011e711b2b95fefa7bb9b5939761706aa7121024906420bddf1d8800a4338d938fa137cf27e9ffc51c6
SIG: 897e6f2797c3f326d2cdb1d2673d360631f063304580ff5b4eb43d39ad6851834c9cf891d9f0905bf8de075f7635dfca601adc0f14e7b2c76f7571bfa468ed0c
TST: 214
SK: 400796ef60c5cf4084dee1801c4a1975e482e70aef961cd42e2fd5a3fa1a0fbe
PK: f47da38128f2d012cc5797571d479c83e7d8a3409802f9a7d976c27067cbbe43
MSG: c473325e785b27df4471eefb9ebebd6461d570800181100ff36caf3c38f67c1921b157ec8e6126f955aebd90ea3fe5385f8042cd704b27cc1d6978c0e2a296695f5ef97b7c2e16ae4ff4d063c688d7f46e964e1f0a00503f357345977683d6e4c3423d56bdb6ce864b6987e085e83e70c7c1a14e0e413f592a72a71e017d505b64c24f1a1a6b813e064e6e0cf8bd4571d0ff2f267a6a13e0cd430463b6ca3b88f0cd40b0fb83d5bedf6f7d47e170e87d0a750093693eda232a6daf98125727b9588ecb894ae373bae3a445a106306469a4c2cd77ff
SIG: 84d3aa3f361844396754d80d9fa05b8b2fa4abf3a0f36b639bee9cfb5c8530a3a9cc34677f92a913c41e800f2e8041f7666d07ed85f16a57d817b1241fc5ee04
TST: 215
SK: 6703a6232c5e2e65e0ab3b92e2aaf9f5fbd33fb46988047d6f4d0ff5387fa029
PK: 047cffca8b7b11ac6eacc0eaa0c5b73c75b9c637956973af9d97b2dd5b605d6f
MSG: a26b30a769197932a3a62854968d760151612366778dc994576a2e0e0355496b46200e506948a0d102b6651b2e7334ca6c6eaef8bca44b425970a0b37d6bde0da9d3c1b9f51cbb25bc335cd6fa928a74f2c0dc2c6e99d37a12863a474d4df43aad35415ffcaa24d8c29f914572ab2abec3892db49e679c5ea220c2f519a7d033ac1a2c5a467869e30eda3d2635ca863431473f958d552bdc5582352c290d0ce4fa9cfd0ad42799c227ec90b7c9e5db9f5a7b6d569212eed94d323326805f2b3a0010d6c11eb4107c8283037652f50dc067b6dc81f4db
SIG: cae96879e5b603be866609d4a053bfa12a51378e99b2a2812e4789267d8f32f473243f8af74b9be73f47dea50f0d165ebf49458b73e53d88580c191a182d1904
TST: 216
SK: e0e72f8f178633626733bcbda2ad2a50e653890f15359b6c22fc7345ad333109
PK: d13cee540d84b5667d516fe7ec7239bf8da91546ee791f84edd8ffcf3a083e76
MSG: 791fd613c1095292c8a4a2c86b47ae026155b8465b607dbb416477ef79a297c9d7758ce34af9dcbf1c68474f30909fbe74b7ba429632f2403aad832b486b72c23054ad42f7653a9ddb456cc791f348886a7ae5dcec7c0ba815f7a93a10fe331e903b970f7b5028be49d14bc5620d63792672b98b9488c67ae16646693e112047f0ac8921ff561c92dd0596d32df0a6e507ac1b07de516c98428d570a37db9bcd7c7e61c6948ab3fe91250dd1d5bd671275df9a972f22c2ba36804747aec1ea2416c1f41ab87befde31629b2d43317ce41cda03626286c0
SIG: 14552171b95245ac0f0e5a6e7a2f541721068db650c6dada04c28cab7c49195f6436712144cb31913c562e30c39d8a8549fb64ffea81c7445143b5f23286da05
TST: 217
SK: 544dafd9960d829756c6d4b3eadd44375fe78051876bf978a381b0decaaa8096
PK: ae4f6425c1b67ccb77f9aacfea28eaef769c8cacee035205cdcd787e8d07629d
MSG: 447fe7344cad1fae09d6a7d05f09d503c1b3d3d5dfa584810c35bc41e4955693706154e2d751b2f1b525e1a14547ba7f8b232088a6fc922702d93a11cd82949c27bed645dc351fb4c1242cf41d01575412e792aed214531d94fd66e03dd32e972fd77f6947a353e1ae5e00f5a6ca77992472f096b6e7475fe534e913a77bcb0d681fdfb3a7a0dcb56d274df4aa109d4a8a37794a9276f50006696ff12ca4d0254039df0fb3f72a960da05c9872f2e33ee81d1cf7a6f48bbce0aa18c7c0f06ba55e67689e0af587b500eab79cc7f9640bca104b7fbf31f08e
SIG: a2ae117c8de4ca6d6fe75e466023bd550c26fedd3e74ca13adb625f272e175f14d5df550ace7d82288efefabf96311a123bee23889ad3711bff2b8087946bf0e
TST: 218
SK: bfbcd867027a199978d53e359d70318fc78c7cc7bb5c7996ba797c8554f3f0f0
PK: 7c5ae3bab9201199dfbe74b7d1ec157125bdbaa4520f501da3f248579dc6c22d
MSG: 117fae13e78777b6219f020214c1b87c57046d1c09ce82ee2b5629898d9b0de74a15cfe99f80548ba913d7036c56285a4cba493b52d2cb70d6365ace3da12b1f34a2778af36ef52ab82ede04cacaf2793f5f89831e3b205a9ee4c1d6fbdab4ba4d9fae65dd79a5fe76b4b39a3092cc7148d211e85ee82ab463d34dcee9061d9c21ded2051bbd50b413f0e21a0e48d1ffa8dcae240b3495be25d93151b57aa271ab99aa708ca28080cab4804fcefa929f5f1ef3f4c6c0fbfb40bef7ea1b509b36ba1260323512379d7bc3fdbb5d3faac9b00e21f12ea1ca2e29
SIG: e48615b65633e61993b0aaa1fafb74b9629c384fd592bd735fa1f62c5cad11291fcd8c2e91a50bfe0b03b43502fff3a5c382b9c2821907efc34da5ba054af00e
TST: 219
SK: df2df8a9d66d5638cdee09324e7b10f8ed29ab91387e3147b7dc03f7cd800508
PK: 5c042e157fb7fb12d4d4fef2847141ecfb57c1253e14eaf3004d6513f52fe625
MSG: 21576615c9346a63dccf0c50ecbd7c6d72ad452cfed43ea73202cc7a98576056b9664b54622905a1e7221720730ac685d3bd3977ec3959d446bfa941e725b6fe16afe5432c4b4bdee7aa0fd8030948ed6fcba7c0bdb40c2e517da97456e74e1f93d5ed676de0f4a8b0aea449404bd15b6da79dc1b813965fe5572410d76f5b5eac663050570311dc9842b6fbf8806aec03151715cacf7f21802e8bf5e98a89c0d7d0d098b73c6efc09962e36b4e030c1a64b5d349f5f2042c74428671e4a2c7fea0caee2422d85c4fcddfed32213859a69955d4e3ebb7e1b2022
SIG: 9a1074531ed43d07bffc7f2b6c13b8838fc75cba02c7d1ec7ba38bca3cef20dc9badf3a3064a2c93b1842441420b6a8d421a960d70dfb7c70eec295f21f83f0a
TST: 220
SK: e8ee065f9907f1efa2daecb23a0425f353094da02bc2c931f0a587efc0d13de1
PK: c72651b7fb7ac0337a172977496fd7f2a72aea889385835e563c6b6053a32dc1
MSG: a2f0c1373473a305d8f1d99138b06b9a9694ffaa8a88222de9f729bee1305175dfb17001cc77f67b6d40c90c1a28fb226c11286db4a13e45e69211242bcdd01cb6e2c454e76c0cab881b4d2d9d3ab100a5d61d1725d866e4fdb66d93d77f5b308693b9b5a333e57fa25d1e5d2e38df6e4e9ec84159bbee1ffea926836a0101c91483bd5bc88a6f1cc4d4e7f008ad08453a0123429dd335781c7cbf8d685a8999ed1177607004a13c4cb5ea4908c542607d3f2cd6690cf1f2a7455bbd38f538f07a103964317efbcee37eb46931c027cf153ef86e43d78281ebd710
SIG: a510dff42d4559a19a7bf0fe0bea53d3e1f22dfa6be55039895e12a5d07da5f2e37713ccb2eb216011628f6983f871fee286e66fff4be7582c961a1ed7568404
TST: 221
SK: c72e67d8c3fec004ff618718a9099eb8ad7b06ff3b8c542a7e8b9847313475e1
PK: 4eb002d3cceb188c6658fec51cb479a65264ac555c75cdc2249cf1ce3defc16d
MSG: a8f34135c0132ec95b64b0cbf51d66900143370406791fbb55f2b8ca953cc74a46e08b002fa2da21b951b8871f7a29bc6d38790afc66a329c397d9f9250bae0e30ae3426e08d8ead0179a3b313c908839192f289a3f3b6e960b4c5cebef0a09daa9c7a15c19d4ebc6fc2ac3cd02232e832b234edd7965d687bfeb758f70fa7963841b7859bb97c971bd557bc8769524ac4c6eeb3579793334b522d176bc62f86b4d5c0d4017036d2b6bd4e4384416ef8263139691a8606170d73c93d6417dcc1a08a537c9ed4400471a46f52907b46b10a8b6889dbb4647a8bbc7149
SIG: 2d7bab8ebda7fca5bb3c25f51dc51b73e6ff6a3bb1b52acc7811a7d2595cd6fdaf730494418e2f57efdc5617b066fd7b6207680d94fb8c43d3d4740b41cb6901
TST: 222
SK: 696450b557ec3c94cf1af1326475634aa81def3814ff30a02ba7f2044b59c0fe
PK: 8584773c566b0eed3f43281705b575a434e47d6cf6b251b89803fef53534cb29
MSG: cc257829f30a5f90dfdbc247d42e388738b76c41ef8a82a5e0225ddf1e386d77080b3b9df86c54b85cdf2c32f367aba0c3b6bf888a5a6903529b6aeb4d5407a10180149114130228fc4356ccf366b77be89796a9e71a0c693f31e584a4f143097ba370363b67b2f2e2fd8d6fe8b4e8dbf0d7dcc1a8360041158aa2aff7e2a325b8e518f193a28bae05e3d52b26621af402026d7f250e86dcee301a58b631eadf4527e958f02a61587f0bb516cefac009fe51052fff53336dbd94e7266d3b43caba8a1b38e5d871c2a24a4c412fff3f7a9a52a8ab23bac9791b2b5a669a
SIG: ce8b0a5779f4f5f401e84d65927a0c28df829e95d09bfa97111b8700078ff894cf7277e34a716144d55306fc9e2f64cd287583cc8003be0e8faf26af7640140e
TST: 223
SK: a8dd35f054fb6ff6f0ab094a0d3d1c262832181df35ccd5192545ebd6a9cf529
PK: ca412338d3814b886d964b71925e1aabb3ffd07834dbe7dc512568882b53e4a3
MSG: 55a7ad9132d63ac161e7adb132b9189fdd84c361c1e4f5419a6df73df4d7aeb29a8dc4bf01490d4f484e2d12077517f5fc7ad0bdeda20a6cb0227942290b08c3fe33ab9b2135bc38a6579a54bd982f7d1417ce867117aea918dbd3dd476e7eb5b5d3c3e48a864a2f942a31501aa2b29b53b80513c95d6a411844f0dedf16a29ac267d331e53bdc2539bfcf32dc9b5d640f1231e2cafb0ae94bb5189426863364262efb47b5b5ccdbbc93324216a799b6f50d3704f15ed59af6cc7d910cf062d1be632dca5df213d487d8564f2b2bd7d818bba27c364013d92d7f72625462
SIG: fa709fbc8382af83d11812618dfaca452eab83e4c53fe9e5858467d07b6767e17975c1e06393d6dde15a34d9473d1cf4d6d8c2d57394520080fac4e43448be07
TST: 224
SK: ae1d2c6b171be24c2e413d364dcda97fa476aaf9123d3366b0be03a142fe6e7d
PK: d437f57542c681dd543487408ec7a44bd42a5fd545ce2f4c8297d67bb0b3aa7b
MSG: 9e6c2fc76e30f17cd8b498845da44f22d55bec150c6130b411c6339d14b39969ab1033be687569a991a06f70b2a8a6931a777b0e4be6723cd75e5aa7532813ef50b3d37271640fa2fb287c0355257641ea935c851c0b6ac68be72c88dfc5856fb53543fb377b0dbf64808afcc4274aa456855ad28f61267a419bc72166b9ca73cd3bb79bf7dd259baa75911440974b68e8ba95a78cbbe1cb6ad807a33a1cce2f406ff7bcbd058b44a311b38ab4d4e61416c4a74d883d6a6a794abd9cf1c039028bf1b20e3d4990aae86f32bf06cd8349a7a884cce0165e36a0640e987b9d51
SIG: 909008f3fcfff43988aee1314b15b1822caaa8dab120bd452af494e08335b44a94c313c4b145eadd5166eaac034e29b7e6ac7941d5961fc49d260e1c4820b00e
TST: 225
SK: 0265a7944baccfebf417b87ae1e6df2ff2a544ffb58225a08e092be03f026097
PK: 63d327615ea0139be0740b618aff1acfa818d4b0c2cfeaf0da93cdd5245fb5a9
MSG: 874ed712a2c41c26a2d9527c55233fde0a4ffb86af8e8a1dd0a820502c5a26932bf87ee0de72a8874ef2eebf83384d443f7a5f46a1233b4fb514a2469981824894f325bf86aa0fe1217153d40f3556c43a8ea9269444e149fb70e9415ae0766c565d93d1d6368f9a23a0ad76f9a09dbf79634aa97178677734d04ef1a5b3f87ce1ee9fc5a9ac4e7a72c9d7d31ec89e28a845d2e1103c15d6410ce3c723b0cc2209f698aa9fa288bbbecfd9e5f89cdcb09d3c215feb47a58b71ea70e2abead67f1b08ea6f561fb93ef05232eedabfc1c7702ab039bc465cf57e207f1093fc8208
SIG: b6c445b7eddca5935c61708d44ea5906bd19cc54224eae3c8e46ce99f5cbbd341f26623938f5fe04070b1b02e71fbb7c78a90c0dda66cb143fab02e6a0bae306
TST: 226
SK: 6bce4dfd53bfa5506f2f554d2d994a0dc40cafcdec7e1be050006e5c5a4b38a1
PK: c890023728d8397070291771e65e034d34d4aae5e247653e4ff4c074591da702
MSG: 3239190747ee33d40bf870ac9ad49d88ee320f63c05257e8ab2c60306597ce76d1f1e792ab6a65caa544fbec20892fd4960594f31b3763ef07d4982eae4a2dbf3377dcc1e3f95e46ed39b7f0222f04bb5c3b434c8f9f310de9f122a29f8241e81e206549ae628d2b8ad768972c98847c1188ad04c835356378bef79cd126869405b129fdbdc3bc489cbd1399505dadef7617b5be5da173d3e80e5838c99e349276242729e0219bd7476ae5c4f81a12878fb483a6c0e9b0df2962eb0bf00157782cf768a1b71c010169ee8522def0024ad7e45775a290639c53aaf48198c42de75c
SIG: 99ae6782ff27646c27f61e23636ae1881521cfa5ed256f70bce7ce00b68280ce8e0c82aa765afb8b5a1ff2fe42c57441e458e443dc8b123477ae33d884888c0b
TST: 227
SK: 17861a8d4154acd4fa9c8fc947c1886c11290be222872ff4f8cd25939e4d1361
PK: 43773f4449065eaebaf8937baf758560b0c4d2de46977839b3b873d5d7d5fd8f
MSG: 184df5ea3215ebe180390b0ff042ba2381155a038dc732f76a01c7e70f82d1ccc9de9a0596b3fee447209c992684f643df21f4cf9d179262790e8623e42472dc351997e6da189c07e1e8882c07f86c6337ec0113912cf92215c8de1982b8fc57bfabc55a3e8736f73610429d97feb51d794f505d0c5a0b3abd48ef7f55a628f90b8567a1c15ea9d190d7bf4ec2bc9334ada6cb92808dfc2064836fcfa46b96fd7a5d6f4b054dab09b73595feb89ed005b9ec9d3188121de69696d64e7c7bbdfc1c469faf148c38a7785970afe1acd06a92c99478fe44974e3bb2095e4467e9b2e996
SIG: a5ee024ccdbdd4c21a24709ec53dccb7ee17626dd00a093d0884f5b45c4c9d1691840151c33c8aa07b69b34e16f61647ebe793ae4daa70cff48e6ab42ffdbc00
TST: 228
SK: 0a84baa54f11cf17090fec61f3f9401508a3a03887aca1a7939394b1ee40a925
PK: 309a73c62d23d740f2e93c18587ac15e7ec480d25ac0794e10f8cd461cc2b130
MSG: fe70017b14678b0d3ad03e183d6f53314378379ab3da65b3511257b3d54086e86f2031139021391af9d72085ff7c3dc8c1e2d91e53333855423d0f785e2cc5f8b7799fcf1b70e6becb788e53e9020f2995ddb0c383a1f81038fc3d543ce0a38c9c288a9bc4077f4277dcc6c5642263fcfe19688005a603f57675d2434f3ed1f46d32f14eaeb073e83ee7086da2fb67659d3fb68c62320b7727b3b8ea006576bc2c7e6b5f1ecefa8b92e70c92c88951d0c12d91de801c38b7ca5a0a04b4c3429aba86386e96e06afd20d4c5c2fe2b9b4273eb05201a79273abdbeb37ed1830d226b6bdb
SIG: 4d870bd53af8f13f214d9934ec903ac48284092cd9b162a44ccec851fa942de715ccda07b7991d712723e7a4d5b4f0374ab85ac3867e0b53ebc46b530f9fed05
TST: 229
SK: 38379423dafdbf25e19d7231bddd80b4cefcfe2aed932584dfa0cc3c9f9232de
PK: 597e81dcee9448b77de6829e7921c8a390535d89a0849430aed66364ee140d8b
MSG: 36125ca66668802906237e63a2fe5ae610f11a7cf92520d19e6690a3adfafd5d07a784bc1a0e185273d11d340d5eff901597dedf450c4699d43f3fb168d557f6c9c03077c3cdc370d34832ccdf2a8e3d75796490ed0242899d25ddf44bfc66f329cf4c45168703c31bc9202d890f3969ffd3ac35a12818dca751ceb8808fe81efa26a5e0d200c5ec1d94a5097ea74b6498fe288f30c48d727e9d3d35c8e12d85420702556f2861484ffd09b4f12265cc9abafeb82cf590028895a7d050ff57ccf5f28022d016ab4094b062e48b66fd36d1e19626e5215efa40fb7e3b7062f81e954830c9
SIG: d8b50a88aed6f2a96d082213adf8b2519f6a0bbd30dd3cb0f3fd3ce1c643fc029946cd43462ed22513f1d65fca24bde3818166baa86daa798792afafe0c1a10a
TST: 230
SK: f925d274aaf1fe1a21656237385e97f7783e78090c5d4217fece7057c80f426d
PK: 3b0fc370be3a4b19a88ab998c59504ffb59a87606338e673df5b3fab4d9bfb8d
MSG: 143caafa5f62b13e43dffa49d420fa99f771b1926d40d6cb2bbb427f27b6c266eb3deb2d8bbbd47b8214ad40251cb1907ad65eb94193e54ad85c6700b4189e80f1cc0154c63ed151a8bbbd30e01637ca58e70aa3ee52ef75d0873078a405014f786eb2d77b7f4422f927823e475e05b24245f9068a67f14f4f3cfb1eb30bfede7b3262230ced9e31361db19636b2c12fdf1b9c14510acd5bc18c0ddf7635e003503e6f71e1c365cdfb4c65ee75b4de0694af87076374d631e6c4b8e240fa51dab5e1f80ca2a06c49f42ea09e0475defb184d9cde9f58f959e64092aac8f2027e468126f2fb
SIG: 79549a317d10a0be322a94a151ad11e77efc4836cc8006a85081273d7602a638963a9caf19c3edf1e25fad1e9d68701a71dea727da6a5c5bcac9339589224b05
TST: 231
SK: 971f806be6f07d41be8830ff8dae704b08638ad6cff722d8432538127b769625
PK: af6ac98dce2078a6c73f6097bab63f205caf6953afa284d042bd50a4fce96cb4
MSG: 013455d049aa54ed995fbd94e6369955495395e4438822259b1060e9a34779042a1a69211f6ea2077399dd234806ba0b353cd79a57e1c49b250ab27106dcde576ecfa115eae461febb12d2da25ffcf17b715f8d95c2f0c425d5a81f700115b70d49e1cfe49fcaa14fa205e28ec85247f1a6e7128bf3bb3060dc08464bda6538540d0ac472093e5a0720fde2f3dc4788e0e9b0dbfe2a2b5f1a0f3f80de984025b15c65af77f671e1c5e2840444de5c7eda025e6dc1a3ff16e26cc54cdeed56be73f9b01ab2b1bc16c8ef58a5b76dd47287807e5c50f0d7c0a5b8120dfde645a012c5cf11491bc
SIG: 2037a0a7674b84ff27d0b22f62b4bac65e2dc0f5fdc899feb7800f25c29981dee641c5a50f8b9410970b49d2d53658c89ee16961dccf5391a6918f2a84eada0b
TST: 232
SK: 2bb0652f8fff6901991148c68a3267877271006ae9589149bb206850cdf52fb0
PK: c03b77be983e74a234c1986496b292e139992eb7529e70b3afad7ae4fdcf8a66
MSG: b923ca67e396d8656fa3dbce8289a38bd3c128cefb30efc1862bb944b4507805419824ce2b83d690ef4cf107492817143bf64c024989af1a7d2e1f5ac97874f86bb0d3773ff840f514d9a1394a3959b011d3a6b816a3fae5de17b2a9ff349863d27fbbb50cca734108751000d6358ca0647a93eb49e2e7af06287d48f2c09d5c1c73e4d8f77ea2bcaa7356795b26728719bed5ffdb821578bd5d66bf92edaf8b238b2bbd7d1e2c30a787f901a33d0a76669a9c3c7f2b552ccb8349c7ded5e1a46170cf28e359e2fdd54b05a562f528c68a56974df82d466637c8e53246a7217e4386801e0e3266
SIG: 4e158deaaec3d88941296af2d27341012b0241d4e0f46e435e375c9875e89f5e32c057b527bc3411af096a77bfceb45b983efe455e3f03155d6bc7b0acc8e60c
TST: 233
SK: db9b812cb3c7c03b977f487d3d65ccd9cd2f3dee11602067dbfb72b589ff3f79
PK: ffa038ad8c3b378ce75d65844d08e3d6a92d194a1b7862e9d9720d20679b2944
MSG: a70092c7697cd4a209567c38ba7fb71aa8f15e5827a20876923943fd6adc659c9867ac6f58a61dc7cec3d362411682000c1a9ad1295eb8b70f242d86b5865eb76b87e3f2c6941d2612ee3bcde8f19765566733152ef54e95690943285f78b375f4036585d4739deedeef6d946db61ca458ef4f650da963c385e29dfdee415fe495845f55197a870f8cdeb5a010ba6bbb32bf1a588cc774d4890184c4b2924a5b8073313bce226585f1adfc229c90bc6cc9d212e62f05d33bedac961d77cf8c2620e451de817f8c1bb16a2c59ff804b635a73a8cf8c181b3f9401c3b643d18a2f706ea9cae47071a6
SIG: a628a77421b2abab576eed35d2ee3d14561b21fa14a6e2fac263c3eadd79f2fc0669f9429b910b8422b4b29ac026a42e98d181be3507c5ed7c748a1fdcf1d807
TST: 234
SK: ce379bbe2fa8abcba51c7a7543de5b7180771b3c44bc6b41892e7b88979bab90
PK: 7f3cff89f41babf4fa64cba33a5bb17f413bbf2a1e112b50a8e9b1f821d849bf
MSG: 001a74f095c814d3beed67a8d15fc18efe235dc3f6457812a4039b7a46fe9a0e9de81a7a4e5fbab5ebe9e1e4801bd11b45c9f7ad0636a09bff42164be5749a04c02f0ab61f0ecfdfef799b827da6a274c8d3b39f2e3805a6791287eedb2314d3f842b558b9b489afe1ed37bbbcfc5e60a431d5ac60b39e946d903d6bf6b140e12c7e07f9ed7ac46a3999c6245c8ab1bdb21879a317a3dcd257a5c4f349b7f59e4e43d62d9f1cd16f518f1ca6cad37e2cb20f2598c4134291c6b8a98aae5247e26eefb76aa38c9c8231c17e9dbf271cec80fba5b4a834bd9be81ea841637aa9cdd4c4bf26d7ad24ca3c
SIG: da98dfb189385b2c853b6cf375738046a8f27ef27974abcecea1db02989b951fe433a6ce1e225b3fa82032fe060a7d3f6c183fd1157f791a064b407650571600
TST: 235
SK: 2b2ee809d647023e7b77fc541f44875a35fa941d37f7c5b21fd34934d2391935
PK: 2c29d53e1bf2c7879d73d20ba88ca07a0b216d7f6d05d93663a65c3d9e10633a
MSG: c4147d64ebfda41a1be5977262958104e940c3876bcd5b6956acfdec32c660914d62623c210663cb2cbe6249d7f5274991c60e950e8e2809049953c69581d2469f4fe982c7434fedd9d4e00ae08896d62cc1fb984dd233150cc2483e159cff4097df8c036bb633003abbfbe18c8fa79b5a22270838123fc9be39b8892c80384a385028c1a81ec58c8f21060e78afd2c04bfd2d30ca3977c6edad518cc1e2004cdc14bf3d15f5f528e5af277fa182275870e5c012f5f82fb1afd04edde4578ddd2160a1a3dbc050e80bdd811bc88ead79bf93f010cd0fd4433d0bc348dacfd0947cceda62bfa49711d013
SIG: 12d90685775572c9eabc9be2574ca9ae66f0e652e578b21736cd6e654f7c6b1545883d56bf760ccfc3cf87544e0004c798061257e130030cb997a788369a9a05
TST: 236
SK: 4ea18d6b4af8053b885ec188be48deb86ffb2a69a4cec86637bbd7b41b807c46
PK: e5986059976233ed77382c3d9959f34e317962696553e86ed1e5902c4bedd167
MSG: e9c89a1a1119373206ce40ede3b89a82f89462a1dee9e789e9845eec21f571c0faefd430ad338e4a72c047a39a4259580387fb9aacaddc36a2b51e7b60a87ca1321ff806794cd6dd4549a4df45c2dae3e539c4d7d06b6e6e9f466ffca2fa4978ce3dc792e44a6283880cd138a75a226f985da41ffdc0e32a5a85c85fe9a43ae78fcfe57f4dd7540a6dd3924a49ab39eb69950d421151d96b1e4fd3935890f634cd52a73a755f5c2fb72f9cd5a2e67ea930915e133b47cf6b7c10a9d889c6af6b5f1f4f51094d27fbba228ac2268b344027fd49e426343cc0134399b4b510aaea50234df42c37fa1c4f4d0e
SIG: 27570c002a487d000ca3928b83cb4319722c46dfb4cca260de790ec0e3c1932688f87362952818b54f51bc7aeeb263f960bc0da8964bf312ef93e81f06c80b04
TST: 237
SK: fc1b75d17d3807217351d2aa40d9b04f525b89ed3f5fcdb311bec2aec5cb7ece
PK: 55e484e774a4392a9d6eeff835a8fbb232cf6276a89c74fc0d1bb2045a8b21be
MSG: d031bd11da308097e3beb6ffdb2600ee6a193ca6d8324501c972b1a25166fa7a369f5bc882ea45612cf02580254d21b40b0363237e835dae2656c1b7f4736e88be53d6b119c07f5729bbd82f67de03588322879243c5990a7e61f56907b24171a57cbb0bbefba2316277af9326f9cbf3538bcbf6780be41825a2ca774b41bdb1cd5c608851ec2339eb2f4feeddaa891a6326b29d97d7fbf311e3bb749c5d4c058dcc14f452f9334991e271c16d6508c818633927f429804ca7a38170f1b9f6bd73ed675e11e8c0d321fac912730b4ba2f7c428534adcaa4dad314c55807e6c642d494c6b2f0e8cd129775cc0
SIG: 9a68d151fea3909893359e60b96b68b2a3e2946f2b47b875398a1e39eb01463d35eae7d976f833a762b51f2726ee0dccad5ce3600564fd9dd58c23807fdffd05
TST: 238
SK: 0d0bf4d42ef810b179eb841771de6dbde76361caf894e42a14b1e09787ea3e06
PK: 7171510b43fc17efa80b15e320b1b0a408332542e0d36e4ab9a649cd941b5aed
MSG: 8e2179975d0a8e5a69fe875a3cb1e79aec49c3853e30dd0320fe3ebfb638b82f89ad1643036b37e56e0b55e0a9e22a4e283d7a27485ce9102db6787d6628b77913e10896774e495c26e8bab26e7f9a94d29aaa36aec9c26ad3f50e5d8c0b7698bb5f01b876d0d65fcf5e9e32cd7b89829ed05b0b8f63a93858985bc9569fce429fd37a211abed650f585c3b55900443b6c5d6e8a48ba67deeed07b76e969fc88430fce2709c0bb5ce926ab7f44e0cd79f4ec359ef76748883fcc3d026edd06c8b9cba54b990d30aa41f1448a10893fb0539280c599d42361433a34cdafd8ebdd92efb9c38a36daf4c74060c696
SIG: 24446bdf03416a4d08614466fb851db50e91a623cacd1b0b35660f3cf933200e15308708da3499a5ad25f0f0306b7942762e20a765b7ca9b901c750b3a95320a
TST: 239
SK: 57b5194d26abe4ab2116c0f03d23dbe116d48825a25e77d64648b43692ae25bf
PK: 499c02dbad2a4eab3b6ff1aba3944b91c3f273a382c548a6f3a19c83f0a86724
MSG: b4813c9d13215fe9f63a78ff7ac95173eb810b4613f0f48d6876b2bd3b2c72bc7d98cb1ac32bc41ca47f09896f79204ecfb8264ce8f3c3e76dc124da8ddc6e0dfc1e13b5a529f20c82613fb9a82e5f5d77326a861faedabc7325c59af33dae6744025e649774fc4f79134bf9f6e3d5875dd91bc8a14cc36a66283d01d8d108c13327eca53057ba50bf210c19f139de6494982646198a1246c271b0a368c10aab95cd8961235d742df4545be68bd010dc0db23b673e623609e420ee76b1056c520f9ce8fbe8ee1863df97d17b7174636c3a2b612295091948810d1d4b8a5843760a2887dc55ef512af041ec54fad3
SIG: 4c7345960c8fd48a7dead71dbd61908468efa865a135568c8f9ca0055483468617a7e335840f57c6cd8f2c9805cd47a9d7cdfde53da8ef4f1adbb6f698aaf100
TST: 240
SK: 068d27b21e2acfcc19c3e9673dd44142d98aacae894930e20ca067439e749a79
PK: e22ddd396f955bb90e284776aa76e921e50699d0ca8914a9b7b841eb5ff47d6d
MSG: 1c6815423d1a2c5ebe8828d1646527c17b2006e547f016b5350f010d79b13df4fb8c6ed57ba9c26c3cb0e0a64178b650a3ea5444a4fad5b20a3eb8caa702634011cf7892a0727b6e8150b0770429a37a8a0bb3a7edb891a7c90240bc0360b14e6dd770a990b31b31f33ddbf653988f82742e5eec31b27368eb0e4f1ecf4d676f49214a520d1e5b2bbb59ac2e13267e07a0cbacbed9f94d7473ed697828b0928fcc616ee02e51fcd8db4d8f7533b7b139a05e06f9e0eae32993e3025aef0590b3fbb4292a3ac40765e8584ead00266acdcbdde1457a03b7d57bd5c9e64fb06b64a50f35f0a1ec34b6ddbde767b96ffd
SIG: 0c173c488ad001cbb9c43d7b30a7c071a2fdb08cf7f37daf71d7ae7128dc0d43f0f095b2929c54b773ed4a1f0bf0dc4f364f0601e8d5ae062f5b78c05bfbc702
TST: 241
SK: a34d52563159e0723e9f3fd133bd96e20adae623f8c798013bc36b441489bdc2
PK: 1fb658e645de6d3efdb083a73fbd592fcd4b800e03c7bd681aeae6576bfbbe2f
MSG: 1d215f85c089f35f307a746c66c7c1e41d6ba37730d759e6e5622d6c6a198e40f63d37873b715df7518b3c6bb5e95a467726b97c9a0f8f5dfcdbfd1e0de357661ddeab555042b945fd899fad6d382d7917da9e12dfbda0d69900b3975165a73d0ac9de01fd3048b8fe5f0b90be67e03dc22f653a0a13eb4b0b753f3f3bbf787369ebd8bf5e00eb78bf0b3515a91e68b1d5fc6920bf4f4259f8a730efc7f1016d501ef6fb7cb8366fc8e716cfa50ea8b203cca1a316707e0b0fc57eafce82d62f7ff3ae04ac8fd041b55b19a352a69e6d4b79d0e650175168e34fa3358eac816cecf2c8dd1bf2a589113e91bb818f91f8
SIG: 5fab5a7140d47873684305aa6353d3862f5fc13e54a40c9563cceac8f74008c6c445631fa864e0f1c345b5954f80056aeba25662b78827b5e8e3a9437813720f
TST: 242
SK: 58dfe768bf52118494b29975154cf452bd9746dc7de1d6bcd18ee6a05acfd858
PK: 0f1476c6cc2a1b4764af75805e77341f14a0d8b09c6a5b2ea287fd517c3fa6b9
MSG: 609794201c4f6faf488790d61dbff3f41b328c5b0695cbe9aa8a136d72b4977b21b500f216e9f32168ada8c13bff25327647e30d8a244d74d88303abc90b7f71aa07ca04d17bc8a0167d6e63fb88baa1dab81d50f1e91f46f5af77f2e8408b826336a35052efffdf4af79596af1bb2259f83c1bc109cfdc3dd50fd96d310f27ea4c6c7690f21815ea92bd79389680cfe3ed40c80181190688d24222d9a1ed52ce6a16b41dbd9107eb6d2e3594e4494d75dd7c089e3b26ffd00d1003c92c4c39ae5382ef9291491a880ca4ec3ac2b86e66719b92b6f7cea2cb0bbb1cf624d0d1abeae556e5f73909dd546277037ec972fd4
SIG: 977137a38af44f4b262abff7e07282433c58926d562fbc6180bde6cd9497861fb6d955cf383d999fa1037b8b1754ce888c9ffc1560a451d0e9db8d74d2940604
TST: 243
SK: 5a63ef9bd7dbf0e89fef155983659e8a0a6ca002bc42fad5a45af8e0281923f4
PK: e632f4dc994231cc1790c21afadaa977a589b0eb0da19fcb2792911b15ecf8af
MSG: 796bc8361c6e8eec39838b24f53971e820f82361e0510eb4def1db2512387d6bf35bbdfa318879209435d6887b1410b3ebc1455f91f985e0fab1ce1c505c455576bca03539d048ad3a0ed1f11c73bac6809e2ea147975bee27c65261aca117df0fae7008e2c3c130bec5533ab89351c2140c9d1a62bdf688629787f954e1c610cbb75edb86209d7c357cd06ef41931dd5dfd1c7d407fa4ee1ef29393beab5713173802cce2d56229cfa76b601662c4d9a84a4936c52abb1981378b717eb55cb604a68d34f03b219f32226ca0e669348a2d8d2453930eb6e9c2bf66fa4e92c75136e148cdb034130d3f646382e1c71579ac70
SIG: 75461f99650c0368058113a15ba16bd2337b2e633da38112878c4834fac9ba2e307c866c02af79bea33659614cbb4465c57ec3effd4c478ae38a34a05cf1ed07
TST: 244
SK: 8b2f06141e401163f90f674b04dc90dcb6dd3386419339662ecb0dffadf2500b
PK: 54da934a659119198553fd4566b660d8d610adc3290cb84829c894148cf3f67e
MSG: 1deb25d43458690323a7d26a26695090993474f467c6fde5ddb34da945be3cea2f6b75652ae21cbc4fd22763a1b45583e1c3e88bbb5fea2049b7336c91159988c01526824ca3bef16b362b9202b8b9754185bd61bea8f539aadf4a1ab135fbc31d2a8e33178073106cbbc02d4cd0d3c8feaa8eb733084356251795afbd78ac3c4f8a3ba19aed755c646f35569c7a6c675b6d6918e834969aca03f71a2e72ccb17003bb75b62e852aaf58b3baea89bcd64a32eb14a6b9e10de48971e53d0e9ac99a78f42de0382ef0e80ed3cfa343f35e4a9983b9aeed986d3a57f47e5e46d40e9d677302809a2d37e4ec011f051b4d031ed600
SIG: d68e3750dc56432397401c98ff1529db9ed48fea246dd4ed383ec74c1a463aeb784c87b1fda8bbce970fc97aa9807ddbe95d41fb022ea68c1e311654fa1da207
TST: 245
SK: dc649fbb1bee0a44814d6d9e9080d5d90c1fc173ab5fefed826a74723a774e0a
PK: 0214c89f3867ad2e8870e50f8c2a6254986d9c220e3338411300cd9c6404d4b1
MSG: 328700a8ae581c1edc4e2c00c78bf4606097f9bd75aade205a243c5fd7434d6222da937e2881a2e3c574356d4d5679301da99e11cf749c27921c8caa2ab2a564d87c5df8ecf1a72b680184824f6986022e3fc98bd2a21c3455abf1154954fb30c89882947b02f35af7b1bfad05237d242e2b74832fc536196f2e59d1acd0c1db6f1943d0f6043bbd6a769083ed66ba0e05a50feb0acf72b6c16ba9af039afb7fe2a4aaeb4d06181c5a1878689e67a3f5d0ad39e794d6239a7e0a12ce820c5be60fd5f1dd79702f49d02b79755fe873f5785c72f74625cd7e2428262597d31482c2c0508801fd96319d61b91ba253a5e722f414cf
SIG: 0e0c5e4e184375da4ef7e2a2e4888050cd84e2fe21d08e84a852db2be3fbc372c472de0954dcd1dc11aec493c569f40fc6f77f03ee524fb06ec40faa1d6cc10f
TST: 246
SK: 39b8062da43e64e1676765d62c7fb8e0a99c4fd417d6f7e3319bb13044205f3b
PK: 6227cefe88ea4fb27b37b5f797778bd72fdafeadccd9aeb67ad437ce08fba6a8
MSG: 740af679e3069fad059fa4825fa41c59fbd484aa649303c27c4f7a94711c5b713b2a6b8987859e2271a6a71eb0b4a15abde4f5168f6cb9dbdc6a27a2a13d52c9720896a1f4ce3a5345ee793b6cc3ad80d7d58163d5455b9cbd073e2b7adbff95590c7172271bd91fefdbd01657ee1750651036cdc3560b444ca2184bf4f3ea89fc973aab6fb4a8ee5704bbe5a71c99fa3b5ef0d0396249758297699ae202b819690dc7ac4692770346907845e2210d5363adeec03f0fc7761b7e0ec0fea1bcf6b04fc54b3e4c40d19b8fa649ac8479e8f80730c0c94e9f4a1ad506f2bcab0c49540f6decaa77b3d657dc38a02b28a977ece482545a
SIG: c5f626490c0ef4e1efc3edeb0cbc3f7de267057fb7b6eb8f0c813584965bc5c421feedf54241cae001ec6d5e25c9b1fba0385e5dbd95a06ec1d8ae519144960d
TST: 247
SK: 52f4675d8ccd0eb909df0a516648db26fa033ba41d43fc3845896d456e14265f
PK: f39e7dafc97b0a84dcbf7fa14a9403ee1fa92b85e5a7e5d05f031b44ddf1f794
MSG: 74427110857cb4af0a3342c2b52997bce1a0db6405c74e9651c5b85979acb071e567fe70412c4e0d8c9fa421914f6a62f2ae420b7b2f4cf80c90574221222288b65867eaa66e7e0a0557a26c549f9a7a4e70838ba4074b4cd7a9d758b378b88dd49441df802a444dcbc30624933b59922f33c20f019fe78ee24b8fba79a682f388505ac9c97f4eb87c611880026b4c23306b865173f5d716abc6cd9a9906db3430136f754129c443b20c42be2fbcbcd44034d714f58a4ba8e756607a02b608ef49648f2ad0cea99e7ab30a8dd7814004f725f49301d7b304dcda625c296d928cb581736ab739c86b469241a8259351fd37b4780a9993
SIG: 4bf668827a720af68898a06ea7b44545a34ca896ecf311feea47e0686d911fadaa03118997153c65361fea15de9bb891b8909872045508ffad0cd9eab21a9702
TST: 248
SK: bad73c9fda4ceb9da6c701c2a6e2efc0467afa0a74f8750c52cf1fd4c8e7489a
PK: bb0f027a9035376e1aa3206c3d774475e351f5767ef86ef48a72c037c24cce62
MSG: 74b966cb780771aee63d734df3756702d1d5fdeddf32136c6358b836318a4f984fe71e7716adddbd649eba44cd4282e0055d8c1ed2d35123d66e5a98f1c0838ded563b9a20eb8007538fc7b0713e7e485e3c28f6ebc421a29dce2524db7f29205761036ada62e5b0b7d5b7f294ff17f338232fa5fd42b6f7253304092d848f50735248595da0f7ef28e568e9916bfc56d7ed0d811b59d5d891ae43e1b198071306bf525c678c6343998005fbb7869d1c40f8cac807fe2ef03f3d5b933f58978ef2906fccf7444a2936e63d928c690926c9c994ed3d666263e956fdfea27764bc5f74125bc46bc102dd3e5ff93b5e123e4b38bdef697e15
SIG: 197d6b6cc88a98c06dfca0c01225edfe38a0b2289f29f8a44ec0816a952d585e2d59b5b08de100c0606296ccf5e92a99e093623144b8b22db87d929225546005
TST: 249
SK: 707327a431dba77639b3966b2bc095f8eedf57f7a200e3b0077ce420389c92fe
PK: ee2496910864189fdaa3c7757eb3cda9ab1e70fc9e7f71a38a0bfc845931c95a
MSG: 32ef31b64eee700fca2ab21a267f8d9d3bdc689c7538fe959bf713fa995db2c0ad36dde430a8417d437b72c74e26dbe31d93701d4617fe51825cff7a544fc9f44e4345e14b4b11e15f26ffc2af8035f3f970e4dda44c0ebc0363c2b56fde218663bf78839092538fc2f39153d4eb29da0c1a08aa966601cc68ca96e993b01b173a261b2ef327650382f568fe944855b0f4fd9d15e752ac74dcfd37b3786fffcef23339c21e9270dce8891dd5eeeba9608fdc7b6fbcc99fa1b5903daa0968e1b691d19d06f215ded047ef9d76610f5de220f5041b313faf9e96c9fd7db54b5225726af435f9cbd9fd87ab40ce8f2c6940b55f0faae87850ca
SIG: fb99029feca387a5d765961e361d7172b98b7e0f11290bb1e5b57b51bc2123d0bce29020392a4fec9ae6a72c4c386cea1857cb8f9c50aa9a76d7f1687fcf2900
TST: 250
SK: 6aa5c9f008f990473ba4a6286a416614026661f11e1a24efa81ac35852d1d070
PK: 605ac9b4dbdd5033d6c828bfafa93c0039440aa11ca724ae834043e07bd032d5
MSG: b5165d3963f6e6f9ea5657e9f07ff3a321eb338f9a8c3d3c42306b2b278978b31c623a631be3b04c41edfdeddf538e1b765bc8785401c1af29d0467a64411c497395d755dca03ae3272f4bc1fb1918dcc1ed6f04d6498404a8ce1409d447f570a4359522cc54629202ebe507ab693843141bd5ea0573b20f321a483ff383a46897f5926fe0b8afc25572707b63eeed283532928a4144196497942c572ac547605139256b0aa0eaf04db1a256012ed453b173ee19ad6e9b1af3f45ff3044a641f8c8eb0ac7bb45abbded47286b2a069d3908694ee06f2fbd0ef605a7911026ea9ea3c4913f38c04d8b69565a7027867ab3092d05f4cfb18fc7c
SIG: 9756303b90655e935251032ab19cfc95ca1c2a2c3ea28b033bd47066cbd4c7d8982a8b9886f1b9cd02e88a65564da8dcc34f308ba9f10144ba469c2efa49e004
TST: 251
SK: 8efb8b79742be21e6d31de678bc81450ba8621082cd6f0003e22861e2291c481
PK: 33381e356c4fd386a3f7b969afd9f5c00d2067b698b3f1f00f3784202d3084cf
MSG: 6b750325d3a0f08a147700b51a9b3725571094818ed69d1f761013eb86f323f73c49f5e439877c2783b336d1f1a674ef3e431fc1ae0180082df5fca69f848139fe6ab6739a0592ebd6d4705c7f0136b22189a11d60d4d3c9bc80fe7d7c00952d5742f9c0c2121fe792df133f221db991fc960ee64b9d32e0178e542bce8efa8d03ac8026cd77ba8bf0b24215b9faed2eaec920e925d5ec46fff6bde725e91c8280e4ada232a5433ae9680ebb53eb55553147c93370574854896154514299c093219a111dca4e637ad5001338c6d4d5ee9098c65832f7af835bcb622128423036c79a5737738a7539f8d4a6b8b221b56d1401aeb74d4571bc009d
SIG: 923005cb4848402aa8f9d5da74030b009444924c214ad600ddbab4c153a6ff022b53cf6364cd7ee99bef34fe144da964edfc38a0ba633312650ebf0e55a06009
TST: 252
SK: ed046d688b2b0a1bc3daf2119dd321a607b16d2a2d1d963add1209c665b5ccba
PK: 8734f1ffcbd71cfde290017ea6253e580d59e65b541b46521f5e5ec1451eaec6
MSG: b9cc90fd8de2a141f95116db3b04be83e98522597ec2174964245180b9a473767d6d470a217db5ff5a1ab777e1e28a0b16975e2bacb873020444b47ed8326421b90ebb503688f090c11b3b13617c5c5052c297a41e2893775e34d59ada49d994c0e4a9f5220e9f0315a67705a3ec08af0dc724b5cf67ff34fada8ba7109ed2b5a8907bb403fb1a838b4b059f18c792d7bfec05dee0c9cbbf1753409d7db3aceaf47b4c61398497b0eca6c1f8ac08a7ea1eb9c40bc4e92e888212f7d9ee14fdb73158160944ff9bcdfef1a7469cc70f9474e5f24dfffea585f09eaaab4be2afebbe8e6cf86d35680dc5d1b92913e848256ec736316fd0a2142063b0
SIG: 721bfd4776cfba13330fd37269e979c1d7b6ce54a51b82f456e137378e582f192a12089da5aba76a7b161813dce56b72892a35330c94f7ff21d09cf09e553504
TST: 253
SK: 76ac8e570a39b3a0232c45497537fb2155acec3617865ed1df210f00b49d1b8d
PK: 312a3ad899ae6a25507ae6e4524e10b63a6e7ae53d9cffd39cf28521d93533d6
MSG: 53ced9db2b479e59d3ed643f7cc3784c24b8bd4c63206c72e23fa850028899a41ce1a8bdc003f12b7c29972c9a08bcd231fe0e1a0fef0bafbfa4e0e027d72004075ba37d490eb9964e783bb98f9e503e9c1fd3d23fb0017cc7c7a9f86d171f041e2355d8c5e6229d34c7eeacb6358cf3060d5d265bae2004a558878659a30dfed5f2ec788b4e14397b5d00c29db5d4ebf16639a8df292a3d24f6983cbca760d903e976f5b698642ba1fed49e79c38f4bb3946efccc9d6aefad336d558f78e4f205422e10384a4e531e75807efb389d2af4cab43825fb87f196a9080769fe7585782970a6918affe10d20d629b705845597418d699de3f1de854f94bd
SIG: cf03f525913c44303b2f80079393c21c1158146ecf99636f5d97adfdd9f35839804c23804cbf1e553cfd4b73f689a9143aec298f8276e1e4ee0891f1ba75de04
TST: 254
SK: f64a66ba0f0819f3001416c220bf52d860130a19764aa8ab38d15b2aa75ac022
PK: 8125253cd337e00d45b45079b585349561e5f542a81f6d2fcfd985c10feab2af
MSG: 8072862ed0ab35921db5ec2cba8e6aedb0441fdf47491006c01e6456ad70fae3c4152dcfbfdbb8f0fddec5e96b12bf67989ba96793f4861a11b63909ce8d19b8ca64a544b31ce051fbc88e062806d9965cbd2967b01614e86b532fbf59843218dc9c19c80315f044731719371092a3da38878bc4cf77de972e860466b8fc45e465dc3d0ebf94bdea60ef0b9891ced41b997b11b31ee4167db60c9cfc8b85beacfe223cc1829213774085d7c06d2b2e632cc21cd9660df47c4fa918bdd596ddf622dcb652642b67527ba8ed15a819a8e21f48d7ee70247f5200e37c259dffd17eec8c232f970cb03182fe3964132993f6ecb7c4db18ccef390c9eb3639e
SIG: 4de6f5250822d7c9d5bb98582500b5c085f541ebdc450ed1acaf83684827ed1dc77147aae4b19e14a7dc5bbe1f1e4f5771d8a6e4f2351739afb08c806d558701
TST: 255
SK: 8439b1d60aa48460135eb1002cc112792995079a77e6e8ab020b9abaca8920b4
PK: eadc3e0c5bddbc3052c3b2f8b0a94566c2b2c879ed17034ac0e6a45f2b3e32d2
MSG: 5419f6d24eb46635d4a7f8eab803cfd0d04de092afbd86f2a6961a8d1eb8c0d197ba55ee08c991822a5aa702bae0337abd5ca7faa15e1f1ae369946e9b81216c0f5fc22bbd4433c3de93c5caa2741683bbd0e1a78df28dda19174101876334d40339659f021ae766162c6cc5421b79cf9d5c090ed4af07ec84493035bd0b2421b533684295bbe76a70fec596ef8c89c5c9dda3c33b7735d2d2f20b28f1a5402e72d04ba291dd59f14af08adf56eeb086d769c6bec3451891372345fd6bd02dcf95e803af0353150e182e323aaf683e036d9a135d2e6f98cb4d327e2ce7d54247f3592ed067b4ce7627174f996f28165c9c11f07e5ee9cee63851c6b68ea2
SIG: 62da81e16440821b593b6ee6540e15d1aea75d23e0a1bbfedc808c9548f87e8bbf36915a39a74716f645cca5714d170af907576d4f3705e543d2adddc5ff2303
TST: 256
SK: 3a046397f0afc072bc7f907c74d38fd1b9afdf27e14a3534768b0dd2df3a1c22
PK: 99cd70ef3be342493393872f54c47deaa081021892d11a3268f3145ed4f3abe5
MSG: f08ddef46cc6c34179820c9861375172fddf774f8dc3f7d64aa432da8e5fae644c0a8a9e6908517d505debd612868ac6daf95cd7e1699750022ccd4b88dbae2bbf73546ee4b835d319a842dae8b9ed683323f31e5cc57919bc9dbe3bcfffb2ada48072697ff4a7d310c91adbca81faf26a0eb7bb0c404ac9d8dfec63e9c64e2f420c07d323b7c0dc3b73507283aeb1cee51db4e1a83a692c7c1ea398f6f30940fab85e2138d4b85aa4e231e5424f5b064ed026f0ccb99d1c85a9eb15f5934a11359d411cf94ae8ffa3361a224f46bab852d184a248b4c31fe3a7e7f5134c051031a9f328a7be4a7cbbb1d8d863a400fd2d58daa44f1b9d8e9ddf961ce6322f
SIG: 5024ce60257965687080c5b1fc7d1301c32aa6fcc835497d9cb23a74a6ca2724f55353c1b757827ca5440c9ef8f8c1050913e20aabec35c497b56041b5deb209
TST: 257
SK: 124f7416a80453e4cf1cd7b5e050a9761418258bf7d27beb7f23238c4540be2d
PK: 0da34ab173990150df7399b6bcddba93c6dbcbf4d176941cb5071e8734c5dc92
MSG: 9dcb9873ff054db11d0a9b19de6885ffba7f0e681cf7fb8f6cd950c48328d1f919ca46054eeee6c9e57843ebdda7b24bc3503c4d612abb1a314f39f58221d2b54dc755acca7969740e7fa8b1a9523b8c7379fd395253f4e6cd054ee24b75613c3581d49e19246a7b3be1cecb334be44f3d626fe3b7b269e628d44580c20636eba2642f2744b959e65757d0ee601843f188e95d17253fef567068a5405a3a9e677fea3d7d55f7ead19a3f30c5f985671b55fa120cb9d05f471b6e1e8d779a2c803a19e6d0d7cd507887ed647c2a95483f933991ed45ae301a2b0e954a5703d248c78810aa0b199cc2bebb2f1d71cc40487dbd42eee0f745f7d285685b1fb31b15
SIG: b0572104aa69e529e3465a6fd28f404a4ec20276a993b1725eb8c5f650b4a216f1871b24e368cc46cd1ee0174cda1b5e4ae2200aa9fc44522d975a9c51814908
TST: 258
SK: 25d13b3837601b07a975693e5a33d5337c34c1127fe4c27490612aaf7f642e9a
PK: 3a07cd68ee2692d51cfad1a80e7763b18a043c74f4e1b01edc55ba9a9e07795a
MSG: 115b3220b45ca8f36c7ff5b53887d47e669b78dac13b98cc7aaca5c2e19fce81ec8617ca410e11c9a9118a668453b329ffb718eaec739172f0a849a0848192a5bdea18ab4f60d8d1a0d338952d77b2cc13efe83c76e8dd58803b1d8b3c9729ef102b20835b7de872bef3010f15a4caddf07cf7bdd222d84b174bc21527cffb1b7ffde81e281d30cb7bce25ea3dffb6ea1fbb06cb70569a95ed1a07e97ca42de70aa218159efd608fa9b0896e0b58518a322f251d133e58c8fc1428ab0a170ed845c75fb403f1ffb97d2d2a6d4f277911d326c1cabbb8516cbc17908ab81ff8d79af44611ea1d05879c1ec81d06936e0f4a0aef6d5748e181d30ec25236597a973d
SIG: 20cbf08392fea6a99cf446a95c199caa0c0f9813cc217b8d228e2ed90bab95ea92cd73ac95834764d33e42243c80a7603491c8d3e49ac715fd8a5b9e4789bb03
TST: 259
SK: 7b3a76decaea60c41e95b05877a7da82064c27278c8d7df5f0bb95f0ad2d0435
PK: f80db5c28721b1c611bd87eb145a98bbf383b068045df2458d1a6fda099f7fc2
MSG: 375fadaedd9cac49b64e1574028046069f4c83654c8a7011abdb64db16b47fa311798172f9072217b0a6a43e5df6ffcc1154bcec1c68e1d35ec05880d012ce76e4cebf301bb2ec983d00b4a0540c937ff1c6df9441c61bdb3be8e0c7c11a35d49b6f55c381269a0e768efbd453447fe48b75ac39646ca82eca7d149304423491871c10dbcfc5973a57fab8371c30cbc4e90becc0b67152226ee177b4ff368ec879b391eb95e36dcbb07b2c16ba395545d4529f727b1a11ef65d120976b7ccc86af4bd204cb9489c921e43ba5e850cfe59899f1c1ec4aa5c92b6dac6914b1952b53dcb540b409231381568987bb2236bc40895df3f17eab7c0274f2244f958612e88e
SIG: 2cd26fb3c4f7440a72affe93564f6f6559adb15cc7a2ba10879fb7d67e47d4ebd02fe4823698a5fbd4a907fd69184c255a170e5f1747fce968102dc219b50d02
TST: 260
SK: 5ff8d4052608eb033a5e94b603ce384d8452f60a26498b9112567f3410c18666
PK: c4900de24d9af2482763109926af7c481380fabcda9440c1a53ea1cdc27e6568
MSG: 138c60557c2e9008afc03d45bec71f961149a0835926751c8ff3935c7d652d83e1b0b1da7d5bbe0b8e171a4e49aae06fd8a9deff78dcde4d25b1aa899998a0f99e1df6f9337a3ea2f24b76c317a7014db4e5283191795a70d8821d217846490f958701d39dc2c8ce47d928938874d87b3558989bc77af820979a351eef9594aa5b94f3341eded4ea20b08c3e7c5610d43267818dfac0a87ddf527fbce8512bbf85b66c9bb5d62f0fe84048f23b19604a5c8d82b1f25a8da02731feb2ecae489b8475f7bd326ddf1a08189e46c08cf50538c2a363e2f4eb2c01a204c7ffbc0b981adc0fd997aafdf2a222ee84c309f6e95ec7de4fa85d4768d5c003165028225e22e09e
SIG: b737d4e5be27deb6d87729c636dff7a406c013f313c38cf683fe14f75a3b3005d9535d7e5815c8f8b37c51d6927111c979f7d9d81a347aa9cc09ed4e6c18e90f
TST: 261
SK: eedefc1757e3a7e5ed3946dbedc396a362f683d2c51b0b9f60765d4bfc5134de
PK: a9872bc2192fc02b189ceed403ab9f270a032a835fdebfaf1c9d6934ed8304bc
MSG: b194db73f994cbdc3cbe630ba72c47c2249bc0592ab547942b1d1b882b44f5b3855e568bdddf92ef05022d88fcfc294e76b64a00e9c74355373763e49a4ebc47243d48a9ad588994a518f80f8615c2b31da587a53e529d435a8697350dfcde02d20cce7d5eeefe3f5ab2aac601259cda38538a1b8301f9832e75ab90f8a932f267eac181003965d5266f206180c6c380ece803577ccb46176bf607159486f24259747e2ca6fb1912db7b78a973b2846387c1208030ee1f400d0c5b5e8bde9635ae55638ba17c734de8638bb85dfcd76629a7f9f40d6ab954d55bf8575fc9c9a595097e0893db5a7b8a6c455ecbd3d22d725e19de2941f467f9eb93d66a0e2bbdbf92ed1c
SIG: d5bea8ea9a5fe9ed6d2bf839930c0c6cd5039e988f551fdedb5437e1c1af0ed7b3897c035711c3c51926be8d1b32024d5cd582f5f8369ad84d18b12502652f07
TST: 262
SK: 09d22bbaa5956cfacbbf9fd5510975128686c40c6ea96b89ef4c0f0c649bcd7f
PK: e559ea8acbdc61b6709a7d83ae15849a6c78b203923dd0a299239ee4886930ba
MSG: 1c26a0f3a1a5b2d7d5b297af8a6a689d7c62a25267e197d23becd2f2b816c4de92fbdaffb941c3fc8db7a84335a84cfbc92cb3ac806ed58df16b6b8e119a48df4f27c71e931a5938e7d002734885e13a258a15b6e1136efba72f1d096b689f7618f49c968063e8f991fa0b55601e430eee13492a1b09413eb23813591a7a9f070cc396ca9d1facdd4f4ce37c40f7245f55035e10fad6b85b5f01a1daacc0df94069f7de8f6467f96d1fb98648e8a0520a8cd723c98e9dc2dd4b2934d8228f0ae1a415bd3a7cda38d7a9983ce1af6f8c970a2a591635fe12b917536ef815eaf1a3138d70ce70a794264d7c986d9ee3290445f15a9248f2765271e5a992196ae331abd4164bf
SIG: e65275c4328a70ad62408ed7fb1728be87a73a814fee8ebd94f2665c71bc66ab0c1b07a600b30bc081a74c536857c20610384be268d9af3e3ecddd3eb0c14c0c
TST: 263
SK: 77826ed351a3f09254ae5692885d774cb3f24410a4809fd90f8a00da9aee9903
PK: 3eac8f41ee73e6ef136821f7957a1c27e15638d0e3916e6caac6fb7beb7bcfb0
MSG: 1ff06c0b3999cecb1900a47d267beafbb35d93d14cb2c8925e3e3fe5d967586925ee4baa41998edd0103205810aad5c0bbdc77874476810246d13089a64db576424fae0bed9664a42a491147d1ee3b9c3b1ba4875be15462392540f9978d9a4630ba4c525499751a45efc299ec7d73b17f9ad275ee71a687e72690d7320242d2dc2bd4d5c5cf0f17a465185dcf60f8efff53903f20b0c2ab2192d44368f2f2fb36048af071f7aa857b14ad1d11461205bebe17e02be2e3ccb6092821885c4e0d4811be3f45b1fea088453e022432f562562b43a355cb56270cedb6c2c42dbf9be850e77192fdc65cfd36834be988dbe9a93e2518c138b090fb9da827cb1c91c8fe52fe7c57f7
SIG: 977adccdb829b40bbd8e53856a783db346a39dff62041a2972d29009f1c9ff81b8ad54cb901e497c1d3021b50b6c69ee73558fd7be05d625f5727f9af2ce8702
TST: 264
SK: 99a99531c3cd6e3e9c900a9eeb26267e72f09d11b651a897ebb79be016f64c6e
PK: 9bf9f8b48a2728e02608fc19899d219656839d1cc1e9a8984df674ec26662f41
MSG: 7a89c0c1952fdc4298dcaea854efc134656be147e9e8e82fc9a449059d80570f75676b81c4a94f76a968200cdeb0988c73f59afc72ad4c3103e19fe63b7e95e140b5cb2efc7b97a6ffbb6c298ddace3be6d2ed3d598b8bdf0c2fe6c97602142a76e978514c196c1b9a88efdc1925fc506155cff9a2f21ab634e2b93e96928a5d8f7ce4cb7326d9689469242ba9c6a01b77496badef87578f5a17284e900a72df141c6199b0e71ab5da4375037617ec6196d4f4e23ae2916a72d0fce796022305ac9fbbbbe4705b340e42b78e1c02bb1001860cdcaf71ed89255dd56cc0b31c59d4596dcef84e22234be562bd801e94111d83a78064c90f9d82fce91f68abb03c73b6bd8d7e02d4
SIG: 0e89da5d949cf2bf40c7e17c2d0f9ceabc88a092eb4d49cfbfeab7c8bff43245c67b9e2e92f9bcb9b34b3fcf8b01fa2ea7a9649f814c3aa98b3dd04540c31d09
TST: 265
SK: aa58403e763bac405db065eb11eb6be3e3b6cf00ec4a222b52bff4b6e3d156ac
PK: 167f9b9a4665f93f5d7d3016ace6fbd13420b2e51e72bde59eedf26993b66cae
MSG: 3baa0998ff02b32b90b51f9a840c7b5c5870cfb1810a9b0f77b55909d47ad335147a991c29fbebfc592e9307175c1964129a2d5efc6215807453bcd726969781222bcad1c99a49748b9ee667c4d0c82889e2f50064c115dbd8fb483d72ab0ccadf76bddb2dc727dbc3fa5c4624c283d8921c8aa4425110dcdd69c05e5ed59b359625eeaaec1e27eafe9d9a5ce736c3f9c527ea547818b9bca6811be4cc15058a6f5b683303b80c90c94a83b8b15869713a66b1e0f656331b286d1ef7698834ab3e138417aad6bb3ab3bd9fc78761a482dfc654f3f8628c8d9fc16018898f1641e8622bd272e38d41706cb9cebe6ee5e173576bf61bb1188cf2f39c62220bba88fcb4de4898b25b04
SIG: 64b598ca5b8f9ae742e46ee0d8c1aaf31458b50c25d267a677e44be5b755f14d51801a30399bfcc38d14071aa0ae93da825a581ab6c20725a0a910b4735dfa0b
TST: 266
SK: 1044ee3708c0b0e909a8cb2ba2cd0af8d28a5de01d962e826087fb232df7b2d2
PK: 46d241ea0c702c1889d44655824629b67284d4e644a48fa45455d27ac5f62529
MSG: b8a445455fb66e17e3143d35204c9ea93474eebeef93963ee5c1d377ca217acd4ca63e5755da08fbffdbd4352bf165193896c8d6f76bb4cd3bc2d3a476a4e320824a1210ce74d0014d747f111eec310c5c89ed4d0850e811f80a8bb28dcaf6f411df83e2c1dfd90c4ad23561454eb5d756b63b4ea7f37dc5d466c16ef70d11190c4f5316fe2aa8597440e88bbebaeb35ea5f04f07b0339264158ef909ad5163bfc248cd724133e274f812695f290e57176a96b9393d07bb310299f5d2a6b6dd1dabcb51bf29c5afa7ebb0701c6c84767ac137793091fe0ed6e47d780628a32c84f83e00e9c16742a523ecb63c24f4a338ed299a06194924f44c5a5d3c937ff9b0945982ad24a2d1c79
SIG: 7d6bed7f87d090abe013c31e1203903bac9c93445d06c7b53d31d15f970d88647a7ed2c3a63050ba19d68043aadd18bd861de1ac4715b8e828b2b16f8a92b001
TST: 267
SK: 95dd1a5e658fa6c8d42507b3e5b8edb5baeca62deb00fc5d4dca8e1ab5835e59
PK: 3a5323dd1e07f323bb6d83e9c2db92a29f62e2e003ee0deacd7e2e4e030d8d27
MSG: 9b7afd48c474604c26367531556840c388668b0f3840063dfc9869ad5b901274b931293d04f3c8e8f7f8eab815a641d7c351284e8bb0437ac551bb29438964e6a7c7ba772344b333f9eda5a77568c8931ddcaf21e32e07b10bf4820fb859bcf87b81c4bff426f24a4d468f2e9aeda8f17d939709970db11df76247e98a39eb8b38f5949f349f2ae05ab48c018517c48fa0205dc7f1566453e105e48c52eb455c0c40802f797b3eefb1e2f3b1f84315aed5b0711c6499a691b74b91f12ef70f76c4c05c1aa1a993e2f3e528ab343dd2368162f4036a61a13a88045dcdefa85d68532275bcf5b8f5f00efdea999a95783175d9ee95a925d48a544934d8c6b262225b6ebea35415dd44df1f
SIG: d02a7523dcbd29576ba809b531037774df41734a41175813119c6a6a788cd9b8ad780865678667699ae66d010919a966a051c08163df67a977ee6e220d0dc30f
TST: 268
SK: 1abc0b9aa01dc57ca53efe7380962b1a88d50a964f5cd98640982c74393f2926
PK: 8d4fd14394d7c1405700306983fbf76ea9f171b15a6b56612a1feb1cbdae5dd5
MSG: da2dd940d5e1db6e80bf7e2b782e7e745cd4fd252e981517975887dd05ac77ed837d082961575efedf301fdf24b70718b991b8d92bdd2e6bee17c8aa4bc694a727bcfc78fd85195c42caf883a2c38d161cadd79cfda9a39110e1264d30bd4c5c4a5876777f233b071b1b0b408935f0468954cc744af8063b004ede56cd981c4dd5608abffeaec9e58f3fafaa671467804b7fa2558f4f95174201f183d80a5914065fed53115b41ebc338f78df050053b8a4e75ea7c6fdc354dad27bfd8a2e66fcd7ae2f587d24be0d4a33da30a220e51bc05fa4e412b959fd95d89ea6ec0162516c096a9433a9e7cf599c928bd5305c2173bf7493ed0c1c603cd03f082cce44237a79ffd8be9a672c2ebaa
SIG: f738af2d3e290b3d23d9aff7414bfc5ffa47235dc053687a8ba5c8541b8511f781566cdaa130e0677db55fa8be9d81a092cb58923a8628494d2f62d95c167100
TST: 269
SK: cbffce2c9bd3e23e406e5f66e632dcfa726654d29a955cec983173235fa359d0
PK: 49653edd64a55f7cd40eaf3f8e72eb96dbcdee398f34817f2c95867949710b14
MSG: 1ffde6826e4f0c24a7961f191e74cc0bbc928e3f1aec3efab32765c2501cbc1620e7ee6f61fccfb00cfca9fb98143b529bcc8c3d0fdf89ee7c342f101815fabf7deaf9f302a288fe175826d590d99ee6fd92da74f9596b783c0e7d47d711a32f39ea4165e5212431441b498c6b70db3b09d1f4e4a14a6bae39da5088bb85b3285ce9df2f90681af2c74dece439aeb91e1c1b0712eddbee8d72569828f37cb720c509d02aec476070484e9b16ec7179947ac96caf0e1be8b6b74f372d7235fe6e3999df733bccd482dfe2e631f56b582667dce5e3121763adfacf3b18cf2095f7394dee4927fc2bea6b5824d90cd59e854ec5872b4551b02efaba5ad54a9b7a8f6de5d7cda5825b325b076ded
SIG: e7ced4fa2a7dff73f1068bbad0ec9a1109043c97a62effa148876f0969ed4dc608e28bce797af3b82532c94dec4d6811b7f563679129facf17bb73d69375eb05
TST: 270
SK: 9f91231497484cab39b9e20f861181d397908577bbb2968242d071bca4813ffb
PK: 8824bc6cd6a6f15a5f41668f2b3bae8fc4967383078d08b51d6d1b2b93a1071f
MSG: 21d4fbc98163c3fb6e09f775c2ab7b18b18792340bafedacb49605622e3c08aa3b2b8d0e0902f361aa1c0f652e2732b10a0c5c6a05098996b588267cc8951a78b5d431e7222bbb508eeef1b5e8b8d01d3991e18dddc6ca8d222ef177ce62938d1810eecf06f4738b28f440946ccad2a12e39d38611bed3a39f93419a179ec2b1b52d5fe5c80c23b84d8803755f5146092cc199b4bdcea5bcf2037bd53ff6346694155f027d8ce2baffe30a5666596c00783aaeade9c77fc8637942ece017d6484c2899b1918d3a480bd5157678d4772d271f9b99768ee1bcc46b2489ae87cd030f47d1333c7672cb902cb4f5fe746e853de57940ba2264d3e629644d653a5b7af78ce64a993f36250f8cb7cb45
SIG: 0a1c706dd8a13077ab18386c65fa97cf9dfc43542d1846ecbddeb7b3c93f3c66f3ccd0447aacdd4dad8fbf736c4ff9dbdb62bfc14d8883e385bce9bac56a350c
TST: 271
SK: 1e2bd5487c5f5ced461f604dccb4e78eb91608f0b821f5afc4e3e534f7960392
PK: ef825475cf2051a2017ae532f077d96774347d2767ea7b45f9c1b860ab993506
MSG: 1dbbbb13cdad88854b809ceded273343d306a8deabf3ff02c9cec6f002b8e9e10ef5d1b0f5711f33267aa91c171b61e960f740457b81d751a473f44f750a080cab80af7ccca7dffcfac9ee4c39dc85cbdf51259ccd3470d9bad3ad30f4ee5dbd4fac6bd5c6c4df7311a470044695a7e1a7e18572207588afa57eebcd4d575b6d424457ee92465ce1863e3c677cf875fdb98d4078ebe7144260807052577144cb8e0359aa42ad155d79dae3deb99c4632c191c799cbfe587d954787068d663bdfc0fab1334f1876bf498c4db5c53db7b0204ed5a521c62f09eaca8d0189f3b394143f29c421cb5c8d07bd751baf4cbe3bf4be1701df4b2207dfb2904d84f4dbda51cba576d5a5bb16efe698edd608
SIG: 4d33c96a2e3a5db7391adf65c1cc3565fe76eeafd0b5c7abb0b492a0b51e1fa33639946a243b2ddef357552298ce0aa95eac6fbfe660988271877eb2a7da1806
TST: 272
SK: f78db14d6d1a643dd7735baf2635321244e7ec8ca72c5c38c98c809db9cb5a55
PK: 5414f75f52f3864afb0c79c2c5c1d06b4bce400fbddf17fe9cfb2a8bac47a0dd
MSG: 05caf1b8edc3b173fbc1ed29b95e2bf06d814ba2407d4b31c728d04ec273d25394423ac7d4fff2ca36ee90273093c756e2bd13c96d4a3dc7f5be1759fcd328eb66c5882b58fa4588e5b2a3713a4154a2340d0b06ad019601b0e028e497f898256b028af95cd8168df5e58a57cd1ebfc0a0c91ced61dbb480aca7df8dca91eb16e98007cd2cd1a2045b0e4477d12d5a4072f365426567c9d61577f3485c8f46605e7f475ef04a3948f60dba8c5508d14bfddb9b11dd044ef2d84c16b9a9038d8e78eda43b91297df35f4361a383b41d49677a687d5b344ad1ab0fc73017b3bebf32306fb3fd7b3d5071f3ab5f6e49aa15540cad6503bea7784cf9421801ce1385839893362a97fae121300d6783af0f
SIG: d7cbd4181f67712007b7f0e18452e0a024464d9dc9b5ff9cf669d1b91169d7573262f83336b97c861bfab3fcf669223ce8caf319f21d23f1fa331a2d89b6ca0b
TST: 273
SK: 7dfa328e90a1b849c219e3da832df9ed77448234f0d89ea5d17a3d64e7883daf
PK: e30ce6fd5f5800389a70cd117364f59945afb180f229927360b06b4835f8dc91
MSG: e5e495d663f47236714532687a24308f942ca9c33e088f7f106a5a723518cacbbef4a68c939a6950b2dc2589f82d354e575272d42b1383d315ab8a20aa0cdc9d4df678ab3b26612b5dca66e71f9f3fa7d9e731dc481e2bc7127cea3b6203ca6cd8162e90886a73dc46c83ddefc4b9e2d53d29dd387c624e08bd8d53be928a40a9aa8ae8b1c8d0fb6a7bd6dce5f62315b7a2181f627f256bbe7e2a95bf464e6132204c174209629840235b2c39913301a4b40325d118d384bc7ac028cd4f12702e161191b149e4209058a55122bbb8b22b24683ba4f8e2e6ccfc08dc8c8b1bcfb6d60bd8f062196933df319ab16906d085730eba1720d4b02c67daf38cce6aba38e25d68ef95b2f521913a1d77d5eb650
SIG: 1c61d53b872f8cde598609682c79f6c5df007c513a71cfb3a06dcb82d85c4b00ccc40b00e59f595393088b4cd0432855c67a207da71f87e72c409b3e50279507
TST: 274
SK: 6ce13d3c2ec71fed83131a69d5d030314ab49e6565ef68163fff09ac5d9b47e7
PK: 9c7b1118fab91e0e7b192a23d95fb877cb7936cc6c8a330592f48e6784edc292
MSG: 10bbc311eb2a765e0167ff37618ff70e13f02d7b0617ae4ac06befbbe149c972a994f680ca4dc9a92ec7efa53997fad356b9ff4ebdee629541d1f4dea62ed0d2494f9ccfdf07a9310491f61c4b3e2700b4a3c668d678329a38c2eff9d8cba431fb959e7f7655bd0fbd77d53bbbc2eb8dc51dd718ed98728a181686be122b844d3da331e329d3959b5923f7734325a021026e2754e17a15108be801465ad958dbcf21df890cfe5d5b883ca43c61cedccbdb58b849ea75374f1e918e803e577a5dc7a1c17936eccfcd3481bd2b1eb075b83237ca6f3c07c19e9af9731267be82d4898eee96ebc900d48b059d51b0dd415b1c890660a88d25f5c5f35d8e45e523e0ce3336923ab43670e35c5057d56c758876
SIG: 608b2bf6f6da05c2ac5bbfd795a2ac32c79c74153f9431dea59768ff4c225e3b693b645a506766b860850ee97ea43032b05b69e56767e8eb9d1918df9afba805
TST: 275
SK: d45ee69a5f1a7cfdd0343f8770d1c6bc026f067a70dbe839a86f2aa068c33f81
PK: fc8d9fb0e4f34793090755e0328096e01e281ea351b8d95cd9116e131a5ca54e
MSG: eb5ed8ab79cbfe61c25981b9d1d6b70f10b60194b4161fe17d11aff1767994aa0813e9ece2f4c5d531b99e8adf1888c30a63893eb451aaf55acd5a52ad8c401faa88d6eacf3e49470566114fd0c6a274e9544846b0ae9bfa124d7951eb26715e19253ff7edc8a70965776f23ce46031e034a200723ba3d11e11d353d7e7cd84aede267ff64bed418cb9f28c61cd0f63b6ce2ecae14b20bc6bdaed8c428bad18be4b7d66338364acd8042a8256f258a69969b8d3ca2eab3aea3706e5f21c3b1efcc254a824bb4e7ea7aba8827c8eb82786c665aa973821931ff990a63fd34a74a6d8c22a882b0b935152ccb36fcc76f4eca65d67c8680942f75dfad073439c0916065e83877f7ba209303f33548d9e40d4a6b
SIG: 156c51c5f915d89b8d1400350f8f217a5c02e2629ede9f4a30b6e71d1ea7a953cc6db31ba5c778c269920b649fb4221c6d38cf2cea2a7de3ad423e04faaa0607
TST: 276
SK: 8a76eaab3a21ec5a975c8b9e197a989e8e030899eb45d78968d0fb697b92e46d
PK: 2d9c813d2d81e2730b0d17d8512bb8b5d33f436cabaa13e141ca1cb785014344
MSG: c6c78f2e2080461aed9f12b4f77c989b19716780fab60e6ecb9793b4bc7ed69e5f70fa6bdba16e9bd3194969eea6665abfd630deeefa3d717b6d254dd24bc97dde21f0f29f9ed34b8bd7a013380f4f82c984fdbd95af9805b744bcd952c5a71fbb57d11f411c18cc30bc3594f7ad8228cb6099394a1b6b0a818581bdf93cce58f3a4a23e55db3e69ca9d60cfb3a907fb68329e2ffb6c65f1e828d28127109c9e9fb70160f2ef82a2ee9f9bd170c51e13fd3fc1866b22c79fe6d5101217979dbe2724dcad8a9bc69acc42c112dc697bd271eea550e9e50406bfd28245b83b8f012d34db6dbdd55ae6e575745c153d6e7534901027eadc2fcc33a5287ddbca6d3aeab8972294dc6c712b9942547277340e7ad19e
SIG: fceecca4b014fecd90b921b0fa3b15aeaa4e62caa1fb22729c70269232c33cef0d0aeea66432c128afb9a3646bc7f03a12774da8758398c2a0dcce0bbbf6740a
TST: 277
SK: 18a8f93648cdcf47133630af1e11c0ceea3de07327314c96580df775597d7a9c
PK: 2912f41ab4c87e3937a03331802cba87716b4eea14b9fba6f546d0ac2c0973df
MSG: 592093ac7cd671d6070b0027edac1fb015cc205d78bb603f378eb9f8aa388ca830db3cb23420c7e852db0b55241eb88a02cc627aa94143be439aab4bf2634757470406e842f20eb10f0700e3c2da364f588a8000f23850c12ce976f326d2df1bac13e95020b412b175bf74bd7ebbacf3ae55c0daebb5c010bf804feee1d7d49fae050bea55996f53cfe1f15a0cf20727db4ee311c260bad9682d7b965e27a9491f471d4a473aff646c7d424d5a0bdcbb8a0233f4b3060dd04c98ec98dfd05ec7247884e2d8e152d4ae52b3d5865d9efd6706a60e088e1e7c9f624510abc7a2045a2c7a7588e2535e73191dd5cf05421563f556a13e8236670343cd5ba4d466e245c4ee3b5a41e70c9a0f5e6ea2c559ebe61ba81e
SIG: 3b77394cd69f8b45d00cfe3a79a7900628a56518b379ed8a11581fc3a376e5d66807df11e70904f696c741d21d139310fa1b89a93bdc4d2c3997991f5220ee00
TST: 278
SK: 206cd2b8114aae188d81862ccec4cb92c4ef5fc78c24435a19f9ed9b8a22f47e
PK: 97a67ac2811f529456df532737d76bed7e387da83bd55459372fdfb27ffacff3
MSG: 480c4800f68c79f5dfc0c3666c0ac429b30fe0c5fe848750db2171380b80c8e9fec0a054b16d08674cefe2f64ec28bb6b0596b35235575f189bee259aca766c222ac0a46cf2af75774da4e34a0b54fc2ac49ec8bedf4887cd9b7be4fdb7f686902ddfab04627e26ea2dc3d97d62a4b1546180218ed8fa113334819b5275cc54afdee44309008596507971675e6d8b8a8edec4718f2d4bd735213cbbd18791faa8054174907a7ac17d7143a4757e493beeec4849d0b836f18bb2b3c9016f25af47fb96199251720549f15d149503d41095e25f26209daac39154485c3ded7cb1a8c3e83a52f5a06ec09cf83df00726b7968f64c0cbae299512fb438560f04b3b644346f938ac8e90486614cd844b54eae078bf678b3
SIG: 73a40d9da08fb98ea25b67e721557a1a51225294d316b53149af895fa4d63cb4a3f56f688566ef6da42fd2941dffa06d497aa902165d50213a6214116299a90c
TST: 279
SK: 59b144a708abec972729a04a6c13f0ea020b4ed4a48298023a568958c21215ec
PK: c4f4720092ed6179a082ae4d6145df3771786efca9bd9bb79c9f6667d2cb56b3
MSG: 3857bd260b8aad9d073f06765d37fe893a3f53e23de866ddac33495a39ad33ee9e9d5c22502bc1c4b5470d0e3f3a585223fe4cb93cc4ad2b5ba6d78826a53fc0253dc580a2018cc9ff1cfedbd3ac0b53292deefbc14e589acf496cb5f7670130fdbb6cf38d208953c015a0474675b724bd109f7cb89c33016751fe7aa785d099d09ab20dd5258cd764ac8daf343ce4790ead0863af43121aa527a37a11628f47869668f8eac00d80b6bf9906663d7a2899c1cb678cd7b3eb3bc80226b8b13b6e46877f38f07c3d9c86d3368baac4a6f6b93ccebcec9811474b6a6a4da5c3a5966571eed05edcc0e3fe7cd15915c91f44eee8c149ae451f375518a79fb600a971a39b9433dfa19f91931b1932275747c262eedcbd27f1
SIG: 1a80850fcbd6e643c6ba8eb684dbef7df015159228daedcf0604709186054db185aa7baacb09d6caad01638eff8e468735a60124de0c5376e94340e541a98007
TST: 280
SK: 8d1621eeab83270de857335c665bbf5726e3722225fd016e23bf90ab47aeec3d
PK: becdbc024dae6a94ed4e29c80f2aff796aed8feb2c1b3790a8c72d7b048a2c61
MSG: 97facddc82cccccf788c31b3305e93eba956f89613e6e53542b043267fee544c2b0a8ae8886a31b9d321a63c27623baefea840b2a8af5b2330193ffb5baf873c335528afeae2160163c851c5a2e58154a1b0569c2d1366c0710437623b0e08c686e54fc279ed4c45f3e856868375f78224c777b13d75de10d79173552425d15a561904155f2117b2f14713eb0b04648a3bdeb3302167d1973e788a06cb00d48ccb269fa71af8ba68eae55dbbfd9594d5c2b4dc13ae0321718561acdf67dc8cfcc25bc46bb66e096a1941d9335207d3f7d11e8904904fabe3a50a3883e7078047df252f38b67cd28a6ac45c7d7a1d2a1de8d45747cf09301e01cdafd0cd99a6e91b704d509fce692fbdef2f71a5ce0b35bc15c65f876824
SIG: e08d6caa5f39327d6e6652ed74dd1a37844b979f5cce747a606f5679f4898bbb7643df7e931b54a2b40ebdefe83003f61ca0f11112f023c6a3e8cc18cafe5f0d
TST: 281
SK: f2735d50ee3a9a65b58c8acf551663e98809ec406f73e3e7f4e73bc4ea923874
PK: df48a5b94a07af3c2c99b8388762243233c850dc175317d602638e5b86ab49ed
MSG: ae31e94e7197e4e4d0239348025ed6681e513ce1a6e0aa0e5b979373912150ef113e50ef0569c483f7568c4bbc4703c5dacaa80a0de4e738383fa1f10d6d4071a31b99e6485143972316c86522e37c6887a1c307b29b0dd6f9f1b438310af9d8d7346fb41f9b2dd2e80b14c45eb87d4ed48e37a5260b52257b3e99787a13c55392ba930c08e0240e960def0c29b8550745cf149dee53a5d174ec065d2d6677dee1fc42057062c34e27ea5dbcdb861b9f670c6032c7846cec8e87a7c9520e27967b0186ee71b77ed6d029bbdd70949cec4a709329fa37fee002490cc1bc4c2df6f763f9858f33d750c5b505a67e237063c0486f9456d3c620d9ac7c98f1381de0effe41c18259504a150d68a6a28b0a3eea803b855315c9e0
SIG: 6942a7696417efaa591b95e11f02d763bef5279b932a8e2a7cbb9f583695c14ce5cc556bec66799b33cb592da4df2735f9eef2c3ceca4362164b6cc93da4e105
TST: 282
SK: cad9d21a01c7e1d15df2fbd79c516eb8c3401e9fe28467cc7b21679d4e331a3d
PK: a7b55c15d6790b40536fcae5ad2892cd66b18689f499c1fdeea66d4a7df39424
MSG: 70702bf19c919f9836defd7b846fd9992d8b7eb2e106aeb71e60a31b4ea25a41b212dc7de7c91cbd613d58d0595db833cfe7e50584f25569602c7744fa675d156d0f63cd2b7c089c8a00686a437169826a12dc485b38c068a8007142e5163747011a07a415683622ab1e23ce577c732ba14f401fbc3043e0693a9205c19a92298a3d9b08fb7afafae0a9f016bc750ee631a5f5da5db6f9ba2692c74caaaeb4d097e90e3c02d2e3a7fb3aa000040b7c17b74564e646bea16bad611ebc0859a3828804ab4f5cfba417d254515ca3620a3ad683c46ca6267bb49539bb30e369087e67438e9489562750dccba3aa0b1b0a6c267032d20c2adb75e68df1123b5259bfe4eac6cadca6778138a37318adb30e8d669f3bc9692cc74b68
SIG: 31927d01db9f2472f4df6f63c18ebd83c2b1aaf88d580e848854df8cba6395d3da7bd6bb9edc1fce1c7d7e1360558fcddfa93915be076efb8ea2dc5ea7b20d0a
TST: 283
SK: d9be842255e9a16b0a51a8674218cee7cd9a8bdf343508397f4ddb05f3fa0082
PK: 7931bc6dfa3324943aab183d1285515919399ffe0b710677f0915d3a5be51e92
MSG: ac6c55b134663e41f02a6dcb8549eaa1c013f59658d81d812f95b74009513723671945e1324f90f8a3f971369181b587bab45665f788d663ab78140c5a22c1c18d4afedc7448a748afe5bf2387003c1d65ab18482ef98922b470da80ad14c944951ce4aed37390cce79a8e01b24c7dfc1141c0eca2c7f773ed4b11806a34615513486e4ee11af08078a1b4054cf9880298608dd9b3faa1a242a452fe511604b3102c313d14cc27c6f0f8471d94555317eaa264cdf52c69e18f461e47903d21298716b172ee9cb178f08ff2d3c9c162121c2ed21d8734b2f0630d399146cbf76e028a143f2bf7bb50af0f57b9ba8021d264b00c6662f84c86cb6d5952b3d241f7dc3e700c96616cbcfb0d0e753ffd5d21ee320e65e97e25cb8609
SIG: c93845658c9560d2c0e28f282adbd4652bafd3bb2edec17c94878f7b94d3c77afec906ed292a8dfbf5f8e7c118e8f2ca33dda7909d9b695b8ff5a1c0e97ac807
TST: 284
SK: cfc48cc6f65811fe7d7bba85d1cd84858fd6f7edd638f4f552363ee7685f69ca
PK: d29c10694c5e8e3f3447ed78d34dbd74a2b301373ba871b5850c333dff7bf8d0
MSG: 8e7defb9d16d036bd642cf226e32773e605361c5ec4b951255788db0a042c63e5a4367d61524f10e6258991325a39ab6b03612260c3fe3df20b34202d34395bd4ed40bd61373df781a4c8bcfbd15301060f07437732333d8e49736322dee6b22438e787d8856b70c26ec57d6dade9c3c28e27220c5670e393544ed095937298dc3adc73865f777e90037bdef834716476d78f4e6cb4961a4c68a8a836338a9f5da179c4d5e93c3f70dd35eec709653dd8de37996b12056d4eefcb4b6b3c13ba984d832275c4386ebf4a8ff7f078be3d428c1e0d9b162381f06a5b7bb12704003d91f25d1d8fd43626ce70fff59d2927768a76bf7f9ef76ff95489f38edcd1c9e9b8a8b0ef66c32805776d5ae9fbd84a7af4fa6563ec70ac5733a44
SIG: 80c5d51e96d1cac8efd3459825e79c1e9f65af701d1d29e1f95b036707113b77984b7b3350f04077333c957f8fbc7d9b040c362651417b9899027cd33edb1103
TST: 285
SK: 15c9f7c4d84a5a479041952e6a8cac24e76fd2d275c197e6b521929b43ba6c5d
PK: 8633c1829d29091df71fd5c0ef640572e4b64974cd097dbebbcddeba041647c0
MSG: 11730dd45dda80d84d080d92e9bddaeea6878e4a0b3b512d9ea733808e1cef51d49048d6c78116a4bde3c64aceaa52beca86b331ab59e9185c70286a02bb5dd04f5c7f4e9c7e445e77458565f159c783dfd4d976a910e937789d2141d416ed3a7f608d26737a86b20b624e3c36af18d25c7d59b8d7427ec6c4d3d438d7ae0949dd7d748c1ffd6f28e8285d440422d22a3761202e9584f5cdb3504547aa4b685730c982cba213de08020a5e4e46a95fac4b481bea0b630abd030ddd335a20fe2cf7094aef4813956991913c6821f4b5410df4f133fe63e22c08092a0a65972722a27ae42011a807c327b417237c540114eecb9f0e96cda5dcf0246f1d2717f49b9cea9dc6a3da9b396f0270529226f5dcba6499918a6c289fe055fec8
SIG: 1e36bea5a583767ebd80306cab233155b7b42814b43473cf45cdc5039c939744a9694b87220daf4ccd29f25cea405e7c08db2ef17f3f034dbb49cff60283e306
TST: 286
SK: 6d2d0d823f294746b9a5512e14e73c1d855b5e4bca65fe817729810cc5ef840d
PK: 1b6480a6a90dfb472984855cef6f1ab31eb7b3f13c8ac00fa556d20b53e5ae17
MSG: 8772721f72eaf7f73040c068a7c3753bffca7dc2d0930c6525f425e6005c25cd4c0ff5095c9c61a5d8a1967b8c86010c884e509e6b1670f79046e22979ebd354734090d3ada21435c1f8254f7b5222cd5564f064e977640366449f4e5008f870f9c4840565bf4fb5f574c9774ba2568e71a9ccd82ffc59b694f26e7de4ce2e3fd880a0eef387931333ede00dcb065e6d0f79591a2aa956df1948a265cb95750d8a233b15c288a05487c515663f93e740fb1570fbe4bd80c68e8d9297345a8a01cdbd88f4a39bed9c5ef09f144bce5de568bf3733bc53b2039a29cb3e194501adc1c10e86383aac8b0f85c67a6689bbe1470a392476313439ca88d98c021c0eaec25fb2f9a160ce5c786170be0238fb8785dd33bfa9059a6c3702d0de05
SIG: b515f49eb32ad478692df88f07b7802c6e0e5327aa08a6366e4cb1d1e26f9e65fc81abebe2215d649100f27598273a412b624e842d8130403797e57dec975a0a
TST: 287
SK: c0cf799af7395bf27bafa36cab437045e39c903bf807548319ce44f287494fbb
PK: afbf550ca290c905bdd92fc8831ebe3dfeb6daae4f56005253cc50951e50edc2
MSG: dbe65780e968de9e40ffb57cf59a60fd93b3f9a5e7d8ed5180adbc578ca1bc48bd9fb60a1324c9c2c1141479a0dcf0f1d07e84936526df42333c0d773e3fed9e4038de5b95ad905c92cbe040487bf55e10e1edb429a0ecc4e0e8d00a988a9cd53e2eb372f4fc4cd9537b269ba3a23cefbc8df6476e75434b81d93e8891bf417c82e363f3e4abf80a4f73aca84ac7df6337f536d63d939d92cba64be742221116069ef251abba0b00af01718bb580ddbeb79973ef10a68b4d0fa023d6ebd3079d6b32a1aa20a21e9202f27590c3f0c0cc253073c3f822aac459d39f50758b70c00710a3c98438416508522e512adaa0afd503a7ceb04fb94a4a932ce80cd5a7f11bb861263f58e5749d542a110de7c7689dfcb0c51afa9d54a58ff89f3f67
SIG: 5bba01a4c7b25542d06912de70aa1e220423fdf8338a9e693395cb6f0dc1fbfd018e3c77e50aef90a9080f30f1f5792b2431078fe6e3e00464245e17cd8dc107
TST: 288
SK: cdaa50e8527dc7a50fb37e28fa8b9568c37e8567e0b499997b9aed676180c3b0
PK: 7c56e164510268c182b423747904f1d3a5809330f6e1b29266ec46e73be1550f
MSG: 94fcfbaaa303dece7b908f874cc5f095061f1754bb35780db666b63ab8290811bf1c521a7f8f785ea270dfb39d0d6ed95ab71955a11ffaeaa268e081ff3e4f2425b41880a987151e678e89111350942d820c3eec36212426663be175e5286b4ad1cc804e3e3a03b9fa3e82838ebbc2615a645f2ca1468ac4a1cdbe523761e83f4381b0c8550ae5e8c8cd1fda57191436e27cb883bc64be86a9dc6110ef3401d88a7debd1b701d9c257a6826cf01e9e2922e3ae577f2834275fb0ecda80ed8cf1801e0bc5e01e26a77c48bdf46a5c4894d22ab53e741827e24bed5f0750ffad05e53f1d5e61dfd316b191d9797ef713131a8b430abe3fac5f3c4a2ca021878b15adc8c5f542114260e687a9d199d230c4e0d3fc696993b59ccfa3ffa9d8d2fb
SIG: 137bd10a50ef609384fe668768fb871de741ca0f53ff8477d7ebfa90aafd5e2681fdf1b89250463c15db8e17a58825fe9427de089c34de13cd07bba18d4aa40d
TST: 289
SK: 0fdea9bee6288f947e0adbdda4dfb2baa03891af25024a5e138ac77984d00507
PK: 70abd86430d7e8d63209c8b373ec4e4b79e989e6725facefbade3c7574d23cd0
MSG: cf72c1a180a2bc37d8478d9a7a39acf03bf2a50790f7902f81121222d31d3ec916f4f24cef9d7c41dc021b0e8487bb892e47305e54520303e89b30b263dac4a9ba375d46c40fcf400535c959d2b746a7fc970cf65b472e84b5f1d0ebadcfa1aed6fc47facce16a366a3b1d6e516813c1960975f8f2b43042fb4eeaabe63c6f65db45ddb7db888a19a9d7ba6ca479fcd70c5d1e970f12c14f4d24fb7e2f357bd3a94aa1b868ccc0847f2eef21853e253bafbf07c4e6176a1ef077167841ebbe5629337157f39f75c71d21e7e96c51a1b16fa8dc60f0b1279fcda2641fc8591e3c492f15bf83caf1d95b2cd91332f1b4202fe72862ca2ea2ef92c11db831d82f8fc3d41fe29a76c211a758e2f71bd89d2c6610f201429f348d56e10e3b7af53e27
SIG: 80c42dd5df03b285a86ac95ce6669f786a978a813a9d7b8c6a23de76fbd09bdb66c5dd1cc9f1a176cba388d5051764a32fa27f0028ba4898068bd01a3ee17208
TST: 290
SK: 03d5e466f8298ab5438a30976d1322a7215a642dd5fb4c3f8519409a7522f092
PK: 4b3ed4db080e2a452e16912c14504424920a60975604e4f379258d1c8b193d6f
MSG: 1b47b70013cb53e1f8f4971e0f39563ce87edbc2cedd99e5a35585df8b00a852f7b9c97c7e4a5465fc5605ae8c5c36570a99201a7ad6031287ef0c7b2ba6e57b056d0fc8d6ca43bf6cbdab098934b403197b525d22d45e6b29c78f8d6183e41ffe197dae25ba22b06669ae05badd7e1da6932a7d054cbab3f54e5146223ad8671231bc16fe62679bd2817a6b80e653998c4949f81ff53b6173163e11da3e6d3c76d84c713225b4173d6bf06a85b6988a48be4359cb515503ca563f4353f8e7d45e4d94462c89a04a00f1b3b0ca6422d5db029c507d464834a20c78a713661d84edffc496d69282619894437b4487954cbea2aa7261e6a62b6851154a5d25fb6b4f09c59473d385ce03e91ba865eab66c58c0abb0b7a78e4be927e55460ccd70d82
SIG: 6d7e4658f26f337c98e03f13542e2f39440ff7bf8d88f3f6dfa4d64948cd96b79051492fc28f65f2cc0d23a0c4d5e2307bb1c47e11e53b371f091b69f80dbd05
TST: 291
SK: 76cc18a1dafffa100586c06a7b40f79c35fe558c339c2999a5f43875cfade03e
PK: 4b9da8d2f137dc6c857a99a5998dd89dd5f05971a21e8c776670eb47bc1270a5
MSG: 4522b1d82373f7a318221e7e57617503ddf44fd53997522a1d963c85b708d0b245de372ad52ec7f54f6213d271f7c91d5a1d36d134db389df0b081a06bc0c7a4875f724092793172c9115641c6d054f1d992e0fae4df58695f0ea3449d7a4b3a8857e19803fe49b6d52c9ff3746a574a2756956579f9fb809a0edec92c55e95ffefa3d05f165822f464a21999f29691f6744ac5a3ee49017880645e837edebfd2e0f24997f041145a72e2376ada283186ca2b836362977195baee30a3acc81b243f3ee376a2c4764c783667a4b1177e7951d3e3c7be4f1bd7ae8c60fd5fb0fd91f0c1c14d0d2327e8f20d92c0dfcc53870e9d99fdbf9dd9a17e882509ae7baa8653e39edc8ee569000d624cb93a0754a798d1f811f6a0ef5501a17bcf25fd0f91626
SIG: db74751c66e6b1866044dd9ae99f19e6334f179e79d8b8e0c8cd71d22cefb9eab7e3e7a9c2da225f2a9d93a313d1cbf1b7fe2597b8d702bf3017a6a6bc7b7b06
TST: 292
SK: 71ad980d58ad8e7d33306689358936a372d5190b24ec7f9bde749cb81150efda
PK: fd35a75fe5abc20104691a24a4659440b55aeaea902ac3be274af27aa8312869
MSG: e87ae073ff5dcc5485a19940e4e3ff263a0618a9025ad4032dfb36d171ce881f71c18a49210eb45819806142e2f00db3041835bf2c3bccf1dba02b8b5a5bdaf8fea316c0623dd48a564ec166f037d587c8c01684e5e5c0ba9dba4d23b49a0309244e282a51408622edb05704747e0cdeec976893777071098972c113a8ab639c31f1613233ee460eea8a8c10e1e6e152214529878cf1adaeaf78cf19bac71361815bf57955498fab4f0f2b7586c86f9f4c2ddf8972f9b9e0eb636d84bcc14385b2d038be55a963702efe225a50bdd0c4da92a2a6a09100ea04a211d396458dceb4487116837d139eb0f122538ed3986ad0af4da2dffc89f3269ca88538086e691e5beae9581e7c63d8e612da2c47f74dde1d94951eadb0df60c3897d2a3095c506093b
SIG: 81670b1029e481e9ff3c171f05c16861c846ee79cdf2e21e3bf952bcfac97565f2b1dcedf69d2e7eb35caf5662e8bc671fbb96756a63a596264d1b7f4af97e06
TST: 293
SK: 61594e24e75f996b4fb6b3e563f6a4f9915cfa65ddb199b01fed7f8ed7824ecb
PK: 8627d2141579cd2521aa076800ac354b9e3a47d71cedc8547434268225e33005
MSG: bc01b08c7caa236100a012a726477d0ec389dbfadac73d5106424c5d1f3d1cef1695cfd93a7062ec8bf1067047854920162f651357bedf1cd5a92ec29bdb5dff716e8f6025515a9549ba36cdc35ced7c5c0c368e6cd92f2f10ae146a20728c374bba509641ce88cb42fff0cedfd9fd67f310f9d01a3f3690eb21db17bce67ae35c4cd24c209f09f044759d8d5a7d248e2bd966524ba8c0c28974726b43bd05de843433cc400598922974623d9acbfdc761c4c04375a952ce54caffaa96acff6d9dc278742af476e1865cb8c20d13d1c1900863bca231e44c6b0d47cb41d510f7958f48f304d03da033484a3e1f273faf6983375b7d3be03d8a0a002def6365beb2fa8ccf1a94987adcd33d0da1177fc5159b6e56d004301e921dbc12ec0a73f413cf2c48
SIG: 6302b3ff2710be306c92b9aae30d23c3d4beff394e63201e6ad11713345c4fcb5cc8d3dd10adfb82bb11a189ce7ec3e4222727624fc17881c14788d2710e1608
TST: 294
SK: 54e6bbfbf8c06ff2c066318c2ebf03d506547bf43c2d7a5d4df305a3032b7138
PK: 3b71aa1def666d9188f403f82ed30454aba5bc9f470f6eb988da187c92523284
MSG: 0318d7cb4805af9821dd3f914b0e076fea04a7d2db3a59a00affead3325a2be40c1f87f53276a8552604f228b976e288b9be906a7bd25b2ffab8a8af5d0f6e08786fd034e2fe1eb7ee033979860dd1e5327287e9e615f5dc5a960f17026b56842fc8d44cad002edc8501cfb956001502e4ddc81a7700d9c0be88eb4aaa64a6cbc39de82f13c11086de1a4270d3af97284bac1caef1d3edaa1071666bd83b2ede3962d98b9d93497ddfd8e97dab3089950cf30ed11db77ad1437a0af5889d8efc44e612420e3907267df3acff4bd3fb6e8ca5badf8e72f9de39528653058524456a81da5f84982afac34bef5f71e91f8f90938a6f5f1f287716de56a0946d261e87bc775ce189e41a77baede7320a3c608fc971e55d0a773c4d848d428637f11b4e4460390c
SIG: 3df4d09079f830e3f982283681ba37b50f3c73de2c5d22a291358ebb1fb854e510f63f9a48e9fff7fd8311302ea3e969394e6d49c9e3182054942f6a744cee03
TST: 295
SK: 6862061be0de9dfd998118204b2b98db3ce7d7e819dbc10794af0ab2b06e8434
PK: 9c5f7c2265dde1b25e4f27ec71580d52dc89f2c3a712bc1ad5d6d69e711e08d4
MSG: 1740dde8434a0d689925679b0c180300cdbd0cf6a89ad8fde34653316cee4c571a4105c9e9e0284238fef2c38a09157c5db94340571b390adfb69ff4c0dc5053253a679d42cc1f1bf1ff429229ea0a5044c6f79564e0dd287f53f015b83187d9ad27d91039af062c437b1575a0eab6aeb8aa0d27b27665d6dea9041ff9963a3118b3298a8544e3fd69ac6877e3e4052fe4422bf03560b2c57ec531ee8b5ff53c28dbde35bb45c35077636e6f841b59d7eb77bc7791b6093858a3a80a3aa6d778dbf53db9d06119c50b71c791c0495c576d1b59d396873ed871485352c8299a359da5ee9d7f36ed1455f89851a30851bea719685aecd08f25562609dd106630735277e1d6519bb1687de8b8c68b9671452edbb3491da264cdfa0017c512d2769759cb925fb664
SIG: 965edb34e8ab8bc3204a3201d22186372de4242600297cfdb57aa1df074ec50ddf10105e9d4c89a266c34db7772aa94cba946429e68ba62bf9a0ac90f5f05b02
TST: 296
SK: b2250bbcb268d2477c8312b1900fd99982baa29a68974fbf8778a1228dc97550
PK: 44aa8df1181674b05ade980f7eddbaf3bd7422a920287cb2d2db59a063eebf74
MSG: 7ef0ae1336a6fab37f99da5fa7d0dec7409c072623ead84f241d53d0596b461705fb1b3c537d36b89e8960febb4cdc0d427ce2fc1be58dbbce151e35acd8b6ace40a19822914a4bd8c4af632f136418ac49b184d55193ebcc32d0d798709b1a8fe294fba8a1fe72d976b4400d4a393242311b0f8cc994e89475b0038ae5d8914938e8f6e87c6f50b9d656c45d7b14231efed97f3c90668913670bf5be2efd5c270c7cbaf01e8572e9800978dfe2e10a2fc0440b855629bf9cd409ea941cb69226cac771b15ea77c0326848806ff8d2e201e6e26cd5f45430dadcff8f59c321c1c9c6a29b94882935447d3e6c2e8804b1161576bdf0320fe53c307d9cde426077a7677cde3c1bc83e18e60a0c4ee6dccd877c213a8e4cca640ee04929804570ae1f96157c04357a
SIG: f2b8d92ed51ebd1000bf9dd3411a9fa9e7aee54c4c86e24ad0f9ad5c55643a12d680019ca03f216bd4bd32c9ce1cd8a528c3ffaa5d5b1dc91a4be56f0e2c5e06
TST: 297
SK: b809361f55cfe8137fbda880fc62cbe44c216e141893346302b336045de21878
PK: fd23e42ff06644ead347abcc1b3e03b0e88593b61254981dd8ae59454e61b3e0
MSG: 17ace197d083aaf1726f53e5ef81b5a8c09222f260ee5f1f5404ab78d900d489688449b843bad3c498aac6d80b4639b76e6e81c55276a6f9c7cecd70b71aaaf2018ef76c0e30154aae86a5c86d4e8d0e4ec68cc427060bd56514f7238086bbef5bfca1f5671b18041838fd013572443dba48fbdd95ca740b0daa4327164a1e34677249708f77bd793e7caa6638b5dc9fbe6f0dfd4120209097209c93cedfaf21b6bf59ca6e99e6209639444f0e827bbcc0a61c3a237ca22a283213223ab658e712c7556238d3a5fe31722d65f5706ef6d64d73232d3043220f14e5cfd3c2c83a83d68e20274b6f96b29de040cec8475030b6a8a87d29808dd381795c3d22acf5dc193b720d95a752d9f123c209ffba004e48dd06dd8c9e172bc9e087d80bc5216c0b0b6e77031241
SIG: b5b5950d3772d2eef88e1b0f5df5ffae2f2103885e71446d346fbb5daef94967a6b7b6e4be885110065876c665b7812de46ad31ec3bfcbeaee13ed0c1e0b300e
TST: 298
SK: eeef8074c2eb9a1cee2f2d3bb05325546a9fb7cbe44b599461fc5885f5fd9cac
PK: 9b892941a0573b7a1673ef480f081168d9b7496a81f9177dc427ca1f84cbbf7d
MSG: 9ae39feade905affcbedd2e72a6f2429b3d1108e5bc1a9dbaf490a6299bccd94acc413adacc918b14afa85c78bc168cc00740c3da0e08183915f79b7fe3868ce2a7e886b32ad45009805bfb81b8c07b3b1022420c0f009b889d7fc22fd1997ae34198438ca94778575122fcaaf96e6502c33a75a129a2d0dbb073d93820d9c96683db318990be3fef4cafc890afbd9b1504c7439a08a065e7814ee4f9b6f57ee16baed3f0e3aa35dd23d3528a458919ad77048b4e2e6172346be249a50af02bc6c853304c208ae0ba02771262a0d8a465f71fa0635e53eb2ef0a847d56a0bcd7dd3fe077c92bcdca3069a4a682a2859928315ce3eb445c6072a71492ee82e172a20be0b648b756e6c775376f0c7c3df8e64288089c2f81ce9593c6e08bb1cc1b27fcbd392fc7952c55
SIG: 6f7101984fd6892e2144b7d45619830caeb6713bfab4eebbe217c5becd249bd9d752eb76e9fa995e7c71ff7df86bb260cdda173ff5deec6af204b7dde011de09
TST: 299
SK: 61faeb15f857f6557862c8b8c7ef41f80545520996fcc1127b8c2491822201ae
PK: 60a290c0fc425a0874673d94f9bb1400f9dacde9954f9f5b05dd48ab747a3950
MSG: 253b566eccb563bd6e480c69739b8e372519a3437254e0e5029cac86c71638f2df2a6cf9e56db2569934deba90db75547e3671747df64d6f2aaf3c110fa67a7094ccbe4cc5355f0d43235136ee26dbe37f4225d3bbfe245595280585fb548f894e86c516102580291fa7a02859557fb98eb588870828b0990ae9d74f3831da58946bc7a5ce1ba498b4e8be8989a3b50d7e8789f56b8b4fecbc2a33bfa3ef591a0fbcd932fa93e19f3a812ae5e4e3b4b242be7705a5874af73be310b0058266a378f23c1348524715b0ccc18d6634b23636c316ba6a1dd2fd5092c06716a717b54d0eb9fc7f636f85bbf225a2cf035b4b7cfddd75351682c0576c6b3ba5a1c0b25ec594e7709dd09a0079772ff3acc67fb6c1b37bb3742b726e77e80561d9ab73160b73362581da5b9c7f
SIG: 31f90f50b2dc705f1d92f12ca9975d76f1b2826ada3cc185b0ed6c83860777bd8c489b59855a91f64839d49ba467985abb376c47a4908b271b8f77c58d01fd04
TST: 300
SK: e6b9cd4da07cb34f30391cf68f0d87c7cfcf68f810ffa40f9739c95deb037f71
PK: 569ede0f04630b43a04c5a66b6a5636b766c75965984a7477e15491960fdd864
MSG: 69def0523afda696f8448f9c1143abc26533e68695a090df0d9e43d0c0eff43583e6f709d2043c815fbb3f96ba2b0dc3be6fecad5dd38148788e4a0385a9fe7a921fcb8ccee0e4d3aed4bc3d216d84b414f9580b02820c03d92e675e685c4b5851f363bb4df97b417c3fd90022eeafa20dfbe82964f2ff073d255758fbe567c76b2c35e2b09f8a8d7afa32c6f5ad01bc3ebf6e210606db038ecb6820ce1ea4dd529fc1adfbc2a138565ac6d0f4a4109bdd47b8aa6ef4b8bede454680d1dbdb75fe1eb2e548d5de7cb6d792fef3aa0d8480a6030b30f104d7e76b58e9f476ebf2cc832923b50c50c111c3515fc518852323426ca778a596d3195da8585d8c3aa92083313a6e6585b70c98b185b472798a61cde77e62ec272f14b0d9eb4f22f9c7c05817da6fdefe7879a584
SIG: 1e375c94bd809ca0cdd02f89ecec4e437732dd20a0a84b254eae889d8070e682d113b0be22e41e6cdc3be877680e7eeb7f0995e6622dc0b434fb0949dd994b0c
TST: 301
SK: 4d9044f17b5a0977dc5aa9916a924300a244a1ef7f060277ad4978351ea64291
PK: ab9c0692a606b2567c19c30f9faa3b4cfe72fb237077767b76d3b2ae1490a6d4
MSG: 7c8c7189af67327af1c6dd2c30e975f190e3b38d008b4585167e0d450740d46734587f6d208784245cc5cb062a2a277f17ebb2746f9bdf4a8237ca479ab0a430177e19ed7dd3622576b14cdc08282214fe5ee4d76b43c16ac90864c51be8aed45d7b980df7917f290fdf795846465f27fcb7e5730637944f0577c92f32375e995bc0cda9d7196f2c0c1ac8b80d12a0439963ebd2254c347703575816e7964c13d44d629280c312ea265344de38f3b18d9150f8f924afb44b6bfb9eda513d59e65e2ef18666e6c2a21c4018665befe92cae581d3cb14e23e97d830002cb90931ae0210068af394ebe351be5b817f3674bfbf40049030e4fe505d34a1d502a2c50d8e638e926c230676b7edefb6bec77b1c0ce609325287ba5fdd7a9976987bd07fc6a4344956ebf818f08586c
SIG: 6fa48aea4d5b9af65af964cdb709443a11fa84f7d44acddab16e04a6fcefb27ae33c05b36da13c23de517d6e6ac574a03ea630ba4fbb958131129aa7f1354c01
TST: 302
SK: 75ad76bb4c0c229a5adc79e444b13f88a96459862c8cf0ba498d0c996af94a7a
PK: f074dd2b9c1c309105ec951bb5812a91ddb54023b3809ab379c56af0461af617
MSG: 0ca8c1c74128d74e9d0a7bf8964291d074917f2f9920efb911520567642a50a615abcbd00aed4abbfef1a983cce333e1d0df3e6404fb9043c6803914cd5fffbc66a0790c7878a24089a571f895662a1d18be3f01ff97fb3323334b6f5baf96551448e4090d033c464294d09133b151d5b5c6321b50e2241de0ef6f882889ccf4ad3540d5a1e3f7548fb13be71c16516606e79d0449c2a08e5dc23148843c84e97ed24069161c8e75208f33e95b3e10d1d49a2faef9d986ab62809f62ad39c7cc871f375a4f5a6faf104d7e11b890cfb0589902685216ec07cb8e8e9e7a7c43635e23212b69ca3b7ed54f0b97949e3d9a6662f8e4b3ab09cd495294c331c047d86ee785ff658bcd7fcf9c480605ce05e810068d60fc9b26b5f063eb9000d2657a5094284ac80f1375d0b66d6f5f
SIG: 0c4643a8be6dc22f4beb6bcc70c6172ec7608378653cb4e99f3ae795eadf4e982a297609ca7938f5df632b095628cb75062d3d51fc0f3323bfa7b22ec4d47205
TST: 303
SK: adc6e9b2e103b62c24ad4346410e83a1a0bd253e4abf77911850c6d9666e09f9
PK: fce316e33c910821beeddd634bedc58ee57999a76ece384605283b99b543b78b
MSG: 8cccd98ebbf2439ffdfac41687638faa444e1ca4b63d13e898eaa8355492f28813ab813fd01510e112be106b2045d30f63335d248904d521de181abac03e3d2cb2d16c44b3b012a0c51f9901aef9056c724d7a2c6b2acb0a07555940e4c6e21154890611adeb6489f461d3e5ecd1af5a4d2b0adaf41747436eb414757a8fe4775674e3c6e5de4569d6fc6c788e10905eba32c270a393e6f721a765294e2ac99a9b6e534d3df08d1db97d602ac3195cb0b77f5bd4acaf737fadd6991f0688abc74918047574eac28289739a664e0e0e20574a2c25fde49d14539db1cedd4a9204a70acff0a62c8f25cd768ffab15c4db316840a4d1bc92e212670be07c5bdcf537590607dfbbbb4d9f98b89da0b4df7d88f3eca4814d16bfa20c8d2fa94f9f259f2ee2d3a83c9e4171b1a262c4b99
SIG: cb017d6d2682c9854366259aa35f30d491cfaa930998c297dbddc6aded5b3d401cf76d80d8a2764de131718b6e0c481d7196bc72579716b0c0f6ff053e68c50c
TST: 304
SK: 37fc1beda4060b6c57883ddba0776c2bcf5ac28a651326021cca97723730fbb0
PK: 7bd7bf1c99dc82e06f08bb454d8fb288a57927e07ff1b12af15ee2c12fbb6b3d
MSG: 3dfcac0265a024a83cb932674489a163aac314bf3d969f27596e451733b99deba5eeb779210baf95bf545a1ae6b8a915860693ee890f939320e06a844483d18c6a1bcd03c638bb7d1fe2a82eb448a311b1302ea6428f54a39f45a4d560be1557a2b254c45c137f45cc68356836e21bed0b7f73a518ce09db0be393927c339bf2a4b5987539404ce650284de12e3b553b262efe23848332ccfdc35e791a0ab43f139c71ed0fcb2d173bb377ee46b1a9dca9277e77df855f2830251e31e26acd86763c8d7eac22c882fc174f2b5e75ca6ad1ade03f942bb2a13bf541906159158c68363c7480c5b27a99320f8283a2699d4369c071c50dbd90b7792e4772efbc0b195bce84cc4dcfff7072a48968db69f9feddd0f9ced659eb5db7167f35f988cec114887dcbfdf27d02d300b3e1abec
SIG: a01dd65fada27039f168b123419d8abfbda48c572ece24fda06e1a5ec31e084f4ee1cbf9961e88ed51e189fcb7f5f235de1e5b28d08f2bfca190b0f019ecc207
TST: 305
SK: 8d42f4ddd2bbd2b827b0a0d31d8f758ebd13a1b9b3712228948ca610bb8858e5
PK: b7354898794f9db0a8af6eeafcdbdf011d3fbef0212ad938a4a4ad27ab16ebbf
MSG: e3a2bebc0496d8974a8f4061880369314ed9e440c1b77e26fe5071ce694ffd2136db0c4d5e880e6000083a75c90d3cf72b9cf5a2b1a9002c2701a2ff59b0699a8f42d79dd8a5fb71a8125453d91fb80080a3f0a16584282f17ec7dfdc2e5c69c4d9bdf484d55944dae273f211cfb76ad37da45871365439af35eea1fbecd4ca679b59b5e01bacf49c7f4e5efaa406ba1daeb085482af5ded89dc6885ffbe3d14d2931b83897e28ad06e5564e2789baea81bd932aa279fe8e324b9a8ef111c2abe2f137d4bb50d8ab76cebc0bd982a23919751ad4d49e88eb14173d3310289a872317e4a451e88d54320891870f15b2d53324430877a9fb5b49bb929f211c5b89764dd9c3a595a1451e9f85a238540002566e53a99ed1e6ddc9b4853f455edb4cf1980d56bbdc1313a36e76ea9cbb048a
SIG: 70764be39c6dca0f067abe1eca490fda951fd4e9499695266e270b9b05eae706ca8d1ca6a92d7c488ec6ad8ba11457a42a5e31702a9c2bce892dc40535c09f01
TST: 306
SK: b62de5a1acfe4ca2d1f0c132afcbdae66fb29a02f297fbc2407fadbbf2454200
PK: b63b2d0bf355f7b6d0bac07403411c40afbbb2f707503b3fc2cee8a1c7d0a838
MSG: e659e51d7b193c4b8e2b3ed73a9d7557ed2bab6153883ab723592f730a914567142b3fa435db3219f83a542dc7a4bd805af666ea865b853146f8e3a9fe870711f90d12b0693492af2a1edf99a16458f781f1266ec437a5296a822ca9d69ce844b5c59097a2a56f3eb8fd273a636116db774300922d45b744657a692f5e8bfbcb06d2422818aeb51e7cda68acfbeda16e7c79580dcccde24e8e3d601b16e063b43a6d0d1407552f7504f5be19882e4ffe32344f5f473e73a8f6ed37b0d8d9e5e0a0dc9828395bcbd8f3a4e3124869249d058be0e045de0b1e12b1c83ba0aa227c95b82bf742c3eac0152b33e6d19be8b33a35bf705daab10622a90aed022ea6e439ed50a9308437929924ba3ab111ad0caa6feb0a6eb165824ebdb0866571efc07e5222ed8686b14d9270bf76b945d52014
SIG: 5cdb00e98de73eab480be42f8a8a6163809a0d37101b6a5a4eed6a0c92030d09a5562c729080ce6f6594c8fafb1f594772db7a90a9e7da15896e82f70569390d
TST: 307
SK: 9732059d7bf0200f5f30412430336be4ef1e3cae62938ad08729ce3ba714cfd4
PK: 0de8425f5e30b2b8aebb8072009a30cf0411c3c8238f4e4208760c56c33e434f
MSG: 1a13e7ab603b48eb896fe17173fb31950b0dcd5a35ffdbe1371c7a5bfba593317589d9652d88797729180b8d0e515abfe6548f160421e537d5c94aef2b34c7ebb097420003bc0f361b423e7e14630a803c118202540049f68c9cf46fae0368d162e400d77bb4523cf6c753b975c245bc99ed2f413a9d06c2da6ce0cc0987b6406b809e8eb319033d2de9131dee3b1b7b5c95d653ced8fccf998da1768511eca4d3c5f735adab96503b3551803e4922635095ef811be4c08a6cbac917cbe6cd91a4ae5a330ccec0e8e815371217a3de62f2d2d61466219833f33447132f4d43350c58cbaf422475edb128c56d80a495726b1fdbc56551eb72d0f4fec26ba8bff5eed6774b85039a5292834b5d1cc1b09ba0a3954d29323673f5e71276a12ac4c579355bf1ecca48e6a716b9fcecdc565c51b9
SIG: fba1749b641dd4df34664bc43c00468c7d75e84afad72de473fd1e9c87da15ea604fc2549a1a867fa80850e9c2a59cd99053886760a8d9764b84dd672676720d
TST: 308
SK: 9c7f6f379e3857007e2ac6324cbbced57ac9eee4477813f83a81fc8cefa964d5
PK: a54ba396d687634d3eccf41c5782494f5f10a521a1e5d388523d80eeba5b0b2b
MSG: 3f2d3072fe7383e541551ea9abdbaeae6a464ae6b9f0ba786a441b2d08da5bcada3c5424dc6931d6b39523e2de0a0c2e4e6b5b8cda925e5eac938416a2c51bf13d49531d7ec7114b1c82feaf90f3f87591e397d02702f8ec1b30d99f5be7d2203e4fe4db2ea47e7b4589d8ac506248d7347466edbc96ea32bf3a6ea7502dd60c9e84902715ab2c6ca68f5b00e1d909d83aa6ab662d8aea870ecd861fec69f2eec0ae677d2995b0ed688faa8ef78244e0d1195697b07122ceaa11f5a6ea58fbdfa2e2ec2df9d18693ae96d47127556e91f0864982c13419b04a63f208e730d26951882aefe001bca3408bd9862748c6cc876c28cac3bb2eb3395818c2091e0fbd7a0b4468c6b0d00cd008c11c3c3ad01080a1f5a40ae2e4b0c3a071efc8e1d1ba6ace6d4df0ff19829b0c680b3aeb759177ed34
SIG: 65685f9ca5982e15a22ba3c83a0348348482dfae57cea178f0780c057baebe4af632f984540a26019a7fb34253c9ece7ff308ada233ce0686347ab5b21ce570b
TST: 309
SK: a478f35abb73727b6be6ee5e56eec323c9517882fd6919360ebbbf5d5cb8b83a
PK: 7a6e266a54d135dda0009ccda8a94a4712ae5cb14761e8436e97c4b7814d8e8c
MSG: 0173a34050b43748061ff8f5a3d7c43b6360847786e8bb75e536fb47b645b214f221ba24d83d28bc025024663e534f90f6e83a93d8bddeda2cd8808155652a908c437c2db6f3ed4912f57ca5b97928a73be964af59df4439854bb006fc295a87b7b72239c7fadfec40715509d98579daadfb8d524b4cec6620705efd4104c297144aea722974e12c5ecee5391ef2d93ac2b124e4ac496147c8b70363585d7078ccc53e2ae593350bc25548a0542526ab00afe477a0f4b27397c72bc74a8a8ab156e62b8bb47c3fbb4b34913e459687476bf33142c614702107ffe2cc01e25fa30275e1e2e63cea9168e4a47c02de097d4d853b27675c5bb330b94a974ead85e2bdee8ee17cbb5653346658df2f91f6bd739491dd71988b3a976a3e2e7a9d137410f4acba9feb5f11798c9a43b6adce14365a7c6d
SIG: 9d16fd40b9f8dd9b4a1a8c6d703b9fccbb940b1e0ae77a5970374af0cf726f4479fd30d7dff5cf53494d9a296ab6b9e46ea6c136b4db2c71c21b97c1c8254d0a
TST: 310
SK: ffe825148c0959b3a68de86ad8e8af7fa5e078f363dc124213c90020da0c9089
PK: 139152a0bd22962dd919ae3e0b1620e03c033c2ad0a3979ec6bcd1705e23d598
MSG: f125780d0cd088530f0c87b70bd42ebab56adb5ad4345f929ae5deae07fb55322153a8f023d38843bf5d6a93fe993eee71bc2ee563b25a50918f03efdb5dbf7269add69ded3e66953895620d9b6cf46ba2348f8d66d7f092235e378c1e3edfebeb78084bc8dea013f9933aae14a041948276d01f1cb5834b0e590e13d931d19292bb1d8041ff2fe2e1171a2e0b9a059821d0924dde7f3b1bb59813f5e3c63520aafb8801ba62c7097d4d8cf437a568a7f0087c6ea0fce6e568c4883f1cd12c749d06a6feb278f1086a8b04769921f78a9959062ab06f98ee80c2c7854ffa760f86a89ee1a51266053d195e61bb1dbd18dd89ff394e408ace0f641a395d56118ea72b7d8adf78b1655ecece7e8250e8a3a91cb8fca0d9ce0baf8980a387c5ed4318663280e5b4531f3187c47eaea7c329728ddd0e40
SIG: fe4e89ee31786c0a3d3de3649bb93f0b8aef1caf5a832ec5e4067810705adddf539b8f4e05ad08cf3479e45b42c96528f6d59a4625703ddbf15b63093965d80d
TST: 311
SK: 49aff421a7cd12722aa84c48c1fb1c5f8d9e277d0a99ecbc9348c3aaa74be422
PK: 88d2c26266f493bc67578ca0b1f51160cf0fdb6a09a906db9faa686f11f8208d
MSG: 70a1ac144b75fda75586a79c36fd39cce5f5cae2e6375852d3b62a9630336a293ea6d2ac6e5b57da21ef364a595bb0750f5bf4d2b320676423870e4b8e0869601f16680619048c4ede276da69f205a70176e25ea04bd089763e709ba343fc8831e52044eabf9441e6997f8ba1aeb9ef0f491170667a7f5fc9627cbd0551b76be27283a4b0c5f667846688226a115ee8020df08042b19b59fe551316a6cb6916860b9ecd74154b4051038a17352372ec14d3c957d2ef50ff786189a8aeb9c08f45eeb5eb8b040339974aa9798c425d7becb228c447a6d0b3cef271893e0f7076e223a7e87c6a3d270a033bc97a4565edce0aa91ffc3f7801775a6f29b230245bd71fa034353de372395d1bfcbdebba081330f7c076be99c2cf4867f15b78d52f46fc7391c9cb95e5d64643baffe72a8e3a650667fbb3e
SIG: 749181284df05dbe5974b91782a1a76ea08642cb0f0c98db586c575c210cdc8b651bd34b757ae38e4b6be9465235bd0eca430e26c3eede561c6e824dfa200e0a
TST: 312
SK: 703a6e2b62d0090c61d8659b6a963e03c9d62c1b38f7d70e5f9ff05590cd0360
PK: 370c21de6ef2fab534ada999869c90bc9b92ccbf249b79d39d95441d1ede210a
MSG: d42a1756e84df4b4e9773f86f7674a2cd78e71e40aa8f644e6702dfbc2c2c5ca90fc242e9cb0099cc8f2c2d3136baafc0ff695482fdacdef9f565610b6e1900722f435c6385b35e9f6c436ca037e03f64e2233dffa58db3b91cc1daa0bb0c54c8a43e469d2cff7fa2bf8f5d1d877931089c82ed89aba42f2ee2b86e445cfd09f4cd78b35191bf467e784eef75dc987e046d37d4d4e8e9bbe14af80d03a1f40898384b9d3279fac9c57fd9c7eecbe19a5acc15033b84e07fd0e409bdbd5a57f65641183a6c0a8ec426d1f1d223166ff0a1900b2e92b7d85835d019d17775e5093ccd126f90f63cb7d15cbeb531324219cd64ded6714b21a65371af07210dfdf0e4e58ddc7d59f4cfa65c421d814ee2c9bf6dbf64873d579b09ee5dcedd733063e039ac9a5f9ca4c2525a4cc8e984da7185e2d64fad81c8a
SIG: e5fd64da028800c6ceed068a5e596f1621c70a8cb138b31b32647eb4b07bd2ecc5942c18844f367033f67398e314ba2c7ccf299c069787777025d845f2aad60e
TST: 313
SK: 76849c188e3edd0ff5f8fb874dc0456645518445e41a7d6833e616c3c48c9868
PK: d670e2ea07db60c22ab79a93ebf49d22a6245ee3af07b3be584eda694c37729e
MSG: 1eccb0bc8eca3ab5bee68c5f8caa34536766c705f50827db7ac375d4fe30b58ffb7e2fe490cc71a8ff86c006d6174d05793ab8a55dd51b06de417bc0ac452cdc7cfb0bb00362b6765d20db23eb1848027064a1d9091d3b10ed776f28b76768bdfc08f0bc511f76faeba76cfc4cb5c83dc9ebe8a8d79edca923eccd524009cafedc90e3ad87d1392e1fccf4e60ccab95dc0ab54bf44245a007a96d46634b1b2965b829c3d7daa765972b54a7b365b6f34d77d7176acd8d894f6b417091b6c00edb7a4e81379988bfcecb692e9c3c4310a7e240e5c1063cde113f22a684a50a112ff47d3898812efb92637072b86163ad89316d221195acbfad0a03a1fbc2d967fe83f84c8459fccd490b9c5b3e55d27e9484e943c417f2128d73701da28f49fd3683f33a39cdee234bd305b9491e2f3eb621be3dd1dbbb31b
SIG: 7141399d51daa6eb4519bf3f01b233920fa908fefa612f0cd7d5af8a9a3c44190e3f6384a8d14d37c97030ef5018cf8aee8aeb1569a73d84862a59b7df72fe09
TST: 314
SK: 83ae48ad70da0bb3cdf87481ee2c0c8571c2ca986712f8bc2329e9a3e33383c5
PK: b785309000df95f5a04f7d89c4113301057adaeeb29bcd28d99371b537bba2f6
MSG: b7521d3f71c679fa7037fe7488a641f6b97c49454acc8e36b903d8f9ebb54d89cb56efd19e04ba6a7c8f48a7d3ec9decd3f1cd0faf6e978118e6adce9c6c6be63c6a6a1ae21651828479a46bc9a0f7943040f940a0d470c8e577c5d575cb53c1bf3ab1feb050dcb6fef0ba4447f299fdb9f27ecb0714ecfefd74bad7b122a462c24a209848a03389074578c5bdc36396d809b0f14018da64917e6bf87ef405c8f3e333ff9c3baf6339667620794bb4743f0514b5de7d7fdd947a7e3501ee88efad159e33a1072fbb99c7c71e9d13a502d5a07c4f817eeb7f0c5319aa41a96d5ff4f15a73c29b571fe211090e172c8db518624612a5c371a9d7cef6de35ebef96e88e1a78af3bd5dd35251ab54d73718f3e70d2d59021531dc73184f0fc69c2e92965844ec27c1c02af5e9a3469de355db2256e0ec2a4eba30a
SIG: 43332351d3fb7b45fcf37c607d442ea80dbda2cb69c2884f424e65ea3a331ed8472d4368405cb736b2d6685ad782e239fe833ed789a2923185166f608342ee05
TST: 315
SK: 39e56a65623a0aebade0da12ce1df378bc924073f73a549effaebc465d1a78e2
PK: 83da8ad50bad09eb3e94c725df3cc3a119736adc859ca1a10503f48ff2fec596
MSG: a96dc2ea3fa1351492a4619d9194681f8ec400a97158244482653838ccb7e156a82d564368f83a6ee1be46bc34b817200e8464c3d12b5ef2c50b19565b881c4c3d4563fb947eb47c3ee9c1ee7853269874455bfacba305f307d1ac5309eeae5c07fa5c4d428edbc8b9528c4415243a9ef580aff8fcfb12000a71fceee89de97f90279529bcc822ed3cb34c82ba5fec15f4945663636d67b5feceacc31d25f98aea07f7800d5a1034251cb91dd0963ec2c1a54773a4d96c18357f8d101de58e932f8c6cdde8e3cfcef5a7443fdba7b78320403c0196844724a612183e34bdd808ce7b958861ca37115730eaede1fd0baabe976efefd0365fdf926776c536f47ff80de5c18291bb7e9f1b913ffd1d94468b789752fae6ca897c0cca53ef1e731d00c8bdbe8929ea6b1dce1f31a20688d37b0f3a2b4153b306bdba1
SIG: 398e8260011f57d8ac8c58d5457bc652c7414aaf6fb2f426b7899056605c0afc28392423b2b571f5e6c3c7f6d60245e53ebd03bdc5ad3c1ad8738cb32214d00f
TST: 316
SK: 4b9921852f409a323ae38175e8d76a211fc4d9c654178eea3baa7a767a6fda06
PK: 4c723e436b6bd97f44af52503b21cc50d5f6ad6cfc8288345dde8054e995582e
MSG: 3f33d8fb83e68741090a37bedd745cf141aaaed8c92ffa742a52561777885805ace14246ab98a8cb598c9ce3de9b29bae5fa04b1cf828de11aff80a7ef8a3a38aede4f3c3563a25d049badcad5ed7e47fdbba6e111307eebe9ef4906bc989728b76e84afe808e6653b271e21104aa665f1898dd2aab23090e22b4e344a2616fbd8ee4ad8ed8108395eba817fbd14fec5c17dcf56b8220856b2b833e091407d5089b35ddf34b86ff7dc9fde52b21ef12176ef3370b7f3a0a8cb1b058a51aefff3d279d80f51a68bfb592587b45c5c63a7e4d625b887de486a118316c3b6a238575f92ac5b1c94c3f5dbbd96686000d6d39cccd558d420e4d447a8cbc4bc7b8c6a03af0f0034fb3518d93800f0f713e4b13732e16ada51801d7e559cf839d1058f64955698311399345416850dddcc5601a684fd09e6afd3944f5e19
SIG: cbf1f1642df950eb71fd09590d34c265922c58bd8026bba3fc0e594a6bb1f2b90da3dc1d5f6b6d5b405a896d1dbb71b8685c4dfc444acaffe65ab8331789f507
TST: 317
SK: 1bff652a2c8309a393ac11da3aa97fb078bb284ed5e1b8ccc983652ef8556cd0
PK: aaabdc091fc3682354201744e9b73fd2a6cfb281914bf2c70ec3dc1dec7216b0
MSG: 48d02698a97bdcb3ef078dcfcf5750005f1702d300e7e89bc436e381113401f852b8b4acff60ffbd4ab46d202168d98b8735e79cb350e35b070ff6bdcafd954b551969b6b1a70c9131ebd40d96140291d8d2b091540a8b18d8e5465915c25dbc6b5c9a687942533c372c8b4e95a953677169b950edd3464375cd43132ff9bd541ee22bd418ce23195f65d8b289f633ec8d71e1a801b06c3c827f627e723d2199100ce73e8e4a4440e778317a474910793b47b10ffb55db7f281c7d7a033bd80048b82673b87cf95e99422ba628688f3c971890ca15d12f572fa1977a17307069da304ead3026eb01042668890d17008cd1e92c46cbe9c857e7193de3aba3911e4f86fe0a1698ab7cdb9251a8424b2848b96ad81ea239d365fdea92ea5c0473d0a6bb1e371356bdfad2d0350336d3e1947c936fd0c25195445011731b
SIG: 93c9c33493fc64172d51e16a0a1cd729a0d99e3cb864e89a42987f39dd8cd26545fdfe37581911e803677da4c55b0a683ddf62b728f8f30685ae58f628ebe609
TST: 318
SK: 002fdd1f7641793ab064bb7aa848f762e7ec6e332ffc26eeacda141ae33b1783
PK: 77d1d8ebacd13f4e2f8a40e28c4a63bc9ce3bfb69716334bcb28a33eb134086c
MSG: 5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b
SIG: 0df3aa0d0999ad3dc580378f52d152700d5b3b057f56a66f92112e441e1cb9123c66f18712c87efe22d2573777296241216904d7cdd7d5ea433928bd2872fa0c
TST: 319
SK: 25b0f0bb3dcb422a6f3c6c220eaadb11dbfe489c2d455b276cefe8cba057f9f3
PK: fe03c9c4394adc74b13f47654bead8bc855958b4194fdab2097ac1b157933c05
MSG: 54d99f969efa8870fc20fa9a962bb372619c324439728af3139c2a07e8c1b29c1e4eedc2d40ba722f63ce37670362af6f5202add668c4fb4d62fa8bacbc7d07ff3bd38c15a01064259cc34134861632967460541a99b8d5182bf59347b5a59879aa3b091a1f3e04135bd6301be5226d4895e5e9c2b15e48e5ecdf44129e6122853a606fc118466fa720b5ab165635c3bde04d74289274fa03547accbde780e1fa0bf2c56f8436a53e73878a424a29aa9de385dba419ae6a5d12e004276152b58d325b302400a55333c38cde4908ae1d0121cbeca950809c543314277c1485e68d9f9c0a962d1b1e0dda1d4a52b56f8308a80b92acc9f4ebc3ed45d91a129da8675621af676703def3b84113183b2e3a8c56157f243f13980f3d1756fea7668c91503d35c839a2120c79ec954fb546d7b542f987289534ffdef62d47fd5ec
SIG: da50d5242bf51c3951780cafd926d67bdf5640d5d3bb08433831d56e48e2592a1c375968bb4d2fbea56145abf2d82991363b1565fa1effe214011a686e39950e
TST: 320
SK: bf5ba5d6a49dd5ef7b4d5d7d3e4ecc505c01f6ccee4c54b5ef7b40af6a454140
PK: 1be034f813017b900d8990af45fad5b5214b573bd303ef7a75ef4b8c5c5b9842
MSG: 16152c2e037b1c0d3219ced8e0674aee6b57834b55106c5344625322da638ecea2fc9a424a05ee9512d48fcf75dd8bd4691b3c10c28ec98ee1afa5b863d1c36795ed18105db3a9aabd9d2b4c1747adbaf1a56ffcc0c533c1c0faef331cdb79d961fa39f880a1b8b1164741822efb15a7259a465bef212855751fab66a897bfa211abe0ea2f2e1cd8a11d80e142cde1263eec267a3138ae1fcf4099db0ab53d64f336f4bcd7a363f6db112c0a2453051a0006f813aaf4ae948a2090619374fa58052409c28ef76225687df3cb2d1b0bfb43b09f47f1232f790e6d8dea759e57942099f4c4bd3390f28afc2098244961465c643fc8b29766af2bcbc5440b86e83608cfc937be98bb4827fd5e6b689adc2e26513db531076a6564396255a09975b7034dac06461b255642e3a7ed75fa9fc265011f5f6250382a84ac268d63ba64
SIG: 279cace6fdaf3945e3837df474b28646143747632bede93e7a66f5ca291d2c24978512ca0cb8827c8c322685bd605503a5ec94dbae61bbdcae1e49650602bc07
TST: 321
SK: 65de297b70cbe80980500af0561a24db50001000125f4490366d8300d3128592
PK: ba8e2ad929bdcea538741042b57f2067d3153707a453770db9f3c4ca75504d24
MSG: 131d8f4c2c94b153565b86592e770c987a443461b39aa2408b29e213ab057affc598b583739d6603a83fef0afc514721db0e76f9bd1b72b98c565cc8881af5747c0ba6f58c53dd2377da6c0d3aa805620cc4e75d52aabcba1f9b2849e08bd1b6b92e6f06615b814519606a02dc65a8609f5b29e9c2af5a894f7116ef28cfd1e7b76b64061732f7a5a3f8aa4c2e569e627a3f9749aa597be49d6b94436c352dd5fa7b83c92d2610faa32095ca302152d91a3c9776750e758ee8e9e402c6f5385eaa5df23850e54beb1be437a416c7115ed6aa6de13b55482532787e0bee34b83f3084406765635497c931b62a0518f1fbc2b891dc7262c7c6b67eda594fa530d74c9329bad5be94c287fbcde53aa80272b83322613d9368e5904076fdbcc88b2c0e59c10b02c448e00d1b3e7a9c9640feffb9523a8a60e1d83f04a4b8df69153b
SIG: 7a9b736b01cc92a3349f1a3c32dbd91959825394ff443c567405e899c8185ce8fad9500e1fce89d95a6253c00477435acf04bff993de1b00495def0834ee1f07
TST: 322
SK: 0826e7333324e7ec8c764292f6015d4670e9b8d7c4a89e8d909e8ef435d18d15
PK: ffb2348ca8a018058be71d1512f376f91e8b0d552581254e107602217395e662
MSG: 7f9e3e2f03c9df3d21b990f5a4af8295734afe783accc34fb1e9b8e95a0fd837af7e05c13cda0de8fadac9205265a0792b52563bdc2fee766348befcc56b88bbb95f154414fb186ec436aa62ea6fcabb11c017a9d2d15f67e595980e04c9313bc94fbc8c1134c2f40332bc7e311ac1ce11b505f8572ada7fbe196fba822d9a914492fa7185e9f3bea4687200a524c673a1cdf87eb3a140dcdb6a8875613488a2b00adf7175341c1c257635fa1a53a3e21d60c228399eea0991f112c60f653d7148e2c5ceb98f940831f070db1084d79156cc82c46bc9b8e884f3fa81be2da4cdda46bcaa24cc461f76ee647bb0f0f8c15ac5daa795b945e6f85bb310362e48d8095c782c61c52b481b4b002ad06ea74b8d306eff71abf21db710a8913cbe48332be0a0b3f31e0c7a6eba85ce33f357c7aeccd30bfb1a6574408b66fe404d31c3c5
SIG: 4bac7fabec8724d81ab09ae130874d70b5213492104372f601ae5abb10532799373c4dad215876441f474e2c006be37c3c8f5f6f017d0870414fd276a8f42808
TST: 323
SK: 00ad6227977b5f38ccda994d928bba9086d2daeb013f8690db986648b90c1d45
PK: 91a4ea005752b92cbebf99a8a5cbecd240ae3f016c44ad141b2e57ddc773dc8e
MSG: cb5bc5b98b2efce43543e91df041e0dbb53ed8f67bf0f197c52b2211e7a45e2e1ec818c1a80e10abf6a43535f5b79d974d8ae28a2295c0a6521763b607d5103c6aef3b2786bd5afd7563695660684337bc3090739fb1cd53a9d644139b6d4caec75bda7f2521fbfe676ab45b98cb317aa7ca79fc54a3d7c578466a6aa64e434e923465a7f211aa0c61681bb8486e90206a25250d3fdae6fb03299721e99e2a914910d91760089b5d281e131e6c836bc2de08f7e02c48d323c647e9536c00ec1039201c0362618c7d47aa8e7b9715ffc439987ae1d31154a6198c5aa11c128f4082f556c99baf103ecadc3b2f3b2ec5b469623bc03a53caf3814b16300aedbda538d676d1f607102639db2a62c446707ce6469bd873a0468225be88b0aef5d4020459b94b32fe2b0133e92e7ba54dd2a5397ed85f966ab39ed0730cca8e7dacb8a336
SIG: dc501db79fd782bc88cae792557d5d273f9ba560c7d90037fe84ac879d684f612a77452c4443e95c07b8be192c35769b17bbdfca42280de796d92119d833670d
TST: 324
SK: 1521c6dbd6f724de73eaf7b56264f01035c04e01c1f3eb3cbe83efd26c439ada
PK: 2f61a26ffb68ba4f6e141529dc2617e8531c7151404808093b4fa7fedaea255d
MSG: 3e3c7c490788e4b1d42f5cbcae3a9930bf617ebdff447f7be2ac2ba7cd5bcfc015760963e6fe5b956fb7cdb35bd5a17f5429ca664f437f08753a741c2bc8692b71a9115c582a25b2f74d329854d60b7817c079b3523aaff8793c2f72fff8cd10592c54e738df1d6452fb72da131c6731ea5c953c62ea177ac1f4735e5154477387109afae15f3ed6eeb08606e28c81d4386f03b9376924b6ef8d221ee29547f82a7ede48e1dc17723e3d42171eeaf96ac84bedc2a01dd86f4d085734fd69f91b5263e439083ff0318536adff4147308e3aafd1b58bb74f6fb0214a46fdcd3524f18df5a719ce57319e791b4ea606b499bfa57a60e707f94e18f1fed22f91bc79e6364a843f9cbf93825c465e9cae9072bc9d3ec4471f21ab2f7e99a633f587aac3db78ae9666a89a18008dd61d60218554411a65740ffd1ae3adc06595e3b7876407b6
SIG: a817ed23ec398a128601c1832dc6af7643bf3a5f517bcc579450fdb4759028f4966164125f6ebd0d6bf86ff298a39c766d0c21fdb0cbfdf81cd0eb1f03cd8a08
TST: 325
SK: 17e5f0a8f34751babc5c723ecf339306992f39ea065ac140fcbc397d2dd32c4b
PK: 4f1e23cc0f2f69c88ef9162ab5f8c59fb3b8ab2096b77e782c63c07c8c4f2b60
MSG: c0fad790024019bd6fc08a7a92f5f2ac35cf6432e2eaa53d482f6e1204935336cb3ae65a63c24d0ec6539a10ee18760f2f520537774cdec6e96b55536011daa8f8bcb9cdaf6df5b34648448ac7d7cb7c6bd80d67fbf330f8765297766046a925ab52411d1604c3ed6a85173040125658a32cf4c854ef2813df2be6f3830e5eee5a6163a83ca8849f612991a31e9f88028e50bf8535e11755fad029d94cf25959f6695d09c1ba4315d40f7cf51b3f8166d02faba7511ecd8b1dded5f10cd6843455cff707ed225396c61d0820d20ada70d0c3619ff679422061c9f7c76e97d5a37af61fd62212d2dafc647ebbb979e61d9070ec03609a07f5fc57d119ae64b7a6ef92a5afae660a30ed48d702cc3128c633b4f19060a0578101729ee979f790f45bdbb5fe1a8a62f01a61a31d61af07030450fa0417323e9407bc76e73130e7c69d62e6a7
SIG: efe2cb63fe7b4fc98946dc82fb6998e741ed9ce6b9c1a93bb45bc0a7d8396d7405282b43fe363ba5b23589f8e1fae130e157ce888cd72d053d0cc19d257a4300
TST: 326
SK: 0cd7aa7d605e44d5ffb97966b2cb93c189e4c5a85db87fad7ab8d62463c59b59
PK: 4889855fe4116b4913927f47f2273bf559c3b394a983631a25ae597033185e46
MSG: 28a55dda6cd0844b6577c9d6da073a4dc35cbc98ac158ab54cf88fd20cc87e83c4bba2d74d82ce0f4854ec4db513de400465aaa5eee790bc84f16337072d3a91cde40d6e0df1ba0cc0645f5d5cbbb642381d7b9e211d25267a8acf77d1edb69c3a630f5b133d24f046a81bf22ff03b31d8447e12c3f7b77114a70cbd20bbd08b0b3827a6bbcf90409e344447a7fbc59bdd97d729071f8d71dcc33e6ef2cbab1d411edf13734db1dd9703276f5eb2d6aa2cb8952dd6712bfae809ce08c3aa502b8135713fac0a9c25b1d45b6a5831e02421bba65b81a596efa24b0576bd1dc7fdfb49be762875e81bd540722bc06140b9aa2ef7b84a801e41ded68d4546ac4873d9e7ced649b64fadaf0b5c4b6eb8d036315233f4326ca01e03393050cd027c24f67303fb846bd2c6b3dba06bed0d59a36289d24bd648f7db0b3a81346612593e3ddd18c557
SIG: bf9115fd3d02706e398d4bf3b02a82674ff3041508fd39d29f867e501634b9261f516a794f98738d7c7013a3f2f858ffdd08047fb6bf3dddfb4b4f4cbeef3003
TST: 327
SK: 33371d9e892f9875052ac8e325ba505e7477c1ace24ba7822643d43d0acef3de
PK: 35929bded27c249c87d8b8d82f59260a575327b546c3a167c69f5992d5b8e006
MSG: 27a32efba28204be59b7ff5fe488ca158a91d5986091ecc4458b49e090dd37cbfede7c0f46186fabcbdff78d2844155808efffd873ed9c9261526e04e4f7050b8d7bd267a0fe3d5a449378d54a4febbd2f26824338e2aaaf35a32ff0f62504bda5c2e44abc63159f336cf25e6bb40ddb7d8825dff18fd51fc01951eaedcd33707007e1203ca58b4f7d242f8166a907e099932c001bfb1ec9a61e0ef2da4e8446af208201315d69681710d425d2400c387d7b9df321a4aec602b9c656c3e2310bff8756d18b802134b15604f4edc111149a9879e31241dd34f702f4c349617b13529769a772f5e52a89c098e0dca5920667893a250061b17991626eb9319298685be46b6a8b68422444fa5a36bcf3a687e2eccb9322c87dc80165da898930850b98fc863cada1aa99c6d61c451b9ccf4874c7f0e75b0a0c602f044812c71765adaf02025395b0
SIG: 985ca446ddc007827cc8f2852cbd8115ef8c5975e9d7ce96d74dfed859aa14a4c15254006bea5e08359efe2625d715e0897ee5a16f151203be5010418637de05
TST: 328
SK: beedb8073df58f8c1bffbdbd77ec7decb2c82a9babecefc0331507bdc2c2a7e7
PK: b27e908b805e296fc30d2e474b060cd50c0f6f520b3671712183bd89d4e733e9
MSG: 35ca57f0f915e5209d54ea4b871ffb585354df1b4a4a1796fbe4d6227d3e1aba5171ed0391a79e83e24d82fdafd15c17b28bf6c94d618c74d65264e58faaacd2902872fdd0efa22e8d2d7ce8e3b8197f0c3615b0a385235fa9fd8e4564ee6e6b1650b4cfb94d872c805c32d4f3a18f966461d3adbb605fa525884f8eb197627396ba4d995d78ac02948a0eaabb58519b9a8e2e7985cd1de2c71d8918d96a0168660ce17cddf364e3ec0d4bd90f2104751a1927ee1d23f3e7a69840ed040b00e5f6e4866ec58813149cc382aebf6162608c79574d553f47230e924a0ef1ebf55d8e1a52abb62a2d7ac86027c7c03cc83fa1949da29e2f3037ab986fd2fffe650e3149babae5a50b1ee9696f3babec72e29697c82422814d272085500fd837fe3c7a973ef4c169af12dd7f02700620bb045bdbf84623f326350570b3cadbc9aea4200b28287e17ab
SIG: 8c890cccadc7760e1e82e43c44b3dc0b685a48b479ae13cc0a6b0557d0fb1cbabba63d2a96843412ea8d36c50acbf52b92cfb2dce49dc48af6ddcf8ee47a8608
TST: 329
SK: 9184ef618816832592bc8eb35f4ffd4ff98dfbf7776c90f2aad212ce7e03351e
PK: 687b7726010d9bde2c90e573cd2a2a702ff28c4a2af70afc7315c94d575601e5
MSG: 729eb7e54a9d00c58617af18c345b8dc6e5b4e0f57de2f3c02e54a2ec8f1425ec2e240775b5ab0c10f84ac8bafda4584f7e21c655faecd8030a98906bd68398f26b5d58d92b6cf045e9bd9743c74c9a342ec61ce57f37b981eac4d8bf034608866e985bb68686a68b4a2af88b992a2a6d2dc8ce88bfb0a36cf28bbab7024abfa2bea53313b66c906f4f7cf66970f540095bd0104aa4924dd82e15413c22679f847e48cd0c7ec1f677e005fec0177fbd5c559fc39add613991fbaeae4d24d39d309ef74647f8192cc4c62d0642028c76a1b951f6bc9639deb91ecc08be6043f2109705a42c7eae712649d91d96ccbbfb63d8d0dd6dd112160f61361ecdc6793929ca9aef9ab56944a6fa4a7df1e279eaf58ce8323a9cf62c94279fff7440fbc936baa61489c999330badcb9fc0e184bc5093f330cbb242f71fb378738fea10511dd438364d7f76bcc
SIG: b3c24e75132c563475422d5ea412b5c1e8e6e5ea1c08ead1393c412da134c9a1638284ea7e2ca032fe3d3e32a9066a8c8839903f6ef46e966bb5e492d8c2aa00
TST: 330
SK: 354e13152ee1fe748a1252204c6527bdc1b1eb2eb53678150e6359924708d812
PK: d45ff6c5fb83e7bb9669aa8960deb7dbc665c988439b6c9ef672c6811dc8bcf6
MSG: 8e5fccf66b1ba6169cb685733d9d0e0190361c90bcab95c163285a97fe356d2bdcde3c9380268805a384d063da09ccd9969cc3ff7431e60a8e9f869cd62faa0e356151b280bc526e577c2c538c9a724dc48bf88b70321d7e1eeedb3c4af706748c942e67bdabdb41bec2977b1523069e31e29b76300288f88a51b384b80cc2526f1679340ddec3881f5cd28b0378d9cd0a812b68dd3f68f7a23e1b54bee7466ac765cf38df04d67441dfa498c4bffc52045fa6d2dbcdbfa33dfaa77644ffccef0decdb6790c70a0d734ec287cc338cb5a909c0055189301169c4f7702c05c0911a27b16ef9ed934fa6a0ca7b13e413523422535647968030edc40cd73e7d6b345b7581f438316d68e3cd292b846d3f4f7c4862bc7e6b3fb89a27f6f60cd7db2e34ec9aae1013fe37acff8ad888cb9a593ef5e621eae5186c58b31dcfde22870e336d33f440f6b8d49a
SIG: de2b46e65f3decef34332e500f2e11306fbdcf1be85a1c1ee68ba3045dcec2c7be608d22927da1f44c0e2083ae622cf3c29d893887994efcfa2ca594f5051f03
TST: 331
SK: 7ff62d4b3c4d99d342d4bb401d726b21e99f4ef592149fc311b68761f5567ff6
PK: 7fdfdb9eca29d3f01d9486d7e112ce03aa37b91326a4283b9c03999c5eda099a
MSG: 99c44c796572a4823fc6c3807730839173774c05dbfc1492ed0d00509a95a1de37274b3135ed0456a1718e576597dc13f2a2ab37a45c06cbb4a2d22afad4d5f3d90ab3d8da4dcdaa06d44f2219088401c5dceee26055c4782f78d7d63a380608e1bef89eeef338c2f0897da106fafce2fb2ebc5db669c7c172c9cfe77d3109d239fe5d005c8ee751511b5a88317c729b0d8b70b52f6bd3cda2fe865c77f36e4f1b635f336e036bd718bec90ee78a802811510c4058c1ba364017253aa842922e1dd7d7a0f0fc9c69e43fc4eaeffaaf1ae5fa5d2d73b43079617baba030923fe5b13d2c1c4fe6fac3f2db74e2020a734b6121a0302fce820ba0580ce6135348fdf0632e0008df03ee112168f5cfa0037a26a1f69b1f1317edf2a3ab367455a77e00691215d7aa3133c2159d3da2b134cf04f0defbf07a6064011e64dd14d4f8f064356655428804c2771a
SIG: 058f79927fbf6178724815c7b11c63baaa90bcc15d7272be082f8a9141861c816433055f6cf6491424853f9ec78bb91ace913a93411b4e5ed58bc4ba5715c60a
TST: 332
SK: 6cabadd03f8a2e6ebab96a74f80e18164e4d1b6baa678f5a82e25604af989aaf
PK: 2a4a3179564194e00100c18bc35351d8b135bbae5b32b28fce1d7b6766ca4b32
MSG: 279f78cf3b9ccfc6e1b01e1a82f50ed172e9a8e1e702bb15661dd7dc3a456ff7a7a7fdfb081db3867079630c7f70fd753292ec60ecbf50632e9aa45b996505c66e6dc3c6ae892e21b6a8705e4bbae8f16a3378554b31fdb0139dcd15c96a8a7e4b88756a86d18db5dc74fd7691197dd88e2c7d5df52b049344cdc477c9cd7e89eda99ccfb1d00814d0152b9654df3279372ca5f18b1c946f2894a76b079ddb1c3cd61fbb969aeec9193a6b88fb7d136c07f9821e5c1074b4e93bcaf6fa14d0d1d7e1707589d77ec1337206e53a1f06cc26672ff95c13d5ff444766931ba30a0afdcdadd2098e9c41fd87a3f23cd16dbb0efbf8092ce33e327f42610990e1cee6cb8e54951aa081e69765ae4009aeed758e768de50c23d9a22b4a06dc4d19fc8cbd0cdef4c983461755d0a3b5d6a9c12253e09568339ff7e5f78c5fdf7ec89f9186a621a8c0eed11b67022e
SIG: 4e65c6c1d493045e8a9250e397c1d1d30ffed24db66a8961aa458f8f0fcb760c39fe8657d7ab8f84000b96d519717cff71f926522c1efec7f8b2624eae55f60c
TST: 333
SK: 0fa0c32c3ae34be51b92f91945405981a8e202488558a8e220c288c7d6a5532d
PK: d6aee62bd91fc9453635ffcc02b2f38dcab13285140380580ccdff0865df0492
MSG: 53f44be0e5997ff07264cb64ba1359e2801def8755e64a2362bddaf597e672d021d34fface6d97e0f2b1f6ae625fd33d3c4f6e9ff7d0c73f1da8defb23f324975e921bb2473258177a16612567edf7d5760f3f3e3a6d26aaabc5fde4e2043f73fa70f128020933b1ba3b6bd69498e9503ea670f1ed880d3651f2e4c59e79cabc86e9b703394294112d5d8e213c317423b525a6df70106a9d658a262028b5f45100cb77d1150d8fe461eed434f241015f3276ad7b09a291b4a7f35e3c30051cbf13b1d4a7fa0c81a50f939e7c49673afdc87883c9e3e61f5a1df03755470fda74bf23ea88676b258a97a280d5f90b52b714b596035bae08c8d0fe6d94f8949559b1f27d7116cf59dd3cfbf18202a09c13f5c4fbc8d97225492887d32870c2297e34debd9876d6d01ac27a16b088b079079f2b20feb02537cda314c43cb2dca371b9df37ed11ec97e1a7a6993a
SIG: 7e9ab85ee94fe4b35dcb545329a0ef25923de5c9dc23e7df1a7e77ab0dcfb89e03f4e785ca6429cb2b0df50da6230f733f00f33a45c4e576cd40bdb84f1ae001
TST: 334
SK: 7b06f88026fa86f39fce2426f67cc5996bedd0cfc4b5ebb1b5e3edbb47e080aa
PK: 3f1469ee6a2e7867e2e9012d402cf5a4861497c01df879a1deb1c539830b58de
MSG: 71175d4e21721297d9176d817f4e785d9600d923f987fe0b26fd79d33a5ea5d1e818b71f0f92b8c73afddabdcc27f6d16e26aafa874cfd77a00e06c36b041487582bb933760f88b419127345776ea418f83522254fed33819bc5c95f8f8404cc144ebf1486c88515409d3433aaf519d9920f5256e629419e9a95580a35b069b8d25533dfcbc98ad36404a951808e01378c03266326d120046975fde07daef3266caacd821c1403499d7fdf17c033c8d8c3f28f162b5f09dfdaca06285f00c6cb986dfdf5151aa6639608b5b13e78d65a4368585b16138754fbd113835a686cd066c2b89bb0953c24d50e77bf0fc457c1e0fcf5d44da8db9a88f062be3b688d5cdcff1d1c00e81ec9d413882295b341fee8fa427dc109adeb5f284eec202f1bef115bf96b1782d3ccdeb682b69bf92d170c007d5df80e1ed962f677dc24a145a1e4e829e8dec0104e5f78365944
SIG: 42f133e34e3eb7032a133ed781537ec62e44a5ce8381e5e0bf9e13a914a4b2c757811d6d3b1e86672424ea4230d10f7c610abb7069e61e319b4066a2bd7bc900
TST: 335
SK: c3f5e149968a24f4de9119531975f443015ccca305d7119ed4749e8bf6d94fc7
PK: 39aaccdb948a4038538a4588322f806bb129b5876c4bec51271afe4f49690045
MSG: c46370e37f2e0cadcf93402f1f0cb048f52881ba750b7a43f56ab11ce348732fb57e7f9aaf8dfcbe455e14e983c248d026a27e7f148d5db5a53f94635702b895127771047a876d14107386c5e0ff8933345bbd7a936d990d33efa28c2ec4e4864ffd2ff576f7c88f954cfc1c459e883bb712dae3cdf6632066f1f4d13a509615b3360cadc5a307f23e52a51b40a6feebe0b18d0e9ee4e348f33cd81a8def222f6a59b12861d335bd9af85cc004be46f1d3a424f4870ae9dc587e5a4ade136b9370649348c33ac3bf1febeebffea37085ed59cac9d9e696470b234609e9a10a9d431ff91e69cb5135fd117ff58a36539744ebe70cea6973c00c7a4d57b62f4a7136d731b8e46ff18ec0ed69070031905075d8541d568cfce6eeb76242b7819a7b6a93552111bb88f165527cfa6966d39fcbe0a7dea008e39c7a3e577ab307cd1d0ea326833d52654e172955f3fcd4
SIG: 5fa2b531677b00b85b0a313cbd479f55f4ab3ec5cfce5e454d2b74176ccc3399c899f9d6b51ed4c1e76185ac9fe730c4b4014044f7041185bc3c85722eb2ea02
TST: 336
SK: 42305c9302f45ea6f87e26e2208fd94b3c4ad037b1b6c83cf6677aa1096a013c
PK: 3b97b1f11ce45ba46ffbb25b76bfc5ad7b77f90cc69ed76115dea4029469d587
MSG: d110828d449198d675e74e8e39439fd15e75bf2cc1f430abfb245836885bafc420f754b89d2fbbf6dd3490792e7a4f766073cfe3b302d089831ace869e2730fde45c2121ec3ef217aa9c43fa7cc7e9ed0a01ad9f1d2fc3613638ca9fc193c98b37455bf5dbf8f38b64708dfdca6c21f0975f1017c5da5f6434bda9f033cec2a631ab50318e017b170b240bf01eb8b36c7e1cb59e7736ac34444208132a8f59e4f313d65d849c6a4fdf13e20ecaee3823e589a171b39b2489497b06e6ff58c2c9f1dc5d3aa3bd10e6443e22d42d07b783f79fd43a46e1cde314b663a95f7246dea131fcd46d1dc333c5454f86b2c4e2e424dea405cc2230d4dcd39a2eab2f92845cf6a7994192063f1202749ef52dcb96f2b79ed6a98118ca0b99ba2285490860eb4c61ab78b9ddc6acc7ad883fa5e96f9d029171223abf7573e36230e0a81f6c1311151473ee264f4b842e923dcb3b
SIG: 18d05e5d01668e83f40fa3bbee28b388acf318d1b0b5ad668c672f345c8eda14c2f884cd2a9039459ce0810bc5b580fe70d3964a43edb49e73a6ff914bbf040c
TST: 337
SK: c57a43dcd7bab8516009546918d71ad459b7345efdca8d4f19929875c839d722
PK: 2083b444236b9ab31d4e00c89d55c6260fee71ac1a47c4b5ba227404d382b82d
MSG: a4f6d9c281cf81a28a0b9e77499aa24bde96cc1264374491c008294ee0af6f6e4bbb686396f59068d358e30fe9992db0c6f16680a1c71e27a4a907ac607d39bdc3258c7956482fb37996f4beb3e5051b8148019a1c256e2ee999ebc8ce64c54e07fedb4fbd8953ebd93b7d69ce5a0082edd6209d12d3619b4fd2eae916461f72a4ce727157251a19209bbff9fbdbd289436f3fcacc6b4e1318521a47839cba4b14f7d7a21e7b5d6b6a753d5804afcd2b1eb7779b92abab8afa8aa4fa51caec0b85dcd0fc2a0676036d3f56630a831ffeb502861dd89161c708a9c006c73c930ce5b94756426ff18aa112fb4eb9a68500b48d4eedbd4167b6ffd0a11d49443a173ce9d949436748fc0634f06bb08b8f3423f4463dba7b4d199b64df578117f0a2645f0b2a1e2ada27d286f76733f25b82ed1d48a5c3898d4ad621e50ed9060daad40a39532e4d1bf162ce36804d5d4e2d
SIG: 1edef9bc036971f1fa88edf45393c802e6c1a1631c8a06871a09a320821dce40beca97e53a0361a955a4c6d60b8ca8e400c81340911ccb4f56284041cdbb1804
TST: 338
SK: 2dddb6b8fd04fa90ece1a709f8418f2e5d0c9c43afe7cfce19e6ad15a73476f7
PK: 8059de6a7c4776489ecc2e7d707ffce30285bf30a23f78d72db49cfd6ed0d492
MSG: 474baa590a4cd72d5424e51d8257b3d44325bc4c5063a0033c86ebbe99ed7212184c19944d082a115379dd4cece973faa0bca6485bd25f3744a719e70aa0291e1b5a96e637c140616a98263357c76b6eb0083fe51414e386870d0fdc7dd9abe4ff6fb5bbf1e7b15dac3e08e2615f655c3104ceb32a4cc2c9e9c43cf282d346ac253ccc46b635ae040973b49735720ffb890469a567c5824e0c00d7ccd5509a718092a906461c4d6163eaf422418f5fc6e009fc3f529ac61a2f89bb8e0ed45d940c4c2331ff8d8e1d6d58d417d8fc2656a02e8701aee75aed918724eebe4a2cf4744c5c401e217023df68a6f6a0228bd05a679a697d8de7036b9ed269090d3c65486afb91e27954eb15b964665ede7ad008f12fb3a9d0e69c13b4254f43819e0818a4195f68b8a38ae81f3fcb1879c95ab4cd0ffc38e381089260cca967ace5a085b457ab5eb363852101377570f9ac9e38
SIG: c634ea7bf72e895a2e796e2834201415b8b45e05e045559284eb9052c0e84f62a5a9f0c9764f7576788c7228b19ef517c195497325a48a9344b147c12fd75509
TST: 339
SK: 5547f1004baedfce5cfc0850b05302374aad24f6163994ecd751df3af3c10620
PK: 7ce620787385ee1951ac49a77352ee0d6f8c5cd47df74e9e3216a6324fc7cf7f
MSG: a6c17eeb5b8066c2cd9a89667317a945a0c7c96996e77ae854c509c6cd0631e922ad04503af87a3c4628adafed7600d071c078a22e7f64bda08a362b38b26ca15006d38acf532d0dedea4177a2d33f06956d80e963848ec791b2762fa99449b4f1a1ed9b3f2580be3ac7d7f52fb14421d6222ba76f807750c6cbb0b16f0895fc73d9dfc587e1a9e5d1e58375fbab705b8f0c1fd7df8b3ad446f2f08459e7ed1af59556fbc966dc249c1cf604f3e677c8a09d4363608774bf3811bef0642748c55c516c7a580fa3499050acb30eed870d0d91174cb623e98c3ad121cf81f04e57d49b008424a98a31eeaaf5f38e000f903d48d215ed52f862d636a5a73607de85760167267efe30f8a26ebc5aa0c09f5b258d3361ca69d1d7ee07b59648179ab2170ec50c07f6616f216872529421a6334a4a1ed3d2671ef47bc9a92afb58314e832db8a9003408a0487503fe4f67770dd4b6
SIG: 29df3ad589009c667baa5e72dabb4e53cb7876de4e7efe5cc21ead7fa878db57f97c1103ddb39a861eb88653c1d4ec3b4306e4584b47b8bc90423119e7e4af00
TST: 340
SK: 3dd7203c237aefe9e38a201ff341490179905f9f100828da18fcbe58768b5760
PK: f067d7b2ff3a957e8373a7d42ef0832bcda84ebf287249a184a212a94c99ea5b
MSG: db28ed31ac04b0c2decee7a6b24fc9a082cc262ca7ccf2a247d6372ec3e9120ecedb4542ea593fea30335c5ab9dd318a3b4fd5834299cf3f53d9ef46137b273c390ec3c26a0b4470d0d94b77d82cae4b24587837b167bb7f8166710baeb3ee70af797316cb7d05fa57e468ae3f0bd449404d8528808b41fcca62f5e0a2aa5d8f3acab008cc5f6e5ab02777bdcde87f0a10ef06a4bb37fe02c94815cf76bfb8f5cdd865cc26dcb5cf492edfd547b535e2e6a6d8540956dcba62cfea19a9474406e934337e454270e01036ac45793b6b8aceda187a08d56a2ce4e98f42ea375b101a6b9fcb4231d171aa463eeb43586a4b82a387bcddaf71a80fd5c1f7292efc2bd8e70c11eaa817106061b6c461c4883d613cc06c7e2a03f73d90fc55cdc07265eefd36be72270383d6c676cae37c93691f1ae3d927b3a1cd963e4229757ae5231eea73a9f71515628305410ac2593b325cc631
SIG: 4c036935a96abc0d050d907bedbe9946fb97439f039c742e051ccf09add7df44d17da98c2ca01bdc2424da1e4debf347f8fff48ac8030d2cc07f9575c044be04
TST: 341
SK: 282775df9ebbd7c5a65f3a2b096e36ee64a8f8ea719da77758739e4e7476111d
PK: a2b49646033a13937cad6b0e914e3cec54989c252ca5643d076555d8c55e56e0
MSG: 14cc50c2973ea9d0187a73f71cb9f1ce07e739e049ec2b27e6613c10c26b73a2a966e01ac3be8b505aeaad1485c1c2a3c6c2b00f81b9e5f927b73bfd498601a7622e8544837aad02e72bf72196dc246902e58af253ad7e025e3666d3bfc46b5b02f0eb4a37c9554992abc8651de12fd813177379bb0ce172cd8aaf937f979642bc2ed7c7a430cb14c3cd3101b9f6b91ee3f542acdf017f8c2116297f4564768f4db95dad8a9bcdc8da4d8fb13ef6e2da0b1316d3c8c2f3ed836b35fe2fd33effb409e3bc1b0f85225d2a1de3bfc2d20563946475c4d7ca9fddbaf59ad8f8961d287ae7dd803e7af1fa612329b1bdc04e225600ae731bc01ae0925aed62ac50d46086f3646cf47b072f0d3b044b36f85cec729a8bb2b92883ca4dfb34a8ee8a0273b31af50982bb6131bfa11d55504b1f6f1a0a00438ca26d8ab4f48bcddc9d5a38851abede4151d5b70d720732a00abea2c8b979
SIG: 15763973859402907d8dcb86adc24a2a168ba3abf2246173d6348afed51ef60b0c0edeff4e10bcef4c6e5778c8bc1f5e9ee0237373445b455155d23de127a202
TST: 342
SK: 4730a5cf9772d7d6665ba787bea4c95252e6ecd63ec62390547bf100c0a46375
PK: f9f094f7cc1d40f1926b5b22dce465784468b20ab349bc6d4fdf78d0042bbc5b
MSG: e7476d2e668420e1b0fadfbaa54286fa7fa890a87b8280e26078152295e1e6e55d1241435cc430a8693bb10cde4643f59cbfcc256f45f5090c909a14c7fc49d37bfc25af11e8f4c83f4c32d4aabf43b20fa382bb6622a1848f8ffc4dff3408bb4ec7c67a35b4cdaee5e279c0fc0a66093a9f36a60fdd65e6334a804e845c8530b6fda363b5640337d027243ccfb3c177f43e717896e46ead7f72ca06aa0ff1e77247121baf48be9a445f729ca1390fc46151cbd33fcbd7373f27a6ba55c92cbf6945b09b44b9a4e5800d403070ae66048997b2197f02181a097e563f9b9acc841139258a258bc610d3bd891637356b2edc8c184c35c65af91aaf7b1c16d74a5f5f862548139254ecf550631d5f8849afdb5b64cf366ff2633a93f3a18c39b5150245fb5f33c9e4e2d94af6963a70b88f9e7e519f8fa2a0f2e3749de883d0e6f052a949d0fc7153a8693f6d801d7352eb2f7a465c0e
SIG: 552c7347bdfe131646ce0932d82a36d2c1b76d7c30ee890e0592e19f9d18b9a56f48d7a9b68c017da6b550c943af4a907baf317e419fbbc96f6cf4bfad42de00
TST: 343
SK: 2770aadd1d123e9547832dfb2a837eba089179ef4f23abc4a53f2a714e423ee2
PK: 3c5fbb07530dd3a20ff35a500e3708926310fed8a899690232b42c15bd86e5dc
MSG: a5cc2055eba3cf6f0c6332c1f2ab5854870913b03ff7093bc94f335add44332231d9869f027d82efd5f1227144ab56e3222dc3ddccf062d9c1b0c1024d9b416dfa3ee8a7027923003465e0ffaefb75b9f29dc6bcf213adc5e318fd8ba93a7aa5bfb495de9d7c5e1a196cd3a2d7721f8ba785aa9052a1811c7fcc8f93932765059cab9c9b718945895ef26f3ac048d4cabf91a9e6aa83ac14d43156827837914eb763a23cba53f60f150f4b70203ec1833ff105849457a8da7327661fb23a554164e05fcf0146b10674964be6f6aa0acc94c41ad57180e5180d199bd9102f55d740e81789b15671bbd0670e6de5d97e1ae626d8a0ebc32c8fd9d24737274e47d2dd5941a272e72a598928ad109cde937bf248d57f5d2942983c51e2a89f8f054d5c48dfad8fcf1ffa97f7de6a3a43ca15fc6720efaec69f0836d84223f9776d111ec2bbc69b2dfd58be8ca12c072164b718cd7c246d64
SIG: f267715e9a84c7314f2d5869ef4ab8d2149a13f7e8e1c728c423906293b49ce6283454dd1c7b04741df2eabedc4d6ab1397dc95a679df04d2c17d66c79bb7601
TST: 344
SK: 4fdab7c1600e70114b11f533242376af7614b4d5da046ac4bedea21d8a361598
PK: a25c9a94d6e4ecd95a4bd6805f762eb1c457a8d45d243238b1839cbba8f441cc
MSG: da405890d11a872c119dab5efcbff61e931f38eccca457edc626d3ea29ed4fe3154fafec1444da74343c06ad90ac9d17b511bcb73bb49d90bafb7c7ea800bd58411df1275c3cae71b700a5dab491a4261678587956aa4a219e1ac6dd3fb2cb8c46197218e726dc7ed234526a6b01c0d72cb93ab3f4f38a08e5940b3f61a72ad2789a0532000fac1d2d2e3ad632ac8b62bb3ff5b99d53597bf4d44b19674924df9b3db3d0253f74627ccab30031c85e291c58b5fa9167522a46746fc307036745d4f9817786e5d300e6c5d503125fea01dec3e3fedbf3861ca2627a0518fb2b24e5a7a014178719e9b345f7b249ce3a413280c8deb674f59a25be92a8ab6400c7c52b0728ae34e22b2ec200c1cbaba2ccd8af29249d17af60c36007a722fc80258a7bebab1cdaad7462a8b7588c2f7e27c6d07afcf60117fed11bd6859e75e3b4fcee3981881e95dd116827dd4b369af069d3c8f2676f8a
SIG: 5075c090cfbeb6b01802af7f4da5aa4f434d5ee2f3530eebb75c85e08621f83edc08aa96693894a4277633ba81e19e9e55af5c495daa5e1a6f8cbb79c01c7207
TST: 345
SK: 264504604e70d72dc4474dbb34913e9c0f806dfe18c7879a41762a9e4390ec61
PK: eb2b518ce7dc71c91f3665581651fd03af84c46bf1fed2433222353bc7ec511d
MSG: 901d70e67ed242f2ec1dda813d4c052cfb31fd00cfe5446bf3b93fdb950f952d94ef9c99d1c264a6b13c3554a264beb97ed20e6b5d66ad84db5d8f1de35c496f947a23270954051f8e4dbe0d3ef9ab3003dd47b859356cecb81c50affa68c15dadb5f864d5e1bb4d3bada6f3aba1c83c438d79a94bfb50b43879e9cef08a2bfb22fad943dbf7683779746e31c486f01fd644905048b112ee258042153f46d1c7772a0624bcd6941e9062cfda75dc8712533f4057335c298038cbca29ebdb560a295a88339692808eb3481fd9735ea414f620c143b2133f57bb64e44778a8ca70918202d157426102e1dfc0a8f7b1ae487b74f02792633154dfe74caa1b7088fda22fa8b9bc354c585f1567706e2955493870f54169e0d7691159df43897961d24a852ea970c514948f3b48f71ee586e72ec78db820f253e08db84f6f312c4333bd0b732fe75883507783e9a1fd4fbab8e5870f9bf7ad58aa
SIG: eea439a00f7e459b402b835150a779eed171ab971bd1b58dcc7f9386dadd583de8dc69e267121dde41f0f9493d450b16219cdf3c22f09482ce402fe17ca49e08
TST: 346
SK: 2ca7447a3668b748b1fd3d52d2080d30e34d397bb2846caf8f659ac168788ca5
PK: ab331cd40a31d0173c0c8c1c17002532807bf89e3edb6d34c2dd8294632b9fbc
MSG: a82bcd9424bffda0f2f5e9eae17835dbe468f61b785aab82934737a91c5f602cb7c617cdffe87cad726a4972e15a7b8ee147f062d2a5a4d89706b571fa8aa2b95981c78abeaaae86203fa2c0e07297406ea8c27111a86dbe1d5a7c3b7ae930904d9890f6d4abebd1412a73ad5feea64acf065d3e63b5cbe20cf20bbd2d8b94f9053ed5f66633482530124446605918de66455e8cf4b101a127233c4e27d5d55bf95bd3195d0340d43531fc75faf8dded5275bf89750de838fd10c31745be4ca41fa871cb0f9b016706a1a7e3c44bb90ac7a8ad51e272389292fd6c98ad7a069e76e3f5f3e0cc770b9e9b35a765d0d93712d7cdabd17e5d01dd8183af4ad9365db0a0fa41381fce60a081df1c5ab0f8c18f95a7a8b582dfff7f149ea579df0623b33b7508f0c663f01e3a2dcd9dfbee51cc615220fdaffdab51bdae42cb9f7fa9e3b7c69cc8ada5ccd642529ba514fdc54fcf2720b8f5d08b95
SIG: f93ada15ae9cd2b54f26f86f0c28392aed5eb6b6b44d01a4e33a54e7da37c38e8d53366f73fd85be642e4ec81236d163f0d025e76c8bbdd65d43df49f09c1f01
TST: 347
SK: 494ea9bcce26885b7d17d1fc114448f239f0ce46e5f247b4c999fa8629692472
PK: 6901e5efae57536ba5fdd96b59657359065f25d391a1aa8cdc0d38bb5d53c139
MSG: 3badbfa5f5a8aa2cce0a60e686cdce654d24452f98fd54872e7395b39464380a0e185557ea134d095730864f4254d3dd946970c10c804fcc0899dfa024205be0f80b1c75449523324fe6a0751e47b4ff4822b8c33e9eaf1d1d96e0de3d4acd89696b7fcc03d49f92f82b9725700b350db1a87615369545561b8599f5ea920a310a8bafc0e8d7468cbf6f3820e943594afdd5166e4e3309dddd7694ef67e694f34fc62724ff96ac3364176f34e8a02b4cf569db5b8f77d58512aedabf0bcd1c2df12db3a9473f948c5c3243309aae46c49efd088b60f31a8a72ad7e5a35acc5d89fa66807eb5d3ba9cdf08d4753cb85089ee36f5c96b432b6928352afad58012225d6157f9e3611426df921b6d1d8374628a63031e9ffb90e42ffbba021f174f68503155430152c9155dc98ffa26c4fab065e1f8e4622c2f28a8cb043110b617441140f8e20adc16f799d1d5096b1f50532be5042d21b81ea46c7
SIG: 548a093a680361b7dc56f14503b55eeec3b3f4fd4ca99d6aedce0830f7f4ae2f7328539b34c48fc9760922333dae9c7c017e7db73b8faa6c06be05e347992b06
TST: 348
SK: 00d735ebaee75dd579a40dfd82508274d01a1572df99b811d5b01190d82192e4
PK: ba02517c0fdd3e2614b3f7bf99ed9b492b80edf0495d230f881730ea45bc17c4
MSG: 59c0b69af95d074c88fdc8f063bfdc31b5f4a9bc9cecdffa8128e01e7c1937dde5eb0570b51b7b5d0a67a3555b4cdce2bca7a31a4fe8e1d03ab32b4035e6dadbf1532059ee01d3d9a7633a0e706a1154cab22a07cd74c06a3cb601244cf3cf35a35c3100ba47f31372a2da65dcff0d7a80a1055d8aa99212e899aad7f02e949e6fee4d3c9cefa85069eaff1f6ad06fc300c871ab82b2bedb934d20875c2a263242cdb7f9be192a8710b24c7ea98d43daec8baa5553c678a38f0e0adf7d3ff2dcc799a1dbad6eab1c3d9458a9db922f02e75cfab9d65c7336dae71895d5bb15cac203f2b38b9996c410f8655ad22d3c091c20b7f926d45e780128f19747462abc5c58932fbb9e0bc62d53868802f1b083f183b8a1f9434986d5cf97c04e2f3e145730cba98779c7fed0cab1c05d5e4653c6c3f6736260bc78ee4372862ffe9e90371d762c7432781f35ced884a4baca05653ef25f25a6f3d5628308
SIG: dcdc54611937d2bd06cacd9818b3be15ce7425427a75f50d197a337a3b8ba6714ef48866f243bd5ac7415e914517a2c1c5a953f432b99db0e620d64f74eb8505
TST: 349
SK: 8c34b905440b61911d1d8137c53d46a1a76d4609af973e18eb4c5709295627bb
PK: b69a8b2fdf5c20e734c2ffb294bc8ae1011d664f11afe7fbc471925cf72fa99d
MSG: 30b57a389b48a0beb1a48432bff6b314bded79c4a1763a5acb57cea1bfb4c6d016cf090f5bd05bbd114e33ae7c17782dfa264f46c45f8c599c603016fe9ff05b6b5a99e92fe713a4cd5c41b292ed2bb2e9cf33a440542e821ec82cbf665c3f02e3dc337d7fdb58e31b27cb2954541468814698510df18c85c81fad12db11ec6b966f4930da5646b991db97445097da30dab61cda53a41083cb96add19de6c5eec323bca9d3530e38c00b35af7360077601be6ac97f3030f930a27b90fe8b6911bae389065adc15e1882300e2a003274d23182d5efd5ba4b9130c07bd5c65fecb8b5cb7eb38836b318befdfd77de4d6ca0181f77ae5740891683225f549dd8426145c97c5818c319f7ab2d868e1a41ceab64c085116069897bf2ca3667652406155ed0646431b6de1ccc03b4279ae4d326679265dce82048e7298e1f87fcec0768ac0f5d8ff84f7210be54d411af8edea7217f4e59413121e148c60da
SIG: 3e0b72073dc9375eedcca6c4fc1cd315938a050c92716bd2284f4629a962beec0b7d7cf16ab923d58f5b90d3901a8e5c75c8f17dab9998e007d8c49511973d0e
TST: 350
SK: 77a83e18c9f000eeff7deeac959ecba2206c0aa39d2f0e2aed5729482a7a0229
PK: 62b1b316135596bfbca6037ed847c61fb7f09fa36ce90abb7789b86f768b59dd
MSG: f3d5fa2acaefd858f1df26e03059cdcbc2468ad74afc993d0db9c4cde4113f8d55c7da71d38ba06520531c61fddb5f33d5f0353be2376e580711be45c0a30b1fa01b55e228c6fa35e3f95b67909fc7df3fd464d93d661a926f9d11f7550c17fbcc3496526e8f10e0c8916677b2be5b319b688f21e81aaa9482e5c93e64ce8c437b9c1e14fefed70a3fee568811dc31cadab3d5b220254465336dc4d97a3bd096b5e065e0cfbe82849e2c1905aca486533f0da7a61f1e9a55b8e2a83262deeb59f2b13d3a8aef5700845b83b25ae2183c0ddac0ce42f8d25674cb0d0d220a6de7c1858bb07d59a3372344d944602aa451d2b937db0fe6feca0beba81721fc361ea7509e2b6d397e1c191b56f54ab436d0d27ab4c061bd661ad1a4452387e8735754d07fa7ef4d4548b172582425b299046e6301b5ba6b914418f149cf722e10bde2e0d41700f12c8429fc897b7819da92292240cd45565458c9a7b29c12
SIG: 1eaad8420ac12c99ac1ff4476678e3cbbe94da6a797f174664d5ee0f641433fb1e7cb2f5613e10805df8654cd8e0d45d96230932bc7f20b04eae836435134309
TST: 351
SK: 73b03373ef1fd849005ecd6270dd9906f19f4439e40376cdbc520902bc976812
PK: 663719e08ba3ba1666f6069a3f54991866b18cc6be41991b02eb3026ff9e155f
MSG: d5c2deaba795c30aba321bc7de6996f0d90e4d05c747fb4dae8f3451895def6e16e72f38eace756f36635f8fb0b72a3a0c1f54663817a94d4fd346f835ab0e657f001a6f2cecb86d0825bd02639254f7f7f38ca99dbb86c64a633f73baf933aae3563281f4005e2d0e7cec9fbde8e588a957e211068be65b3d3d35bf4e8d5bb3478333df9ced9b2abaf48697994a145e9321499fc5ee560f4fbb6849e1ae8eb3d1de0083a21a03f6a6b28176f0130d3895e50e75e3d7d0947a7bc2c5b9ff69895d27791442ba8d0f2180712b567f712ea912f3b0d92c19342e0106ff1d87b46ad33af300b90855ba9769d366e79425d98e4de19905a04577707cbe625b84691781cd26bf62260b4a8bd605f77af6f970e1b3a112e8918344bd0d8d2e41dfd2ce9895b0246e50887aa3a577ff73be4b6ae60feb0ca36f6a5f8171ed209e5c566529c0940d9b4bd744ccee56e54a9a0c6e4da520dd315c2872b02db563703e
SIG: a40abe98fc69da8a1ff9ff5c2cca93632e975980ee8b82c3c376022d6524ab736d01b072f2b681b5f1cd3ea067012ed6d074e949c42327a366caa9e4750a3c08
TST: 352
SK: eab179e41ed5c889ffe6aabdc054faf1307c395e46e313e17a14fe01023ffa30
PK: 86f34746d3f7a01ddbe322f1aca56d22856d38733a3a6900bb08e776450ec803
MSG: 971095cebe5031530224387c5c31966e389b8566390054cf45264b44e18964b7be52c33c4ffb259af16283438fa15dd66bc7791b7533ef10cb0beab524a6437626f4cc74512851adcc2fb129055a482c61107383fb7c5241831d5551634eef0dc0b8f9053a00971aa8fa1ae0898e4b481b6707e97c0f942040b339d92fc17bbade74675af243d8b2dafb15b1db55d12415b85f3037291930ab61600ba3431f8eb425be4491614728af101e81c091f348bc5ffd1bde6ae6cad5c15b3aa7358078cc4effb54a86e7f0e0c55e4cfe0a54605ed443fdf2aaba016585da617e77341d52889d75dd540d39fe8b7993ed705cfddea0cb0d5a731d6bfcdb816afaff47e963eedebdf241af5593353d6d401a34f029a8cdeb1904cc2caa4f9635cc2ba6b7b1a29da625ffc383be2f5a8f1fa4f39b2d4b4f4c2d8838ce258a04d4a120493fdf07f68c0ffd1c16b768a35c55fea2cac696b5c20efc10865cde8a64627dcd
SIG: 143cb28027c2f82e375e5f340e7fe6e60ce7bd51000b49c74168af85e26ed2ed630ed2672090164cc54b052da694ebdd21a21b3053f4dcfd7895ea5f6c8aa80d
TST: 353
SK: fbf146ebd51075570ec51ac410ae9f391db75b610ada6362b4dbd949656cfb66
PK: be7c2f5b21d746c8ea3245ce6f268e9da74e00fa85c9c475260c68fa1af6361f
MSG: cd7ad4f17fcff73acc402dc102d09079b29aaf2a0f4b27cf6beeb1e2b23d19ab47deb3ae1becd68861ea279c46691738f4fff47c43047c4f8b56b6bbcc3fde0723d44120dcd307a6310dc4f366b8f3cd52db19b8266a487f7872391c45fe0d3248a7abf2c20022d3769547f683067dcc363cd22fd7cda3cadc15804056f0e2aa2b795008c598be7a961805e6df291ba3041c47ff5640275f46e6ae82092d21abcbcfba11e730216008822de3ce462400596da79f7ae5d1df8389112ad98868fa94fb0546bfe6a67aa8d28c4d32072d2eadd6256255f18c2382e662dfa922a680e06a43622c4871d27d1807f7b2703070c83db8dd929c06038b2183cb8e2b9ec4c778d7ecf9e9ffac77fa7737b055feac2e7982aeeec0b72f1bbca2424e1a844bbac79cb2e7400f81dc449d0560b521a7c16bb4167e6696586058a9b8ed2e5116690b77f2a17e5c0b16a83dcbd2e24552293e258b32ba7f844944379342698627
SIG: 6768006fe0f201b217dd10eb05d4b82adcfeb2ecfc8373c3308f4150394811eb60491881a2e53d1289d96478e18a64c34b2a19832cdccfd96a2e4a0c469fdc0b
TST: 354
SK: dff0eb6b426dea2fd33c1d3fc24df9b31b486facb7edb8502954a3e8da99d9fd
PK: c245085ece69fb9aa560d0c27fdb634f7a840d41d8463660fbe82483b0f3cc3a
MSG: e7c9e313d86160f4c74aa0ae07369ee22b27f81b3f69097affae28dae48483fb52a5c062306b59610f5cdbff6332b1960cd6f2b8f7b41578c20f0bc9637a0fdfc739d61f699a573f1c1a0b49294506cf4487965e5bb07bbf81803cb3d5cb3829c66c4bee7fc800ede216150934d277dea50edb097b992f11bb669fdf140bf6ae9fec46c3ea32f888fde9d154ea84f01c51265a7d3fef6eefc1ccdbffd1e2c897f05546a3b1ca11d9517cd667c660ec3960f7a8e5e80202a78d3a388b92f5c1dee14ae6acf8e17c841c9557c35a2eeced6e6af6372148e483ccd06c8fe344924e1019fb91cbf7941b9a176a073415867210670410c5dbd0ac4a50e6c0a509ddfdc555f60d696d41c77db8e6c84d5181f872755e64a721b061fcd68c463db4d32c9e01ea501267de22879d7fc12c8ca0379edb45abaa6e64dda2af6d40ccf24fbebad7b5a8d3e52007945ecd3ddc1e3efeb522581ac80e98c863ba0c590a3ed95cd1
SIG: 6b48b10f545ddb7a89cd5829f4e5b20146cf6bc96e550d06f65de8bdae7ccdded26cd630f86c9266bccf88e924033e04f83a54f8290d7f734cf8673cca8f9703
TST: 355
SK: 9f32958c7679b90fd5036056a75ec2eb2f56ec1effc7c012461dc89a3a167420
PK: 1d7269dcb6d1f584e662d4ce251de0aba290ef78b97d448afb1e5333f1976d26
MSG: a56ba86c71360504087e745c41627092ad6b49a71e9daa5640e1044bf04d4f071ad728779e95d1e2460584e6f0773545da82d4814c9189a120f12f3e3819813e5b240d0f26436f70ee353b4d20cea54a1460b5b8f1008d6f95f3aa2d8f1e908fced50d624e3a096938b9353854b96da463a2798a5a312ec790842c10c446e3350c764bf5c972593b9987bf23256daa8894d47f22e85b97607e66fc08a12c789c4746080368d321bb9015a1155b65523ad8e99bb989b44eac756b0734acd7c6357c70b59743246d1652d91b0f9896965141345b9945cf34980452f3502974edb76b9c785fb0f4395266b055f3b5db8aab68e9d7102a1cd9ee3d142504f0e88b282e603a738e051d98de05d1fcc65b5f7e99c4111cc0aec489abd0ecad311bfc13e7d1653b9c31e81c998037f959d5cd980835aa0e0b09bcbed634391151da02bc01a36c9a5800afb984163a7bb815edbc0226eda0595c724ca9b3f8a71178f0d20a5a
SIG: 9881a5763bdb259a3fefbba3d957162d6c70b804fa94ab613406a6ec42505b8789465ca1a9a33e1895988842270c55e5bdd5483f6b17b31781b593507a6c1808
TST: 356
SK: f86d6f766f88b00717b7d6327eb26cf3ceeba5385184426f9cfd8295e2421ff2
PK: cb1d250504754183704dbe21c323d66f9f9011758f6d8dab6f597b199662145b
MSG: da8423a6b7a18f20aa1f90ed2331b17b24067c40175bc25d8109e21d87ac00528eb3b2f66a2b52dc7ef2f8cecb75c76099cfa23db8da897043ba1cce31e2dfea46075f5e073203eaeb3d62c84c107b6dab33a14eaf149aa61850c15f5a58d88a15aba9196f9e495e8dbecbcf7e8444f5dd72a08a099d7f6209990b562974ea829ef11d29a920e3a799d0d92cb50d50f817631ab09de97c31e9a05f4d78d649fcd93a83752078ab3bb0e16c564d4fb07ca923c0374ba5bf1eea7e73668e135031feafcbb47cbc2ae30ec16a39b9c337e0a62eecdd80c0b7a04924ac3972da4fa9299c14b5a53d37b08bf02268b3bac9ea9355090eeb04ad87bee0593ba4e4443dda38a97afbf2db9952df63f178f3b4c52bcc132be8d9e26881213abdeb7e1c44c4061548909f0520f0dd7520fc408ea28c2cebc0f53063a2d30570e05350e52b390dd9b67662984847be9ad9b4cd50b069ffd29dd9c62ef14701f8d012a4a70c8431cc
SIG: ec61c0b292203a8f1d87235ede92b74723c8d23408423773ae50b1e9bc4464e03e446da9dce4c39f6dd159bea26c009ed00120bc36d4a247dc0d24bcefcc110c
TST: 357
SK: a5b34cefab9479df8389d7e6f6c146aa8affb0bec837f78af64624a145cc344e
PK: 7b0f4f24d9972bc6fe83826c52716ad1e0d7d19f123858cb3e99fa636ac9631a
MSG: e21e98af6c2bac70557eb0e864da2c2b4d6c0a39a059d3477251f6178a39676f4749e7fbea623f148a43a8b0fe0610506fa658abd2f5fa39198f2636b724db22d1aebc2ab07b2b6dbffdee8cece81e1af1493ec1964e16bf86ab258ca0feb77e3c8717e44038abe152c14be15660bf93b2d48d92c4ed7074d2494210621bcf204fba88c654d5ffe01e1a53d08f70bb237089dc807216ff6a85dbec3102237d42590778acf6c1dc566d5a2bb9a63bc21c329c272e5965baeeb0fe891de3cc8cbfa8e541a8881df68942e7ff8dc656bd08575f6aaf924a176d663b1a1f43574d11768c701b269561e55438dbebfd443d2115cb933d1cde4a915b54c325c27f499ef02bd012ff1f9a36390922887600fe712bcdc23eb5974a305372ad52951f83f0e58cc49e289841621917f1fcb0235147240dae4cf3b99b6ac6d8de94efe7c4436714508bcd0114c56068ff1b7c16d51bd906437874d6549ab5d8087896872ec8a09d7412
SIG: 2fbd899d72b6d39e4f45b8b62cbbd5f3c0acb1ad8540913fa585877e91ccfef7bee50a4b0f9fedf5cc1e0d1953ad399c8389a93391e1b7c929af6d6f3b796c08
TST: 358
SK: ad75c9ce299c4d59393367d77a4c9f8df8dcec765c6dbd25b527fb7669913604
PK: b9910548fe6312a119c9993eebcfb9dc90030ffb0e4de2b7ccd23cbeb4fef71b
MSG: 62fc5ab67deb1fee9ab6cca3b88a1df1e589f0fd4a88f4aa7738948761fe84372c5b18e4655220c1d84d52acad32e229a5c756c20fc62fe4b4b4e5fd7077ae4ed5397aa796f2307ceedb6505b39297856f4aeb5e70938e36ee24a0ac7d9868306f6b53910623b7dc89a6672ad738576ed5d88831dd338321c8902bc2061f65e94d452fdfa0dc665cefb92308e52301bd4627006b363d06b775a395914d8c863e95a00d6893f3376134c429f56478145e4456f7a12d65bb2b8965d728cb2ddbb708f7125c237095a92195d92fa727a372f3545ae701f3808fee802c8967a76e8a940e55fb2d810bfb47ada156f0eda1829b159cf05c7f36cf3847d7b21de84c3dc0fe658347f79396a01139a508b60022db1c0e5aeef47e445e66f783e62c96597bdb16f209c08a9132c7573136170ee3ebf24261265a89fb4f10333375e20b33ab7403464f5249461c6853c5fddb9f58af816892910393a7077b799fdc3489720998feea86
SIG: 6b7ef27bcfbf2b714985033764fccff555e3f5bc44610d6c8c62117cb3831a07f4a8bddb0eaed1d46b0289b15de1aa4dcc17d71be96a09e66ba4dc4627c78705
TST: 359
SK: 1ced574529b9b416977e92eb39448a8717cac2934a243a5c44fb44b73ccc16da
PK: 85e167d5f062fee82014f3c8b1beaed8eefb2c22d8649c424b86b21b11eb8bda
MSG: 1b3b953cce6d15303c61ca707609f70e7250f6c0deba56a8ce522b5986689651cdb848b842b2229661b8eeabfb8570749ed6c2b10a8fbf515053b5ea7d7a9228349e4646f9505e198029fec9ce0f38e4e0ca73625842d64caf8ced070a6e29c743586aa3db6d82993ac71fd38b783162d8fe04ffd0fa5cbc381d0e219c91937df6c973912fc02fda5377312468274c4bee6dca7f79c8b544861ed5babcf5c50e1473491be01708ac7c9ff58f1e40f855497ce9d7cc47b9410f2edd00f6496740243b8d03b2f5fa742b9c630867f77ac42f2b62c14e5ebddc7b647a05fff43670745f2851eff4909f5d27d57ae87f61e965ee60fdf97724c59267f2610b7ad5de919856d64d7c212659ce8656149b6a6d29d8f92b312be50b6e2a431d36ae022b00a6fe360e3af65432899c43be0427e36d21cfec81f21aa53b33db5ed2c37da8f96ac3e7dc67a1de37546cf7de1008c7e1adbe0f34fa7eb2434d94e6a13f4cf86a98d497622f
SIG: e0303aefe08a77738dcc657afbb9b835ed279613a53c73fdc5ddbfb350e5cff4d6c9bb43dc07c95bf4e23b64c40f8804c7169952e3c8d59a7197241bfed0740f
TST: 360
SK: f0790d93e2d3b84f61ef4c807147aba410e415e72b71b0d61d01026fed99da3d
PK: efdf649fb033cf328e0b287796f8a25e9c6e2e871b33c2c21a4028a8a25a4b28
MSG: 7973e9f32d74805992eb65da0d637335e50eff0ce68ea2d1f3a02de704492b9cfbe7e7ba96fdb42bb821a513d73fc60402e92c855deaed73ffeaf70952029062c833e14ec1b14f144e2207f6a0e727e5a7e3cbab27d5972970f69518a15b093e740cc0ce11bf5248f0826b8a98bde8bf2c7082c97aff158d08371118c89021cc3974ae8f76d86673c3f824b62c79c4b41f40eaa8943738f03300f68cbe175468eb235a9ff0e6537f8714e97e8f08ca444e41191063b5fabd156e85dcf66606b81dad4a95065584b3e0658c20a706eaf4a0777da4d2e0cd2a0fca60109c2b4403db3f03cd4781c1fbb0272202bcb11687808c50cb98f64b7f3fd3d43333bb5a061b9e377090abb1e0a885cb26b73c163e63ff6451ff2f4ec8249c7e152bd03973a1e964e2b5b235281a938399a112a24529e383a560dc50bb1b622ad74ef35658dcb10ffe022568ac3ffae5b465a8ed7643e8561b352ee9944a35d882c712b187788a0abae5a22f
SIG: 08773a6a78762cbb1e25fcbb29139941bdf16f4e09a1fa08fc701f32f933edd74c0ae983c12a0a5b020b6bcf44bb719dde8ed0781a8298265640e1608c98b301
TST: 361
SK: 4cb9df7ce6fae9d62ba09e8eb70e4c969bdeafcb5ec7d7024326e6603b0621bf
PK: 018069dd0eb44055a35cd8c77c37ca9fb1ad2417271385e134b2f4e81f52033c
MSG: 14627d6ea0e7895460759476dc74c42800ceef994327518151490d9df23067914e44788a12768ccb25471b9c3ba9d14fb436dcba38429b3a0456877763c49175d0e082683e07a9058f3685c6279307b2303d1221b9c29793d8a4877f6df51587384dadf751c5f7bfbd207d519622c37b51ceeee2c20d8269f8cb88d3fe43d6d434d5bbd0e203c1532d97ba552147227496c87f67b50bb76193add0144df1c176657585408362ca2ed04ad62acf1c25e341dfd1498d85b4b1349a8b0b9b02c43523c55853419bfed37d5a2cdf17dfbf1a3bd7759d6ae180f9d27dcd9a8933e29a7c0a30771eea7c2e0fa242925d2336dce585629057d844323964f6d3d11ff0b3f829a3be8c9f0468a6823d8e70ab5a2da21e15fa8b041a29812222e9c30b2bd9a12d1fdee6f87876e8ce81009637a8bb2236129a47ca74289ee4aad429ffe29f47430241ca8cc3848b7200fd6e1470651a9a0a6f72c9033e831df051408a6260f65cbaf6e012b18e
SIG: e33c07836c537d6bfbd0f4592d6e35b163499ba78dc7ffcec565d04f9a7db781943e29e6ce76763e9baddf57437fd9c6b03239a6e6850e4502a356c2e12c3705
TST: 362
SK: a136e009d53e5ef59d0946bc175663a86bc0fcd29eadd95cfc9d266037b1e4fb
PK: 9c1806ec0454f58314eb8397d64287dee386640d8491aba364607688841715a0
MSG: a49d1c3d49e13c2eda56868a8824aa9f8d2bf72f21955ebafd07b3bdc8e924de20936cee513d8a64a47173a3bd659eff1accff8244b26aae1a0c27fa891bf4d85e8fb1b76a6cab1e7f74c89ee07bb40d714326f09b3fd40632fad208ea816f9072028c14b5b54ecc1c5b7fc809e7e0786e2f11495e76017eb62aa4563f3d00ee84348d9838cd17649f6929a6d206f60e6fc82e0c3464b27e0e6abd22f4469bdfd4cb54f77e329b80f71bf42129ec13c9dfe192adfaa42ee3ddeeda385816fbad5f411938c63b560f4ecd94534be7d98725cd94c99ce492f0f069ba0ec08f877a7812ef27ae19d7a77be63f66bcf8d6cf3a1a61fc9cfef104c7462a21ca7f03afb5bb1ac8c75124b554e8d044b810d95ff8c9dd09a34484d8c4b6c95f95c3c22823f52ce844293724d5259191f1ba0929e2acdbb8b9a7a8adf0c52e78acdfdf057b0985881afbed4dbebdebbdae0a2b63bd4e90f96afdcbbd78f506309f9bdb650013cb73faed73904e
SIG: bc094ba91c115dee15d753361a75f3f03d6af45c92157e95dbe8d32194b6c5ce72b9dc66f73df12dca0b639f3e791d478616a1f8d7359a42c8eae0dda16b1606
TST: 363
SK: ff0f1c57dd884fbeea6e2917282b79ba67f8a6851267b9f4636dafda33bd2b5b
PK: fef6378ad12a7c252fa6eb742b05064b41530ff019dc680ab544c027ea2836e7
MSG: 522a5e5eff5b5e98fad6878a9d72df6eb318622610a1e1a48183f5590ecef5a6df671b28be91c88cdf7ae2881147fe6c37c28b43f64cf981c455c59e765ce94e1b6491631deaeef6d1da9ebca88643c77f83eae2cfdd2d97f604fe45081d1be5c4ae2d875996b8b6fecd707d3fa219a93ba0488e55247b405e330cfb97d31a1361c9b2084bdb13fb0c058925db8c3c649c9a3e937b533cc6310fa3b16126fb3cc9bb2b35c5c8300015488a30fadca3c8871fa70dfdc7055bf8e631f20c9b2528311e324a7c4edd5462079f3441c9ecf55fa999e731372344fdc0d413e417aaa001a1b2d3d9bc000fec1b02bd7a88a812d9d8a66f9464764c070c93041eefb17ce74eff6d4aff75f0cbf6a789a9ecde74abe33130fca0da853aa7c3313ada3f0ae2f595c6796a93685e729dd18a669d6381825ab3f36a391e7525b2a807a52fa5ec2a030a8cf3b77337ac41fceb580e845eed655a48b547238c2e8137c92f8c27e585caad3106eee3814a
SIG: d5008486726cce330a29dd7e4d7474d735798201afd1206feb869a112e5b43523c06976761be3cf9b2716378273c94f93572a7d2b8982634e0755c632b449008
TST: 364
SK: 0bc6af64de5709d3dbc28f7ef6d3fe28b6de529f08f5857ccb910695de454f56
PK: fb491fc900237bdc7e9a119f27150cd911935cd3628749ff40ef41f3955bc8ac
MSG: ac7886e4f4172a22c95e8eea37437b375d72accedcee6cc6e816763301a2d8ef4d6f31a2c1d635818b7026a395ce0dafd71c5180893af76b7ea056c972d680eca01dcbdbae6b26f1c5f33fc988b824fbbe00cacc316469a3bae07aa7c8885af7f65f42e75cef94dbb9aab4825143c85070e7716b7612f64ef0b0166011d23eb5654aa098b02d8d71e57c8fa17bff2fe97dc8193177eadc09fb192d80aa92afa98720d4614817ff3c39d3acce18906fa3de09618931d0d7a60c4429cbfa20cf165c947929ac293ae6c06e7e8f25f1264291e3e1c98f5d93e6ecc2389bc60dbbf4a621b132c552a99c95d26d8d1af61138b570a0de4b497ebe8051c7273a98e6e7876d0b327503af3cb2cc4091ce1925cb2f2957f4ec56ee90f8a09dd57d6e83067a356a4cfe65b1b7a4465da2ab133b0efb5e7d4dbb811bcbbde712afbf0f7dd3f326222284b8c74eac7ad6257fa8c632b7da2559a6266e91e0ef90dbb0aa968f75376b693fcaa5da342221
SIG: dbc7134d1cd6b0813b53352714b6df939498e91cf37c324337d9c088a1b998347d26185b430900412929e4f63e910379fc42e355a4e98f6fee27dafad1957206
TST: 365
SK: 2f5e83bd5b412e71ae3e9084cd369efcc79bf6037c4b174dfd6a11fb0f5da218
PK: a22a6da29a5ef6240c49d8896e3a0f1a4281a266c77d383ee6f9d25ffacbb872
MSG: b766273f060ef3b2ae3340454a391b426bc2e97264f8674553eb00dd6ecfdd59b611d8d662929fec710d0e462020e12cdbf9c1ec8858e85671acf8b7b14424ce92079d7d801e2ad9acac036bc8d2dfaa72aa839bff30c0aa7e414a882c00b645ff9d31bcf5a54382def4d0142efa4f06e823257ff132ee968cdc6738c53f53b84c8df76e9f78dd5056cf3d4d5a80a8f84e3edec48520f2cb4583e708539355ef7aa86fb5a0e87a94dcf14f30a2cca568f139d9ce59eaf459a5c5916cc8f20b26aaf6c7c029379aedb05a07fe585ccac60307c1f58ca9f859157d06d06baa394aace79d51b8cb38cfa2598141e245624e5ab9b9d68731173348905315bf1a5ad61d1e8adaeb810e4e8a86d7c13537b0be860ab2ed35b73399b8808aa91d750f77943f8a8b7e89fdb50728aa3dbbd8a41a6e00756f438c9b9e9d55872df5a9068add8a972b7e43edad9ced2237ca1367be4b7cdb66a54ea12eef129471158610eaf28f99f7f686557dcdf644ea
SIG: 9f80922bc8db32d0cc43f9936affebe7b2bc35a5d82277cd187b5d50dc7fc4c4832fffa34e9543806b485c04548e7c75429425e14d55d91fc1052efd8667430b
TST: 366
SK: 722a2da50e42c11a61c9afac7be1a2fed2267d650f8f7d8e5bc706b807c1b91d
PK: fd0b964562f823721e649c3fedb432a76f91e0aead7c61d35f95ed7726d78589
MSG: 173e8bb885e1f9081404acac999041d2ecfcb73f945e0db36e631d7cd1ab999eb717f34bf07874bf3d34e2530eb6085f4a9f88ae1b0f7d80f221456a8e9a8890b91a50192deaaacc0a1a615a87841e2c5a9e057957af6e48e78cc86198e32e7aa24dcf6cffa329bc72606d65b11682c8ba736cce22a05785df1146331e41609cf9ca711cf464958297138b58a9073f3bbf06ad8a85d135de66652104d88b49d27ad41e59bcc44c7fab68f53f0502e293ffcabaaf755927dfdffbfde3b35c080b5de4c8b785f4da64ef357bc0d1466a6a96560c3c4f3e3c0b563a003f5f95f237171bce1a001771a04ede7cdd9b8ca770fd36ef90e9fe0000a8d7685fd153cc7282de95920a8f8f0898d00bf0c6c933fe5bb9653ff146c4e2acd1a2e0c23c1244844dacf8652716302c2032f9c114679ed26b3ee3ab4a7b18bc4e3071f0977db57cd0ac68c0727a09b4f125fb64af2850b26c8a484263334e2da902d744737044e79ab1cf5b2f93a022b63d40cd
SIG: c2695a57172aaa31bd0890f231ca8eeec0287a87172669a899ad0891cea4c47579b50420e791cdec8c182c8a0e8dde21b2480b0cfd8111e28e5603347a352d04
TST: 367
SK: 5fe9c3960ed5bd374cc94d42357e6a24dc7e3060788f726365defacf13cd12da
PK: 0ce7b155c8b20ebdaacdc2aa23627e34b1f9ace980650a2530c7607d04814eb4
MSG: c9490d83d9c3a9370f06c91af001685a02fe49b5ca667733fff189eee853ec1667a6c1b6c787e9244812d2d532866ab74dfc870d6f14033b6bcd39852a3900f8f08cd95a74cb8cbe02b8b8b51e993a06adfebd7fc9854ae5d29f4df9642871d0c5e470d903cfbcbd5adb3275628f28a80bf8c0f0376687dae673bf7a8547e80d4a9855ae2572fc2b205dc8a198016ddc9b50995f5b39f368f540504a551803d6dd5f874828e5541ded052894d9e2dc5e6aa351087e790c0dd5d9c4decb217e4db81c98a184b264e6daeac0f11e074cae2bfc899f54b419c65dcc22664a915fbfffac35cee0f286eb7b144933db933e16c4bcb650d537722489de236373fd8d65fc86118b6def37ca4608bc6ce927b65436ffda7f02bfbf88b045ae7d2c2b45a0b30c8f2a04df953221088c555fe9a5df260982a3d64df194ee952fa9a98c31b96493db6180d13d67c36716f95f8c0bd7a039ad990667ca34a83ac1a18c37dd7c7736aa6b9b6fc2b1ac0ce119ef77
SIG: 379f9c54c413af0d192e9bc736b29da9d521e7ba7841d309f9bcc1e742ec4308fe9f7ba51e0b22aed487cb4aa3913b9bebfb3aacd38f4039f9bbbebe1ad80002
TST: 368
SK: ec2fa541ac14b414149c3825eaa7001b795aa1957d4040dda92573904afa7ee4
PK: 71b363b2408404d7beecdef1e1f511bb6084658b532f7ea63d4e3f5f01c61d31
MSG: 2749fc7c4a729e0e0ad71b5b74eb9f9c534ebd02ffc9df4374d813bdd1ae4eb87f1350d5fdc563934515771763e6c33b50e64e0cd114573031d2186b6eca4fc802cddc7cc51d92a61345a17f6ac38cc74d84707a5156be9202dee3444652e79bae7f0d31bd17567961f65dd01a8e4bee38331938ce4b2b550691b99a4bc3c072d186df4b3344a5c8fbfbb9fd2f355f6107e410c3d0c798b68d3fb9c6f7ab5fe27e70871e86767698fe35b77ead4e435a9402cc9ed6a2657b059be0a21003c048bbf5e0ebd93cbb2e71e923cf5c728d1758cd817ad74b454a887126d653b95a7f25e5293b768c9fc5a9c35a2372e3741bc90fd66301427b10824bb4b1e9110bfba84c21a40eb8fed4497e91dc3ffd0438c514c0a8cb4cac6ad0256bf11d5aa7a9c7c00b669b015b0bf81425a21413e2ffb6edc0bd78e385c44fd74558e511c2c25fee1fec18d3990b8690300fa711e93d9854668f0187065e76e7113ae763c30ddd86720b5546a6c3c6f1c43bc67b14
SIG: 84d18d56f964e3776759bba92c510c2b6d574555c3cddade212da90374554991e7d77e278d63e34693e1958078cc3685f8c41c1f5342e351899638ef61211401
TST: 369
SK: 6132692a5ef27bf476b1e991e6c431a8c764f1aebd470282db3321bb7cb09c20
PK: 7a2d166184f9e5f73bea454486b041ceb5fc2314a7bd59cb718e79f0ec989d84
MSG: a9c0861665d8c2de06f9301da70afb27b3024b744c6b38b24259294c97b1d1cb4f0dcf7575a8ed454e2f0980f50313a77363415183fe9677a9eb1e06cb6d34a467cb7b0758d6f55c564b5ba15603e202b18856d89e72a23ab07d8853ff77da7aff1caebd7959f2c710ef31f5078a9f2cdae92641a1cc5f74d0c143ec42afbaa5f378a9e10d5bf74587fa5f49c156233247dafd3929acde888dc684337e40cdc5932e7eb73ffcc90b85c0ad460416691aefbd7efd07b657c350946a0e366b37a6c8089aba5c5fe3bbca064afbe9d47fbc83914af1cb43c2b2efa98e0a43be32ba823202001def36817251b65f9b0506cef6683642a46ed612f8ca81ee97bb04d317b517343ade2b77126d1f02a87b7604c8653b6748cf5488fa6d43df809faa19e69292d38c5d397dd8e20c7af7c5334ec977f5010a0f7cb5b89479ca06db4d12627f067d6c42186a6b1f8742f36ae709ba720e3cd898116666d81b190b9b9d2a72202cb690a03f3310429a71dc048cde
SIG: eb677f3347e1a1ea929efdf62bf9105a6c8f4993033b4f6d03cb0dbf9c742b270704e383ab7c0676bdb1ad0ce9b16673083c9602ec10ae1dd98e8748b336440b
TST: 370
SK: f219b2101164aa9723bde3a7346f68a35061c01f9782072580ba32df903ba891
PK: f66b920d5aa1a6085495a1480539beba01ffe60e6a6388d1b2e8eda23355810e
MSG: 015577d3e4a0ec1ab25930106343ff35ab4f1e0a8a2d844aadbb70e5fc5348ccb679c2295c51d702aaae7f6273ce70297b26cb7a253a3db94332e86a15b4a64491232791f7a8b082ee2834af30400e804647a532e9c454d2a0a7320130ab6d4d860073a34667ac25b7e5e2747ba9f5c94594fb68377ae260369c40713b4e32f23195bf91d3d7f1a2719bf408aad8d8a347b112e84b118817cb06513344021763035272a7db728a0ccdaa949c61715d0764140b3e8c01d20ff1593c7f2d55c4e82a1c0cb1ea58442bf80a741bca91f58ab0581b498ee9fe3c92ca654148ef75313543d1aff382befe1a93b02190ce0102175158e2071d02bacad8dbe9fb940fcb610c105ad52c80feb1ec4e524f4c0ec7983e9ce696fa4fcf4bf0514b8f0432b17d5448fc426fea2b01ac7b26c2aed769927534da22576fc1bba726e9d65be01b59f60a648ace2fc3e5e275789fa637cbbd84be3d6ac24457a6292cd656c7b569a52ffea7916b8d04b4f4a75be7ac95142f
SIG: 17f0127ca3bafa5f4ee959cd60f772be87a0034961517e39a0a1d0f4b9e26db1336e60c82b352c4cbacdbbd11771c3774f8cc5a1a795d6e4f4ebd51def36770b
TST: 371
SK: fc180035aec0f5ede7bda93bf77ade7a81ed06de07ee2e3aa8576be81608610a
PK: 4f215e948cae243ee3143b80282ad792c780d2a6b75060ca1d290ca1a8e3151f
MSG: b5e8b01625664b222339e0f05f93a990ba48b56ae65439a17520932df011721e284dbe36f98631c066510098a68d7b692a3863e99d58db76ca5667c8043cb10bd7abbaf506529fbb23a5166be038affdb9a234c4f4fcf43bddd6b8d2ce772dd653ed115c095e232b269dd4888d2368cb1c66be29dd383fca67f66765b296564e37555f0c0e484504c591f006ea8533a12583ad2e48318ff6f324ecaf804b1bae04aa896743e67ef61ca383d58e42acfc6410de30776e3ba262373b9e1441943955101a4e768231ad9c6529eff6118dde5df02f94b8d6df2d99f27863b517243a579e7aaff311ea3a0282e47ca876fabc2280fce7adc984dd0b30885b1650f1471dfcb0522d49fec7d042f32a93bc368f076006ea01ec1c7412bf66f62dc88de2c0b74701a5614e855e9fa728fb1f1171385f96afbde70dea02e9aa94dc21848c26302b50ae91f9693a1864e4e095ae03cdc22ad28a0eb7db596779246712fab5f5da327efec3e79612de0a6ccaa536759b8e
SIG: a43a71c3a19c35660dae6f31a254b8c0ea3593fc8fca74d13640012b9e9473d4afe070db01e7fb399bf4ca6070e062180011285a67dd6858b761e46c6bd32004
TST: 372
SK: a2836a65427912122d25dcdfc99d7046fe9b53d5c1bb23617f11890e94ca93ed
PK: 8c12bda214c8abb2286acffbf8112425040aab9f4d8bb7870b98da0159e882f1
MSG: 813d6061c56eae0ff53041c0244aa5e29e13ec0f3fb428d4beb8a99e04bca8c41bddb0db945f487efe38f2fc14a628fafa2462f860e4e34250eb4e93f139ab1b74a2614519e41ee2403be427930ab8bc82ec89ceafb60905bd4ddbbd13bdb19654314fc92373140b962e2258e038d71b9ec66b84ef8319e03551cb707e747f6c40ad476fbefdce71f3a7b67a1af1869bc6440686e7e0855e4f369d1d88b8099fba54714678627bba1aff41e7707bc97eddf890b0c08dce3e9800d24c6f61092ce28d481b5dea5c096c55d72f8946009131fb968e2bc8a054d825adab76740dcf0d758c8bf54ff38659e71b32bfe2e615aaabb0f5293085649cf60b9847bc62011ce3878af628984a5840a4ad5dae3702db367da0f8a165fed0517eb5c442b0145330241b97eeca733ba6688b9c129a61cd1236aff0e27bcf98c28b0fbeea55a3d7c7193d644b2749f986bd46af8938e8faaeafbd9cec3612ab005bd7c3eeafe9a31279ca6102560666ba16136ff1452f850adb
SIG: e6a9a6b436559a4320c45c0c2c4a2aedecb90d416d52c82680ac7330d062aebef3e9ac9f2c5ffa455c9be113013a2b282e5600fd306435ada83b1e48ba2a3605
TST: 373
SK: f051af426d0c3282fafc8bf912ade1c24211a95ad200e1eef549320e1cb1a252
PK: fa87955e0ea13dde49d83dc22e63a2bdf1076725c2cc7f93c76511f28e7944f2
MSG: b48d9f84762b3bcc66e96d76a616fa8fe8e01695251f47cfc1b7b17d60dc9f90d576ef64ee7d388504e2c9079638165a889696471c989a876f8f13b63b58d531fea4dd1229fc631668a047bfae2da281feae1b6de3ebe280abe0a82ee00fbfdc22ce2d10e06a0492ff1404dfc094c40b203bf55721dd787ed4e91d5517aaf58d3bdd35d44a65ae6ba75619b339b650518cefcc17493de27a3b5d41788f87edbde72610f181bf06e208e0eb7cdfe881d91a2d6cc77aa19c0fcf330fedb44675d800eb8cff9505d8887544a503cbe373c4847b19e8f3995726efd6649858595c57ccaf0cbc9eb25de83ba046bc9f1838ac7b8953dd81b81ac0f68d0e9338cb55402552afb6bc16949351b926d151a82efc695e8d7da0dd55099366789718ccbf36030bd2c3c109399be26cdb8b9e2a155f3b2cb1bfa71ab69a23625a4ac118fe91cb2c19788cf52a71d730d576b421d96982a51a2991daec440cda7e6cc3282b8312714278b819bfe2387eb96aa91d40173034f428
SIG: b8f713578a64466719aceb432fce302a87cf066bf3e102a350616921a840964bfc7e685d8fd17455ac3eb4861edcb8979d35e3a4bd82a078cd707721d733400e
TST: 374
SK: a103e92672c65f81ea5da1fff1a4038788479e941d503a756f4a755201a57c1d
PK: ee63a5b69641217acbaf3339da829ec071b9931e5987153514d30140837a7af4
MSG: b1984e9eec085d524c1eb3b95c89c84ae085be5dc65c326e19025e1210a1d50edbbba5d1370cf15d68d687eb113233e0fba50f9433c7d358773950c67931db8296bbcbecec888e87e71a2f7579fad2fa162b85fb97473c456b9a5ce2956676969c7bf4c45679085b62f2c224fc7f458794273f6d12c5f3e0d06951824d1cca3e2f904559ed28e2868b366d79d94dc98667b9b5924268f3e39b1291e5abe4a758f77019dacbb22bd8196e0a83a5677658836e96ca5635055a1e63d65d036a68d87ac2fd283fdda390319909c5cc7680368848873d597f298e0c6172308030ffd452bb1363617b316ed7cd949a165dc8abb53f991aef3f3e9502c5dfe4756b7c6bfdfe89f5e00febdd6afb0402818f11cf8d1d5864fe9da1b86e39aa935831506cf2400ea7ed75bd9533b23e202fe875d7d9638c89d11cb2d6e6021ae6bd27c7754810d35cd3a61494f27b16fc794e2cd2f0d3453ada933865db78c579571f8fc5c5c6be8eaffce6a852e5b3b1c524c49313d427abcb
SIG: 2aa2035c2ce5b5e6ae161e168f3ad0d6592bcf2c4a049d3ed342fceb56be9c7cb372027573ae0178e8878ebefca7b030327b8aad41857de58cb78e1a00cbac05
TST: 375
SK: d47c1b4b9e50cbb71fd07d096d91d87213d44b024373044761c4822f9d9df880
PK: f4e1cb86c8ca2cfee43e58594a8778436d3ea519704e00c1bbe48bbb1c9454f8
MSG: 88d7009d51de3d337eef0f215ea66ab830ec5a9e6823761c3b92ad93ea341db92ece67f4ef4ceb84194ae6926c3d014b2d59781f02e0b32f9a611222cb9a5850c6957cb8079ae64e0832a1f05e5d1a3c572f9d08f1437f76bb3b83b52967c3d48c3576848891c9658d4959eb80656d26cdba0810037c8a18318ff122f8aa8985c773cb317efa2f557f1c3896bcb162df5d87681bb787e7813aa2dea3b0c564d646a92861f444ca1407efbac3d12432cbb70a1d0eaffb11741d3718fedee2b83036189a6fc45a52f74fa487c18fd264a7945f6c9e44b011f5d86613f1939b19f4f4fdf53234057be3f005ad64eebf3c8ffb58cb40956c4336df01d4424b706a0e561d601708d12485e21bcb6d799d8d1d044b400064ec0944501406e70253947006cabbdb2dd6bd8cee4497653d9113a44d4de9b68d4c526fca0b9b0c18fe50fb917fdd9a914fb816108a73a6b3fff9e654e69c9cfe02b05c6c1b9d15c4e65cf31018b8100d784633ee1888eee3572aafa6f189ea22d0
SIG: 627e7ca7e34ed6331d62b9541c1ea9a9292be7b0a65d805e266b5122272a82db7d765acc7e2a290d685804922f91ed04a3c382c03ff21a1768f584413c4e5f00
TST: 376
SK: fc0c32c5eb6c71ea08dc2b300cbcef18fdde3ea20f68f21733237b4ddaab900e
PK: 47c37d8a080857eb8777a6c0a9a5c927303faf5c320953b5de48e462e12d0062
MSG: a7b1e2db6bdd96b3d51475603537a76b42b04d7ebd24fe515a887658e4a352e22109335639a59e2534811f4753b70209d0e4698e9d926088826c14689681ea00fa3a2fcaa0047ced3ef287e6172502b215e56497614d86b4cb26bcd77a2e172509360ee58893d01c0d0fb4d4abfe4dbd8d2a2f54190fa2f731c1ceac6829c3ddc9bfb2ffd70c57ba0c2b22d2326fbfe7390db8809f73547ff47b86c36f2bf7454e678c4f1c0fa870bd0e30bbf3278ec8d0c5e9b64aff0af64babc19b70f4cf9a41cb8f95d3cde24f456ba3571c8f021d38e591dec05cb5d1ca7b48f9da4bd734b069a9fd106500c1f408ab7fe8e4a6e6f3ed64da0ed24b01e33df8475f95fa9ed71d04dd30b3cd823755a3401bf5afae10ee7e18ec6fe637c3793fd434b48d7145130447e00299101052558b506554ec9c399f62941c3f414cbc352caa345b930adecfaddac91ee53d1451a65e06201026325de07c931f69bba868a7c87ee23c604ec6794332917dfe2c5b69669b659706917f71eddf96
SIG: 6887c6e2b98a82af5ee3dfa7ca2cb25d9c10745620a82956acba85cb57c8ec24279fa42f092359a1b6bbeafba050f14b6288209e6ef7bc1e0a2b872c1138f305
TST: 377
SK: a8d73d639a23cc6a967ef31bcabb5d063e53e1eab8fcc7cab9bc3a17fde9c2f8
PK: 8daa9f4c8b1a44691bf44521f2f7ca45dc7fc61f6a4ce6f98faa41c2a74977d1
MSG: fd1fac3d53313b11acd29f5a83ac11896dab2530fa47865b2295c0d99dd67c36ed8e5fa549150c794c5549efb5c1d69114d5d607b23285b7212afaab57846a54ae67b9e880e07b6586607cecf6d4eed516a3a75511fe367d88eb871e6d71b7d6aa1367a01421b1088fc2d75e44954b73625c52da8a3a183c60be9da6050f59a453caa53520593671728d431877bfaac913a765fb6a56b75290b2a8aaac34afb9217ba1b0d5850ba0fdabf80969def0feee794ceb60614e3368e63ef20e4c32d341ec9b0328ea9fe139207ed7a626ff08943b415233db7cfcc845c9b63121d4ed52ec3748ab6a1f36b2103c7dc7e9303acea4ba8af7a3e07184fb491e891ede84f0dc41cadc3973028e879acd2031afc29a16092868e2c7f539fc1b792edab195a25ab9830661346b39ef53915de4af52c421eaf172e9da76a08c283a52df907f705d7e8599c5baae0c2af380c1bb46f93484a03f28374324b278992b50b7afa02552cafa503f034f8d866e9b720271dd68ccb685a85fffd1
SIG: c4dcef1a2453939b364b340250c3129431431d5ba3f47670ab07ce680c69bf28b678627c76a6360fc40dc109aa7dea371b825e46134f624572182acf3957e70f
TST: 378
SK: 79c7dcb7d59a8df6b2b2ba0413059d89680995c20e916da01b8f067dc60cdeb4
PK: 298743c73918bd556b28f8d4824a09b814752a7aeae7ee04875c53f4d6b108d9
MSG: 5fe202f5b33b7788810d2508a13b3114d69b8596e6eacda05a04a2eb597fa3279c208b5a5b65daacb699f144e1d660e78e139b578331abec5c3c35334454f03e832c8d6e2984df5d450ecb5d33582a78808a9c78f26ebcd1244ef52e3fa6dca115c1f0cb56e38eae0e5b39f5fd863dffd0b2fb5b958f2d739db312fc667a17b031c4c9f8c5a2ad577984cc4146c437580efd2152173fe0d5782cc2ae9831a8d9a04177256018ff7631e0b0d8a99cb28f008b320421e27a74c31359188663456d85e098c1ebd281701097b6ae5a871e5ccc02058a501416cb91c12cef5be6f1914370e563f1a1b2aa41f4b8ee84cd32a1d509e529787d14a445438d807ecd620e2fa26de0da6426864784d4a28f54103e609283b99ee9b2b699c980bbb7882c3ea68ddc90802ac232f2c8e84291987bf3c5240921b59cfa214969317673d0be7f34b1ca0e15ea73c7175401ce550be106b49e62f8db68695e740e0f3a3556a19f3c8e6b91ac1cc23e863fcd0f0d9eb7047aa631e0d2eb9bcc6b
SIG: 7b7cbe44c771e4371bae13b0722babcc1064155732962f407cba2acd35381d42210bece822f4681121fd4dab745a1f3077922fba1a78045b712902baccac660e
TST: 379
SK: b9ced0412593fefed95e94ac965e5b23ff9d4b0e797db02bf497994d3b793e60
PK: c1629a723189959337f5535201e5d395ba0a03ea8c17660d0f8b6f6e6404bb12
MSG: 555bb39c1899d57cabe428064c2d925f5fc4cf7059b95fb89a8e9e3a7e426c6c922d9e4d76984ea2383cabb4f2befd89c1f20eaa8a00dbe787cfa70ae2ae6aa90331cbbe580fa5a02184ed05e6c8e89d576af28aeeaf7c4e2500f358a00971a0a75920e854849bf332142975404f598c32e96982043d992bcd1a4fe819bb5634ad03467afc4ce05073f88ba1ba4ae8653a04665cf3f71690fe13343885bc5ebc0e5e62d882f43b7c68900ac9438bf4a81ce90169ec129ee63e2c675a1a5a67e27cc798c48cc23f51078f463b3b7cc14e3bcfd2e9b82c75240934cbdc50c4308f282f193122995606f40135100a291c55afdf8934eb8b61d81421674124dec3b88f9a73110a9e616f5b826b9d343f3ac0e9d7bdf4fd8b648b40f0098b3897a3a1cd65a64570059b8bc5c6743883074c88623c1f5a88c58969e21c692aca236833d3470b3eb09815e1138e9d0650c390eee977422193b00918be8a97cc6199b451b05b5730d1d13358cf74610678f7ac7f7895cc2efc456e03873b
SIG: f1b797ded8a6942b12626848340fb719fcddafd98f33e2992d357bfdd35933c7ac561e5b2f939464338c5666854ca885c4d046eb2c54e48a1b5ed266ad34de05
TST: 380
SK: 81da168f02d46bb87cda845da43f8a6cba2c016878d6f49c6f061a60f155a04a
PK: aff86e98093ca4c71b1b804c5fe451cfdf868250dea30345fa4b89bb09b6a53b
MSG: 6bc6726a34a64aae76ab08c92b179e54ff5d2e65eb2c6c659ae8703cc245cbc2cf45a12b22c468ae61fd9a6627ad0626c9b1e5af412cb483eaee1db11b29f0a510c13e38020e09ae0eee762537a3e9d1a0c7b033d097fdc1f4f82629a9de9ef38da1cf96a940357d5f2e0e7e8dbc29db728a1e6aad876e5e053113d06420272b87cf0c40dfe03a544de96c7aea13ba0029b57b48d99dcc6a650492d78c4cdd1b28e1a115a7e3e7a7cb21333d4ff80858dfb67782c16354b8716596560d7d8e389eb15a052a0bf5d16eb54fb3e4973ad4984e72a187f5347d5b262c32b1647e42b6a53837096cc78c2a05ce1c6e12493a03f1a667584cb97f4fcd57ee944c65b7eed25f7ae0f3f6cede173fdfacf5af1db143730d18096664914ba4cfc6966f392022781c66a9417ca2680b51f63e4fba424ecfdbc6a2f01787d0e7484f8a8ab390aeaa6d1f7ed325d82feaa1692a4984fae43da87329b045da8f0a4f56b695aa935de152ce0385153720979a2b7006d405fcb0fba09e23b85fd19b
SIG: 4aaca947e3f22cc8b8588ee030ace8f6b5f5711c2974f20cc18c3b655b07a5bc1366b59a1708032d12cae01ab794f8cbcc1a330874a75035db1d69422d2fc00c
TST: 381
SK: af2e60da0f29bb1614fc3f193cc353331986b73f3f9a0aec9421b9473d6a4b6a
PK: c8bfe2835822199c6127b806fabeef0cb9ff59f3c81ff0cb89c556f55106af6a
MSG: 7dbb77b88bda94f344416a06b096566c6e8b393931a8243a6cab75c361fde7dc536aec40cded83296a89e8c3bef7d787cfc49401a7b9183f138d5000619ff073c05e2f841d6008358f10a2da7dcfac3d4d70c20d2ec34c7b6d5cd1a734d6bbb11c5fd8d2bce32ac810ef82b4188aa8ea3cfc3032233dc0e2600e9db6e18bc22b10044a31c15baceaf5554de89d2a3466807f244414d080ff2963956c6e83c8e144ed0066088b476ddcb564403447d9159f9089aba2b4d5575c4d8ae66fc8690e7349ed40832e6369c024563ec493bfcc0fc9ac787ac841397fe133167283d80c42f006a99d39e82979da3fa9334bd9ede0d14b41b7466bcebbe8171bc804a645d3723274a1b92bf82fd993358744de92441903d436fd47f23d40052a3829367f202f0553b5e49b76c5e03fa6ce7c3cf5eeb21de967bec4dd355925384ebf96697e823762bac4d43a767c241a4cef724a970d00ff3a8ab3b83eed840075c74e90f306e330013260962161e9d0910de183622ce9a6b8d5144280550fc7
SIG: 50f9f941a8da9f6240f76d2fa3b06dd6b2292ed32d1c05218097d34d8a19dfe553f76ae3c6b4a2ed20852128461540decf418f52d38e64037eec7771bd1afe00
TST: 382
SK: 605f90b53d8e4a3b48b97d745439f2a0807d83b8502e8e2979f03e8d376ac9fe
PK: aa3fae4cfa6f6bfd14ba0afa36dcb1a2656f36541ad6b3e67f1794b06360a62f
MSG: 3bcdcac292ac9519024aaecee2b3e999ff5d3445e9f1eb60940f06b91275b6c5db2722ed4d82fe89605226530f3e6b0737b308cde8956184944f388a80042f6cba274c0f7d1192a0a96b0da6e2d6a61b76518fbee555773a414590a928b4cd545fccf58172f35857120eb96e75c5c8ac9ae3add367d51d34ac403446360ec10f553ea9f14fb2b8b78cba18c3e506b2f04097063a43b2d36431cce02caf11c5a4db8c821752e52985d5af1bfbf4c61572e3fadae3ad424acd81662ea5837a1143b9669391d7b9cfe230cffb3a7bb03f6591c25a4f01c0d2d4aca3e74db1997d3739c851f0327db919ff6e77f6c8a20fdd3e1594e92d01901ab9aef194fc893e70d78c8ae0f480001a515d4f9923ae6278e8927237d05db23e984c92a683882f57b1f1882a74a193ab6912ff241b9ffa662a0d47f29205f084dbde845baaeb5dd36ae6439a437642fa763b57e8dbe84e55813f0151e97e5b9de768b234b8db15c496d4bfcfa1388788972bb50ce030bc6e0ccf4fa7d00d343782f6ba8de0
SIG: dd0212e63288cbe14a4569b4d891da3c7f92727c5e7f9a801cf9d6827085e7095b669d7d45f882ca5f0745dccd24d87a57181320191e5b7a47c3f7f2dccbd707
TST: 383
SK: 9e2c3d189838f4dd52ef0832886874c5ca493983ddadc07cbc570af2ee9d6209
PK: f68d3b81e73557ee1f08bd2d3f46a4718256a0f3cd8d2e03eb8fe882aab65c69
MSG: 19485f5238ba82eadf5eff14ca75cd42e5d56fea69d5718cfb5b1d40d760899b450e66884558f3f25b7c3de9afc4738d7ac09da5dd4689bbfac07836f5e0be432b1ddcf1b1a075bc9815d0debc865d90bd5a0c5f5604d9b46ace816c57694ecc3d40d8f84df0ede2bc4d577775a027f725de0816f563fa88f88e077720ebb6ac02574604819824db7474d4d0b22cd1bc05768e0fb867ca1c1a7b90b34ab7a41afc66957266ac0c915934aaf31c0cf6927a4f03f23285e6f24afd5813849bb08c203ac2d0336dcbf80d77f6cf7120edfbcdf181db107ec8e00f32449c1d3f5c049a92694b4ea2c6ebe5e2b0f64b5ae50ad3374d246b3270057e724a27cf263b633ab65ecb7f5c266b8007618b10ac9ac83db0febc04fd863d9661ab6e58494766f71b9a867c5a7a4555f667c1af2e54588f162a41ce756407cc4161d607b6e0682980934caa1bef036f7330d9eef01ecc553583fee5994e533a46ca916f60f8b961ae01d20f7abf0df6141b604de733c636b42018cd5f1d1ef4f84cee40fc
SIG: 38a31b6b465084738262a26c065fe5d9e2886bf9dd35cde05df9bad0cc7db401c750aa19e66090bce25a3c721201e60502c8c10454346648af065eab0ee7d80f
TST: 384
SK: 31010d1d67eb616348e84792b92d5dc128553cb52f6368159fe7b816cd0e7c37
PK: 266543d96787ca901fcff06e6e434491ae0970880a5a187d535edb19db5cabeb
MSG: 39f89a5e7aa530b5463d498f8035b9909d55da527cdbd4de6d228379f089e608a9207a2c5b9c42051a60c8ca3fb97a1c06cd747d9d0739970ceb88ce526f971140ea2ec21f090ba075bf8975faa508b1cc10efa494dc172e6d3d3f3f75dc8e0e96f05c0cccb2f96e911cfa7a2c82c9845018bb1f9d75f82e3dfe1139347b2ac058b014ac93760c90f5567ab5c4eba04b49fb09ddadd305be511dfe05c96ebc86fd67b5d0ab57d85f4fe5e2f0fa9d88a68f0f6b6bc8bb944eb3c0b17557e55d5ea187d922a42813e69057c9b6a7f75e49921b7079e58f8a63719ee3e1ad10cf0e8a70c4f1540218b70494bd029ee02ff9727a7d85d377919ec4051479b70f7cd6767723fe42c1c7899c2b7c1f702dd6b4d13b672d488f34a0e969db79cc2cb2524a948a8de4c5b623ecd90d6e82d97033c125637d1cd8c84803d8fbc012846ffe484f6c02149258f9462fa1e99c307dd0062fe0b6f11eee40c2629ef7c0f6a5107259ea5b9ffb6f29f12c32f7b5228cabc986ab66450af9dcc3da09d0e0b9a4
SIG: 7b1eb677c3e5e6a8b4ba69fcb7f6b1870e42a8d58958a35c674e2db82107481c4c7b37f0f689d39d9f51e181b17b1108c15a3e27b29df3a4315dcc4faf122205
TST: 385
SK: 8ff2398cd51f51d4c2c57869a2218b8486822031f400729f4ac4d5909c48bafe
PK: a5a88704b68677be3d16c3dc0052cfee6e2b30e08609059d4cba52c6d96061fb
MSG: 993953e47a341188bc592942e1557af29546e4e9368e2f1a5ee9806e2baf66b6190191fc5d2b7e47de37ff054fb2bbb1f031684ada5d607adda3d65433122fa904e0456faa84109bbc517f8ad39660876382adcfed0f7620cf1164622eacd91eb37a8596462ebe9ebe26bdc1e32cc34ad46fb1cea420e73c31215408e6d35425f44a829b132f631a3f6dd4b873a000667e19eb22fffd5903aaa7d4c8fdf21953c3c6178f5f8cb2aa6bff92894ead835888df060a3c9043026e0e2cef275497e7d105df3b644a98f26bf00105c99413ee0af8851954d65ceb8d79ad3071b8bb87f0b19743d2556ffd9819830b6eebf7ecc7e045661f43570ce9fdbbe2d252406fa90d04236f222c429ec16b1287224ada1a532161ae8b481bcab8d47afb3ed0445b3060fd6759179856f4085c1e585fd7c1409799af693cf427bd1d3dc10b5ae3447a8d2a18dc3a12a6860b22175dd5eb53a0950432e2d7aefece8af0ade3d8567743de43690f2d253723c5d7e48bd30d2937593701cecde9154b7665cb611d7d
SIG: 417a647829c92898e520ff5311daa0a139cd8fffcb25a18e6d9b50cb52cbc35424c39ebbb5d5ac6a6d63f1f53c4df212f7025a8aaef8e36493c874c3ce341a0e
TST: 386
SK: ef816c8f5ec34ef41f68831d90cd29e52de8973782d003ee4edada2ada2691d6
PK: 47f9b363a88a45053a05bb72160852bfe8f7dfefc2f37283de346752caf092cc
MSG: 9593c35cdec535bebb6965da68eab0b646bffcfbd04883bc4cef90d5d01f018c63c9b0ddfb3cef5e786284d5218caaaf060e9288952f16301ed8a4c1bcee256356a0c8bda359fbaa2782b10c86d18e20f7a0ec99b27a0b4dbefc0a262a3bf68fe81444dcae5f693eb0f16e6ee03f8fcbf3a3398146d20ec4d2657761fd0320fee7ea703c49a6a543bc9bba911e7925038710e8c36552d476d6027f58b2c52ba51ad65ea4f039c78f96b889102bb4bdd69b68e9c3d45b5176a2d82b0b95dc321016370dae30c3936515db0464c41774301c74e42d89b8bf4b9c19ed554b12febac0f60ddb3219ccc5603531dbf2eb5f293425d72ccefa0c7f144aba89347b296be87ff18994b4a0c70c930f059303b5dd4c8fe1e6bbc3cd68c6c0d84246dc6e6140a2abd1780b13f1594a6019d1778b7cbb3a3e3a34bfae7297f0b3edc376941c32352a4be314b84a9d8d6d7f1f38a0ad3798020aa2a331a402be9c704484744a730cbdedcb904b6fde708fbd14bfdc29efd461d1d0b5825de0bc79422b69a2722f
SIG: 65c5d10ea7bfdbb38d55364a9968f82b548224dff3363b2ddcf585163dea27dc63b0563eb1a8dfbee951d3c9b33fcd6bbf0921c3abb21786b229069bd9ca000a
TST: 387
SK: 45eb0c4dfafa2a7690ef579c095456ceedcd32f0b6144d0c380f87fb744a0b1f
PK: fc85632c98384b5f9682aed9cd664cf1f48e588be2d568e5c734494df4c712b8
MSG: 6f66d847405a03d7bd6f8d2897dbdf04e76d7df2d9470a4996b7dd6db88500f8f4f83e960e219a2486e24545add13614550414d827c41a9b08318daf01b15214c64a4266cbf8a5717ada3e62c26729073e16ddbd66f2d520e1e09935de05e4db11c396d477010aec66aafb762e69238d0b9e76b452454bf9e451e76ac79e6990d41b932bc32917093783c91bc9cf0bbe3b514070a1e692ff34fd06b66ea11f39e10af933ee96d8e9b677cb03737e7964eeaa725f121207f9c1b26a96c616df7cb7caef47bda901368ff2ea586e422e65bf21a691bdd2c13e67fff58cfbfed81782049dafa0f727df88623f2f7e8f262daf939542a187b8720a9b6b2b09890e54876b28a43874abbe3bfa981f8138b772c5d51736885f86acac2215a0b010dfc2c6b150845d4f8296252586a3e115f303c3d8a582e20fd2d43f6c446e5d00280ec179823b7fb4c1b0feb94eb4ef1707f5184e3b52461a7562d1f307cb751cdbbf6eae49ffae91862358e74e9548822b8a049fec6bf4c7a99cabbe09206577b657e31f
SIG: 55851de8e1092f78944f6c6dd95bf07e2dbc8df7f57ad576829b978e3af58a7a8e94ed4dccbc0182467edf0bad4bae7ca84aa9a0c17c61a9e0ddff1d7525d704
TST: 388
SK: 709d2e199006f5369a7a0bdd34e74dc784be33880ea3c5dd10ed5c94451e7972
PK: 06f989202ba2cbc9c150be611262aca00c45f012f89fbaf89f8ceccba0b1934a
MSG: 62f003140fa09e0387d187a0ff96c4563df9f4e28c2282c0183ac3eede1312354921f780fca5361d3068d29949630b7530cd5914ace0468d014b6f53d839b82e38817dbf2d8392c3ce3424eab86a24d804c7acb1ce7acfe0a1cda4393924283105da4a7741196e027550047f85b7a0a01d454124efc0e299f0ef9ad14350543053482261528baa56e65999ac802c00a336267c635106b26403c19f391d53bd82861d6d48a4380b3043aa91d649536881204eccb0de20d43e5a3755b7f600916eccae42a0c9053b462d9417a13d67d778264a896e8eaf90baf66d29e5438a716781123a89fa9b8beef91d965af2f4a1a5bd5d2e2aaf46d5c94b7709cdd38d05feee4bfb76a359077c16bc4be9116e69001271cda565bc19bf47d4f986bd9c0d184cd8a3520ca1bdb4b505aaf7cb4ec9f94789779d30714e79116dd5019d59b28b17dad96f4e2155ad9c61274addc6b638109504e9ed19f4eda5377762648c4098224e3391043e4c2ad591654c9e7f974efdf0b0504b6fa5f646cecf44cd372412372505
SIG: 629bf97b0c78ee6a9c8759fbea28224e27abbb6cbe4dea5bb797e6e0fe80c913f953e3a9b623352d13acf4ce6250fb029a1e198d72bd5e7402e60e9e48ca3501
TST: 389
SK: 5151617421aadc9c95a442b45e7ff6de06a2c733b85bd789fbad414ee3c91add
PK: 14941d559761b30ab0a86d47e0f7d1896b33784527c80af41cb84810cbff9dbf
MSG: 216e9d40bcdc3b2650188d121c9f8ef29e914facd022fe01b90ed11225f2eb93538e5fcee5ab8045e9199aa76a16bdd0616805660e247fecd7e22821b69b1f8e8a58ac3fb85691d75d5957a1daf53ff9ee6476d7c4bc541e6ad38e3a34ea90fc52a48b9399f92d17c9bb0d7fc3104c55d0efb4ea5b831ff9490b3f79f4d9d699594b741566f2b50a8fc78cc403fa40f5abb6638a32f449a8b3ef029c402f46931ad2bd3e8e683108714c989ae21689e9c444b9f55b81119bb5035bcf73e97ce43a2218c7bc3e430d1e814f34dee057265d3194b9f43875d8381f525f78576e64ce692584faa30fb743a12d1b77614d2e10a6b856b52be27cdb630ba1f0d3a6f8ea9844542e584ea0a2777527d0c52aca949aacda45ad83d16d5c83d663adb79cad6f3e39e990fe282a14c353aa2379d7f06adab74cea021b8983a57f1d0cf703292eb05ece89c53f3a1265610e0c1ea8ddd444d1ffd6bc3d03f0a6e4d0df5c5b8dc1f95d9f5558b118afe6bea0f6c2931363f03ab34e757d49364174f658efbbf38dc177
SIG: fae4773b334460c77bf01ec6366c4fe61c0cab57d8a4b03909c619e11ee3461c13fa21576f63870e423dd04181e4a7013a7524f246fe33853c674162a7815104
TST: 390
SK: 38bed445556de74482bf5fec0506f9af330b151e50d4774dfe8591d7b7e0276b
PK: 4c0f9c49a42f4047bfe6885551c5e4b856cf771a67af3f89dbf602f9db9220f3
MSG: 0ff0031df0beeff3710c6b763f9b8ec81719bfa1528ce46519adf3d3412d93fb188fd497d5d17091c0f0345960dd0eb0c09fc4005173665d4d97f95c13828bc76b3492b87a4b64253c8b5fa47aa75fa3b86d5abeea8de5959a602289136f60a69b309e773b2255cde19ed2a2e199c33db11c16ade08a319750b851d92c692924fc9859be523431cbe78ec092db1129210ebbeaa7c2a2c000eeb105ca0301a48f3e45fdfb15b275cbab83ca5c99d737a585320e9e3b317179bd86467fa9694fcdb2ac6ad36ed7144843dbc34e423d35afd7d8972a1c43c199a191abd6ceba4936d395c995a3eb13cb057f88a9dc9490fe98845ee5d26a89fb642a2a516dc3056c54d3637213363a8628a42a395d942b954a89e8ef7a744d8ae5adac88c616efaa90e2077205a60baffede5c87bb14dead306229495f698f3e490616966b1636387d0d86183f945b24a9dcfccf4d36722cd12ebb6bd8e78325752afa2b1abd13c4bdbcadd170869136826242acfb721de5ff27ba8aa0c018b225ed3404803ce9fa2d508d8944
SIG: f702d0d463282fc7fd5f8f9029b89c626cafd83450c3bb9dd8f6589f0c4b4b71f649ea212e5e33487c59c168ea3ad83150f1fcdfe8c53eba65adc2023c25830f
TST: 391
SK: 055460b32dd04d7f4b2311a89807e073fd556565a4771857d882794130a2fe5d
PK: 260f8fed4bba30b9e12ad8523fbb6f57f0a7a882550061f1da46fbd8ea442221
MSG: 7407f96ee3e79c69d36ce1f64e4f188655ea68b947e7e2be97b05ebc6d4439e950276ef3f0e6a03dd48b24f66929b49c1580eb468807e1e7a25eb9b94da340c53f984f8b81603efb61047bf3f14b686d9798003d2f68589a79ebfad54409c71c90ff67c11fbd76cc72c2d145f458e42f88b75d250eadcafe66bf37ffc837b62ff006685b7f85a9d875fc078c82e61fe35d1922527a551dab62f9e477499146bad912203e664c417c3679c02d872abac0032f8cc77f77bfe54d3326fdee9276a48ea4eb251350406882d08c830e7649fe6854558a7513ab2d8d2ac3e5ced8a808d2aee454779edabd1aa63bb19f718f470bdc8451cd9b294941e3497063b1e39b6ca184562fe838cbfeee922de24ddfcf9882c5e615b11bf904817fbd647139db80b4e8feb37f11e1852d7e876db9cb63c94d7ee34192f7200b5bc77a0311ae43b806ebd4c2896c53f58f7ebc1625cb20d7107ef9db0da28788523de991ef6c5866b18d8de83a954d3281e06dbf27c4f2382e08cd0e0f6ebae3f961b77fce5a95a9b0621b756f
SIG: 23f4f1627fbabd7891d7d8489631c7231d22de71864e262ab4da84ea8a13a60feac4dcfb1812f1200444b775f121d7266d755ce9b6a9ad796559c0a26b516d02
TST: 392
SK: e9f6d31b936942c526e0f9ec4f5a7ac25fa789e0c434bcd9199d720c743c84c4
PK: 32126d26e28231c5b585b13f43a01c6fe542946b07d3a91e57d281523f5cb45c
MSG: e88133f3d17642d5c22779a85316ba0df34c792b4efee49ed7dd93ca3322ef47c72e5b2e4595c77800434b60719adf54e4c1a34c89fa1e27ee8d35a0921f9755ac4a77a6c1684ea0f5c8ee5f759ce59bfe8315800a67aa6c64ddfaac92eabe6c2c613779784b3affafcc620f2a6dc5cb8d8dc7d74aa4d79494678494e5e6394c433c14809ff40c9a592d0d694a81103b44531e1f48bc13965d15af8bf3340488f8cd58f09ae1a6616bf85ac9de7e0c6696aa2f1bec15e17a44da4a84edb4ec6d77247788ba0de3ae12a155cbedc0da2f568eef0b75a877ea5b0c2c0d4bf2c61d468a46faadfaece35fc263a9be9987f4f7f78f05c707784378c7b8f7daf9ac3a122aad39a1677966da9ef286c9e062c4f439ad0bddea26e54b2f7388e238b2a64928450d34564c5a447e7afbbedd1085f1f24c11ae084322d1a32cf8aa473941f00d56b1618213cab3900aa606463d9f800e926f9f42d4b082d8c5ec3a4a025b45f9aadc8bcbd17091b3da49e9453dc55e89b5b5fe6b31f5eddad10b6601572568d8e205d3251a
SIG: 7e3b1c4c716c808e90b974458915f3b2239c42077119fe270788fae520578bd7da6488044132e1bef23e3b23c34d9c1862744f28fcaecda6cac0fd72b93b6a0f
TST: 393
SK: 6bf4caaabb96854a38a572f4ce6c7838f7e750118c73f2723582618e2307f838
PK: 08126373d056f00e54b8d43d77c35f5f919833e90d8aafd6c8246d27917ad091
MSG: 4776e9d60085481fa537bf295bdabd8b1cf632a8cd40bce6bd325c129f977000e88468ebf2dc158ac0f207212db00fb60b8ec8bae229372e9a6b01530a7ed1bc9d389ec8913f59030d5b54af56ae1ccc28f37cc96a8e53204e92a677766adfaada99b0281f867f61ac9ff7d972ee3ed427d72faae75d4aec01b5ffc37061b6f0f7e5714c4cf30d5b731b0746065f19e4c8922dde642f80fe24a3c8dcb2e5f1c266e2af6c37decf55a2baa54f0d5cf0839370c3e0b4e77a4f36bbb3162014933a4a4ebcae8c60961ac6dcf134f30828d31402ae74e7e8513c9d2ad8ee46b7a9d53a1f87ebfce04f461bded1749b6fc4c4f25793525692d7a0e426c84e06082cc3e6abb51368370cbb106c7a0897f66d92c9739cff9f2706d6a2980ecea3ac4945f0f47e656bd9637777e853d2a839104327dc049ebc34f049d6c2f80eca99db7b418424acef752260d2d427949323997cd9617edf50d441d0088b1d47912e35cf542315265829f383f45860d3b45e735bb2f8586dcf58db4f2acfb4a68853a96eed7b89769d365613
SIG: d2113f80d6cf928486a250a679d6e74b35ea9d26061fa94d769e1a8fbfa0a734227f55537e4ebff59336db141cf5d6d482a0711f1e9fc72ff70956a11b4fb909
TST: 394
SK: 5d9585736ab209b0abe8bf74aca4eea4f6d1650b532550a223e044580f8e20de
PK: e77729edfd2144b2b12078765417fa21f1594f09b269e9b6706802b4f3bdfe85
MSG: 08693591e6c58a5ead9c85fe8ec58508f81a3467636c2d34fcc1f466e5c6dafdc37c35cbee35589c6997e2b15448132744e5a1e131bb49bf5c2563f87ead3efe01e88cbf24cc1769c78cdfc167e378215b15859c7a28ece70e188fa330267d3fc57b4ace6c1520ec67875067fd33be86f4a1967afb3eb164c797cf28d8072aa69d82afa38374f8e5797c4c28471b7d69f5b9c7b4acdbc19f3c5c5d400808a982a47837aed1b3841d69890eeb31494e10e3e513d12d0ca686c7ce651778092703fef0dcc0214077dfb361251bdea4364dd41b97bceb0fb1475a50e4708f47f7878c74401e9771cc3fceace89169981aa77250850090d181d8358ebba65e290acb0352bece8c579832a601551816d1c05621ccbbee0fbe39ea2f195393199e69c234c2fb1c37e474840860ce609161fcfce2869574be0d38f95e20f4f8725247b9627b46e834905101ac12b934cbf87cb2d190d2f51490a82c4e810eddb81f956a9f36bda497bca506a49ee9cd47fda5b7f2b884a3648cadd12ab61898ada46ecc970f81dc9f876845db
SIG: e7b08e1d5809fdd8529443d65ada5dd655ea55b5415a011393be7071676486d358e8d2a460ebe075b0e701b24c9e3ab5f2b033592d4de3b7f37fd541f6920909
TST: 395
SK: 60b142f165114143ca30a604fef51c686436aa1b9afdb266b3e398ccb3c4d855
PK: eaf6c5a76ca99bf7306498888c3b7a1feae98bf8988d7f2e1547f8f53a4528aa
MSG: 1815dee1173b78264720d35b7cc2454a000a65fff214e2473e20bc83f3ecde9c04c1e0696ce6e55519dd2a75ce0464bf601adc381e793ecb9f8ce7ab87b6ca2a3e410f639069451978d14873d3390fab8623969713c3dfcd58d86d124073761ee09a652a48767f9646cb726ac454ac9a1bc5faed3026b703982bc2b1e0758210e1d62519230eb2b2f4a486bc55168560c4363df5ff5adfda11ac7ef51b18196c94337c07aef117990f770c0f1e8c0f88eb6ffc40e8ed7c3a80a632db1e7f63b63096e2ac49e57792b31143e2f4faabceae66b27471681c36fc1139007f9b548cdc6e3b8fbbdaba7a8adb843431238bb461ba24f6e09f62c72d6377b4048cb0134c25a5411a20bfcfc13e48d80e36bfb0da7e0185d33f1928636e15dee0e5df8992a16572b13ea8f7cf85cae32d529f66e8f6d2fb2ad0bbfe7199169b2567ba00c781b20a48e1d70df9fa3119cd7e5bbe58884b0b51218940fa815f85625fa203471cee8084780eb0b9356f9f3d4f6df740301d707ef1ffb3519e3f90b8064b98e70f375d071426881718
SIG: a621f084ea1a36ef812a9755c9afbb53dadaae6b3a53fa8344ca40d3612a268a35fed0fd398ab75bcd639c547937c94155ab1a7a3467dd4bfddfacab1655e908
TST: 396
SK: 734ba47033c6140232dd4a7a14f1a7743eefe9070bad9662491630cc9d28c1f3
PK: 2fa5df3026d60742e2aff6b57842c7126846c8a7bbe9266efa7b3f2398c357ea
MSG: 5d3c659810c3fea52a6df3861e5cdc5b703cc1cef48558c61d8c51d0edea5a1479cfe5063d82ded9ca681e5748887c40ecfb9e1a9a8b7f8509d10776461c3923399693a78189089178d5aabd15f8c846642be47d6d4caf13824edcefb809868fa72ddf035c4de8ef0a9c832264f66f012761ce6955bc3c416e93e29188025ebbb13a553258c1d7c499c9a4aeb10bb36f61d1bb4cec5ae55d175722b9a9696df881951e35200b9653cf6ed4b3d15de087a9d1c319fce8582156bebf3fc91e0e610ff7a15308fd1d2c6069fbbb2947d3110731d245ae2963014bd76dea42db125cecc493c8e9091a76646577729aed4966fce9699fe12e367d665df9e95a9193e1133e143af92f82b66ac7764e5033178690521809a7107d8ae9b88e0ed1f35b1719901b930ad0e1cbce7fb30267b1155204f605f525e49de2988ea7f74be8815177fd976a1bcc126d9c9c135c5b4276d38019c34aefb7a0220f7f5aeff380aed627b070c2c9e21533bb35c08e394c85ae25e6862942599c65dbae5977a584a88180e0c8c71e5a8409e04ef7
SIG: 9bd074d1d0bd28001baf7d2d4e82435df08c4264d8cbb1c381183c2f01223f79f94923ca178cac75564e16c7f56079088f7ed885de4d509fbc78f438fba3f607
TST: 397
SK: 45e34d0ef4c196fa6d572b6b1774b5218f7c3291304c13500df7070d90e8039e
PK: 13a7304dff423359177abafa5e6508d26769ca99cf8af45c383f3ff634406003
MSG: 3d9ed5c64b75e135df2f5e85300d90f21b363935e2817556fc9311751ba7535477dec8356ec385efb82b414062f35bb6d3edeafde305f9900a25e9813c9ee0237d46409650cdcdb5dfa2301a8e2647f8d3819d86f7b7e3070d33440f82c4054b1ab5edebeb27f95b3c4c6fdd468f21600f03b3494da200bab9293c38d02fc44048e52ff5fd0f7217a04d4ce912a180d1628f368280b6892672e8ff98d4629ac28b60c02a301e6c6026c1b9e9ef21cf0392df225008d5a0e0284b282631ad1710f811615697066c98296519948a7cfed5aeeb454ee7a61cc271bd3d499be17df09d3a0e790ee6b9bd99e1b919bed4a063b8d1a34f1afd2e952b9dfefd770969c8b2fc37977abb0fee6317253a23ecc97578168973334c8f91763ab97f29c49baeee7b35f3ae7f5cd3a4a6e697ef255a3c2ec0c752a3396f69f663ca1fc2b332dfe6c0faf78afe9c68d99571e8e896c5093085e9863a27648a9e58f3a9a84cbbfe2b41ca3633dd5cf6e82cb77cecacad8d78b353f48db42d99c36bcad170ea9e98abb2788c33a3c706268f3631
SIG: b42c1f925f4baccd129efb109db354aca31c6898f4f451294749a26a6da1677bd3a5c04119e35f47319f20cfdfc08bb4528b21009e00bd41ebc0f46863bed10b
TST: 398
SK: 888ce2ecceda9ca2b948ac1443c2aedd7595aacf36edaf27255bde7a6991dcc0
PK: 016e572b4f98417c6ee297abd784ea48226ff4fbf0050a5ade8806e7046d3ba3
MSG: 5c801a8e664e7660760a25a5e1431a62159fc3f3aa713780ae7cbce23b8564782799bf2be4817ee2921965bab7e1d44833824c1628d42dcee3e46ae42b2816d0a432a1ab0bd21fcf30adb63d8dd76569544343d0035c760522ca68bea72c404edda1e9095ec90f3325681c6de0f4c12d1afbcba2c7871a1b1e1f19c35b0bed9ec2a87c043d36d819396bd5d099e1aa090391297c733f65a8c5d2120c67635316fab25b4d4847a45fc3f76f2e2426dbee4629975062fce14e2189dba27fb1ded2453f001debfaa899c11660612d2ce2ad2f762ea5dee7e71e58adcdcefa79e8e8b27fc4ccf89aabf176b5d34f82dd15d889f9f087dc9ae8a42a72f3b83583616e170637cd1adf38aa6551cbacca3602bdc7ae210c4a446b3af8db2720e549bbedb8bed215ae00f19da29d8fb0b642d27b2d88575f0ee84f3d129eb774d20f537a1c0fdcf717bdebcfe47f8331a341864346fa6a1c6bbfd178819e387a0d5499a68e81cc9f82ad39e31e4dfe71952d5ea5cc8052a3ceed1751f59dc7ecc9742fad144e18dda8d0582e74e39ca8c4
SIG: 99d83f148a236ebbef1cad88cb3c7694f4986c9250e21c3603a0d941bff199cf77d6ce99efdb20533188d68ad133de033a1fb3468abb706d2b8b4fbac08dfe03
TST: 399
SK: 617390857dc10cdf82b5c94261f58ce2d44aa2f57d298f08a2d6c74d28147daf
PK: 89e0c3e0a0f130d1916e0e3849b7286fa2e3ac4c17bd1f716ee5a72f0257fb8d
MSG: 1fd9e7453eaffd7c9b54055622dde170dd58b71cb945de75351d5fceb1f536bde25158f03786155f953dc207a1708f90d95b15aca0aee3097fdcaae85e4ab1c2cdb705c53e6c2ed21a994b304a75caf2ce4fc7d61f561e74e297397e2cde5cc69056940343aa81375d0af18d17d2f34c0a71dcf1de3c4fc488a14c5fa6b3337a3174b1da7958fb00bd5955148221427c60dba04117c80d2488656dbd5343de891287b50ef4df9825eda76b4977f3acd4ab6d3102fa56878306cd76561491bcfdaa1da567e677f7f03bae5dbf4426c3c4a6c3d082f9178b2efdd2bd49eee97ef4dcf3f0f51bbdeffe5ae6601e28019518f827f02e51f6679b8715978bec3e69d577156dd719959371baf034219fbbd17a2369a8541490f6a02013e33e74f4769be37aefa4defb6bfb3f351c2a261482c2fbec49f85f8445456e8f5a474030cd72d095ef6a622030e1e43a0c5debb034731d2f5e8e4ba3990f077d0c162649d1fa3ea4fe1e81d74aa849e21b059d966cbad4c493ca10bafe7a69243e3c0a6ebfd13d697906303392ba65d4fe06b6a5
SIG: 63e90a6afbbbb0ee696bfb56efd679d68a9851a8947640a97f41f68edfeadd216ed8698e2e43c820c9044caa7adaab5b76762b681831a9f760476a8443c43c06
TST: 400
SK: 877d017436369ec2453fed46e977d6acc3a7be60d31395ad6e7ea9e07480e4c9
PK: 4e65422fed334a55e8b673893eba7c181dd724dda002817b0bae28acdc3f7fc0
MSG: 4ed3f5bdbd41d0e3b0a8a7fc3752eea496d6141678cbfe06757f61e1a168d761b6da83052f7994950d24626f004fbe9b8c9562e0c955fb3b5c08fd2d3d258393a349030c8e156205b40483038be1959f1cba490a87fe13899e4f3752063b68fe3e1c5071f7db0002f01494b4a3ee2e07992bdd200db4316629ee8a95ca347f0b28d6402a6da8b53e6b32581c3691e11ae9b6e0f0494894e649a92d03eb49c4d6833fa1f54f8dcd91d06936a6e62d491e2cea46dd07d9f02d3254b850bc9749f258a61ad3b9cc24b03287331b85a24143aaf8fcccac5f18bfc72dec75c0233516aa6e4589c78c665a186ed902091df97b0d04e83a2d74d789891aea2cacf813fffb5efaf78dbcd7af54ef55c77b1c4c8ace9e9278adc23d76c779d64b3bbbd1fb33b09836ea64a71e4711e89e8da0f709213342176ae22c6e7852c3973b60d9f98889b442aa48d7bfdfdef64c36c586c4fb2ad2e27ebe479f6d722f069fd6106b0d08975d5f721547c3b9c52f9fc5f45bb45b5b632188e80626518a79056bdc4ee1d2be6c6542a21fadea92c6dfb776
SIG: 7688f3f2401eacaf2dd88e170ff1c4d7e94822a77f6b550b569e82152bbbb434057e01230b05ce58ee1dee5226b5c7cdbe5a8ade3b9465f59aed74145d14330c
TST: 401
SK: 4f0b3607d70b0f2698327ef4f1982c5b4b94be78f50c76f43bd642f1f0ede39b
PK: 942b43089fd031cec0f99e5e550d65307fb6c3e793449fb390ff730fffd7c74b
MSG: 9f700a1d2560f69d9bc105bc83bff539e4258c0248602013a959b978a19cc273280d90c0178089578b50518e06ad1eab790ffe710c63d78887a95569144f3e58a8837f93dd516fcddd22bc97a7f14411d424b2e8e9aa7c280119ad94ce92533fc7fea6c66248644ac3e1beef2553a6f61e91b9379b0fe0c68b40681455b311f40df0c97f53fc954242c375e7708d61bad9f51296247274fa01a7328fa5009d9995f501ae8683552b11a49d2638116723b1319450a90138d278cd9512b80ca5792ed16c683bef92ec87884c9f07f137dc47a13146e511065c2e1b4b80efde88ae12e29431beb7aee365c16d80506b99afa6a1406edb061766875832dba473e519dd7018f402eb1bb3014b7cee4f02e980b1b17127e7d25dfe0c168c5344f1c90044f827707dca03070e4c43cc460047ff62870f075f34591816e4d07ee302e7b2c2ca9255a35e8adec03530e86a13b1bdfa1498813098f9ba59f8187abcafe21ba09d7c4aaa1ad10a2f28334ab53996147c2459c01b6a10839e0301123d91a35ced7af89afbac7d9cf8ac9a38ceebef83
SIG: f396a11f2f03c61439684f79001bd4f346a348dcf1d3beb2d3bfe33ea73a5ad4eb97506acfbffb784e77548189cd599f8ccf17355dde80e75024ef2a78d5fa03
TST: 402
SK: b8a0010c784d8d002a31da11d022d30188a4197a1d5f14ea4c0dab29a2e40668
PK: 8bdc63e50bede13c91a41e4b4b7857b9e553f484e3c1ec167dc04c281ea86622
MSG: 5c6ccb298be216808b811e56d972f456b69ad39594eee354701ca6b3e38d1f41a359e5512af98a3a0873265fe5191f4f2ecaf66bee75a3ac0b71a4ddf2a759ebdddbd88a6a1c6fd0fcf7d7cb92a84e3307b4a4f98c710abf4f553dee74f652d2ac64bc30f72bf4354ef7e806a19071a051bcfcfb27e37fddd41eceaec1758e94695c670ef4c5a5902178329db9585c65ef0fa3cd62449bb20b1f13aecfdd1c6cf78c51f568ce9fb85259aad05b38c6b485f6b86076928ddb4e2036f45e7b9c6a7ff24ae1776030e2576825019ab463ebf7103a33072033eacbb5b503f53266afb82f9b2454b8dc057d84f30d9d2cb7c3a31a7dbdfba5b8e49231c231396c47ca042c8e48a1a5e3ec9afe4020595390f9990dfb874e0825ae9ae5e752af63af6fd3e787e75e8d8dc4c66302277ac01b30a18a56cb82c8a7ebdc915b7153255a1fedc492e49660262bb249780d173e1fd20d18c4f6b0b69aa2eca024bf3c80d7d5962cc4a129a7943b27f33cc799a36045541275a2cdb92a40e485ba8b737a04b43d29c3e25f76cb3d93a6b94461f88f5696
SIG: b3f6cf4c0e0f9074ff2c2c47e163202f1e9d6ee117cf757633e4abe74423aa70008ada1509ec1dc117c1c230e9b23786f3d0f29b73aa284536e9580106a8a70c
TST: 403
SK: efc86cbe40363abfbb2a4b1fcce5fd6084da96e7e814de71aadf9a618f303625
PK: 22f295cee727d28d2b9317153e7d9412da1065c1b16ae2a251dd1fb431c62b01
MSG: 9e4fa45dc026710f6bef4ed0f07c544b0bb0d88fa79e7177d8448bc209d71cfe9743c10af0c9937d72e1819e5b531d661c58c63141ce8662c8839e664db79e16c54d113abb02a75bdf11b3453d071825bc415741e99483546b8e1e6819de53017092e4ef871f1ca0d3508f937828a4667db11ffff9416eebb94bf9b84d654603094834a99ca70b90f562a86823624dfe9cb2f9e88c173f13464d4ce255f222db50dd63ab42465734e75295c064b64cc3f15e6237e37f33d615f7c243e4ba308960cfd4393402525500bb7902970b3931d48b35666a2d4d2ab08fa12af366a004346c9dd93d39fb1b7340f104e51fedbb533605b5ff39cf6d59513f12856dcfa198d793b0fc875cdea0741f1455746d8a19c3e9d928f0021b01c25131811e48c3c75c6f41422a8810c6c81f35b454eeae8cd17cf3f2e6f0bcd9f290984f496578623ab8e2738d2d10840eb91d101cb4a23722b72e3dd185440c3b9f44d46a393a34c187a20d610bb698c50531741efe96323512329800772a408065a7ef8e4e4105eb1f5bf6d3fd6b217fd836d89f53b96f45
SIG: f8818310228ca76111524ce94bfcb0246ea63508cee9306592b2f77548edefcf76bd1454508ea715042cec169cea5115ab54235cb1097b10702aa38378028e0c
TST: 404
SK: 33556c60de2f2c9a9303b99add378592060505f8e49861085a4b15f072a7ef28
PK: 231ec8cd845859f69961275119dbe4f715e5ec5aa98bb8741675b3c2d0c89fee
MSG: 96af540ea2b1923f5fd0aad321ac032070c2d65ba13d164e75c3469758fcf31bb31655cb3a721f9cb34be2c90c77eb65be37f606d32a917a4cb9a709ac0705229930ef6eb6fdb0fa3c0fd3a90ce171674ee3ed06354bafc3c7075467a57445b80385640447902be39262894b1f64fea58287dc322d19875972a7c8be91d31f021c70eb682fdf11a10f8f582a126e064794838c69fdf64f5b6e8ba59d48b4384f8e9fb5c087cc7738295cd32344ba3b697ee6b6a8b78ee7a9575c97972a4d1bb18486f9037a0f3c6f471a90f86498dbc0df5232c07e8c01b690bee75302992a7a36fb4437c25a8bf5e34cf7d5b55572c700a079848d381364f9946a91eb1603ff3de5ebdd523bd92564818e237a53e8f522deaa2c29b897e961586e100ed0fc0ad70d160934e694027e5c957920bc0546e901be39a84535597e1f280c222267abe97f41205d8171820dd2faafc0699419321a9160f69b99fd41180945b62d2dd105cc7bbe821d28605e098edfa8b2309aeb0534e756377f59937c67463fd87c8b92ab58119cf4ce6c665af572fbae1de4a2cc71
SIG: e06a7a414457bbbef2bac3775ccad087dacb1fa4bf938894e8c929118e09e678dd19938bc88f43ed0f7d31cc6a0e602c4e4d1fee33d41e74a119fa2d1e4e340f
TST: 405
SK: 7a5c74314e1183334a4b6226b9a82d70fc2a124e3f87db6a2283ee05b68e34e0
PK: beae7d3dd97c67f6273bfaa066131fed8ace7f535fe6464e65791c7e5398576c
MSG: 98bac6724755912992adc2a48b5442376f2d927997a040fb98efe544eb0c8e1866b9616e298d3360316ed976bd946a411fdd3a6b625c0c1a37af0f41cf6569a7884ab8467491a987df3ea7a0b7ebc4692569a34ce3a2ea3503495b2c02d49d7d7db579d13a82cf0cf7a9547a6eaebe68e7267d45a60b8d4772455228cca4036e282e1a1216f34cef7ea68f938270bdb04293c885d005f9f7e638a8b4ead2626c0945174ff2a3e2d6e15a4c0338c09e1260f0928ca9d3499824f3fedc4785da49c5c34a56855e241facc6347a399ddcac4399a8b158198c151461a3b189e58ec1f7efcf2ab2031fb17b6f035ba1f092e9eee2e92c2d6cc2032287f854b41e70fc61c8d11a2e4f0708f02eebd02e8c7e8c7b38a57bfa1a745f3a86c23909f6f89ab16ce7e1813c1d20147f31b4cf2ad0b606fb17e5ac1ab51ef4a7d8093cee9a655f471dc5b146bd1b93e540a3d3d3e2de8105911c10d6ab5ff79c2d06027f7a54561f2071414bd330a8785442251c810e232f83c367f0be7799a93f5238f7f17b5be829fd89123c04833af8b77e5a4363047ceca7
SIG: c2ab1f6f5114a84f218502582c567b37a8bdbcdf6340fa4622873be89106f0a90b4829505f72129df0ab3d8513268774a34df3ad21ce254b464488addd6c9b04
TST: 406
SK: da8006adc492ca5dc86c2959437a75deb6120ff787d2ecb9c20c30b52c26bc41
PK: ff113bf0aa58d546f2385d444ecb7888f8caba43a174a89fd6065f2b7dc17bf0
MSG: 3eb4324dbc0149d2e7d6df632bb0cbe9a9f6dfa83e227fc07bde1b577b3611fb921c9f8313f068e6295d4913a8196be530f6a01f57c09c028491444b784720e909ea1fb69c1c1dd6304400327b7731b33cc46deb046cdab6ad1b53f1749a0c65cb9a7e376ffa02230f536584aea243c639103adbba764321649d7e0126f82e0b4fd9dcb86c731cbcc517f2016841e916bcd5fde871dc098cd913dc546284d1b2165c63e88f32a2789a500856371b50d22fb8c87d1a3caedcdfd01ee5f870a53c284181d632ec66d48b6bdd5646ac39c9e75338a520212062bc3466ef5c58765570b905f63a93d07f8f1baac3526b016da799f3e9e03a4f7f81355e0f7a76f30a42b807322051b71c626a7a296d75b9d9d1a23bcb13c9ef48a912dc057325d3bcfb3f9fadaf0c249b102aeb854aa3631e34f69ad90c2ab2ed33bacc40b9ed1037fae67cdf799d5a9b43785961127d62f8e0bc1589fd1a06fca2aea7cfc012cbf7b5b207ddc4e677d8ae4aec100045ce36c00b74d1d28250791236dc5dcc1ed313c8c246172666f75217437c6034acd64198cd96df2a
SIG: 1f5375dcb3ad2baaff956d8554ecb424176be9a6eb9ea54e814e0a73df2a5d848ada26ba8e1805cd51c5e16950c1ff7d4d2764daa6f4c7502fb865cbe55aaf0b
TST: 407
SK: a284e26b97e538839c808d45bde6f012a354454aef81caa8c55914624f2b7d66
PK: 5ae46e34695efaf463a4208fc4e35b81f2c63593238a56f2444b850f058c3c5c
MSG: 9ebfe910b50a5cb719d95b961e5905f00ec7943b55468ab5956692017645b366071f8fbb77eb49ec73ea7d64511405b90de22db98c3eae39c4039c7a133430e8010bdd39a00fd1a528b113dae149cfad3ae340da27dcc507782ecd8929237517afe7463eca2473c7acf6f7aa04efc9f266ae7b6d63bb8cc2a438b344827f0713d1f1736f0cbb65b99353f20355fa0230d4fa707328a8662654e83ad0530a10f9a69e17c099e1e2b5db18e5f6f1dceda5883e8cab79701a5e9089562ed153ad08c674f097c28e4d16633e092969a8f0bdac54527c0ee03bc200e5be612e3d1eabd87091101b4962afa07b310806992f373076d76a58185118137c9d26ee2cd4c618c18283dd19f0e7a089ee37305b6b9518a78d8098436ef62be7d699808acecf67939d61b3e02937cd8c5f1e746d4274334bc9c37fdcba234c166fd712893f3a040832ec5425e57d80f11ef9ca5fbcd6c147fbbf5e2fae746e0ddb605867e3bd050483c3cd1329abe57a60bf88898dc7e80ede0f4517de8fc807e888b621a00f663084ff94b99996628f3b11690a60f0918cb5c9a7ef
SIG: bf110e2e9cecbc31fa3e0c2438cd1f4321f92cd287005a48528addf76cad8d88bb22719ef91b139562a1511838682674faa9ff7e7ade6c9d573f845036d18905
TST: 408
SK: cc97a96301ceed0f922731b685bad8ad4f06207be340f5a44fd187f29903ec20
PK: eb563a7bce12db97f1891d0f610bebd55101a3125ca8dbb50b25a6b5050d3784
MSG: b9ea3b3df7187ea415a3c335e0834e10f440915b2ad41c71f255d6950a4e9120e4d494fd9e672ce53206fdc417d865897b47ac1054e1ca1068195232d4297435e44e1224e66a912d9d7d182946ff5a9f085bb8ba19c54d16b586a9b30461b6773b93950311e1619886f5a5b3f111aaad094bae31c48f1941080968bd0277bb6fa92eebf324b192df5cc969516c78c7b2d12159b4d1c8eb03160c4cd1907f62ed4b854c569ecc481c08e636f44ed7c390e58b5937d2906b2817bc3769dad9da1b0f79391b55942063055da0d6f249a3e452baddaa032998d7f73398ccd0151bfc92c5e2fdfa9b14855e6b0d3746dce248e219672987252ec747df2747fd3fbd8b714c882d707ee302a904950c34754f85350e1aa3f8ea6293cf01f717cefb6b83a22126df5c4f5698aafd06a2244ad7d01f34017ca0ece6f21040048aba6ca4aeb04325b9402bcd43ab130a105788ac3d7b7da01ea9426dd0ea1933a8189933a6c0c6cd648ea316a7469a5fdc6e7c934d9186586097b55dd51ac487bb80ed11d4df8d33626bbce95e4f13bd49922f00c920223f4cbf93cb
SIG: ffbdd3244181cdf6034f4a450fdd95dee4971a933f8be022bb0a4106aef39af3055b721881c9b54d1e99b9409096fbe6dc2c9966e3679964bd7ef4c808cabf01
TST: 409
SK: 679e3e34773abe4ae25cae7d07ccd0eb3b0ec0a35d570257d62570de58ea2516
PK: 18acffce253b27259579ed9924f479cae312167bcd876edba88b5d1d73c43dbe
MSG: fb2b648ebb16688244f78b2ee9a273599d56b6198900d438a9e99c191425c72bec4f235847e18e47f57c3cb396655f778921f908580e8e83c96c108b20dd416678021bca259b98518fabb2d3532e4851d9d52add2542c0cb3efa3857a17e512438bc0ec4762e2f9baba429c03e99bec4038e6b0ca42bff5b233b24c333b4caead2de374a87b2ab5d80d6e49e4456329d51ae973bc83d7862f3d315e514481b12854a9dfc09e7d14f0d022c0ba3022578eba8f874deba4aa8c833f2b132861d4d51e50fe9aa4b787bd2f051aac50c375390cbbcfba2002b80ad00cdc12980f8ba8bcb7064afc04d5c4682c1029b10a6d45fe6ecd704245faf598c4659597c5d68a192cc1cd4fa45e84b549e8e5e67daa879ae5a520a6b5550519876a562ac49c6db0aa76ec69bb64dd6b5e1a3af2e131e722e7cdd05be34b5fcc6259aa124ccf814cf5b500d176be28ebc40bb21f03e24ccc131e0f41daa1ca02e6b00c9c53fad1248614e940d4b237760ab7569a767b7515dd2d623e57a2841b7d2441cf43049e4698d2f9c9eae7b2910f6ad65edf9cb2bdbd9b29f606e0d
SIG: 1a51022628ccbb88eae9b21773c3f830b7b6e5bc36c9903ce70fbcf459d6a1ed8a1dceff5b19269ebf5a6fd3d8958860f554461f0e9fc0e29af9b1fb1744a80b
TST: 410
SK: 9bfa60923a43ed0c24e2f12f5b86a0716329f93d4d8d3e06238002893278c19a
PK: fb1c00687781b55b893d6b2f4f49cf5f73d2903c316d1eee75991d983a1868c0
MSG: a99028b0f4a3aa5e79abef6c0df4a783ef470f1a29ba51eba00f6214e840fe19e5b6dc6021ab599bb2ee3699576015d79a7939af823535b630e3938c723f6e0b9229d46bb3379acdba587c238567e3d89bc3bd3519b727fc694fff1118bf22c8bc8bc82c4df7f5ad38de05fe9f762999ecaa795f3ae630a9a316d26dce9f1568ffa3f22b0295214020b3d3f5337c149568192218132a90709279c01d23baefa669e1c4e42038173f1319c212da144f1c4ea4c52c005cbc0b5bc283e74483a0dca69279deb17ae5b29cfafa7d0063f4e1bc93537efd937e58a8aca737228f937ff2a741890e96c5725da11b45c413a9bbb4180a419987bbf046bfd346295d62f081c76daf2b0e1eb4f6712feebe6f0a92e358e7ddb85896507c340a01f68d1b0f085778b7c44b014aa6673e501796959a17a688db0959058488a7112572f23cf9cdb53b5eb4b45f5953ba0c0c690f86bd75e89a047bebaf847c1dfc345a4f3c7d3beec98b84b0219003e819f5c2adb45f8717903d1f5bd5d71914c56fcabc7a290f9c41699c95584d6a3a16340cb17baa1fc5e5467af7ac3221
SIG: 55f202efb2a57be8b4e4fd894dcc11a4fc5f8276618ef5cd34a4495adb016a298e6480a35cfc53edb25ff1499fc532a33061cc01a250458aa5e4f7f16f51440d
TST: 411
SK: 6e3af45e66e22890c3f3c934f523a4d69427976e6e52625f8bad558993963219
PK: e097364e76ff9f2e1d167f6b20c1bc5830085e7ec993c138f8b1b2175637e741
MSG: 5cfc2f4b559f8205b39102087617f4d86c7ce6cb251e5f89601dfc88ed28e8d7a670ec0087d2ea5d893021c7044da2899a22d776fe90170e51c203250690d37a294555e74af9234cbf1ad8f22cee8974828a0d09e9554b71ee3bcf880ab98325f706272194eb2e80c701d441b5f8668561b88849f827af703ab0954105fd3c54b3f6ec5493596d0e3bc67818048310c4a3e0c556bc80675f201f9bb9c6538a41d99aa40c886fc431467218d819c23e78498aed0613fa6f973e2211df9fb87f44116f3fe4c26d6cb2fa334c87f78c08ca8c9b9041d83a1230677e0af788598a42e44cfdf6964a4ee80e38402ba67c73a581e552baa2282425cb2ca17ca92edfbf98299102fba761b9b71a5452141bb9c18dd95febc2a782de9ceec08bd2ee3f7f0c1bd8946dba99cf9ea086abafd37c9ca60213f0de17c61ff9c391c9818ed5cd8571778b7dcc13224962386fb8ca14f861e99f3b18edac8a5f130f7bfcd45d045d0ff34c81572a512363d6530f93813e5fb10e9cb8338a7f93800491006f4463e89f0ed4530e5f12df674f598904780ad0812b1e3521fcd0f83e
SIG: 26ba562e8a4065708207c25e239b780aee38794cf983a37acbb9d557a65ceed3c0da47d17f3e8b8f4eeb1b65a2c182ea6f29623b63bb0f1c72592683b126b901
TST: 412
SK: 5f1f271844d9ed5a6a6f209a21408daea470f6fd53ba6479d7407105b7de4d65
PK: 6085d7fb5a9b2ed806c1fd30a2afde760961f7a36b48f4875246e615a2bd9928
MSG: eed6b4475dc263bd2207fe9d41d48282b713f680f2e037384f18b4bf224347f5e4c4b060b808d412eaabcf733dc39a40c6bda0505ce71fa823bd1b1794847678dc034e7999c16369340bc60c64d09bb9187b2e326055a053f8e505ea4196861471622db0e46f0f8954d8a1f07332da4d8ac55712626009912f8a15a9cd63a74a03c92f246cb63cc73f92e51dad1bc9715b1ed3fe5f2e1b2959b9b71e0e37360eb29536cf797147fab10864d6146c36b82335a0ce931408479c7ede484ff73e2dbfffc6c9227e16d7a23f4d90f15584514c39594e17bfbb295de9d62adadb589dbbe0b06dc8dac5b3bf517b24c1837b39472a6dd38931ffbbff5b763638805b4e22321f7afe92cdf502fb63d109ddcd9e4051ad6f45598532be179523710851d3931e887d02c345c79c489fc106a4ae162f7df71ab90b751da7038a6df7616cfc11887e21068fb9e33be566402be504f3fc2742b881509bd4fe6a0fc722649883f8cb655598a15a1d4c229dd86b5caeb711a028defd431154bba46b48172a4d8cbd45bc90aaf874b6085fa284f5fed655ad6fa17d67b3b9a796fa3e
SIG: 319bb4deb2178112241b3fb8f46e105c3b8e4ef721eb200d762ef363e2716f2a89f80b5b9e89970890a09892ad6a58808b477e943b3cfa77774a3645bc745f03
TST: 413
SK: 048ac9ec3ecb30a3b1bfda9b3b79a48c0793b490879e3c8a5e23ee2babcd9b7c
PK: 946c186feafc3580a58ddd526ff229c04720250f4cf6bde0271eef9b12b1c3f3
MSG: d68be8ef7b4c7a4289f2b18b16ade97f4e4fa16452976afb581693380cc54de38a07587f32e2d4549f26595fee2393bd062e9b00bae72498e4148c8b882a8840e15b585c82b5c0defb233518409916615deb3a55a5f84e6b3aab93844de3b1e4d86e09f889ac71c324eb12d0fbd861cc31229540e843a34f8d5be47c0ec0d23df43e06813fca309439904c167d1043c0dcd444b004be1ff27b7862b00eba9433b94b0fcdc67521da0c1d5358636c78f530431164dde20a1cf164f51e29b8e63eacdecc869b41392c667664d91680d9ac516af548f09e60564e814e36e0b563dbae55c627ffc14158a56d8eb3609e174381b21de4ba82344466dd577f4d1103c43c27fb83cb833d87afdf7412b4090909b1dde264daddce967f496bf6f17112bf351e417db5953b13b8f0fcccbf30f5bcf376861c12ef20eec89ed23cf384ee78dc6eb40fd5811a7b23927c13e7dc5da3a921b883a9b2b1155970fb0da7d2993dcdfd4343642a9d5a6347e43c193b5793e4453ac1537aa3d04dc9f774e840934881d78a39ba250438c507250eed2f6e07cc953f783d6b72b1cc619981
SIG: 2ecf5b8a59a8e27d25890a2aa32f4a0673275d539b174afa7b2cebf2e76280dffc338ede85ac8f614039560e2806d9e1e3cf9cce2ceb7874ffe1a7e80cdef40b
TST: 414
SK: 2f057d20b1678531611f48f003b7d22eba5dbbd7e2dd41b7c79d09071f85e993
PK: 620fc4eaa34d787df675ccbf7e893204828db92ead17a1165ac7fa1ab42719d8
MSG: 6e35f6eaa2bfee06ea6f2b2f7ab15fa97c5180958af2e90af918adfb3db8323f447c7bf26dc534997c38b7fc977f642de288cdf253071cacf3564e3b8ed6dce57ddfba9ff783bad2e76df124828fc1031acfadf01a44d41b42161ad9060301c1af1928b9e5b73b9bd21cac60a842b504dc3cc311c522e3bb048bf221444f53ceb08e77e948590e94ed98f1b604cb9eadc93bbe7431c1149b23193ff93e8569f113e1684d8976ecae6f09e0103614be418a472ef55bb8890d72b341cdd7505b50a45522ab63ed791ce8f82feddd7a620a4f6fb1d2fb0ed0c4560d78446d83b3d1b1bb56b366d196020d0624b1fbdb75ce735dd43e8e8df163c44e236993dca341f5132d825d0a4e393a19d38f61e11e0cf392cb9b646ea23c58099824dd8d9fbe26a49e33b23df80607abf19715799c19acc722ed9bcf94a0c29ad24b78b0b035b3241c64cd86edeac810e66745694b5eb1625060edf2d949de0d34f522df2dc60ae694a193f3b82c1d6f83a0cbb840f46c49a3d7d1cf06deaf96c64f8f9e17bd9ad512ae6309c486d9e2a78dceeca473a0421dd1b643c78754271b53ce
SIG: 30df7b0b1c04fb1efa3517e928d6d57c2ca0d07f4e04ffb1f08b4792c5937dd271ccabdc00dce850afe50af5990f224e8420a681d95f9f7f515afec102efd10e
TST: 415
SK: 3a3d27970fe2acb6951edd5ca90dda0fc6dd229c0a56df6eb11a9c54d242dbbf
PK: 564f0dc3dc4720e68e44dd16711e049e6112000098fa62a1b98c288042f7c3bd
MSG: 4374f61c2cd88a3b8972249bfa79b36ab69e3ed484cc60e5d9541fa7686cf4eed1210c5d0dcf42dd25972501909193ca76ae6eb7f471d8bd0d5fb5a6b431bc3de0e0318d50514524de87c4b83005dfb41245fb1af79b84a97b83d3cac7ad7a53364e2e9b21c97b769bdc57f0703116168380f3cc883689eb4a7fa3b26dbe12bc28f8c40381af64df4b5361d174cf75acbd46428740b0d1322d32bbe94845215966ae588777a8c05336e352306d49278d328e496db65e9ecf6ce6405ed1c893490bc48c13a134e1fb6e80debe6d32fce6ef74783c8d77980a441a26aeb4fd83cc855352cedc188f5279ce211f744a40b23ce7ff24437a1dd3373ec5b290da1f94f43a07a3ffea5b5f67b52c196185bce9e9a858257fcd7a8ebaf9040ed091face5a155aa447fa15e12122d25e8fc36eaee2137c7b3aa30b7e3ff6cc86b6dcb9eaf49c9576f0f462008439cb1a3aba013e897a0faf994cb7d59ede5774bb144774f73ca30e6414a7cc7c74b20c51a1404ddc419ef7624593e9bcfb37c0a762eab68faca5863443e16edb759dbc8788732b9e4f59c11192c3fcc872af55f32d
SIG: 22eb8ea0507349b6a0ace25cf9180cb08e0357b04502905fbe69b4e21b2bd94e22cfbdb851ae716a5c253c70d5e2b24ea78f35bc213292543d94e14110b24106
TST: 416
SK: 06d498318da456242b9c3b9ab6d532a128fce044f53882682e9262149c165288
PK: 413517aa63200a17173209a4b3e78ab9383cb4e39efd6794c46a2d13fafa99c0
MSG: 3fe30ecd55077a6e50df54bb1bf1248bea4063e3fa755f65fcd1159ee046efd0eb5f2fbb38b5c00947c97dc879b36b9e536192286086d0dc12053610386174a7c56f22a85b73ff208c5944f393236c32415809da036e73cad8fc3c30378064a76afa930a3baae9aa357061a8c5e8e756a9cecf94b72df43facd88fa49cb4948c6368318a6b1e5cff52e587ecdfaefdb69081f28c2d13bf8eab81dbaa5e3728c4317fb793dd196bca0fe54a6c242cf26e2d129ba0d82a2c3a45bc8d1dfd6f54f8da4f5189c91ac214fdabf4c597381b2e5c40cc71fa7051cf2ea93906a37d57df12d5c7e5cd77c907e442566315bae51a2222d62e3f42d1767882637d66a1d5305ab4010a0e49c57def69dcea839e1b76a41135ba952cc424950e8d3aac19e1d93de7757c15ff9997b3d2a8613cd9a164781d1be331799fa6109cef614305a1958f62903c8c9ea0b23ba706d49c54baccc1e63cb4bf14785fc7b062a9800349bdb0bb927260b677b60f10e62c8780f3ebb5eb6ff0360263d457ab52fd1125c9ce046a95d89d287350c804cfd4ff2b2ddd18a9e13519f20b4d1e051af624640f
SIG: 8250f76dc599c5128787e4f6d3da23173330ce3320dba959bd714cc8cc07c67945d63e75662c075e267460ab7bf561f24faae3b41dbf676899191e3b02b5af0a
TST: 417
SK: 8e8e1db5b1102e22a95c47af3661469f000a33f13b8b87b115d2452a411f6f39
PK: 56d7b3169a95c22998ec937925bd7cad13cc65808cd5d34a6c4da870eaf32364
MSG: b24634fbdd1b7661315d9dc153ba90d66a88622a4158f8bcff25ba9c29e65f297f8e60311800b7331b69fc20c9f85bb7c184bd4086b3a9f9a27102b62362bdb4fa5b201594250fc628fd2e0e0d1be03dcf818c6094c4c29121cb2bf6d908ed8aab427c3771c0c95f0ac1469a0810b603a470282e5980a60729197fe6c20ef681cd1b96932d2058f896ea7416422a7e541f224a5f04253080741c5d4e3eb039db6ba051b4ca5417ce8afdc70214ba4dcc85b623d11e681c6009aee4e6130a83edd0d2c99fb0647e11ede7301ae56b59904ef7025732cde038801ec7e8d90a9a1bba047fe628351b3b89d0bc5ae665a700891f09ebeec05591842adfcc25adc3c71c1ebc4a312e5471be67253b0e9428b0cae37645a0f7ecb89dd79fbd9be2875433667ae07d74a7983c4cea601e72e975c21df993e7fa22a9fabd45455d45e37031558e13a7a4f5f497ea78fb7399f8838c0fd5de4ebb66db290f43a4867d505309f1c1bc27e9fabcbba71302fc1204715ce3fcb0905bfa411c9d1c9ab4a39954e50b8e0cf736c10289563bdfa967553c36cd9e555bc8cc56be594847de9f26f9
SIG: f6ee5e13cfaa362c8971d5a4a879a7e36966525ccd86c5a48cba08d913ece1a79c4cd146b8e9c65125fbadf17bac1cabcde8fd17cfd68fa1f9c44ea61c08a405
TST: 418
SK: 3884b8b79abfd3be6c13985eb859ab743f157cd9deb81b2fe97ea4d6173e46f5
PK: bd7fd9a8def13a542ed2f2fb048886885ba9b5ce59cb7019fb54667986eebc26
MSG: 12adafe30eaf2b9c7203ca5d44b97ffed4bf6517a49988e4e676c8e314adbdbe23d8f2d3e2b081a7024fa525ab5aae26e60057c101e8f368d3addb9376c4682c1f4224d7f149a8474bb9a8f663ef210e9572ce829da388d8aae72a467141adc153473be3653baaa64b5b1e2e30683f6f06dac2784d5bbf0d082aab47305ed8a8efd0886ce63a179315225d1e4d4ffcf1f24ac2f464cf5ed3a8b6d3998454f1c02cdbf0a444ee2b59ddbe0a174a0d937fa62865088ac647499957d281c6949803a5fbdfdd0dd9e91b6976861f3c5f2126f39aac935be09f4b9715bd4f0d5c55df73a6b9f2c0ad26ce49d822bf85bfa2346f3165b03859a71c3d2a7b86db6e9f2e5d7b169a910eeb7ef38fbdfbbec43a9a25f04bc3acfd3b0691542ab6de9db6f03058f9584024f9918edecd90fbb85735d6dcec5bd593ae63e2cc96553599a310f8f2009ba95371196b4d5b80e7559637f22926778be5e1ccef5126e2443fa939c2a53dddb04961eefd34e538cd8d7f0bec2bff1ef0d3a4bdd358317637f42d595538c1122251a94e963d1f81e7b9aeb164f95da9a4ed7529b845ebc961b27b5c19
SIG: f4206fcd34502441d54a73323f33a5dbb4c98557319f21246f260ffbbe5844886db567f4b63c47943dbb78fc35657d7c04d4feb042ff8536f672925c319efb09
TST: 419
SK: ecd519f287ad395052b0b30deac341d2a9df13d6567c891c813a0c9ca52e871e
PK: 8ee94c588e0b343585fc6748fd1b54b5770c64e9937a56357a48d44ae2f51824
MSG: aa71be5f557e10c9fb5f091a3a274453947c07a0e25b26f9509224541dff76f4d96effd0d5a41d319bc9321a86667d55cf49432fb5c3e715388f3f106c9174b1610c8f3075d5931c290099385ce9249e235128e907c53390036fbf5da968f8d012336958de90c5e8e6b1016ad43fb57c8e288dafe14e90e64b63791e5cbe557e02df8ac9370642a71faf851075e5565f6f9a267f4f6b454ce4c5474810b804844dda38392939719793246aa47454b9b0e82e9803c09935d0027f3995cca9713069bb31027f7b2af12fe5feec7eeb06843d8296ec5682262a07dae747ed7bc821ec17018d899fd167b36a7e3773b427499d99dc583bbe4b429afa6a26593953f943e4673bdd0d2a844256131603cd0903256f334d4f8ec82de115b6ca5338c75c8baa44b4ba963c7c78510d8de9b2a5852f42f3463c685fb3a6da61a8e0892662d6a250fcaa6fef74d450fc457b9871d08bb5be3011294ac888fce215d535c3b1a43bb47efe3ad25da159191aed55195469c59093ffb24f65d60c4020bfbe647ff5db7ab8a01d5e487b0b1b64ef25da156db142e6ad872a4dc1ee9ba668465265379e
SIG: e8f51be73fc4e0235aa153a2e1b354e9c5d2d33a11ae0e333478de1d8e6c4456d2e250824c3246ca0e8d6ae3e16677a97344144108c13b959e1daf51cf0fe501
TST: 420
SK: 193f3c630f0c855b529f34a44e944970f4a6972e6c3859359c2e0c8762ba9eaf
PK: 3256f2c82e7c801201210140569faf18507e60338c2cc4118bb1ce605b0ebe61
MSG: 98623f651698085bde02762e8c3321f14da1619b5c3f7c1a568e8c26ff0c62fdcc412475912eb8e8c4b0d30918b8ffeef3509315e58da359cdc2f26bebfb5703953be16b8f3beb1e54a1abee0aebe24e64dbe873402e156f37dfc168eaf8a114ce08a6795d3f64f5151e9a8b8275cc7b49a6b8d8a66b6d4b7632ef80740dc1c1b0a38d1a28f7c1b29fa44541c1aad354d4590c231dae687a2a8fed09e8c1ebbfcc38f347bf06d94577e49ad139f710ed8bb1fd07663c0320846fbb455ab837ef964ae7d4eceea45fd7bd8d509f821e6eb027494efd8dd8e992b88698eec2ebc5e03025be789c18013f201f77aa2d34f5686460e43fb489e08776f98bcde2ceeb9d4fafdffe0375604371ec32f46b81fec474382908e9d250a0ba2780a7d6df407bd2b1eb126748d72511b9b069eb1cd44270f29fe84b9a717751831d04c2818e408f22789376c61c2ca45e32e788ead3a7536bf09da8af4703902f5516a020d89263e93701a2565eef1270418925f35a288e327bab628ac2f0248cfbca3482e265d1621cc343c31f65493f064bad0d7602460715fa486f29426346af53e333b75f5905
SIG: b12510ac5f2f6d33360cddc67291d6c270fd9ee62dc086b38d932d26473fe9a24efbd4248867ea7e915a30c5bfb3b8b19aa01aa2febf0dac6cfd6638a2ba7e0c
TST: 421
SK: a88ad0048d38c44cebe735ea3802ca576e37121c7d4d760dfd88de1663064abb
PK: 14dd8bb306803e5a758ed68ad21d07d88161d50f1c74713777da1209afbaea0b
MSG: 2ce8bca26178913b1676e90ffefd945bc561982660e2a75d482ff30aaba1ba43f82d2e6b909ec10fc09789ff5cf32a5180b601ea80fadece6d7e7baeef481dc6979e2f658ae0f6d8e416b93298f7d34031bb76f716ed991a16d09a582e58ba4003ac17be8b4469e1a889b2fbb2289e98af1c6d5bbee77756713c0778b0dc446a1f6c48c4d40818ec799905f069bc95341657ca5d02b7a539a13a02cd0376a50e8343c0dc20346de5275b1dcd4ad7af725131ac75e954825d30eaa57a68bb98dfc41cafe5710556647b387d9b7fd4e47651e5138050798f6d40f4ee7120b58f74da94d73cacbfd393d1347388ee00b79b8dbfeb57814121bdda60c627dce147d4d568d79052e97b9a5f3eb5407cc46461a55e18a960d8094a5fea48b6937529cc4ec919cdbedf9185456dc00e8d98ad1537ee10a057f4eec4b81dc60392fc9188d3e561785965092e44317f2a48e36605fc583fc173b05db9dcbc7557d06487390fbbba77af3a014e1ac35139caa1c53a8d17347f178e1c54d0f52b40e91042c93e7e481d792e288fc27e4c2fcf111fe97d9e2337d2fc1c3098f06684a31d55ebf362c027
SIG: 1341a148da4593c88ebc5a58821eef77f92186390ff633e76207084e7874ccf0eb1f9ec70a3a3f96b58934bcb061ff920124f7e580fa2b0b279583adf9232d0c
TST: 422
SK: 3f59d6a018f50a822117e5b473609e30cd64920ca1c2750dcb09eaab807a3eac
PK: 457d0e59c11f348f3bfbdd3f327de78c0a7577c0aeef42d4c1e56700d108808b
MSG: 7d103a6c6ba2d09087eef2254c1c903f067695a54c4515e4d13bc1fbfb54d6e7a167349c14809976da04a7e58d96b40aac3b2bdd14b9b50322bb11645f05e5e978bc7fbd02492ef88f87d668280fd708373207ff670fcda97df8485d5e46dc3bd04347f4d7527eab2718f7d93d132ba7758218894e75a7deabe693335ba0dc73bf26c288bfe9be8a736d75e5e0eaa7bbe8d0b77abdd5146e0fc9b30db9f07cf4bf36260a1f41410331f8b47c6b38338c6dc9e801ffe1d585f9b7fc31e9778bca3027c232c074cb18e5b72997005ffeee4bf37c8f874b1b246a6345415dacaca7075a60443ac3319236e23cf6b7544740807052114984b8d8f7e857dcc6faec8869cf96b997dfa9af9184ad623f1d90b8ca759b448eabfce18c17cfdf9a3e3312e63e5f084cea904c1c909913cc4b19d044a3720034973c7384949bd6f9ba9256f98cd394c566da83c31180109f16d10347b7e3e9dd6be3bd3c77ff1a7996a078dcf89dcdce2d1b615695f4cc9f8f4f2a08804641bca82662ce88faa53145b6a45955aec8cc2af81cccb5d7c64f9ece1c9983326484a1e5ece4ce36544d63735f7776f21a20
SIG: d7425ea194a6715c452ec4f6d6c76e6dd374d3ca7ae7a11995d02b942d4a31870dd734c12fca89a8eb0213eb139c14a87a6a33e818603b2e313023fa58737d0e
TST: 423
SK: a1212b34dbca63b7093612d05dab7b4cc8f7b676a934ad01f659851b3bb44e4e
PK: ba2fccea9a080591be71268d7e951f250dedc00416e5f3f908db6cc571254925
MSG: 07c37c46be3c68d05689577aa64a932b906446b29baf12f6174a6b42bbaefd1f1f373e0bccc473ddfcee1a7f21b96a6260ef0aa1f2d8b2959e71d12c953358a2774cc5e6f379a313e435ed69dfd6d4a59adee3cc7ec4bacbdbb3fee5430b73f6051a6096c60e9bc92cc8fa059fac2a93ef7007d64fbe50064964d5a0ad601175cd9caba453f9103b25485545d301f03c5f9f9478bdf9d414bf1dca3b1c1d9daa9971f9e617fbfaf5b02a7fbd5d4fb894c0975c54592b49a0fc85dd0853f30c51502d98fc1ab85a17cc58961aae9764570ba5cbdbc96dfceb8d11da53364b4025fe0b8ba8a353ad23686720169fe973432ffe291a4b11dedda0aac79a5e42620a64587d2059e787013b40ceec599208f66ed0ca6e1be9092ec27db216ee6dadfebc21705bc4a85aee577e57d239af586efeec22cf38d1cfb3cd74dd0d9a3381aa81e6a297e39b819137ad27d475e2bf54aa426dc29c4ca8176df343137a2d79d12ef9aa7be1cf6775e5d8a4430a85c33db61cd2f35187b4f6ea9ebdd753d1c4ef72471159ff07b77870906496249d4278e3f3ca6bcbf37a265b896539190f9a31f1e7b4b65cd1
SIG: fa93ed6595bc958dc042ce1645167b79e8f6734c46f80f631fd5484908f5e51a22427ee686f564ff982f6ef4d2ca1f0ca5624910cdd63c11a3c2b16d40973c07
TST: 424
SK: d9682086fe7dda30b87111060193d847566ab94cfd9c97ab6b43e7a8d3f79382
PK: 8b0b1372d88733ef7233f6379790d1e46e1e07e9d3fb8b0be252ed04c5fa163d
MSG: e8814be124be3c63cc9adb03af493d442ff20d8b200b20cd249367f417f9a9d893fbbbe85a642be2701d1d1b3cd48a85cf58f159a197273143a578f42e8bcc8b6240f93271900538ffc187c0afc8dbcc492bcd679baaef3af5088434a94586f94b49970bba18f5ea0ebf0d27ee482aa83ad0dd0ee609df59d37f818b2c8d7c15f0f6f544dd4c7e7cb3a16724324f77d58948f8475a60d53e5bd510c17137c99e1cfa515af9bc85569d212a21190729f2817de8c46915e021df70ff6d60215f614fc21139904df3b292b749dc4dea02518b62d15862c92d2a4c996701cdecaed84ab628ee984fc111eecb59e48444efc0d456e2c852518441c3db7630ddd5156249a28730983838ae59ac4cc7110fd6de68101ea5b2ff69fd364e3c9448defefe175bcbe117cc11b4ff7549c33e1025b6b592048a8e31969e818dcc188bb19d7a2440a3baba4eb1b81c45679db46b31bcde7776757d9931ec2063fc6f1fcd761ecc57a7d030a85ea273ef1825b05092ab9645359a444ff7d166b575fac298308d9faa68463d1d0f7b7df8a51c6815d37159adc0b593224a818321d7219f09686cfc952259718dfc
SIG: 1793e497eb521ca74e35d14a63868cbe9499da2f21b4eb5260340fca3c1feca78dbe5b14ac10f3fa76fa2e71e4c91461aa75977e5e70792670ef7ff0e6a28708
TST: 425
SK: b52b249a7aeae0fbd94ffcf9a9fde10de61c3f4cbda14b289fe01f82707334ca
PK: 735163bfcfd54f9d352e1c2f3c0170c95c1842ccc7421623ae0496980cee791c
MSG: 1d445e8ee36f6e1064ee1281e6b4a4cec50a91c2b667c8305d1e9a5f7b73a3445882581fb0c11e64f6ee92e811f9f2d6c59c6344be7691d116dda493cade51c0ce77372b61a7c4fbb633401333cbf71372ad2f044e992ac035f5879c053004f8223f237a24a409b7894f6ad518e046b8a84c3f4c6260e6169fd944d57fbcf9ba2775f2d60ed772c46ccd63c850b80d587c5208dfb1a25878c02dece3e602e9632fc3c2c79b25ab41034c6e26b869255357a686781dfe6e644beba9b627da1fcb5ec0be497cf188e1ef1af0601bf16b2911fd9ff34f0e97ac95a7fe2cf90ea6ced33ccb0ed1ef2d4160efb07c591a5cb16c70ca1694fb36f2ca19eba52be3d4ad895abcada4b36f0261d65f59e0cfd2a6148a8892ddbb45810db3bf4a9e26e92c15ea2618cfeeb462d8628f254f54d2af27113bab4f9a7d06791811942bdc32f845922d7b2ddba959140928f8c28d98b44e1d19b97fd39cc0f9a5236d349fc835ac492192462e40ac629bebffd2eba72d2788b244bb777ad0f7b7f96f23412399fc1d87a1d087ba089027eabbc05edafee43379e893291331b460bfa7332e0842ec2573393de95306
SIG: 6f48a9f7f0fa192b66d12175a333612303e180b9fab18edabebcdf6674fdfcc53607089bf980ce35894c2f9babdc4438667ab3297a6248ec0269faa99c724807
TST: 426
SK: 782a93efe0ef06cb2534330efd0e9684e9969b5258123e490239bf24bf9f6523
PK: 942fa1406ee2683e29377e49f7ba757cf50ef0723707d4403d2862257045de87
MSG: 46a4e319a670ac993994a53300c3f79144c2f7fec1116eeeb3621c76ac35da79dbff6e189ca9dbfc9abbda054847b2971b02facebbe926d469eb0a860389ac744162bf6fb13b42cb9bb8c9d72607138e7800121ee0cd633ed535c7ae5f4060bbdd271c9d110abff5e060ea6ee83890b1e92a9256d7b2ba982a3114bb6deffee2696f0a2f9c21aaa5b2defa11aab7076de6e57e86f284bb67f5a49ee685921032c95b74e7e3eac723f175af082c858e0dfa01728c38fbbb4c83581f81ace6c63c6bdaac5620eb9a568e7ebb7b72b3d1a164ef524e7b9f00799ab086715976c14d0df65f7b96bf9ebcda7feeef113422001a03a7633df5e49939a121db899d9b8ac2db4fad0c30cf0b8bdbc9e9802a797c8238e46511ff24068cadcff2448cc0bff92769223348d45d6b6f2c8f1593388c0bbbf44b6ddb50b98cd7f09c730f7de4d008156cb3cde0cab3ad0a58a83954e234a0a8a04b573c9a8e9b929ed38b8b228bf55a3c6e2c6b51f682652fbb708e74640e3313e17b4694d7fdf0111f90608c1b5af422dcdecad9ddb7f50d1bf5bc6378ccaffc3201e6c787b48c443ba240d9d50ff6c0e9df7f1a5b
SIG: 93e7405a4044510166c8ac264ce3b5ba6665d68bad458712dc93c2c390568d7402ef7d57f549b8a1042f7f69a679aa855f34f801d57d79895deb8deadb352308
TST: 427
SK: 6fe7bcf7a684423de1076fd76da783423373b381329efd6157424ec4b2655a94
PK: 7740e91afe45324f8bb990ca2a341279ddaf232c3bb415f178b6092fba195fec
MSG: 0baf0ad440612b4c5a136c3a42be1ca2b7c319862a44a9fd50c4ee73541c5e6457efa81825b6dd4a72194a2968688bd49e5a8f4c04dbafc2e7884c0c70c208d4e954cd1675da8e74c65c497cf9dc69424965bdcba5de52936f925f62e201f99505d3777beb3c2e08b2ec9a873e5a9c21fb4a2f3e861f3cf4d6b5dcd1c88bcd9163539ac62cd0659f4ef232c2ce57fc77f90285eb350169edc6a806ff50f61c7e0beeebecec63bfc9d3983f5bb4b261c746471fcbf2892c6108970b68db5e43c4504ddae2d0ffffa28b6759ae1128e16f66d492ad61e3722c960f88692be81a9f412890ffa346e702c867dfa259703b73f525074f3227c49cec1b645a103bd4471f33f9f1bac327d7917861d0ad91abee60222ea2a3c8cac052ae9a2cbd90855d733d5319133f9541bd0b61f0995268351e2863c1ca2ca51e3c976383f5c4c11ff410036fd51d5ac56b023ce9029c620f22557019ad9b4264ed4d71b434f4a4d17a7d5769fa1e14a69f7ae419ccf5947f8c7682697116c2405f5a1959c54b48f0872f596ed45964488ddec12bdb636d0b349e749eb66092ff4511fba59b5962cb93cc85515cc86ab0c6b2
SIG: 9914cc50fef0935efb89b3d64e3c1c3412aed659b90166222c0d13ec1ce3a68ae6281b7efd9d4ec64b82e73e14479f03fbac8fa3abdb41ea4215c4a4d4949d09
TST: 428
SK: dda48a0d15a29eba9a76305d360e466e72d8040efe2e89c04b6461315a9b8bf4
PK: 4f5cc36a809416b58e15d24cc57968cb573b76ad90887a8ef36cde7eca400fcc
MSG: f5ac19b81f2111a0db0ae30d1513ed343e7f57f7f77d65b8ac7ce3a601174baed9bfa136035976f516d5a870f45db1919f1eb1cbecbe88ec32d191e9248821a7e7681fe3abec11584bdb33de1b4ca94891eb66dcb8539ac41163736ccfd69abb83814dd38cd60381318728052a25cb665471058650ccc75756dbee688ab826ecad4ad5a7db57e8f65f1b64abff82dd53334b797ac40228dd817f239d3ee804a19aeac8cfe33eb657ec9ce923d6b388914cfba2e72bfc2bc3d6f985c0d97534db958eede57b16491ffb755c1a58d78ab377faec0d311818e899260e3ebd1ccd29246fa82d0b76622b2c4bc52f549fee72a30f554f331f36d2a74d999ec10a08294f002b4361e590279c2fb1bda4312ccb24d75282ce7c061a0ca5520c74f6f6333b18c4b541cb6c51e01575ba80512ffa7ce0accd22d14027c53aba1f7437835f1114d68e3acf3ff8de94c8e4ef6d3ab312c91d02970157508f54a5816f467a214e9b1284300289e65f365a610a8ea284666cfe5518e435bccd21627501c725f0b8eb5725e0e06e0cef5db201b48ec91ebf878dd57ce8dac7334848a1bc82c18b065955e4f59be3398594dc
SIG: ce71bc82d531d0f93b57bfdc2f7316cf404ee09af88f33bf806c7cad6b8ffa366236ba74e75c15096ddaa6e3a62a8f5eb1c8c3f6b6c94a6a349fc7c0cbfb190d
TST: 429
SK: ec57b941adf3ca13e77a780577cfd0df5b49edc85351052da34e99f8a9bf3208
PK: 2859c071978a04b7f5407b6d22401a78efd0394bb966b9a04da6b5ef819de3fa
MSG: d2bcbd1bc361ab32c66d72fd48a8e227dc6b8d6b150848ba715ff47dd35c8e49381bb4e2933f42cd26b75b14d9c0039282b62b8556aaa11cd691e828382be306889fc9205137b169d3bf17b7f37693fce286039f03809d7d9d98c8fde46f1101942a279c516706f50191a9112f6a24630e1a26c321e46c9ccc85b6ef942f353a642b9e7ef998c0fce2d3a75b999eeb77f31f9b0813a97e3014c3a86e2558734621a3066dae35845031e35665f1922907dbb739786a8b7658ab60276f2d921d1a51230fc74d19e80184a4f10e9e834abc9a36c429726bc055dc8c063f0eca9c61a8a970bd4bb5f424ee4d04bfc295e3bb1f34becbd9920fe2e77fcf36763f32fc9cfd5e465979c167cabf5a1244b491fc06b8946419046ba516c5b233c414ddefb6da04f2e13daff7a9a0c02a518ede57ad9521de64eddf6f49a9670f632d3f7d42425207d053604fe39d13b9f52c8bc292b0076ea42a560056df25de51ad35881d08543224d7fa5d70b8603ef23ce06339d6cd09e22a95749e50dfbd3b8ad69fd30496b984d1c0a199c8594805f38ba44631a2c59eadc6554d19f9bc98366dfdec2a121d0e4814d2cd3f5871
SIG: 118e1462126b45b8c6803523755c56dfc4e123e4acbb66ba0ba6fe3e053da4119f5719295e0c82ac64d7c5cb1ac898df263ddfd360f3008d91018b26f6a1730a
TST: 430
SK: cbfd91d7695c1f270f69246ab3df90edb21401101ca7f8f26c6d00f4dcb7233e
PK: 513879cf79d2f46df4b85a5c0949eb2116abf981735a303164cbd85adf20b752
MSG: 264a933f7d0aecbac13eef644b0b53dd53a1280904100dbc1ab87b51148998f9da0b3a0a6337f5e3486c2b7e548d211259397aaa194ee4695bf98c2d5f4487699f7397e5d3a7e6d5f628fbd05497c556a50a4d05e2b712cdbc351068e42af19538901b8825310e343e1a17a1867dde0eb47ddab456d316f3521554937bf808ae4e4bc1c3c5b4756e4a165ad9e8827f5316f748cac6998ed2d2104f268407c135e62f26a922460eab6d851639a00e5f08b34765ea0244f475bbfeac183e3b5bd1aab798522798a08ec6bf2257d4692f5b03cdd0a2133de970603e3251475aad8d934af6b2bfc7a650b91bdec143f8ad254cfa506bbff28a03beb659ef5e5ddffe76e23230c4ccd46310b37dd91fa6aa68167f62a55c8a69f9ed1ec6cdb144dd81ab0bcbd62643420bcae67869f64c0b169f3cdf3c905895b7d35b6fafda25ccf23c3d10de32e7f271e300d39597da8f843722ef08364a5f7a105b9655172df7c82d7374f98264c9cdccb496f2e10fd8262fb1a9a9965b0b841ac0d0e9c1a3d9493ea7aa600205b8f900be0d7abb4d98a06583d2295c276318be28d421982dedd5bfc33b8865d94ef747d626af99
SIG: f336137dfe6f42a6669b55f74b80b3035a040367f90656fcef0a644c52272ddc39273cd7726010ebcd8a30a05201ab70b8ff97d0288a2cb94cbc49020647390b
TST: 431
SK: 51a4197ab7686f82f6003a0c32f39d0f2e47555f4e9f8deee75bcb1bd1ef69e5
PK: 06386df86b61f1f8f4dc45b73edaa841920968bbd131cc5ca1c5294eeed5c8ba
MSG: 2aedb7e82f1fe4ce469ada48345d006d1b3bff40eb21867f51fce965640c409ec13ad4d52f891bd79066d6b4d944ca868d8986d242b57eccc4c4a488291b159c8de4392be4b86febaa75eac5d22d3c4f8d6bef79adb9b92b4914d5ea07c7f021e2c29f58d07be8a084100bc152d51ca897d7c131644d0895322e9440a8339e1aa390a7f4fcb51ddfb6df48aaf5676337d87ddd85b1d925e1a9c29fe0818f514ef72f747a674946476907a7ca99e9db8d209641057a7f44a317b90974bc86f9617a968a76a6b8387cf5853e608190c1a79f1e1d686e0de22db6cd9aeb8532c5c85cc90b5a018579f28e502a770a4ec675263d0dd781b4fa53c9dbf8098d57b33ae2afbaeb3e68266ad9aab7174ba68c6479883992670ccf3e5ac6a17e65e31e1fdc85e269c80935ef574f20d239568486e7d94a4f724ab7006098b24f3f61587691435c7f29ce4e5ca71b2b1874556433a358c8c5ef3c880843030c2d13d51b78c9bf1a8824e62e111844396f5af2e25c3126ef3626e26efafacf99830aa41212332f378a167233a0b42213afe36d83dc4582a79693b9d571a57712a08b8566d361ac902647afc886603e24283efb
SIG: 2c072969ff4719212a121938b506c602995b4d02a22e6198d6e87dd6ae076225ac70bb25ef8c0ee81eb6fe953df6b1815949e8ed0506cb012e873cd36cd09b0a
TST: 432
SK: b1119c36118b7a065a195bfb8b79a5c287e09bd287c2daac5e6b01164c5d737f
PK: 88f218ecba99e770ed214a8d01a92a10400acaf1f6eed420067e136ee2c0c670
MSG: 8816b1eb206d5f6dcc2e4cc391d23209006de935e318152e93fc8c2cf08e26432bad9adb3203d898df0a2e7f1f83dc2f3ed3205bec8efcfd31adc1aca5755db9bd4efe54cc17073077de4a3fdd11996e84b6a052f034b41099226c9c272eae12528f16581b91b812850c207144dbff3e850cca848ec2b1dd164744d7b59337d7e3efef008162e680bd4a0899ced60b171f8cbeb48c5158df6cbfdb26240881bd58ebb8b6a079587279679cb5ad82f371b53c8013804c35596c887e436d23926f994e09d98fbb8ce2704174ef38b68262a7f1a712da0ef0dec639606814b3bdcaf253ff31c48e8a752c111bd7101031cc3d38efb0c9c7f19c59081584a0e015ee7c75b10a4c51ff543a30e52d5f94d8188c6b08e9df1e84a4e2c807170ac124a771b99465a0d38b1f1c6330403c82543582c5bb61b220de1b9e0ef69bdae26023181ba4cc077a5f0d425732ace132ae0c6ff0bb18baea83e8877afbe650fe0bd02093f00a7b5365728dcb66fbb881f592945058a5b350665af91c557a547250ad295e68b4fb72457cfb9d5ea1a7b2a39c9ab7d7ace0af5d51669cb6c2c4c07b2256d10e5ffc6b97c660006313c4eb8d
SIG: 24ec1e54fc7e722d37551d02cf135d33f5d3ff535773e02991ee85ffd3aa29997f9c464470197fee81dce110609f870b27c18dfbcfd9320548525e93148e2205
TST: 433
SK: cbb587514e0a34ffc34cbc04f28c9b4f6465f1eb225cca19b864876daef37d7f
PK: 6b705d4677d2d849b6744b1ebed167dbcbf645924b1ff2e6360794bdd0e09788
MSG: bdf7d17c706796efd3489559b527b1c0584b9022c9cbda3aac5146da340d9cea69f916037cd21b3eb1104348880fd5c5b7c65ff820f7499346016951cb715d8df2b41c88cd3c66105458b7b590c21c1ae2f6ea9ddea7470f25e02027d171e0e574a2bb21642f8f9da508e21d8e7335b5ace5935299407bd1b01bdd1423133ef045234e701f55549434ade94a60be1e1406ca5c758c36799ce1703084476e484fb1740530aee84266d07adfb4cc689f3265133a59cdf992fbb9a4b12defbe241ddbf65d12b2fbddfc05af0fb8de42080775bad29c6b0459841cbb648a9a95e48d6e36ac514480a3deb4b36554d8da620808ae9d47329710d20aaa6e5d7f547d81ad30f84c0e3d239cde5b169d9ddf294832d67a8060ba329c4ef39be94ac46434dd2185931d1231f9b6df878a5af0831e0e9d8a08d08069ded6a961ef7f39fad501ffd17d6d9b7c654653c1f58fcee1a6cd803d2aef166c78ef5514a3276d6998dc7c09a3fa982e427c785aa6a9e256f7ba72d5a6ba33eb46f1f9fe9be2bfc14109f64773c00c063b4d5cb4f4f8a0beca92a9a016c4f540feea9c3a31e313bbcbc2ff5eca9967857f5f8a909a29d7f20d
SIG: 1274d6f356eb641472b6b9e5b3ce65d2654e6cb87d3a83fb49d0f7da9c44be2b532604465f6089d680d2d94b0edd2b6b2b805c5e84c379efc059673d31007a09
TST: 434
SK: 8bde3ff61a16995ab9d539f6053219081bcaea1d458ec33684fc1c01fb565bfa
PK: cd9d782a356e847b7a04c885a9b0907cc33ba97ad5390d4ea5fee5eb198d08b3
MSG: a1f40ec5807e7a27069a43b1aebff583ef037028c02c859525eb8fa4c3ba95a901ff3aed78c4f87752fb795522f5bf715be7e3defac10fcf17e3fa5c54b20089a472333327252ec945718fb455e3f27ccfdef823d12d406e62a4aeba3cb9d1c61b2b17e49e200a8418f935f26eeb57602c7aa3b3a24f7e6238d3e08d2d609f2eada0332bc8cb12916cb03b0d4f9cd602002586d3e4cc7e0e0381c045ad2e1ee28298ae7fcf0c10f212808565296f158d2c32e8cb28156581af52bfc3470c3c9582138d2255e8426d648ca237d7aad2856f171638558241d8ae3f62ba92db596568edee3ec0ef370f83626aa0445af08f967863660e8fba5a41c8e8ede1c960514a14687a4a81e776ae0e8e777fb0f250d51a83b55f8c1ffdd78df3bdc97ff177afeca046c72d72af924ad0d0ab2bfc11b7f4abded51c3987a8bb94d640c8710e5fc9a4190e8a008363d7419cea17c40dea20ea5156029f3debf05241918f54af5039e2c4cf2ca2e139f60e45cc65595cdf54a67d92b6ac66fc0c5a290495ca57b07ef5750d05f57d87d0c228f7e4e15ad0ba0178730f951c697583481c66cbfcd48032544aa8d50908304bd81940308706
SIG: 7464df0b67eb90b4b73ff082ad0d60ebfe0660dae97069b52c3727223bf70e29e48711a2bbb438f5f8d8a33bb9c48fe7b628fa8a542ff0b5ae36269d4007a505
TST: 435
SK: da59bbc523404f07646add7908294977e46645bc8a38bad2809641a23de3b15a
PK: b22c0f21aa1c2d45f4b2e56cc9b5e02f9e31a2eaa367ecb482f874cbd8e9fe34
MSG: 097106c3624d774dde2551e0c27e19504e6518cc86369ab26ff810969e7de24abc68b4b53f11d945d49ef078eb4f6ba6bf257ff7b608afdcb30a5c59a756fd77a6c1247f6f2a41100d99fc5206af3bcc6de1d3e4968e28fba0123f6045a1b54d693a42bdfa071b2b914b3c3c0c29b2593d07e8bdc86ca42ac555b7dcd9439df9fbd4bbec730d6327bfae4fc41ed498b4f04a0eb14cee608283aaa6e6aa46676bc88aed5d9939037aad4915661af94bb5f6e653a2cac123287073270e0b13fda1dd4871af6a92f992f539df881712fefb038540d41191123b6b3b4b6ff87ffc929a6be53c6cef02f48f2f0cf2fe64a45fd66025cc2d7ee55ebe2316c000855661165e2a5ba41afc2097957b6fe4c55221204b6fc1f317dd3ba13cac39924026bdb66be4542268875631d277f210107a33767f6d9596e25742d7a90ea791ea4bc9ee84a67fd328b80f791ede96d89663e937f0b755baa9d52bda210cee1db339ff1d3c4b000b653b9bde338049af84364e2177f80dd51e2a1672ee555d6317589f6f1d5abe6c2877358bf94b0b808ff857363fbfbe32e97337e4b8a8c221a9e75962a8dc9b5a3d7ca5f9c9b61c73c1469a72bd
SIG: 1472459cbbae2cf21ce44a15bae9fc85dca40b8182da7d52cbf56ed538d18e03477c140a3ddd0efba43c96aa92f5f9bcdf3481286ce762a7e2bd1e779ba99b0d
TST: 436
SK: 40ea82da41fd15b06ffeb99cd616dc6bc8c1b21477ea239466088e2849bf1016
PK: 5910e580bf412c31a87451d9ddf32b3ab713f9e4a22c590c641c14a5dfbbe0d7
MSG: a06c4e02b83ab7e191ad818cb8187b52a8da004fe838db333c4e02548db6bdf791444642e57fdbc8594e59d7023280bbae82986f399805434bb072c8a27a2dcd5aa62f065bc58b0621fcd365f6cdbf4d57d577d91150301fa48f182f87e8dca7ce45a7d64845ff434d1bab0534ccc83aa0974e88b38fc2508cefcbbc82135b73b384c80eccb8a09e2873cc07129021d81ce129a9df65e613410af950197dbf9afc28edc4e65c3e84da40d2ef841b886bc44719a5d59db2c6dc776401c895e2b3c83783d7817bba68baff59470d6015bba8d975f0eb712f3b8902912805523aa71c90499de689d31ae44e210b8446f2484727cc491b92a8e8b199d628e1df79a28c561e5a7d882e30787d08fb2d5196ba61196309b3bf0c5824a3548c700003fe9913befe12223150012685e90720e9ec6bc4db607425aec531c4fa36086d3b9be391a3f04635a8077a447a16a6fd89afbb9a72d0d355cb0b22d562f43f59d4e37128b3e2d906c8ae23d0aa599c70d3778a076c1a39728f1d6937bd48b978740850566138d34852b63075e89a8e2280edba6f4ee8f61511e9b768e95c78d197b693b109e88818b486a9dfdb74b4c5550acdfbd5
SIG: d298fcc9a8ecb76a98d4a71dfb01d276ab2d9670a95bab34cf1d8364516d1ebdb23903460215307125afd09c758e981a452da95c0ac2c0b958c6917e6874190d
TST: 437
SK: 28bb81a17d4584754d52818cd0f1f21baa777e695844a15122ac05344dddc027
PK: d5f61d519944d13b84bfa7cd67cb0bea4ef2281efa461f22ade4ba882d11b252
MSG: 92e84c7a55b0bea03e17cfb65f7085ce3f445b1542bae997de5f092a24ff243380286d137091a598f35e6dae1a1c648f5a494c819dfb240652ff908381f32d70bc513100aca16fe7220295b1c71835f16d9310a9d27a04a980ace297d5af3f7cb7c78b24997ccb41f54ecbab507eb73ea6a3ed470e49590509f5d1e6032a2605db87f4a9b9ec91602583f14e2fe1bdb900ecb8971196b55c0d433489f26be9ca157cbd56572887ba859f39674a8e0ca08f2dbb0f27073551d0b1990685178b1ae9e7885499143d9d72c8571d11e0d85bf58df94e2a74d9b6846557f9125ca0944ce5718d2cbae1672ba02b847c17a6f6b445634d2f0175a75cf6883c62e5b521c57141f218b2fb0994b372a716c4a217434beab75740b8e91c622187d03c85da001e00247312a465225f5d6af232064a427d3018700ded774b9026777a5275fc04754606c86600297bf7b71aaff8b9a746677a3662f3750e81b50166f6237000051ffa15868defdf090057722ae229964a4ea085e0dbc04ce1997722c5bb65d2b47ecb746fd83a9f6a69c81545a9b502f5e76d3130c5afcb1c9af99d918740837ce89d7cd213fef2fd062ce8850f69659e4ad327
SIG: 9ce45a07dbd28d3f6f1b35630a3fd56f1d548f84ffb1c6ae64b21498ae38e596916e77f79905e609fb1ae0da36138a80f242122167068092cc605796c5669e06
TST: 438
SK: 24bfd4fc45d5093585678101cf563ab8011fd6430de155f2a425f0633ee3b7cd
PK: 9cf5c5fc0ccfaeb28a08ba67707b18dc84ea0698ffbdbc169a09c28123e6c2ac
MSG: ba54128f45be2001dbb060d5dcc47144997415d4294f6eba8dceba4f6cf2234683c4265f88032205296e9b27d68506232d57b688407648f87ceb342052bde9d0065542ff1715c942027e67482af4bc278ff71966fb3f62a2a5323cb1b4bae1e7b8fedcbc73ea05b4076421b0b4fae8bc3337416a17fe124e7ee465ebb38d8792306429d8279a1bd54c37bee8f9c85eebe3afd1f64489d4e53ac5f50657bb6ffb97120744b75d47c6226d5a9c9c264ee3e6a6ded05062ca1006669118454550010919c2633cf086950345e514af3843148e5c64352e69037dfe60d4a8eab3eb8cb54bd39af2f353d5ded2e2bc8b11c09f612e128c6efa41f6eb2c958087be34c6335a43005d11a9d3b5a529c2d1b0642f77afdd8c6b1d6fb2a9dcb65f42f4eca8ea9a054058be8613667610e3eed8d1df0739eca171954117989d1b12189ab57904aa960b0ca85541746385efa985be9d97b5a9029989a9c71498dfabdb813681f57e276b64db491b8f082a885145469a531b7f9f04ca0a2c2f8dff20ccb99c2861f54e5eafa962cc53eaf18d3d5e50d337af485f19975f05930700a8a7253f11f184130d0aee70969d96fe08f216951d9dced52388
SIG: dc935b60fde44359af8f50ed7f919f483ce3f24e2320c55ba92f3e7617c19bfb54701903ff183b42cbedfef0875f42b12875d36a0aeec73ffd09509d92b28b0d
TST: 439
SK: 2fc2f9b2050ad7d139273e93e2a0451c7b5cce57599aa6b08d3edc5bb07590c8
PK: ffe5a17880d718cc7988c2fd9825b03b93450ac1deb8fbd1f1bf3b8f87805954
MSG: dc1297990cc027d56d1fee265c09bcf207a9583e6bab8d32478228e0bc305b9818154c338ceec34b04c4ade7ac61dcb09bfac8ade00d1f29de317060b8a4daf1987de409ca2c3fe4380088073ccf485e9a69516b5bbb4130f20be69b2dd6a9b465159cca1ac88b328b80c51b66af7f4c50f6228772f28734693ce4805a4163dff14b4d039811ee3fce65935444a6ea9a72d78b915c9c3b766c60b7e0329e43c9c57ede94b91525ce5a075a7297219772ef3c029649b586a95a73bbdf16d8fc20368de4ba44de1064be5826b376be31a86ca478a52efb98f1fa333157719bd6e0da80ed68d0efeafee5a13bcc3b457525258f1f7e031f7b403a461506927b1e6c7d4a0c8d84b5f3dd0eb8bdb13edc2b514a81d088eb077a52c8a831861feee8110e41a325dce206b2d67d25f90ef57e0fde709f3e5a39c04eed31e57c193b283e2da7279ee3f1eed482b3bbcd373902c1df811ac33e1de06429e8f8443f602019650bdc2ee8d7f650036a7a22b8fd88517511229c729a3269b3a3e8fc72b01b5a4b3e33f5272f3ad21629d08b1f717935e9e104add2f0f2033432bec82e2121d98c9c1a58e0daba25536a1be8e5088347f4a14e48d8e3
SIG: 7aff162a3c0d28dff41715a974af07ecac2132fc18bc43a198fe664659050da19ae22758d52c9cbb94f1358bb02610a8a351c2116279e7245adf69675dfd360a
TST: 440
SK: 8afe33a0c08aa3487a97df9f01f05b23277df0bb7e4ce39522aec3d17816e467
PK: d004370e6edc34b3e8818667216f5b226b0ff75a58484c8616e1a866444cab57
MSG: 86fb741f1b9708929195031aa1645fb709a8ae323fff85e5470194452e11b7b1279194b5e2427ce23e1d749c3ddf910b017e4f2dff86dbe482c91bd994e8493f2e6824bba3bc7d7a845f217ae9760b3cd00226d9ff2616d452751a90c3d0d3c36d4ab4b2520f67288171bd3a34b2eacae8d44c1e153dda1f90bcd3595dad37713b8d340156ea90a4e135951ba7169ac175578b81e97a541ab9bfb76328798d7d631c14df2ad613e9c6e1147a0e84062ddba035859d46bade5fadd9b32b43dad483c6b8023b32391e51ef1520c68c6191326c494423080c623dc4ad0aa074748d826c29644c38986a77002f0cab9068e6c9ec73cc2e0c584b80e0bc375721f7a8fc35317a5e240e8c66092fb6305b012c70e17aeaff13386d5e28d06430ca585b0c85b274e7fcbb63e3423a982579e5a64a0262c41908e55dbe43dac1e5cc1bb7298be428720a12e3b072559ec2675d457aaf8f13252e28aad63c1513f5f239564d363c8505ffa4e50f6648c1cb82bba852bff0acb030cbe73f059dd87bbd7318c5586e708618a4f4c9f3bec3f4f07c609eebb24ba878c6bf1e4f2d0fd1450ab94e31755217786fb15182760ffbe5a267cbe998a4ff90a2
SIG: 63a8aeac025f2dde9a73286e56c2d62dcb79a241ba0b2e2dbaca8752ed2fc8cc7ab8e6600b67645fb5e818a4e82c29180a6b2c3f58d099cb635ce52bdc157004
TST: 441
SK: 6dc7ccf329378e8131b6defcd89370301068946336b0b762ac5ea51487dbd39e
PK: 04e90d275e79df5f2b6ef4a31505aac05a69459baf2c581b3ce3db29f0f1fc14
MSG: 20cebbe98401ac8934c3e65a5738cb0ec0cdc75fdb09dc96312894b187c0a46d2c38f4855be3eeccdcdcc56d926a8c08ce6e748e2a858f53532e7e5fc5f7014c8c6f86310cc26efef30ae525a5157940ab535ed8e403112b08e35e2bb3dd91a9ae8f772d2aff37d8c40d2b5cc887a6f15050a0f5bcf0360c3a9d12d5918655edc3c13c86ba6f4a2fa3bfcd405ed38f871cf7dff0f75daf2c321084ee9fa81211adb105b25c2288f0f2f7f93ef656b2de190122e7a4bfd4a1bd9893a8485b509ff0bc46cc961051c1db5a12490c7e741922ccc0a665496470276f69c7b77098c1e670af6b9f851252996875eb8035a817fa9be07f2be0bbb12025e0565414c817e9421ac700373893862f24cb165f9a271a64fd2305c6672c46767f8f075be5d2d4079bfadc3956288b0215605311b5bf32f0037b7c5ad502013e82ae3419d9d8f39c545b5888f47106c94d5fd6084d26034a99f5dcbf26a84eb4ee149c62a0410d8c707b1a9b071f74ed23932585072ce6cbd33d4d54ee917916f5dfc64d26a498018438b455739345dd60ae0f4750625915cc829ab6822d6f05f6d2bda0a7bf5601e9a2ed6de960371d17e6f43709c9678ca743adfbdb45
SIG: 04509db003a1a6ed3fbcec21ac44ec10cc06d79f2714960882170316275df80423a1c1a112d881fc24d2812526079058aa8b608bfc6b5e57632240c636d6eb00
TST: 442
SK: ccae07d2a021fe3e6ee23836a711b97b04e0a441f169607572731cb08c269488
PK: a32265e5328a4f49cf06b467a98b9f9d5b997b85dfb7523ca6a0a1d627d32891
MSG: a4bf8297d0dc5e4c92bd00ad5b9c09b1238b503d619116ef74260378349a9282b41f3f4676a6215e3ce6d02238480a96043b2942b3feed12620b1fa97f7703b3eb683c1601bd2f51825c450df4fd1f33b0bf9c23c03223789e06e24cf136d3b557403a66981f4b777dcfe890d2ba96da4a4742aeeddd6a611d05fc215694a5d89a5de6760b1d9415155044c049cb02291a1514faa2e77d2ae33d44585bdac6365bf481d9c97833937eab636ed65742a0d5973b24d54089b2daf084d5414765105e4eca14aaadd1053338a8470505232e4ac633345c5cdee1e4653d1d93583af11854b1d9b65fc20281838c56df1148f35ccf9bfe2f3f80ab73f5b791cbed2d920644cf0316f0cb5d3662b9120647da56afbeb47a952953bc1a37de857e4b39fd92b632b85159f46cd05b6abc2338d4632d48e9a178860de8f65d9bc23f24507b7c5629e0bdaac067c476c9c3941d86f788944d744852a61da716f95f3b04f0783a562941bcdda439590fd186b2a8ebf19a5a7e4f4a3aaab7a87a434524fbc9799c9931eb8ce4e34e99b608cac94ab7e74495668df136185f487d9fbcb6605ad725345403ec57f3f6db364a87f38fea4b4c271552e9f2e4a1be
SIG: 0eec754105447f97d4a9cd246c7eede3fd069018f0d01a41dfabca3e90a741835ea4a9d682342267b250fc1c8c547c89632d9f689af536c7929004ded0d96f09
TST: 443
SK: db5d5f41fddd6768709747ab8239bb4f42a31d34b4fa88824d94bf78d3149264
PK: 03858ce6b2d24079eead66ca0dfe772ecda9af4d46bc9b5edfdc286b95fe9716
MSG: 67ee03de45c3e7030db5246ee5b51bf298bba3e4d0934937fc12d9a629604c53c070e30d611999a9cddaf2d9acda6a9f67202b352369d48260eebce0e78e4d5ae54f677521f84a7be0017fab278b2b57275efc5fa57c617186fc1ba49edfbd3308634878d864f2da1583ca8d56ce9fae77c462039abc32d0539c0a60b7bbba5029e9329d275683d9c4ce77d0b908ade98b0e32b4420d9aee2cc10e4be922f9572582dd8967141c1d402e215f20aee0a890e2368e406dea11bd11177f2e038aa2f1a0dff51a128d955d5e5f8d5d0009aaa82440a96864d6c697f910d1df230f467f0e02a2e02bf9e45da95f255410cc5aab8d85f449a5de99aabd44fd763ec14629f3dbab1a247bffb7174648e43b9fb1eb0df5e4109b7a88e05512b20865bad39f9ea79d52f5188e7ca5194405bfb1a09727617f3f6c88192008edbc0c6585dbf261f149dffb593d42716e5a5777f5462beeb1e9a56a2c76e6cb735117cc1183a38d1e00b303d174aa9cf5c731b2c70edd79cc5dc96f4018f1d71d7198bbb7d134cd2ff8c15f9a04280db26a8fa9997eb86b133c022eda15d8ad5e77cc9f62615960bac2f9bbc3ebbd198f72c572b97156fa7fa229a98014e170
SIG: 5b3d0da7102355486be4d69cfd65886c9d9c8738b293cafb23b2104bfdac8d7d01298eeb18fde3ded6491d41b419cc663752c4e67dbe8986833d20e4ef34180b
TST: 444
SK: 7f048dfcc2650cda59491d4ce2b2533aecc89cc4b336885194b7ad917db5cd14
PK: 08001b5d40958bcb270beea9baba3387e3a4b900fc42275657c6c691a2e264f2
MSG: 917519cdb33519680bcae04faa790771ce7d1397c345f1b03dd7625776f3f195809932618b1c64acd93ad000ead09654a33d14f748b46b67aae0ff12df3cc163280f47cedc16a8579034e49884296772ecbdbb71ca29c166233533c8de54012b412ca13cc258f7c5465d83422f524e4c05f806313478319fd143cf5088e69837697d3615d80a7fa7e7443fca65e753ac1b11d8eff3476636ae02d7a20f4b2388dad684002f5ce957caddd2053d0ed533132a81ca19bb080bd43be932028cb5f6b964f008b5b1c1c5993bc9b5485b22bbef701f0a26a3e675ea31122bbae91d864b54d895afdc79ca58d4fe449213353b149f3143b5144d747c5b4697479ae68528485384044aa2c99ba4b17b184e94982269bde2de0b17705d0bfc46d6906a90edefe89195de6bb8f3fb6a374186c7cd086d13d1b3525a3994dc8020e1a00554ac8a82d6047c5bff5e7f12450f4865da161e1a021fd9be8bd33a32bb54a4ddf874512e74b5cfd3fc3cd9ac11edd878433668e3fcc782b97b6d905adb0ebec42c9254ac90f35822c00f97ff3f0c7c39ed3c7cb3920f5608bb45838bb242a52a8637d7cecdcf489fa183b45451c6c9fcbbbf914f5f7e6b223bcb4675
SIG: 583370971d24652ad213c42615911938fa9aa3d9b7196940e6eb08151200c7b6729d1eff8f4f0904074dab3ddda6af1e4e562b7d6220c1a562683beab268f80e
TST: 445
SK: 9feb3df88c494a99849c6fca194201477a2fa7564e29fb06cb44c1154e8cea3a
PK: c35628ca6ee28ec1c239ddc5bba2a9e09e4846816b143c74dfa2aec1f62551b6
MSG: 95fb7581bd25ffd442c3ae38a19bea7349c7b7683ba6767e148f0afc15373f67c16d471781202e6da8054ed7fb9ee204cc0f63c210a670a5f9ced4294588196330d31b8e8392bef6b48fe3c92078fae11284b4c3ba20d937e2719de7bf67c00669ad23e61384ebdf8c6e60735428c084fe217fdb4709ccb6083fc0ae4a05273eef739023d34bb73f662dacdf110b6dbd3e74fc1491e8c96596075fae5c36aabe2a0a53052bf77c4462438063aa7bc0c50ab920c9eb288671560ca5ba7af44a53db2e2ff43ca56069ea5517cb214e76faa53dbda100003c4f6175414041be74de22ce155d2281b6f4035be39841afdb96dd89aa808e6865bae62d6bedd919d3e86510b9fa5fedd1977c4131b2b86e0f48d7215eb13d5498ca5d2368f81895ed855a527124657ec9539efe3b2499a3b0b338262f26340e22554c79f4fad2b4e419c70bc1a2107d206456b6368781be4b5e2c54da42d336040fb7ba49c32d752321adcd92986e78bedb226ceac50292089bb579027f702217745afe06a5be136b3998a3604c9ff2acd6fa3f3f71633d3102fbf03047c5486f84c4dc2447d863796383d55f08c981fd4dd7dc1cb72b8ba4435af6abdd74e6f6e6798f1ae2
SIG: a1c2607835bec1a1d87872fd8ee488d0ae9ed23d49fd6786fc4996725e49b3262118babb4834877c7f78fbeac02df40ab091b8b420dc9951381e3bcda0670502
TST: 446
SK: bff68955dd6ae0e8ba85ab0d0cdaf04a9f5befd5ef6014f49994a78363dc17f7
PK: 0ad9493af80b15f07a521ccd674fe9e5212a4a28c17c74f6605ffef78a4aed72
MSG: d8f5650aa3581c4d39bd1b8afc96c1ad7c4bf723426f9d7fabd1a5c8ac1d2fe54a971fac765e05af6e407d7269bab661b3432292a484f952c11095bbd20a15d77c41f8f3731a504d518ee10cd006c96ee57372de5bea348ec8ba159162170c63e970f1c7a3465a3d592e1d56c6540fbdb60228e340909646320c95f25698cd4896bdff58e2561e3b3d9a73b89747912a1cf467d63e41455fda77477f46fe6937bb0e79d92ccd52e82dba908a05a57c7ecf49554ab44c0b718e3bdd5fc0bf7070d9c58f860591c18bca8b3a9a148a06548e0f01602b1e6f686037c94ff732e155d52d5b0b44703b3d11163e3f56e3b9c1b86476e4dcbfc53fa05984e8c75dd21843cf96f9e494abbae7184aa42736633e3811aeff402b2fcb7d7f702e447241e22a58842fd6d0c03d33ff5b8c792200e173daa7b217e4b2f4433e6c020acce501b9323aa0241144434b08e9d2469139ff67342208900546200fd971a65dbd6db6c21e3ef9172abba1ea9ea2a249addf1a1eaa3ce11938b13e30913cd0dad491fcbb3285ea378b8ef9227f3fa80b586ecfeae137066f8448acdfb78d6d3e9ef4a6b362df4241ad9ae253b8e1597d656e000cea447a02fa4933328609bba0
SIG: 9319eef740633ada1af0e137644c61fb3e11ba4b01d3c6f25392dc9367872a23be56310d312efcb91bdbab78a75e576ebe9081972415f562db41baf5e2338b07
TST: 447
SK: 1ba919c066bb56e640c3335968e1d1b5bcc093383e2d7cf8b5fff5c61ec47a77
PK: 804c90bdc2b3618b01f075e041fa971b83c5b6cfa3b6b3974f3fa43599beacab
MSG: 87c5c75d8ad07d52acd781d1bb95f78c70e21c2dd66f7aa44234152f98234d128358a8aee98ea903a77b441db1447ae6ff3432ddd4570f7f58036122c1fdcc93cb21573739c19ccaa411508e08de2606f3d8f2db89df6a44a46133d57018462627e22f57ef36d1de024de3d4ae41b752df4821155934b447b2effe512487521be0356832a74ce0e2d8301b79f93175e8b6b961b1df637d8acadc884543c6864f8025ececec7c6e4fe0fecfc40dcd95e8d6ab93ce25595384436b598b73c74b03d49ed5002c0f858cfd9d0df61ede937cc41659d6708b96fc5aaadee109e2a68846baf2c246dfcf3d27c28bd1371e35fc9412631442ee75f38c6e4958070a74f6e6a220f75c7280eab4737d97e37882f3624811675f16caf60cb944bce92e75884c56483c61f26b6371b1b51237621a06543eb4abea7becc4fc31dbb5475b3deb9bb3c8992387104830c6072afe1af244bf681a40329c9b37772b09c5e88e78f7dffbc04549ffa13b4144ddfa538fc4b3300540ad830215e25f11446d289f33122c2c880de3da71c453d7e88f7ca4ea3d1255e82f4bc9e5533dc401c33040e16940b2cf9cf21feaca1c2c6c33337cf75e1884b483bf801536d304089115a0
SIG: 503eb7ed6de1b776c952f255bbd4bcfb0e48bc70c2cc2f1f72bf6881479040c47524ec542ae13f6005ca5016b58b736a50898dd0569d4d38ad298630d68adb0b
TST: 448
SK: 9b36247c17710e95261a7d702f57fe81f2971117a50c87920193b386d494ca97
PK: 29ae39f273e35fb3f611da091600650efbc4fc4d1e7b4c76aced5a83f82634f3
MSG: e8d9d53ba27e98edd55df3c6b245eacddc8a40e3efb007bc918ec5a869178a170bb4a635b7f8f742e37ad45d14a74344a6b522830a522106eb960daf192dc1e0fd70f16160e122516892d0e2abd0d4ae0f0d2e5adcc99ad55302e251b3e7a4d0cb33774a497049905c33de1fbbc1ad2b6c645295fe416b4d12b232efe0a33cd2ad8732eba1c3cb0eaeb0b2a57fa03ec567ca29210bf6ff9542a766f496fe68058aa983806cbe7ab10a47920bac8248818e54a41551c9a0959e8994cac60fc868ad48b5a24d5f24a7a5a3fd90b847e817ad3dd5d0d6f8de2d204f642483bd53585a92ef925415a9b38fbbf07fc0f35e707569cf488b205453ce5433eba6fde8781af72b52bfbcab85ead385d9d3175e21ad3373ad535cf0e357ed6b5383ef3829a9d5095b87dc9aadbe0ca7abadf33ec3b6ffd6eb94afdcc12e8d66a6fc05acf97368db0f69565dcd8fef4d1e49d7dd4ac053c218f5240c812d4ebba440dc54cacddb1c39329e5bd0c3c80dc3259a80f059f94679aa0794ca0115cc62af25e124cb8a9d4160eace6d22c7b1c44544f81142a19ebb02a9bda6429c50e783db4a07f0219e857c8d3c5655a582831c8eabc3f19b59ad8d2c714adeaf4039d5cf70
SIG: 035970a672e93f87eb42cc396f6ea7e1b3dd5c5951572826d1075a15c2d7e454df195b51aae8dc61ef7ab895485f64e5989573d98a062e67ae7356fe5c9e3b0f
TST: 449
SK: 6fede7396c462033189acd23d2f9d02b68898d35f3a01a798fc24d488de93a78
PK: b34062060b2c20076a98fea939b3b3a50451a5f49f8351c0ad7591dbbebb130f
MSG: 5abcc14b9d8578de08321de0d415e3d40e9de31e1888137475ce62bc6fbee8fdd03b9d47c7b88bbceb804444490bf6a3ccb7a273261e24004ea67cefa3d5d173576d01e38f76c1e0e515083c97e79914acf2be4160ef9360bbe986b36e9ff93346b0e70691d934e47f8a503fa933ab2a50426947cda8e810c9ebe3b36982f09aee6092739fa2358b613c7f129db0dcbe368bee52f2f7f1dfe3d2434605b5afcf256071717d924fd0803bbd0dd1f9555ce834dac781df4cc7aa19e7f11da9fb99cb9e6b9e1e6fb4f7e8dcb2236c28aeb6cbc55a130e03c1b17a991cca1b794e6c13732d5b0a66f6eba860ecb98555aa4c218d112b116bce238295de142741f687be0b2487f58ffc5c12a0a519f1e23793242ef857ed398a20699d4351453fc2f092762abde34f4da2dbe0ce2aabaf6bc4c0159f3fe1aea16a036f7eaecd629538f3e0eed83c9a4dc1abc238f90daaf489fd61b34d937b6f4607a788baa82061943dbab26c1d384d8d49f99348800bf361f871f5d6cda18f689918cec31ad158f1863d13ffac5405c162c32de06e32994cc4106f95bb4fffdbefe7d629ec7797394609fdbfeadb46927370a11fb38471540f951b93c6eb238668dc006c21660ba2
SIG: 88a83e2012d209ca03b8ebf6de5bb7ef4ccb5e3df5cac78954aa694930e4de82544ef5083c4892db9f05d77bf63f4fdfce15a4d1c3f85bae8077062bec0e7b07
TST: 450
SK: d559580134ab050aca446ea7750ef6b371d92d7645ec7635fe7851100bc4e51e
PK: de5020cd21a8b32339decbedff24664d9580326327aedf09c5ec6b3fe5405226
MSG: 6842e3190a110eee96c507d4bcb4c548c3a0ed7b1a8ed77dd93b38613b23c73e830b205e62651921ad8296b08d1e1008ad78f2996e3c7f38032e467cffecd77b8525e243cec021f85296afd545d7be1a62568bb0cfcdb90d614ed798bfb7efc655326816a61082251df01613aac88efcea1e0ea2961b8f921ebe1558dee83374a0113a78c55857ce2055bb2c48badbd3d8f4cb19734d00d0604b619073020d72a99a1923e6160a09946567fd4bda66442ef5a7360786d178dae44922f350ce2edc6af73d1bd80dc03ec3ca7005f4109d10c6d4f7d8fa61735110f8dbaedf91a0bad7d7fb5c04d706373c15c645063ff4b4fbd2d559b0afad432d4c496cd8abfea286fa675dc076726ec522b3a3c2f47aecc539f48a792169c4cc8cd41cd2cb6b63ddbc19373ac9691c2bc2f78f22603d5513715a16d4574e7acc4bea6dcd8ca7f19865a49d3664a210dfad290774b10b7188f255b3be4dc8fa86f8da3f73a4e7c929951df30fe66a17c8cee23e4f2ed2063f0b02ab40372cbe54b9a708df7c48a06566d39b19434c6c766987b3ebb00675f44c4b3c1e9f4504e7a9270589c0d0f4cb734235a58ef074cf9decf3601aeeca9f1d8e356cb2db5fce79cbc36143f34b
SIG: 6fcb1ac9290ab767d59b598c9a24ecdb6c05bb023ec36014a40d908ef0dc378a4528b3760d889a79174e21cae35df45d427ba6ea812bddca16e35a69b5e79f0a
TST: 451
SK: 9d4ce975547876636fea25437c2880c9aa8ee6b270d1b2da197c8d7f95e7dccc
PK: bde4993c030477c35890aae82bb5087e914e64b94ffc64e2d7a5a7c919e2d902
MSG: ea0fa32a4a288811301b9ee533fa351fdfbf6bc1d0555a7402767a3a9198558f74bba7031857995b9f326226f1dd5df107b06342203eb8d40c5f1dc95b4f3f88975aa24af8769e2670c46671bebb7a0f1b7568729aee477e8988af9c749f3202708171fd94b337ae67ed21a6c44174014b0b0eb5ba71c277978d488c24c4a7841309846b4e30a4fbbcfc45078d7e14014114b1ac64f7c33c9ac25ea5626c2c819fbaa2a4de8a2bf5f1365d6b70407e8094f99197ce1f0c35e11a98fbe372414ea2064a3a12d1cd5c8df8fc0e79f5b770b58f477f91976ca0139895120e246baab5a026f2d39c687dc0788334b5c626d52cdebe05eaf30864b413eebdc5581ef00d439276e52f479c9c05b116395826b60490b3ce700cc0027f61e46ca2f6fbc2c9de2e800806550afb06d4a08eac7a758e24582a4d6d428b433d365fc31d4444607afb64f15e370794005a3a2244e666d5d4c38ad2009c769a51cdbf738d235942f412d07feeb73b3657d0b0c91cb5940bad6a706e14edcdc34225b1c1f38b1abecb2adcaf819155a94fe190fd556822d559d9c470854d3a43bfb868dadd6e443d98ee87e4d8284f5cf3a6dafaf295b902836c640511e610ae7d0cb1b1d3d6079fe6
SIG: be17444cd465a87a971df84eb102f9c7a626a7c4ff7aea51d32c81353d5dbc07393ca03db897d1ff09945c4d91d98c9d91acbdc7cc7f34144d4d69eb04d81f0c
TST: 452
SK: 0273868232f5be48592cfa05134e8d5554ed1f9a57bc7e3982a330c57e5a7f3a
PK: f172208782db66d466cbe4f4417f6fc477b7349f2a98db56c03a47227546bc5a
MSG: f7a1d4614cc64a3bc48f00c6276304f34d4dfd15e0617b93ccef126c5c638c9d9953aabb7df42df4e0aaa7eac96a4b38c7ba758d860c90d05e3d14e479e545f319b0e5a85ad8f0991b43d6e49c24fa060e3e5df95c98d9451ab833e12aa97f404611bba359496265a6db11917d0da5c6a702d0b102de36dd0c98df5b54806ce626bb96374475f68a6060eb350a7d2aae3204b3dfdf9f1e31be81f7170f8a1b9385413ff8f6881e10c1e8da4c88afb50639ab44887aca2abeecedf110d2958c13fd3390d1b96a762d16ce196920ce85f6c415bed545b1445302a6f001eb8d00e97c751887868d481a0b1e4dfa04b6f761086ee8e697b019e017104bafb98fca242e334c6f18f1db5b6f295f05c559361c6831dabc42c2110703f9d1f64e12ddf26a8679854e9f8ef8479e1f12c35447aac02ea7f242e58632cf2fd063fe665070445b80f3dc6a3303bba96e05fa88eec201c5c2d00ca81b8da6969d0a4dd0483b3477d325a71facd6fa2209b48cb4f6525da73c9c05b2d9789b01448e1527e56a09a9bc6136d9837243c2077b925bbb933f8fb1daac963398c5802aeda3bbca8ae3b8f4a9a871f7ea8e2c0ce898c566217b5c06ff55ff9f4fe78398ae7973641eafb521
SIG: 15e8d8dc7d5d25359d6a10d04ee41918a9c9df4c87be269fa832434d5301db022481bfa395a3e3466f9554ceee0532a8183a0d0550e7d1abe99fc694c6ff9301
TST: 453
SK: 336a83b55abf4c02e25e540329b5275843c2ecb8df69395b5a5e241bd0d8c10d
PK: dd60569844570c9f0a82643f446478b5ac6fc542214231a7ca656a92b5fdaa54
MSG: 9afee8ab482010e29264b406d9b49453d1ce6d550939072182863e4665284ab05d86258e0623b18754c4785238f697f075adfb9e1d31a42e85934ec071ddddecc2e6c2f61334a79526788b4952190716906dde17fba556eea4c8b59727514f6f5615a19ca36da358fae6a6c54f7f4b7a929e31ba7cc71bde7882fa9ffd87300136409caf3ca64eefea616aed58da5dfbf28b668ec1cccffcef6e2e14f8109e9cbf76cfa414f91ac00f48e93eada385dd3d5c16e1a39ea3dd55c761fca361b428f516c05e694fe5c3c345cd94457187a8e604b200a1a0f937ae89f4d6b5421dffcf7ca15f2e2c25378a4113233f7613f4570aa4b909a9135eae4c7b9ead458007ae17126a11d145258af9563db2f7e8925431878b0eeca8affc01ac5913bf5bac4fa3a857c54cc8906d6af77de6b9326b6506151099e87e99b1e819c6fbe082688f34b803d588e416d853169765d62f7e0bdf72c5cd66669a0335562336735e7efb734a2fada327f858bec602d0da08eba4479e7f6dc4def6e4ebdbb730ee91a33445cadc9df52c825ad36149cefbc51ab102033530814bafa7e87961b06367ff896f08ae334a9b1aad703da686706c11a04943ea75e12992dcf6106e372077cd0311029f
SIG: d263f56d59cb9b2896a947267c2ed78a945bac5abdbf3c14dc3ad092b2308cb9315c464942a0a20b2024511d766e85c936499a149cd0bbb209150a1643265200
TST: 454
SK: 88409172618b490393db27d960171cbc187eaf4dd8b320b3d2f824980043718f
PK: ce2e7c5839ef5632a123dc373dc14b1f0505766e9675407604ca7cf54e8d44b2
MSG: fb3e82f11bc286267e123817ad8864e077d9f7a8e7a163ac7eeaf93d55dd111de8083b66b53ce7bc771fc5071a2d7ac2f85d6fc6adcfcec446e16aa1046df37209ad7a29cf9665b439a54d6f8d942f89bdaa56f2f11260cc95993038b0e8fbdb3214f142e6c90b61a1d2b142076206af30ac35784a6dc15a1e79251a8c7731a1c53978038f8d76d70c6c1cdf529fbdb84d1507dcffdd42873dfa6a8fe6bd6f7fd29c80e4b2f933d2b6c9e62c9457e665472655059b63b618e2a9a8e5b9e41c3646173a892b8e6d4bcad6a62a6fccd3455890b58ec2681a95cc9776a9fce83c54a9ef312a331959c7ef3f79ee576eb7b79469c9234b1eaef609884708fe4bb0efac662da871ba61ddabb3fcbdeb8f635657dd9a5d7311e639a824858b9a9868d3f9384da612c7f2e771a46bd2624c99ea2b6ccbca996c1d9c375554f2a551619ce6d5e6e4d6b844a4dbea83ba732331fcf46572c1fb0e257ce1041b265df02e690a92814bbf3b5ecac69ee998766a02b0d2f908b3c15f952699616f2c07d589198989e6056c16319aab6cf8771902c078046a88b2570c13bc5edeba2ed1e3ba131daf94e6891862bb3de7d1063fe405307a5cd975693e9d58e17c690eeef4a2603cafc68c2b
SIG: 93b6e29d63945d5c427387d006c7f0b01956a95fc0436ed42b46d0f17b5bb193ea8c0ebbf3d6d13bb539e35c91f3f0f9fa3414a0223c9060bac83653c6fcd906
TST: 455
SK: e571189b5cd9e788302de3919d850c227dcbb615022e568bdaeb37ac5b2939c5
PK: edda890f42dd5fbc7316a5fadfbec38556f23f51b8efd2625437f6b5069f1ee5
MSG: b62c867ad6227435bfa6dab830684e38d196e1f861aade0fd6a7699b6d60901fefb2d799c35c6f3d8bb94deee834403981866bab84946ae9476c75e9f1d3602b42cb2db437bff33a775822f0d6a257d4b75400eba5b8abb314b71fc6b46f8a34e861a9a62abf33de8482f63f9d7169e773a2dcebee03705dac117fd1499b68e7414f51ff9437f253a1d9901ec3b0bba86965a19383655487b58010f804909de1ffb2212c0252ddd9bf2a56ac46bd59c0c34dd59e46598b6babd4e5f3fffde55e48dab0398c22af9e26baddf77275e5f017b35a9b8f8435f9631936b391cb95d7adf35d1d8545a0fd066412d508967bbe9a20245a269e3be2777117e75fbac170dba352be69b254d353b3b2cb3b7e21b721aa9fe044f8916b4b2a6f8c28f8abe66ac92b91323ac73afd93dfbeeaeef26d19bd9f67e99d48cd2ad2d3e55e45d24d54b50f44a39b90e242ebe9b42bebdb230c470bdfde1bc7721c3120008477393dcc2e15fd22b251feb0e18b02883c078aee4fb760655a671dc7b8aadb9a562420a3c2efa2d342e1e0099d951b42242984f594e6914fe282b1ee128735984ef93a669e6ecba26c9fcb9f09f09256645617f1392d35908917cb8d29e0897c7503cddd5de1959686
SIG: 7f797a31715d7c356f8f1f783700aa9974bb936d661661ad968c7cde1ac9e767be56a2dd49b9230e90110c67c0ed187cb7e75c3053ece844984d296f0d85cb07
TST: 456
SK: 371744ab63c115613929a343709bb019b7357dff72d2a149f1d0f71d3a201efe
PK: e58abfad4a13859f0acb05d0e47d59638f7b1b4936100b988d61e6e70e22667d
MSG: c219de1e8d7ad8df08c49377396fe7c1f2d57bd2170633a00d708faadee180ceba92849a7778506cbb366875bf9124701894cecdb3385147d0671843922a649aff7c435eb5a9c74927503072d0067978716dc80be1545a2dbf5a1c38536e12bd7720c1965d3803a4e8aa55765192a13b705ca1059ded0e806362fc5bbe6c76a1c9674bb853790f7e90af00753e00436da48cd082ead64fddb689890162082f8482924f33acd604640f69927352b43f64402d27a883fa6b72aa70d241dffaa1701a25cf1079358260793875f76a2978e9f9f9d68634eb3f5f01bde1ce49e5921252f949f082795e4eafed7be5b49a9f95edbb4a13532e3f3b3be62e2652231253a20c1d5477e8f4bc57ed76fa19eaf03a11bba429b6496ce76246170e043bc14f2d2f703d968f1deb09388715c37cb4752da8d464e348e0313c8993e24133a7c545284e3c9c907d01b260c4883f9cb3e3dc5b6f7fb6d75536365f2132eaeddab570e7273afac0bff5c9fc0b820f2078e0336052e1fe7bdec86674d0998ec78da1c3f34751f886727695f35eca1304b14734766ab05c1186306ded9db3eef65d3c0456cdae8181afee04b296c6722a88c7ef3088d26f7fe74bc89cf5285c688f027b7e68600486af
SIG: 5eae4ac72af0174ab256527b7cd337a0e5482e615af068db21dae35a64640742604df73fd4ca02ed9515a5608d73195230fadca7b426f02a2fbfd02061af3600
TST: 457
SK: 498b6ee6492d53231b3532d193578ba75d6a894e2e530034e21ab8ad8d2c0d1f
PK: d124665b28facd2d17946a04dfe3d129a4561a2b24eb326d84b62b422e44dbcf
MSG: 0498a59b87cdae28695547e10863bce804d97de0ac8008f3d5fb652c1757419fdc9e0f9736f4c59a34f21cfc74599fa788fcc10c6730c7df8c3d2c1b6a786d1230b65585719d1cb5c490359b94435d6dd671f54d6e9a19b9b5aaad7e0f233f8797df997828d88cd92ef089ef7dbf1e95277894a2f7c2fd0c8e4dfdfa6d3d14589ff01916dbf9ddd811c2f5e01e94298990a145a6cfc26895614c7c963fef308a4e3856c32dd3e359bc56d2cca496ad199ff1a568d6430ac5cd208e0e2d07803ca523e0d813ad3733ab50bdcadcb988aee758ea50439bf38ee649997604f151c602c82900a8205d8f6f670c8684bf5abb5f75ff29a37eb9bf8105199fbbfb4707e162e64c715270f853e648b0aa26fea0f6db562896bf424a9ffcb292fae85b76cefb8bd5a4b3ce1fb39bd2a50d0c9e6d933e167ff629b8a494f2a9b774eb303c781ea02aff1a8afadc2465cc616968015ed6a5a33c3120b945ed5351981e32fb9fb96b2212dcf8fe9ac56e3cf41dc524f800631020b025919178ce074eef078d6842012a276efa628db54058d1eb5b5b705f1e1818d2df5164baabb0c61956ecdb8c706e562fc4fd64052870530ae425b221f89dd6f90dab882e763e7a7ffa141bbaa8bf7a3f21b0
SIG: 112f5c6d3bcb3dd99346d32ad69cbfac3e653bef29c68a33f43231f66cea1d0a195427d6e10c0e77c5d55fe2794287ee32e5e22bafbbd8052ad3606b90f94505
TST: 458
SK: cefcfcd1cff4d8910749279131830b1da19dfc5245f78ca68b8c3c1b622b4551
PK: 1d394abd1b4ed1aedf966a60efd3ff882140a7e56b428374ecb443289a9c7f00
MSG: 5ec94ed06fc1257ae9c183ce56271207aca37a23fdb4b0e74ac9307a1bb112e05ed5a5d047c93109e2e59477b03378346422de36714c2961bb9736a513ca3671c603a68c2be7317b1b52a076dae2aff7bc88cd5eea0aa268faaadae539c938bb4fd4b6069b1945eb6af0c9e6c8aa5ee4a4af37e90c67e248e8d27bd7f9589c4d30e905651baf45364fa049957ea5d9b7146ca68204e5e973d0f1c91a1c4bded66115028a71114f0f4f851bd115faeb954e3f71a01470b2481a0098d99f9d74898c8ba0287cc7834155214173d1fcbafcfe9b08250384439476055883833816c9524cfd5744aaa259db7ebd3a6aa20b5a6546dadefd140668eb0eccb5f668db9fc62983df980850c9d19882a17550d5dca3542cd36003a0d03cffb04575a3e8e1d07015c7b30eca9115cd2b72e46dfddf6a4dda1faa2dbdc89000d433f6ec9adc46146d939f32121b99b28983d98b9dde8c3f6e5779f2b0700cb023db13de656e0aed1da2d5c6ba2652343648ad420f6ab9e55a97482a1a22b3bc2ee598629abad9547edb5ff790990564bd871f81b24b12f2bf8dbdfe7a88375fad9ccbd9fc0ba1d3bba5e3c4813c18a0348aad83fb1b82689054d99b4600dd1760d0dcce44757467bec1946406d530
SIG: 7d83ff66ec79307b1c0c093fda3968a96cf6044f5c802888584018845e7caf2a135ac6f1677e84d22e458e227e4f930209919bc11b12f7aaf2b8c94302d64200
TST: 459
SK: d107cf26f527db71a206e41d17955321013225bb20f93e12df3dc7399e720ca3
PK: 186bf453c95dc0a2fd589a78e2c80040b3f6ddf9a6f8681d146036cf2146e8fc
MSG: 78eb9e13789928a74f360141728ede98389685c836b91fafbf1a7e8c19cfbe21bd3c3d6c6ed83c409ef693f1d735da3fa466497e19f38e30fba2a1023785459070e6e92c1cb7c9bd0c9ba61220157866c3bed2b01e6e6b9b8dd3f0c47c02f181346a0a9b9b5d3d7e18a94d6956855e16e8eaaaab71b10302f35bd8fb1f9b5847304160324926645b0582c2f2f1533a24281461514241db2850ef31c5763b2e3d4fb18fc6d8c1d7e52f7c13392c17e27019ff60008e431f1714370bc0efd9452a61f5c56488d91a185037f1f647f72fa785010d5d78f0a11587ccf66b8088e0e635fff3774193b2edeffd92d6e8a0321128ae64cdb862e631e2ee5ba0da44bbd589dc392b5a113b86a727a8ddb698a334cc668b39b1cde199b88837ca5f00f553f89c622834273641d39bc10c6a24e1eb42587542f03fc1627524ed6b749391f11028706c42364425b2caf20180e1b802c744b49b7bcd9bf7b15c23a0bf1c6965960d341554e1966b6ef82fcfbbe41d1e09d741e309254446777f13c29a67b8bdebc5f7f04d160d60e332e3d0441a0f2f7b192c3e2bdf6dadec2a424f88669806236ee04dea692bd8bb6f91ca0682ece349142575358b9b7be70600b3cb81e1456ba0799fdc01ffd68623
SIG: 8071d97f324f10358f13ac8c61d424b4f300dd0419571c39e40d99aea5f03140e62ab4c97127ab33e98269966ae1d4557e459bf7f597b313f351a20122f0660e
TST: 460
SK: af7ea8e41c8937a4ec475ad81371a171d3d0f9fd7519a04c751ed4ad8ff8fef9
PK: 15dfc71585bac71ef20f374987c555a3f2f07d6b9c787066c10d63cf06e02ab0
MSG: 05f2263f0245ecb9faeb14e57aca436668308c8125df3116c4ee20501d0cde701b366e2b50a1c5edf484144ce16bfb1f7d26dc4275ea9732e264ba4d4a362b40275ba47377dbc332cb65e2f4c8853894aa878a4c175dc5b3b2a757ff3c8d7de660973b89dadf076e2e4fc76239b7bc752a229d44e000ceb667104cb0746bfcf59d69603ae7fc1bcf11d2e33f61dc497ec1b0bd5e4f1dbef435f2f291f30b00a85e833946c8b10484e4abd7d60bdbb1fe6dff5807a53bb89382153013b70ca08efc91b7e9fc5b5dbbb6af123b57be2e140fc471a45d89fa8284cc27e0a1fe771f55598bbdcf068d506dad0a592179ceca39ee9526f9e4fe47bf2bb14fb1486a677d4d7b99a520545676a0f1fa809049aa2414ae7b817d9a036e5c157886e8341d4e819c092a3b48b3606b03acb727c6c2217d0af30121546a94af6b49caa2a8c9b1786fa0c2a524ec7a023e924b5f8a89a53780c7f8781c5b8e869430caa0e6d0437967e3aed44f45c901cbcf1026fbbd4e3dd9a091ecf8b34f7dd5038e543dc7eb6ad5494efb145cf63ec0d355bb8e172f455d8a6b13dacaaddbc56e47de3cf762a1a738ef092f1436680467b5cd82e9e36e2d2b6842b3bd5dce77180ddaf0b643378e698599dd47f5cdbb
SIG: c0f1739167274bf91831c74beb645af790459b28bb3f21325365130f409acb66df1d223759a9758e08fd7253737484e285a6fb47404abe2eba5ef249fd025c0a
TST: 461
SK: 0c57cbfcebde10ede02d1cb01df360d41f2e66a50443d58b5d4f0828c9a18bb7
PK: c4d761ba189971b9462c61bf46a765f88e2ecaa5bf2211220afb00ac657f7ce5
MSG: 337703243ab5b4e4d3481ee8dd1f4494507174412658a93988b5c30403a7b7ed8522ceb46fa1ee02753a874ef0675d397c575da0b08caa8cee3393784d0f0db8459837af90b9056df4e38e417f3ad2eb1a100ef207ce2ca6c610018021661e307099f2b7c4ae875991140bdd3f0f99ad2c5d55aacb84cc1cdcd579e08072b6951fd45ed289ac9ff7f0986ac88a4fbb9dc9203d9baf180c90edf937258c9d0a6d48e220f72d250c7f2c777eaa7fb9fa11d50a5798772f9fd976b00599f1f0276f3a2e4d988ae92125467a8dedb7a16f9e3a56e8d00662b3eb67a35b9b60e73bd935077ee238df8f6e833b9a5523386826c1f2917b1c3ec98e0a5fde89c48b1d446da5d0c885fef0e374bff30a997c7bafd5e743c85d0c6aaa6ef10a061211a2327c6d84eb747a56e9bf60fcd5b553b798834d0c5ccadb9d4b54e7237d12c679c193a287bb2f511cd4ee2a2d8549b44b21c11fbe5723381c6c5f784687fd90cebc5b495af9e414f2961b06a1c8433b9aa3292bcff4241c227167f8d1de054ba33ad81da3eb3ec6e40a6e26854af349540171b75d75fb9a8d12937827fd594d317b7a8d9f1c2fcabda56375568c3e9e514c2efffc3878363dcfad9fd95436b022e8772a88cb71e803bf90381962
SIG: 8af7bbe01b8ab93951d16fca05a9c967d1c52c974bea151ea72e4cebaa20cc783bb61d8d69385cac5bc6d72dbd162beef1fcb5dd0e0a08b48ca0b9f6d9a9880c
TST: 462
SK: fe7172278364194bcfefb4783142b79f59d5fd978b1e47c314d78d4cb3f61c8a
PK: 2e82cce47910c7e2a79bc1f419dc3c3df54f23291fc8193e8258ccd2fd38d548
MSG: 23509451a059969f2b4bdfcee5388957e9456d1fc0cd857e4f4d3c25a4155d5ee91c2053d558062eea6827950de863bc9c3df9672cde8ba741744ebbddb45ec1f4284570fd0aacd07ea58c581be2afc95ae444e678edc2a02439f387cec982ea3a44814a8a302bb3bfe8228d58de039debdf7c2a7eddb4e71ca474f94f7e2bd89dc65b1610733c91fff89bd499f40154a6198fdf5ec7ad3722d925b292196c429499075be0c5b6da9c090c0791a7019eb5e7366be6ce58ab2f04fecd9127c42718047bf47030691521312c0877aa3f36cc5fbc9caae0fde3945d2a868ee2502a3833208eb850a163cfcbf6da9ee6ad9fe067fe241986fe4436d6ae4edc61561938e2a33f4a33db63f69d3f1a8850ed40028869164103488fb795cd82ca067fe1b4897caa49a7ca9a80f3a8151fd13bbb7ff350e8579f565dc1c4a9ca938d27b15b3f858ef45d3dd78b2c358635356315f55a97528ecfec5d11a5b721503107faa406c17034e601474b3b60cf48692e269261158fc353d4df4274381357790b7756087b00cc79e3b9d28a3f2439febf199e64a8b37c91b5a4334e3354e8faf3a361e856c54bdaa43bfdcd6ee6c9f9679588f6069950832348aacba2bfeebacaa2071ddc7d77898ef0f68793cd25
SIG: f6c2a4296b9a3407c6d7a5679dae8666b503d1a17eacf71df493791b8ff0c0aa8eed36b327a29ab7828f46f22de868b628b1cfd501e8599fa31693b15f61080f
TST: 463
SK: a951e4e6ba9f1f0b354831c986942448faede37e11b0f247da2706dceef73ac7
PK: 30362014974bf75c8495c2e271e713d57384384d0a5da88edeea79279c0c58ec
MSG: 20577dcac89174885eedb062489cd512fa72863ec5438e31e95878b75ce2772aee6290a0ba3c8f642c1d0ef55da8d5bc1484f83bb9876c7a8c0b6b609b94d112a06fc83ce8d2c1e08ed6c735e57b244aad6ecf7075363d565ba47865695c8423510909e0a3db4b61ed7aa67a7471331e83a0c58b8220a6245f65661549c1a12d4c0d50c326fb94917cbd07be51e83fe8bb3e46ca01b0a260daaf1d6abe3703d6a925113bb4d57ea1a48b4c7dbdaa03eea814a4b5f02e1dfb545cc623fe17a3bb18e4373f5f7ec2fb5217d23e4fed54a772e11323e730aad7efca8c464400e7679055fcc125a876ef7b8b9de186e229a7abf191d0c56d91815f67872e957bfbc7634aac403576a58f427bdbb30e8c4b6fc6c447741024ebb503a5a9025124a4887f825a43ee940f210a1bd5ae4f6732d60f95f2b83201c4c6dfe279412d7502a5211f8f48f800db30fc3776c4ed3a38bb4634822c98a6d6dd3233be60e42cca45a3163cc84e9e8da647c0711bc4c6ccd65aa1e972c07404d103e74bcc31a7e2c3eea5ac9257ab428947ab3dd3fb153d90694a4073373c4dd9ceb131154fe877473fd996f424f33e316e4eb02b8c7513be6998e516cbba54d94cd0a435e0ffcc2c0a8ef72b630ec24781066aa5efb9
SIG: 0278c86a15208d9be5b1e1574761861b8af72ae08d40cdcbec354e65a9c3d0a06b5fcbb297d09bef397462395986c3093eeb22644c003c3078178cdf674e990a
TST: 464
SK: 38a9b2d49ba8b82f301a5772cea0efc2218455c8b218b22cbaa2aad2d7ad3b35
PK: 9df5ea1f78f810a521774602bbba4942f0459238966c8bcd21900afbf3d84293
MSG: 1778167c49b3a44d4a5ba838b7388553b1e13d36ea4f86d30242e1a822a3bbaff5cea63e2ae2a4635be236fef2b8135d14fb621c0bb773c9c17753f80926eb55d0f115bd09a885d844b818c9f04489a331bb5e032b8e58cda36949c5a8d08b55bb8de965e1f90d3b9cfeecfc6ad9a4ee5cb4047e9450acdc64640166a8c069ea849aebddac1ae4afec91ddd17fa5553fa87c56f7e51ec1cd6b5cc23351d057a4ce4a8923c8ae6ac7a8afdcc0881c0e74ebb024ef7296162cb93c68e50bbb074e651ac87dac9ea59d4c3fbf0fe379f3e97a24566ecae54303bcfb6f0cc9f15f6639430e66b19a427849fdfff833df02689e9de44006c903c559183459b9f4a97f54a0f2a28df7b0e9deeda8239d7b516977f5e7d6971b4502e9885f750af8d1a6669e25e77d5f327c77c87a86e0a1872bc96a76060f5f8a0c40cc973bfc7fe6ed9bca78f884e6a2828b94d489d32a0fd337e69db83fb8789afd4e8ef54c22a78c2587468b9ae071bae3b202d3183ad5f0f8e842e5a8de85bfff49e03c8381bca7fd4278ddccaf0134fb5593a395a77a5cbd434593bc4ad0ff4b8400ec674c4ecaf1d57754be0cb2fa9a6441a9abad7b42197ad82e50827e4a4245573a8f0ef87f58228a2867f4b3b834b6635037940a
SIG: e19e62ac539a9ca251d12d4c71055b0a3f581d19f2682e672404c78ac1f12bbefc91519276a5cbe16f520cf7a7f687a240f0329157c59f50026a58dcdc50fc08
TST: 465
SK: 9a1717873689a03c112dd6b4d76ae73b89b416a598ceec209e27961e7bb1ee8a
PK: eecad1e0e4b863291881a8c241db9ccfffe4e55d8b5a42f307b4436acd0649a6
MSG: e26580470901a07ab0931aa23829802ce04da59fdc2f773bc567f1e65b4f2e2d4a1a6aec1f54158adfce9b099790b503a13d22097ae23ebccf923f3bb1986d6e49111a8cf0d4eb8236bfe0d7c9e93a5efc7feb8e6a9cd1b8d921efa21e449ff49e06c1ccfea31f93e033c3c2a54ddb0f653a09fbd18a70b56315f193e7be56e5168f59563821d4bc3bbb0eaa2048286bbeee5aa3f3e7536cf2b750fd322602bb3847ceca39b75474322d76b1de80fa2eadba152d6f8f020d4d931c53f0a2801224d35deb6ec13b014873e689903607de96d9b7a743a887d2f48daf2ed2eefb202abf6082796981123b966e936dcf3483e2d24d694ecb865fbeb6969f347027fb8b175d24a4c045c0bb4ab5e02ddcbe77d4756c46d137b094473a02307a108340acad9d03bae8403af199cb75cae3162f3815813cc68bf2a5e499e594921149f3bbd214da5137e756521559dc80d9a4b74a0f4943022c7cd5fca42315e0bceeae9069615ce67a04382412313a31d67b346c329ad82e742c0a6ce0a6a02454c113e52022f3cc03fda691ebdfe14c53c8ce5ca9b932ca1a386e3eb4e90a4dc6e8ad8533b5af1aaef5003128655ca64f67fcd97c6ac803002404900bc0fae98463bcc31409f9981748789ade2d07783bc32b
SIG: 1af8be095538965800d8eff6d723d028d65d0e9c6eb5e9d125bb3b1783f11ef7079a49a807e27ef1260be26a3b231d03b2ae151e49f6f189f15b1c83eab01c02
TST: 466
SK: 43bd924db8156008c6b3994a8130d427d514db8a613b84dfb0b8e0de6ac30676
PK: 1b3461c269d5b0062d5df6fa654a2586f647a0684218a06e5e2f7badfb394131
MSG: 6184e6480c42e96cc877269b16371545ff9523c45ea88e76a1348c68ae7f318b088fe4610928239185b6b55bfa0f43644c4a4c97c56ed77d08b1f4aad2f4aa069994abeca96b7bf81b8064ea4350d8a8b02297a51308b61c57c8f1873c6f97007aca3180429e730a6643f28733547bcf7b9adfe327e85736bd04af7f1d9f4fb84a7f3affdf4e22b574ecb4bc8836b10b8453aeaa5c1bf132248b826cc5230f75e075fac9f037561136e00643d08253e7ad652f702c0d15b6d7d48aa6f8e9b5f5cc146e3f156fb2522751c3710041bd922f37a50377e028b0c4e4bc3465d7c84af6a5fb427acb3b41378b102bda46d8f6f203a5ffcf395d435e93458a0b0a4c2e7782fafe119f769f67058c6677f6d10d9cf5cb8748e1805798ed233f6f930eee0e5075bc58b97af9177fda75d53708beb04dc4f19a43e768074609f14065f48fdad5077ce109bacc357174a6b7956f6e7f32e38415be526370fa58c3c0b31f51e6cd4b2cf27f8bcbc21259d9e5c3b5c2946a9fc1b00d9d15c3b7d80bfd9d05db91d249d3e42d8956682044548d83bda8d5cc9212442f30b45cf4aead80cce9b3512c39c5c737d3f8d747afbab265af5eeef8ca9362ec76e943b0a0d7a39f3db11eca14458a7b592e5e4ff2275dd48b2853
SIG: d2a05d88d9d543d94d57ec88ae55681750f20b9be9c1e918cdaf457767f2948dd629e94f068edcf3d9927e330234badc3a02fa5ad3d9d85e948cb0b0cb3cd70a
TST: 467
SK: 8fb086206dd95a2621f598560ccb281f8273c8fc72e23611089baac89d3c3c78
PK: 20276ef479f4d4523ab77420d424e8819c33c83779ed80c7f666e8f4403f94d7
MSG: f02903ed4266e849a4485205954fffa8a108c323b7e3f84331043514e48556ab019497233a5a127bff3cd7c97086becef538b3f339d7d06e532dc7325e597ae357f816dea42a6a22c79d22074a2e1ad8023c424b7e096e5ad8897b05ef7d00d30a04aaf2981eddff2b347f1e27e20aabbe7e7a9544978e092b00cce420aba06187374ffbb37b4c22d75f04e57590f610a27347286c298312a6c9b1bdf24fbda8513c4f8356ccf757068ffc11bc65113783a5dde7722faf4ceb19fbb62f40702e2c6e6a8bb49ef40446450c4c59a2990944da4744f6ee770b930c246669813ce5a9f5a47dd80388981bfcc3a56b5be2c4c7e659a2e9182dec0aaafe9031aa3954d4fe7c431196a561a5b78eaba64f3db1b586c53b16f679a84921a642c260e4653a61de108ebde6f7053afa2cb3f3668ede121020dd1bace8418aebac3a5bd5142f105ac26fe49e5fb140c19b22d54a6291dfc954670247881646874defad814995519f6260e9774a8d185c37881b4f2543c4b63fbf1985016ab41c4d728cbc90b3ab876267bed41d0c0902f6b50e8fa906fc4788f7b820467306e0fe9e036a0a00f804f91c3ca718b95ff6d9e2204bc3161bf70fcc17b2964b56bc612e29402d96f50986514bc7d831d58e42793786d5806f
SIG: a9305e001600d597d05ef671699bf09f0dcc0c44475d3ca31e7ff1bffedc0c67daa1f3b76a035948c59cd87f82453a40950a1c9703c2e7d9280e7303966da301
TST: 468
SK: afa1b846c210b52300e97696f81b8ea774d1df12e612527c55747f29c1937396
PK: b609566bbd1947bd7afaceb14389e836227169215fab66851aa5d70d6e2e3b89
MSG: 4cac1b1f4bd48284dcc9afc8b5955b64b436db704b0335d9755cc1f97477f8d323cb6410ef146ab8a9efb9526d8b62e3bbad1f7295f47ba9f0de958f8ec9b77ab42232437ed974856444cd22e20be35e91813bff4b016f810d0f61d89f6b614db33f34bd09985b593fe3e06e065b7bc6cd39d55c2cfbec7b6d59c0b37dd1d0d35135ab1d1b04f2f30c2f04f4ba2b36582738081cf59190f528363db944ed612931d1d514c6214f9ab92abb1833926183ac52fba2a4551e20e4c0ac959a49ddb167a381e0241d40c086e90e52aca017258975dbab2ba451ee539a718f076a58709c6697418d9c6f13e4d391368bf0e8bd8f2932dd95ceaf7aaca1241147d341a3acd08dc32905483572b89a80cc47231468ab8de359dd525a6257cf196c2ecb82fa8a78aa3a851c7c96ca25bf7ca3dcf3ca21453d0dfd3323d5a422dec84316102f684c359f226bb53779c0b9950939281ef79a58c011993eace085497afa4daf64c9687b0a11aa116cfa7b03936241a5567b646e7e42e9fb592405b8fa3c0a821fc3121b45b1753cec9a83947d211a45499bd63790b87f01472fe566d87696efedbb74ed00048c384ba7f027b3aa4298dc4110349fedf52a96cd05d08bd635771ed4510738d8f07a6021244d1903579a3ea739
SIG: 98b0c6313cecaf7c82cbdeb3d0280641c61a060f65e563aa93ce18300a9b58272dc8680b485e8cd11cf80fdca868fab365378384a142727f2f844f87cfdf1905
TST: 469
SK: c85913a6877877131001623ccda9cdc12b9d4043b8a83793c44696632cd6421c
PK: 9cc67c6948f7bf6e556d0849d3b8d203457a7b61549b36681d754f1dc0841e96
MSG: 91b5009e83d0f6103399c2d3feec0084973a305bf4176ec782537560472db187a11b4dcb4b2ffb7f0644feb394b28e5bfe97247c4a4a231cf6e916bf99344ccda88a7f5d831d6de3d563dd102eaeb108c5bdce44e0632d17e6fa55b18067df2fa8d200a9869f6aff920c51d46a1ced2d903b1d9b6b075facbf91cd05eb41ad811a8ef40d9118261012c72b8979f15153dbb8561293da9f8b77c8ff14f75387536f0036d1713a72ce8c35b1062f2c6732aebf32936799b51c2cbcd6572413e7dfaab8641a02c150237381cf7a14e22c74c6c20009de7d3b7e69cd1b4584ac2c01babaf973c56b3814bb0089720e41968106cf26509d4aa546fcad5534af303ffca42b16ae6c93ee06bc3cace12e4ec718844bd30d2224cc486d106d1c456bfa165ea0120fab3df2c5ab3a523bbfa789deed44032ab0be86eb7cc09cdb7c07aa948dd5277c3df1d9d1843567dec84f9288e085b05ae4b8af2cea5d9a184d50bef85550c836613d5d3af5f9c2928e6a89660fa62719ebff773e46b77e34bc0470da4d2cdbc7071da758c4d39fe65201c88aaa8e6603d0bbe7c3e9b2d9e41b634682092f147341ad6d667f20c64e81a68d629467a54dd86e1ce12c560a6f9b64512d6f3886cbb9f37c37eb3985c8ac38dd6682f48fe1
SIG: 01fccfdb1fb6888b0310a913170f7e366816daebe7650d72513d9506e66f7d62208a49ece0af1871497f4541ef605bde711c9e0a1205ef48f26c03dc1ad4af03
TST: 470
SK: fa1e11dc8364208d8e1cb66a361be7e84c5e368166587d4fdb06aced7f62e17c
PK: 4d8e6f4b3415df6cedabfb295c1984fd419923c6ac41764e32d22daf372c50fc
MSG: 294e63bacccb801bbf04c1f19d0aee16f5650a6e8eea6fe41110663ec01532bd4960a527f15eca4af2f4e6b7b0fc340cf97aa234e92cf7d69d50e4009c2496e3ed4d9aff000f9e185275b817d26a0bab69b7f7ee1ea30daec8bcee387ae46b4b299c27bdc06eea63f24dbee955a6c0969037eef91c34321e3c5c972fde993183b7d23f6e019c3e0cac7589ae4a1521af87ea42df8c22c2270ec23d6d140f9cf6d4d52fac1b9d6c8939ef8131cb62a035c5261538bcdfd6db419a55ef9fe5d7a5ac44579de700858d74a3434844f28342c565892722e27f407d7f17b74a5934be915b20c2400643235f8ab5795f324e33c50644a04033542cb3816d770fa899e7311c14301c1bd0f5aa60a2eb3165680c720e1efa8096fc25d2779275f1842b2db53b4da0ad3e59c07540c28460cec1fdd3cdb7a3478b91a9caf9ac891cdf3aeaeeca9a9656ac1307259922fca74c5cc69f7e25c6bf587973a4b7d3e3ac0635b0db22a0093a79076881c71736ee1d4d45f8ed2d29a0671a64e6ca2f7a5ef404b1edeb842034f571b699bc59e5a37df02054e8482bf1e7b77d8e8397da15d89d7355a5dce86b1683a9ac4e406c08a94a6eb00e5ae16d96722972e5c50c7bee4a84d0697bbe67ceb7ef295f06aaea5abba44466be0f67
SIG: e857db087e28d6750bf54e53797251d8439989576c12da2d9c811a14877c3bd46c4efab861a10eebe7da04c0b0b445c7a390a50c13de36f3a3c7ae0157022c0e
TST: 471
SK: 24a914ceb499e375e5c66777c1ed2043be56549d5e502a844710364042ba9acb
PK: 20d21ee764b1f35f94568200d63bd5828aca8c5d3e9047d23f478b925295fa2e
MSG: 3ff9f66fa2646ec66a1bf933c2b4cc0fbf912b4d6db50534257f97d01e698d05485747de2544e9f5a4a4a075388cf4400ab89b0353ce86198202db3a903767b879a2af9daa155843111af15a2bc35efe41bcc92c8207e00113b04f1303007949ffb6ce8df4b0b34248fedf5d9cb2cee94b812ed58ece2a0ce0454cf14c20e49e09fe664d6e25762e87895932cd5cd32eb6a3abb38ee163078c133e93588791dbf6af499a31ea4453bbcc7a85e406c9848a664052f11113fbb4ffa760dee4c261e396942491119da29a33582f821d4125e0b4162f28beb066031a652d05749aa7244dd4f3d3bb15d268328d6a02fce2501815257f8ad5af4ecbe7cb8ae9661e344f9072318791f3e859091121e08aefca8982eaaf66259d9de4f46a31e716dc033d0f95d1fa936b6c6079b137dd1158d1def113018c73f8ebb9807e0f7415404ea9c78544ace7ce463cd1d1c57e31f4091bc091804cbcddad0e15a40ca91acbe1c6224ed13cafb4df2c84ac9f0c3c9b546007d9dd6e524c467072563d4ac0d700cc1bf30febb334313dae5761745ec0a5e9e8815025958f00fa2e58060d7e9a5f2b727f48699f929c8459930892573f784fef5692518b5ca268e2a73ebead6ebdeb7ec24eac92aa7dcb41b598bd6eff3632d069726291
SIG: 3ae0cc7bca8d73be83a9b809b13338c12706aaef75c4d1a478178f9dc565514c7529e298043ea78d21a5a09dd04f10ae87441e5686a933c92c75548427ad3a03
TST: 472
SK: 5532e09b937ffd3d5f4c1d9f1ffcded26ee74d4da075264844690bd9c8613994
PK: 5093969f377bec3e35f59efda01ab4186c5d2a36740cf022675e01096b1a3f0a
MSG: add4d7a9ce3f63d1f946e8679065545d8c7bf0a2cc3a4c00b8f142f0945ae362c4c9462a7576a4059d57861662884bd80b96d90d279a952eda952d37d4f95cf0d70da98f4fbaca39e169f9d945d41f872397bbdd5701454303d77d31e86348271da40a1b8f1e57c36fcd803e14fa17716c5631efa01d3a795dc20b2bde36ab73ff6a2d533bc15cce22328713c3c9ccd072c3e450d7f22c0c9f94919752cbfe45ee655d1b53676593cdb448704102631caaa976952eaa1f6c2e876564e420f0c646a0f88365f76415b4085f60a338b29c51633e540f0bf32d4087e7d0fb685be88c7595dc531c99b489584560ad8234b18e39a107cf5d842dabd421e77d26ea5e0f1405ce35fe792714eb4ee1a8017648ac1ae739a33d7b1e089105d1e5add27a62ce64154570340af9eb14e7fdfc2f9a2c2fcfcdac3cc4227763f4d629497479f849216e5d90ec16dfa36b72517f7b5486baee7fda4450c352cffbbae73926c843224f8ce44b38dae53f3ead21890b52a7801075291684fd5910ed86ad33e8a007f6c3f85c16b209293740184f5890874d431cd4e0ea4087c49c3471d789c813c6dc9a78699363a1d87197d3b92c0286689311823f4df22ce8035e75732cdea7f5621f67db0e2a4ca6616193221c0aa3d6de50d85282ee
SIG: d527ff0d4a219d61f418121206a54ae4985854a310482744486e4d130a7de97c319df8372c82828c936e6a8afd9c5de1828573d8261ae9365b8f237676182402
TST: 473
SK: eb36511009d37a9c46c4d1374d0bbd0d9981e78cee7d188c5aab983ec239e10c
PK: b1cc212b4521bbe7b19a7693878a558440eec36205d8439d040a46a9902fbf55
MSG: ba2466e56c1df77f22b6f0241fc7952ae9bc24756419a9446dd2b49e2cb9df594e5b6c77a95aa5fbd9dc57fec83962c7751eebb4ba218253f916a922a5139663e3203e3be482be379ca151c463d9ada21446135f356994fa5449f084478f5bb4f5ba6145c5158eb7b1c43c32ebea25e09c900f01ef91e92f88c03c76504ace9646016ffc2789559d0f3cc9d00fb61bdc6af7d3940f302e588e04f79f7b3d4b91a5d193a4f8222bfeb69bf0347d98ad81ef99d130ebc7b36b0783394eea92a38ddd5e7480d2add4e4def53eb99c449bff94e4718b09f2ea9b1f2b886594a95c33a69e0333154e440ab34b7b6c1134d8179b6f0c56251a9ad8e1b6b0f9b8a5c97081a7f8fd05d0b0affc82dbddc8b0c0ab7e833f300626d4b973b3f60feac55571e89cda0f2b441ed2faa669a70d556cb48f9b1d1cbce32ede5d166b1143e264b11ea327681cb559edd13c364bd2baf1fd54bb781807bd59c868b0e4795a779e67f0bd0d14b5a6b9e440b57a5823328b59affbd027eda7dd785079c5f02b5e32890b038730986a39a5a9834a3fed868b6f45cbdd28acb2709aff556263864f9ae1e757b3278c288dbe2932825712773e431f7c29329857fdaea798ed93920893631402e6b13bab62b4855461edb94620f2d1751865f445c466
SIG: 9f583724de552eae82f254ac6e2ed483ec1a07346266735c490920690c1e3fb2a9e9a34194ed6473733b300d4f23c9aec0da5a2022054ca43885a15a2984320e
TST: 474
SK: 7dbc81902e4eaab3077540f559995c387403cac306d486e959c5eb59e431c0a8
PK: e03066139082f613448bdbc27fe53aa3f88994c31ddce002e36bbb2963df3ec8
MSG: dff798b1557b17085a0634371ded5ddf7a5acb996ef9035475e6826336f64ad8b84b882e30badec2b4a711998752f4a1574bc1f89d4325cf2b39861044dd03691e71d07768b5933a3052cc7c81d571a9de061dc19026c2f1e701f2dcf26a88d3401bc99fb81559dca76d8a31a92044a273587d622a08d1cce61c8f948a34ded1acb318881c9b49f6f37c30a65d495b02d5429e7ab4040d8bebeb78794ff736d1511031a6d67a22cdf341b980811c9d775fb19c6478f05ed98430103ea24c0f414d4cc07d860b72dc542ff22d83845a42f8ba45ca7ff3aab0b1e7de2b1094deac08d16eee01969f91bc16fec29ccc061c54db5345ba64842dacc99ee7729468d80a3f095583d8e8012408519d582cc3ff9a2eb7aebaa22db81ffc78ee90ef4ec589dcce87118dab31a6328e409ad5059a5132c82df3cefe2e4014e476f04c3a7018e45267ec5018ecd7bff1dda9267e90666b6b1417e89ddacb5085943befc7ad2f4df5f1ee0af9431aeeb6b24a5515b93dbcf68640f7daf8c961e567d7534900205c3df2184b6ac2da961c4c1d2bc49b4ea96b8154ffd4efffdc5e55a7119cb8af429e85105dffd41fe4a2ebba48168aa05fa7df27c4298735ff868f1496beb4b2ed0b8980c75ffd939ddd1a17e44a44fe3b02795339b08c8d
SIG: 5b7f652f08f229fda1b0bd759377b3fb726c1b9c9a10ef63426d352dd0869bd54d876c3092f1cd411c3757d3c6b6ea942aa70c3aaeb4217a4c7364d18e76e50f
TST: 475
SK: 91b095c8a999e03f3ed749cd9f2faacc0076c3b477a87ab5ccd6631738767446
PK: dad174d359daecca9c6b389ba096452ab5ca91e6383c6d042a284ece16ba97b6
MSG: 9b0d8b00299852d68bbf497fe603961a485466a99a5484005db73d4e4bad814e8574efd54d648bd5c91ae8483c54b2f998b02e1abd6f401a25526843a5f2a23a97bd589d1f7e1ab14915b1e359a396d352c360ae6584325ae4bb7d624f61255c5c7bf0a67acab46c3b57b34534c0ee8431d260576606cbd84d8d1839e73da6fe4b0b8b78f0f958827c2f1d93ba7a346dcc75cb563dffde26f997598e8b5c2f1617c6fefc9be4b28b5401b0006413a251690d1203aaae4f6d8a3fb21f24009ab3bff13737a8a7e6646c02732d9ec5a4a510469e2d299e4cc1ad6480a482aa956f89ddcccc64a136fb15b876b6ecd88c7c86a4dfc60e666207c604167d163440ca9ab9cf87a5e0f7bbc5517de4dee876c037f8cc9d959c8ff5dbe944ff54cd91a771e29231f8b5f17d61de904c955fe2025dc52ed480fb3cc90f232459c607ef7e2adb52c7482becd67ad2149a4128f984038b58aa90176782393604aac74c18209a3d6a78630c01955a7cece5da8384da3baf63aa2ddf5963fae05ba3b81c6a03d86a00ef78edb4184fdc89b1d6bfeb310fd1b5fcce1e219524a3cfb2e972577f06b1dddeba00865dae4979000c008ad99f3b638cceb8e8c7a0f998d34d92143d81c0e1c096a925ceba65c43003ee18d494d003e9c61f77d65759
SIG: 64ee9efdb0c2601a835f418520641e436c7dd47c333d9fc30cfbb9e390fe764530654708b40b03581899a9ac870efd766ffbb4637152f8ff277964fe35425209
TST: 476
SK: 8c568b310ace7d1f0edecefd603a884000544c792565d481c3d3e06e2d82ca96
PK: 5fa6e267c766736841411072d1983d1900acf01d48c3ce11770b26f78da979f7
MSG: b59f5fe9bb4ecff9289594721f2647047b0da5e0e4941bbe57c5b722b476723f0ac5970b4111f893bcaa411f28fceb4f585a2a7187018a904b70ef8fe1f6569a54d00ada37b69cb5e9c9d26c16a903518148e04a1b936a32329c94ee1a8fb6b591892c3aff00bf6e44dd0a762babe89d7060c17b90390d23bf9d360a293b8308383086916e1182b1ba4336f001b8d20deae9a029f7e85397a9ae5cf3ca10c7f3875588b8ffabb063c00ca26f580f69edc527a1accf4f41397b33766bcf6d55eb8de081a48c981d05c066617b80d8f6f5e60e59dd9b930bc4d04586403bb868df75933bdd86230e447036c175a10de9bb39953dcb1966a1f11912078e358f48c5b209a636c7f783f4d36a93ad2cc2e3244519078e99de1d5158b3961e0fc5a4f260c25f45f5e8585e601db08ba058d2909a1bf4995f4813460d369503c6873685ebcd3330a130b75f2365fb2a5a34ea63d958a2a867e90552d2cec8c390084be0c108b0fd2d83cb9284db5b842cbb5d0c3f6f1e2603c9c30c0f6a9b118e1a143a15e319fd1b607152b7cc0547497954c1f729199d0b23e53865403b0ad680e9b45369a6aa38d6685abd397f07fbca40627ecaf8d8d30133a6d9d5af009192751c9c45f77c0bc011268800bf552512730e69973c5bf362ab164894bf
SIG: debdd8e5d3112fd77b394aa0e36e9426bac91df126fa9c317cea7c9d45957cdd96a45ae3ad760413ee1205afd71a29f9c3cb586cd2d7cd1e93bc1652fc34dc04
TST: 477
SK: 3d09afcee3c432fdfb6bdcead54e3da5b1b4165c50d6d310b7fad787b444d680
PK: b0d9028c4d1487d293ed585a76bc94fffbafe2c65d980c494e141e4810a35cb9
MSG: 767165caae0e578f16537e1750be7de87a789a51ff2de11838f564e2580b2391362d2868a5a4708af15d2e2db7b9be39c16adcc1200b34e6b4d4027ddffc1a2a3595e29e855ec5261b20bd55c428b01309badb59e2ca3edb967fc2f4bac0729ddf54fb6c20057bdda9e7af7cbfc092fba865fd3275b9d3bcb0c346b951d170ac9aa650a86df49855d48a1b37ce56c9f27389f5c8b15f5c2c900c4f107c064f603e4f867ef2e9c10a1b74210e6b89bb011793aa85ded43b51b749ba7f70287b6bc1b89434db8b8c8b5d73b214b41e36b528005bfbfe002e21b1006fb9d24babd72106d093e3c7093b3138aea719d69479084647498cd6c9bbb744509cd7da8dd61a627100f03c21e750acb3fcf4631d7c0f618154d2e5fa6656fb76f74c24795047bbce4579eb110643fa98e1f776ca76d7a2b7b7b8678173c773f4be7e182fd24dd76291ac67d9f26a28c5e3cb025c6813a378b383224642b4aefad0c76a6579517b8f360797dd22613ee682b179381950fb71609a5fb5494d2d57dcb00f26d1e72956f4d6672830e05c01b3779677c07ea00953c6b8f0dc204c8dbdccb381bc01b89c5c261db189ab1f54e46bc3edc4de5ad4f0eb29c0a120e437cd8f37ac67d48c7f0e730278708f02b54aee62b72952bc1c0eb437ca8bd5655437
SIG: 89739fe441ca0ced08a6eb5796e9bdda0e74fb473528fd4907edb659aab44d3343229046716368faf88e85c1644af66ff2dcaf0b17ac93ca13819f3f241dd300
TST: 478
SK: 41c1a2df9369cdc927164aa5adf7757136abe51395604266334cc5460ad5683e
PK: 40557834cce8e043580a4272a8804d4f926e88cb10d1df0c5e28b9b67e1b63da
MSG: b64b14ba77d239e6f81abe060accef85f0442b650c44015efc43a0aa2ba10bf48d3018b1953ddfffbcda5bf3bbe0b6b3e4b0d9a32c6b725bbb231e0a2704471ee8bc1d594f5c54226f5dd9dfa163cfc1452c61f93e4f8139ab4ce4476f07ec933661eae91b6d500bf508ac63e4baaf1ffc8f0007d802e005f1b4fc1c88bee4d5e9e76384f5a7043bd660cce71f3b67f01f6ab844298531aac73a39d045370088855005a09c6d04238ea478dfacad1e6b22b2be4c46b0d59b1eba1f060bf7da5d1566cf1fdb5c543a33926af63f01a0db86e1a6711c473dc795ab283c8d93facfb5701fa2f2f6bb99f9b7e3749b071d58607be44a7089bcb503ec1495b5feedb399961fd3677d7493eaa3b3e9cc5e3642f40d47de9bfee7c20b0e519c4eb4a40f4da446ed6ac7aaca053e759c97dabe0a8ec2f58e7f2f9b2072762f9f794a6a4e36060b8872bd2c18d06a85c2c141a78293773ee8cfbf154b9930cd39da31b497e737a7750c90a13f5aaa147cd0dc4311f2e34941252ef198b0c1f50827e56c9f16f595aced6d2a69346531495a6499774d360766ca9be5ed8881c0db26ed7c5e6ff3a4f9b73cd8b654640dc96bf43bd426a0f28c9b25fa704d62ff0288fcceffaaebd3ea3097bcbbd778420ebc520a417730a1b5b3b8c96cda9f4e177d
SIG: b8b2752a097196c289849d78f811d9a62fc767278f0c46628b521f62ed2759d74462a175da22403f15020445cae06da3ed61cca6203b7006362a0e198963d20e
TST: 479
SK: a00611489467122c4c164bfb6a616e6a619b9f83c4367206b85d3fbec38cd62c
PK: 57ab58babb41dc0da0bcd506059aac9f46eca91cd35a61f1ba049a9ac227f3d9
MSG: 34db02ed7512bf8c67d359e7203a2ea441e20e729766c15aa00fa249a3518fc29ef8905aa5b4670958c6a460d77b3a80efcb473859bbaff862223eee52fe58acfd3315f150f3c6c27ff48fca76552f98f6585b5e793308bf5976bad6ee327b4a7a313214b9ae04b9651b63cd8d9f5b3bec689e0fd000dd501770dd0e99b8f99eafa09c396a245a4a96e56896a29b24190b1ef11063f39b63ee3a586b07627dd3500c4e170b835dc0ec236fa5a35c44184707565c4a50662d8dbccfff7f9a7a68d021b4af64d532b7c3d2747418c2d717bb6aca6b58747ae4dd5641d826f79a8a315c38211a538a929e5b451f623f4fcbbcacdb86c8752ea13a617ab414ab653eb2e68d5420df7c6df92438168dcf9c066581dfe7b2c468194a23707de4659bd67eb634ff024741c5fc8698fd4dc41fe5dfc6299b7a08e6ffca37109c0210c8f94ea2d3ddc977ffc0b3794fe6ba4337c7aab434a68ac665484ea8243a84b79aa181ee6ab5aa37a32d879725edc018f8552181816d7d272ca8818a7b92e6ee4454d1f7828dd8afba1a790364b4ff28d84e028597353ebbef24837bc319e1ae8f2b0b6a851b489c3e170eef53e065f7032653cd6b46d8e57e4e111b789ba950c4230aba35e569e06615403407bce0369aaab4eafaef0cae109ac4cb838fb6c1
SIG: c771ba0a3d3c4a7b064bd51ad05c9ff27fd326610fbfa09183039e5edf35472dded8fc2275bbcc5df1bf129860c01a2c1311da602fbaffc8b79c249c9cc95502
TST: 480
SK: de1634f3460e02898db53298d6d3821c60853adee2d7f3e8edd8b0239a48cfaf
PK: 9dc1465b3383f37de00ea2d3c70f2c8fac815f0172029c3f579579c984a5895e
MSG: d10c3e4de7fa2989dba87537e00593d0eed4d75ee65846dab1498b4749d64f40e34b5911c5ce3b53a7e37d2d02bb0dae38ed962a4edc86c00207bee9a8e456eccae8bdf4d87a76746014201af6caffe10566f08d10daaf077160f011feaca25b9c1f6eca9fc53314a80547951754355525257d09a7fdad5bc321b72aa28d1e02d8696d4f9eb0ad3b2196f8bcfaeb1d6148287a3faefef91a7a3e0609c28ce59d0ca14d0b3050dd4f096b7bc2513988ba212128d5026daaa7188846db21c5c1d179ab9487c1a5bd346588127c20398d362d4c759cfab2a677750b9e45676a1e7e092ef02edbf278fb19a58e9bf6c9e996e24edad73f3ce31fa04b6d8533436bf80b4b2f805ed91e7fcda3bc2bab3b2bb157158af0ea8e3f0731dfad459d2e79b6d3715fe7bf1eafc5397593208857e57b7feb2f7387943a8e0913470c161aef4fe205d3637f23177ff26304a4f64eba3fe6f7f272d234a67206a388ddd0366e894eaa4bb05d73a475f1b34ca222bbce1685b1b56e034e43b3c40e81fff79682c19f32aa3f2a895c0709f9f74a4d59d3a49029ecfcb283082b067f1a0d9505750fd867321999484249efa725f52c94c7596206a911f3f505d63f0313254bd445f05be3996b58fe1819af87352e7f0a2ca320d9cc00a5fe77ad41640d50be8436
SIG: d20506eb846923a0b16ff82fb2c3923b00c1b3bcc6e2f6482fba24807521e8e0223f692e62eac993f498f67102a04fd1acf9c7e3888d857c9a080b8af6361006
TST: 481
SK: c738ef5f0935281ba625fa4014d4a4d0be7e28fed779a9cf658e21dba43cebc1
PK: 95799faf706d195e544c76cafddf09d02d1beafc42c9d6c9ead4c1845587d39e
MSG: 168d0bc5598be02f5443bfe7dfb8829985ca5d282af9cf1b1482602f243d486bd82ba039a0750909e9b3c7d4d5f8b8baf45718af0311854f4d1c7837f31d8ee68d3558e7e51e0c646a4a637596ee90057b01ed0a17daa3950b81ab47ae8b94c17d40746913c46ba1478bfca51b167628fc3ee1e22f2f19d6d8daf93df6540cedb7a859d1a2ba5911ba71766e8b7fce0c0e8663616d0180697d78ce3040d438131982f3f8112acca29ae53e539ff8c9ec4106d132f402018518308485f2aa6c9e8d1e62fed60cb249457db33c6fd1fe07445361f08194a2b5a057cb03cc754e5c7d4a7eea53a7f7d207cacca5e68cafa969a3521dbb810399a17f328ee767cf55926b2bd5f029549d3b464579c42655265398472e1c77cc8dd9aff187f7ac34dd456ace999a736ecca6d405d4922c779c600c47b84c9c1df5e5f8ed3b2811d351339113f8453cca4c4411688cb0388258ebbd1872b83610042249494ed560d4cda6a68455d957e806dd0bdd83004c4ca80774b8a0a1665866f17085014eadb3eae7382fa870deb29dd8c931b53019625740e28392f38575c0e2a9e504fc35bd95df56439a898230a2398cd2225c766ef36f12ae7e49b30a9c0aad469d5895bbf721cc0ff51d840c802d4a7eefba84fe5205a2c2f14011922dde561456f79e6161
SIG: f44371e6c3391639d457ed14648184809411e80a3201f8811670e500fcad92f300aabf7fc68e440191e881d6c3474efd6d28f09dc44312fcfcb82701ba3c290a
TST: 482
SK: 5fea38739c61ca83bf7b4ad175a2117627b971a634a305a84fa57fecb8035624
PK: ddd14b0fc06768d5104c50764bfd3b952352a34007c50d5ddd224ff51afcdf9c
MSG: 1013c60a73953549e5ed105bdea150b91e60ec39200d43721304bfc8ec439d39609613c2d878044a9da01b26d86d6d65db93d91a137e9c4808a97d4ef286a903f3f1382cc6d1294216b9fafc013c86b9ff68b55a50ea3766e61dc1ce38348e91d62ce732c152d766b9335c68d6cad77be2b4a0cd50b9a1ec632ba55648a6e7e11a14c06853c02aec4809bd147a5ddd9fbc3be9f0c8158d84ab6795d771b42b1814a17a3c7a6ca0f4a8f7b3a0db1c73ba13b16400dfecbd03d216650e4d69704a707246444d5791fa273752f59cb5ae9fd416a5186613d66afdbd1ce691a87bd7d8b67190e9ac687062a080d2ec39fe76ed8335058251872839e85eb62f18ece187caba55b5f7d5edcade01cdc543cc677e50238b89c5635ad5c8fc220f5e0be1bc667d20989753a6d616fa69f8b12940b8ca9e2c48577132d8691b053779a152cbacff3b8b1bd7af692e56c73bbae4634776cfc213c99b9ae458df1befc8c877742664b0a0bb1f6915c8dae3b3f55dd75aba6a3bcc4176b4e3ba03d0c1c04c3c6408778b2b8e5a8a3eb52ed32a7428c00a98a589d8ca9390a210f4a7ac004fa1fe4c6da694f12276e320b41b0b59f75d264a396d450b631ab353f1612709e7a2e6a50d01cb110e53040546dd3b1e11d25732813aa76be5e81fcf7a5773f6815bbd
SIG: f4e274823f2c396f3a329486aa6410c5ff19266f0770fd04fb14a7602d2b69a4a2b00928e9e1d92389f8033359ed6fb2146467aa154cba597dec6a84173f8d07
TST: 483
SK: 60f9a14cce5d43fd9aab4ee8cc8379d575949152693bf29a6790b035e42a44de
PK: bd4a70740d5acabe49f9a2152082fa2025330e6440437f1d047f313de490dca5
MSG: dd7f44f9eb728ab48de54ecde6b6184bd5ddd8707545a0129f2e905905b55d3e7fd57e28485d258148f6605e2377d5b267d2eaf4cd4b46e454962219868232b6f41f88a797f9cdd5c39ada51a641214fb9db2c2a9b5a5b16e303575318b625cca970b74348727902a1cf268bd16e107113161c8cbc99303c2b9f235541a7b31e433120feba14febe4bcb0f5b936c7edddd0ecfc72c8d38f64cdb6cfc2910bc29a521c50a51abcbc2aabf789de822cb04f5728fee153dd5501b2db59c59f50cab17c29216d66951019e145b36fd7e841bfbb0a328554b44dd7ef51468c3d5b7d3a1f7b9def58d8cf9d9bcafe92c86cf6d6119e98dba6f38ea57e322ddc9c2198d4bbc3b94ea1329db0d458e01c7081b33925a3e287f599a858c50c3a8f18cc2aa634df63e7f10e403adeab2f41db5578790c3b4f041a8b7a4f69cd6e06215df8201ae5b3e1d1d25a0a39bfc3d041a2f98213ef4141245792a76f06d4de25f6467a0e56f2f5cf69400d22117de7b46149554b70c75b9f99484a4f6f035ad3f10e3753cb14f4f398dcf6a64d10cf6c4fac07c91193cc0f54f0de58c6343e9caaa6b4f475ef91a59e083f9f211f5bc8e7e4516b45cf06bf50beb8fc4ab579d86d4a4190eeac748d06e0852c4b9ba8cfc50dd0a037a7bad7fad55af309a5f13d4c91ed3e0
SIG: 72f54bb8bdd17e9e422cd339631dd39f57355015d4cbd15acab7542efd784a321c1f6125764c0d154045b32e70dc2e03fbfe1117468ac3e73127b5fac8d42102
TST: 484
SK: a39053c5c58bf31d462b27a620b0b37b8052c6b1c4102b6145663aa15e978718
PK: 3642ac2a3280dce52ad8dfcfd3709436edc4e7e4ae1b452d9b220780b08679fa
MSG: f65540d3abeb1ee5ea987062c1b579516d3c29c39cbc6b09d60e18fe274c2befe0f5fe7dbd57c2d5835229bb754ec4341394765776d6a9178c4e6a312cd74bdbaca0e88270628cd84100f472b075f93692830122f00f9bd91ac582836c8bfa714aa48e977003556e1b696df328ef584f413f8ab614760699c4d147c3eea1da0435835c9bf7ad54606f0213eb74a1b476141506ae2cd124cd51d66e7e7e579560576305c5fbe8430be3ebebaacba3f9989dd7d199f5a455a50cdb3755037e1a70674a4fef40b4a3aaf7bd3c95b1ab41bb206211c3a1276d3e37d8a3a5c3d5d0f36ef5b4f3de26b7f20f6b2900716dcc22ab734ebaf1e8d00020e5f019551653b9c2f70a4038dfb2f12d25d6d84e79073a6548fe15e4828fe5de83ac3d8d98b7daf92710482c37f7bd2431a8114c6137657bb177882d8a3c76babf1c671a7055365fe90866167a2d1dbc870be83b3601f09d4a317ae254cac9f98dcc7aead9224cd9c9d8a200abc80a2dd108af28fd46ad7080ae741b50054b9b9a9201efb7838bc4c5c2cc3d76ba0fcc49c46e792c26292b7d0312aff955a9f8edf0c696a70a614f3553ad3869bfde48d26a4d367b6cec057e62a4e548554b48b53ecda790ba7a0ab2e3de587bdc22b02f5947634d73099f547db22ec1bbf82343f9a2ca38bce4eb59be
SIG: f7383e966cb2309deedf860100183aaefac672ca16d5419cd6422ca70e16b3976f5f165afc2786117c868234ba1109ede031f8979b50e567358bd4f8bd958202
TST: 485
SK: e0c29df4de45c47539e0896b3a59bc3de6b802fd14dbdc9f25e717ac82c328f3
PK: a69002b0f5ef354ce3b2d6b8d8ba70ab778432b22f144dc9c2eb92d99d99dd2a
MSG: 6a37cb4c749c583590c8d849bce3fa657f10009190cad9be41ede19bf2fdb3c562a6101f27bd37f223cab13ced245a1cedf852f551f857aad9727f62c967c0a921df116f48a80a6040b3c723ab5cb594c4507a3d20cd60514e22164a82b74f19dcfdd83c57bc3652375517414af5d18e0a64ccab36699768d07cf40b7063a83e43d5f607964b1bf0840a45ad50abf83dbc849f40e5b4cfb6a3347b29fec50774046a4b50041032aa4d567e8564b3eed1642040682dd8ae7d7179286cf6e1853dc87d27c3e9e60fa47cf8cb2da0181d53eec40614b07331a4fb7028086d0b1ce2e1115b73a162c527bdd7cab5335b863d108be047bdbca112cc6e776bb453c317314388bb9653efb4444bf5cf1ec8da23b711ba71796c0ae02ba1dcc838455078c3897f07e9e13b76e49274c2e207506b00a0b558883aa122b667db9d670508606a3f54320636cd19f973917fb1875f4363e220f1e12398cc6afd79094743338456813a5826ad3f1aba7cd7beab1fe183859c0cc9ef40a5eab912caf515a8d4c3b93d641b7ab3e76b16c12971ace88ff33e5a1ed9b44e45db8f3085dbf070b256b0d7512ee1069432603d73095db8749ca547963bd71a8a684ab8516b146c4187176386afdf6cb1368a3dd8fcb2cfff77056aaf7823f800b266acce72bf643c6d0c28f0ab
SIG: bb3b8c5c27591fd8b9c5ba489d6b6ee5b0fb4a7b0de51f1639afc673d0e5f75e313aa7e1d0009081dbca7435b687ccd12f64f74a386e772b9e24781b925c8c0c
TST: 486
SK: 198b5fd1c03827e0994ad5bfee9b5b7be9966c9c3a267e4d7430343767403c67
PK: 6682c6f1a866b49b2f8ee97f2e532fa91666bf38da1b4dd65543a1777794cbee
MSG: 3fdaa15c46f25143db972079d7013c7f69a136f45f3f6ba2ced8b828468eb3daa6b50b4f8d3380fec64a0343be116f6f83b6ee64cc4c1b1d08d54fd42029e4285cfc6c6dd5cd181ab533ffcd411f23a1003da94ec9340e2ec71199d678540d5182e139ffcbc505a170b8f07f4a7e694ca92f58320c0a078564ce9de99b0fa8e66b0d822e467a5aeb83567996a48b89db25cade6457794e5414d67e9d4ab7cd6cc2058bb7a513abd709f4caf24bb67ce1c03ab62dbdfe309ec7db0fa3ea7aae8236f259b922d4536115a63bc89acb2051d09e731cbb0df157d9d345bd9109973c2b594f148efc6f3377de5163b7f69869ffef853eaefeb402e23529594fbd65ca05fe4062c529d8e321abc05200cac1e839e87b1fd3fdf021d68cbb3a4142b69cc3af6f632edd65b83f5aa4cb17da5b6ba3fc03edb17c2a3cb5b04836e7660e63c8a0483e243983371dfa9839f9164ad4da0d5953655e3a9518e136da745737c79243c355fc125cbdcc76aec92216846c4574f4f7f298bcde54fd2444ad3025955c100315de5a4e27c333a00284b2f702fdd3de22ac6c240dbc14bf71e62d131b62f2db992473f2f913f60c916ecf57df5f3f021fb330834395b79472caff19fcfa0a271795c76d69b4db3f85b8d2e5c3441965484dcc39aba59b701274f7fc425246856069
SIG: f454f35b18538f877e5d614a76b5276a27fc0b433f215dc4e963b3f047694c780c515c6ef6fe2db4b009009bc2733aec4fd46e615357cc0bcc9f1f7fc21e3c02
TST: 487
SK: 4392f7d4fbd68fe154e4ba38ad5207612a0648556056c39ac116ad468f89bd2d
PK: cbeaef41acac02bf1f780ce934aabd631364b369567be1be28e3906f9db120fa
MSG: cf1709dc9a0867ee908721b136cb93a84229e83b46204777ca8194d08b7a3ca9c912eb243e5bdabfeed352349d20be801b722af0892238e72edf190e6361f57572781ad3c2590b197357641c805383baa1d4972f76c65448532c110834a0baa8f48863e166b706653708cd4057d3a4f9fcb2ceb4120001277d38c43847d822822b777c2bb4da4015a1c24d416d5062a8718491d855aaa5dbf5579c164d8e524a9f2fa3f22eb09861ffe6ad659fe36eb40431222c22d7137a6cabca8db786e39d81f661afde4e39589b4db4d3c51ca53590a14e115d0afc3a877b839a9638bece80c32c19e51b7532024845f76cfe9bfb2ac05130f6758bf7fe993aa93aa272e4e6bd0c75c14099d43e652a223e5bcd64c362d4b8f4b95e016f9350c7fa74e653525d08011558b2c6e9bf4fdf9dbd5ef9b09bbc846afc2bcbc86c4ccc315f6d1ccd489b0cf8ed0d93f2f532a426265c590ba3a59023347d819d9b281ef85310b05316d46c8a8c0365d068a8708664ea4d77ac0cd150a65a56586babd34b74365bb8fe3e6187262284d64432e4c81ea4c0e57c1d71ae980c7f4d1d871032e188bbf9d1758cdc1dff989f2d1288fef4e205e99e7cbf2cc324b8c93046f476c59d3d0a59db6fe37382dc79c5ec16056ab3934a52f7d2880d0471a377b6a8ae84d56ac22d1d54551c
SIG: 86e7ccf06e79362d40cdb7fb75a98978bbd334a1db7590367d60849bd53e2fb1a4bdae590d1f47b5490d8702e7c1a87268b8ee9db612de7bdc2e38fa6deb7e05
TST: 488
SK: 0bea98abe7d63f158390ee668aa050e84a25d2893e49fc83f079f9bba6a55a75
PK: 22192ec0d32ef9835665a61bc88bcf4e1604637921152c116af503365bf6be42
MSG: c178e38d4e83ed2be57ce1c3ab64253a8171e610008181fbfc6d752269f7f1c5a9ec62cb27f19ad99ce1f5116a363d96fdc5a42f358b6dbe7cabdfc9f60718e4012c1bb1f842c5560811ba8374a0637747ff92eac21ca65ddeaf43e9989b7de2d432520afee364ecfba4da669ad4893d0bf69f9f81e7df69657be22b92069745f216c242ccd46d02d35616e16c755e0e37f961a6f3637752534f6dfab8805ab759a032a4e7e4c81953325a2f686bb69a029ce4e03becb3605637c5a65b52e331c26c926ed4711a504d3733bb53c97b80eafe4e75ddd9f415362888c3d4d37bae0e63fa11bf755666437d72f58c91d7a2f8cb619b7620a070b26b18b4d50184c5818712110e36d3e2830f6a8576ba57f9cccb8fff4028bf8ef9cb814825bbca827d649547bf6f2bef931704ca7f6df15f780155ed46eaa7ca7d72e22434ca0483bfb2f7902dc787f617eb9bd41ed4520adfd430948c710805a73c1ba5492e96484c4baa7da24c7435c46a052bf3515d33e42dcef517caa45f36c879121078c688dd10d76656a119762b6a834136fa1f8a643224b9224c543cf0470b3f8ee017d620dbdcc84d985154e9d1ae80e5f14387b88a0f6a5c35905aa57fb3abeb0ea6eccddb004474633cc483b56b8a8e20e8f2e09e979aa09893087875c6b117b5f13847ad8fc05604c4
SIG: 7eb3139b880fdf66376a2090818840049767c837f3ad0036b141667052b33609817ca5e240ed8cdf3ccf3aee29274534594db0b4ccc5c6e5bba3280b873f2901
TST: 489
SK: c25878b0d1e0925c8f5f04a1e5799080963c413a1399c118afb1687c797f4839
PK: 13ac2cad41908c255f671f93934ae5d7be325346725c8b40dc39ea80d70ddf34
MSG: 6856cc7144b6bddcc4b58954d1a2e7101d6584b5d5e719a0aea0fbbdf221c2a2aacbacdc4020c5c8ce681ff7381acd607b0f5239692335700655be2d94c53d7b5148e92a2bc16338c2f4c1a7d1c595af622c240ce579a5e0f5b651bf562518cec8aa2ce4b4aadb1f2fda6cf6295bc37803b5377dab65c9b9a2949fdd49bf9ddc8f96d260ff951bf8e8ccf9827e6869c44bfd973358cefdb010db5e1fe5dbd9f5d2b2ca393c17d446f637059e692d7a91aadcc7689f5f9e1b3052175d9b6b208f9026787fdb66783f45372a24946b1bd1687bf0cfcc8174ebe4d32e43284fc78d7844de0fa22e2065e07528baabaf015cb34d629c3596ad040de31c5620eb266defa7533ac0401998e5673a754365047debfcf7e137a20d16cdd6a5521982f444cfc3429397c641bd7e74a770bb11fcb29483e337bae5169ee82da9a91adf3af67cd814c2825d29018ef035ea86f8de4c7563aaf66e0c75d17ca68f49f0758ec2d9c5179d01aaed7d4515e91a222b0b06fbde4f07a7d9df2de3bcae37ca2c8460c2a6b3749e9bda36d08e66bcc356b390434b4a18cfa45af557dca3d857ff3ad347cfb07e2358c2acfd5cd53b3b0ea2a41ee5c0802fd473db5f30526334da41eb4bc7518383898a0b7507ad4ca289d66c5e2eb75cf255dff312cb1e04eebeb47f2930b90d5e002eb0
SIG: 06f55198b4191914b74306f38e381316eac40b5b5adb8a312464f67175ecf612e0147b1cef46c2518750a5606bb03bc6467bb9321514f69dcbebce8f69058002
TST: 490
SK: 0b2ec62763f687593135da1961ef29a288089696d944b265a5f96893cd2d8225
PK: c1e234fa8bc96d268e7aad028b03f0a911b697715db3a21c2fc7df48ecda8875
MSG: a83434c68693d5fced91bda10213fcd50c48920b90cee9b73a9c61081a0974933f4fdb0a67e671f8351b0ed5ec0fe7b5fb0c87586fe582ffb1bfa2db5fcedd3302428234b2bb0e726dedf45b13a70cd35ab3e299d13f34503508278c4458eea5b7351b05836bdad5b05f60e445fc65737ae27d2e52df9c39e5da0286392d08fff7ecb7066820fc90fc8a44d5616561c50b52714702302bca5874de85dba045045f9f0e604eb86d6d7fbd775f72ea493b2c4ef7c3be16db2ca7e4d8bd79eb20cfb5f0f6f05336b75cc86d219f3b8f2e91ba7d52b64fdd6a6664f04f2fbab758cdf984168691c32f53e8616b49f76ab7b192b900903082cc89656a9705804cc9b9288a3e42170984f8dc454e0864b9341672686a178c060050178a36c6d906b2ce070d8faaacd9a58c794a5ea4108b4a485c65811c2dca2ee7bb10bffff75d4586b990f43763a16fbc0b48ae1fafb08a9a36fa4326845dba5ba2fbd32bbf66505c5e8657ed0107e3e16144ef31fa6aae72e774097483f5480aa45540568fd08cba0d577768004f58ae9b95be374ed7f0299fe721275e476e0b9ab72dc06ea328384e39bf3ac331c625484312cd9b06b15a2954d33e7aaba6be2261886ca811db96b1143d06dd6e0f3cba7a1ae9b94eaf67771bb2d24e2f94de9c470fcde7bfdb32f410198b5aa9698e32
SIG: ff701f34b3594de3b80045f429e5e32dd88d6051d4195f1685be783766e80119368f56b3749725b913f1223f87fb0fb24d9dfa0841d6a0e2eb1fddf775c2d205
TST: 491
SK: 8960d7bee8c6b39ca5934d7cddd16f16b3663e6e03e833c057e2181e4597cb68
PK: 43409095d4f50f5eddbd5cd4d2012298cb41a40e99492d5a2db08be5377ea183
MSG: 308d84c7a5f786e563e5c1ea57aab5e555c00997749d15aee35439efa645da2c3967703115c6c63ed7f94785c5478f38467b86e7626e8fffa4d51a2dc45e6df2a35cec99555eabc9f7a93e2e2b689459b4e0c92b351562c417b1997113754ea59e4a91510728ff3071a2bbd1f465a687f67dae955615031a8ad551fe738a260bbc446b48dca1d979051ab5840832e19d473b666217a9183980d6b27e3d3c76d93665ba2393e6ab1a42c3904d4025932d601a202a59a4c49fdb77f0e02868247de5afdfaa1b894208ac00d77c6bb54c6b2a73a47657e44c85137963b57521af20976248eb261482147cdf7a145c3643e29e0588bfdae6a082904853ce5a10d24970ebdfb7f59d5efdd6a5e7e0d287971c846acd54d84dd45468a4110bab6ef8d9a5b4b2426788900b7e1adfe0624344f98fe59ef8a1e6c405b344eb97bb204773744b6a2d8c6e65d17cea07de03b7f0fe49f1a55c33d5f15ce55df7c9561b251c6ac807a92553e1ce917012dccfd69e7dbd038c7eeecae98623f18fbb650e2218a0bc0fff43a75a116448bb7362f527ee6bc8e10761cccf9bcfc0d000f2127b4cc19211d095a0bdaa4e4be4519e6c8445eab9b3144a45cab9996135bf7f75a78d22275900f4ce1f0a9eac136364103062893dad4390422b77e5f5d1d94d7029c6097b35ca64a7a476fcc7
SIG: 7213dd4a79fd54dec0c548ef42e6cae015be77802bf515cd2582768f72f563ebb2da36af4aaeac56bbffc9932c2e24ec95daff00a5f7a0acab9c8bd3c23bb40c
TST: 492
SK: ef6b9b51fd4f8586ca62658e042fc09a83b943033526ffc326c65eb3a5fb594b
PK: 1d6eece805e0887821876b7ed6ed5b0714d646fbecda38764f94c8155e61d004
MSG: a8f3f19665de2390d5cc52b064b4851273677486d8f5563bb7c95fa94db3356161ee622221f10cbb1fa195aac7231ea716d74b46b37bc85a70dba3dfaa1675217b351199e74a971028f729b7ae2b74ae8c6b3a0679c3e3296802844ad5bba343f6f9f7c4661b4a29b44f17e89e114fb220e984cd980e94c3d2bf9873e0605c92301744a3035ef046bad2666b5c63ebecf93cc140291946c0fa170340ce395092deed79841352fbfee03a927eb458f2a633ed3271652f5b0f9960cdf9015d56fdabd89ee71e259af6eb514b4c1bd4a666f5b5a35c90f35b149457af2944dd0aa8d9b542283a7e5412b775e421d2126f89bebc3ca37f73071621f1321eee52e9690486a33cd7ff9c9967fb65ee4e907b6b852211473d21e9d91a93362ac761760e8c7bbea486c3d605f9e11b86136819a7ab3f32f13ffca16817fed197ff880b4d6d9a808f7f878763a045728df72faaa963e4cb1c09cc2b2da920280c8366b7d18bf8972df16cc23448fbe6b2e6e16cbbf0745129854053189637ce115d2398433c15d6f116a205334824af282fa758494c47868ea8f4dfadc705e861aad2eb8ef3dbbed2a4569e15834a760cce0cbbc84b289e779b988346b9069c744c97ab2bf42b086d2fb0a411f5ce99f0819a3086b4fe9d96c7c9908dce28df1ddd30f3501ddaf78110734f9dcdfec3
SIG: 71d171071cd0fea1c6a9cfad1f7fd835e85ff906778bc6345a4dec4313ecc2bff755a717ebd912a5e02840ac073842f9bfcaa58913e260e3c73393d36685c70e
TST: 493
SK: bad47cd4bd89849067cce1e63c3d91e9b787aea8584edb07f3451ef67e7bd79b
PK: ab0ce9ba1d29bdfb85a0e66b76b5e2e05ff732569e4375ccd75098e9e71d17bf
MSG: b5a61e19e4863e0bb5f3fab6c4970d878596895521fa1e7f678cafa2de53322fd458a98aa6e35805429f651291b95bd9950e155f3ada0b609159a4abda5990c04bc2e764422fb49ef42f12529ff6f6a82029ff0185662e658f83c546eed09f06b5a68e857cdad0eb9ec4eecbfd88f34bc80990f8644a9bfdde1d9f3a90d557a8b828d5ce06a64e3b238582bb4cbeba30edc49e8122c55e95badcf502cc567869c09e9f46c6ff3f6878986b1de00b72a1858046fcd3a6e9cdaf5b073c56f2025063a2d178bd4c1e8cbc1e6e671aa97fb2cb4cc8a62c20be41c776372c8e7be63b482e6c63fa85d7cffbc1b2820bae1fc128343a1e20fcf1bc3502eee81358cc9a74c72af63530f96a25a604648ff570df1eb89d1fddbab28679ba2e9b41977e9a9c1caecdbfc361a1dd055ec51620a9bbdbbaf718c9cc136d2007710399536d13332485ec38879785e0c9ce9915a80251373990a59bce440326031ab1b458bfa5b8a4793da4ee11ab7af20de2a118c9ae521a417b68207fc885e109d8463e9f022787cc730db0b1faaed257bed901710885b74e994f54f6f2aeb64f0f60b59efbf2e3bb6515424603a113c0b8a31ba3c1e9a9b8118c87ec6949b75f49627ea7b1328889391104d4f4a3892cf00f26a73cda2a40f9b7157afc40667f4a04f647dbf93906b84c9a35164e1bc902
SIG: e5724a1dd463a97d1222c518c4925d322202d10f04cd078e771e0fb3951dbc1493a234460754c3aae3df93008dbbfb310c99592bede735a4aeab0323a1210d0e
TST: 494
SK: caba8e0533113a4be173408ba83c0db74260802f9186c391402655acde6015cb
PK: 2d7bef6164c279fa1028a9788e3e8ee8ac15edcf92a5855062952310b4684547
MSG: 2413a32bca5ce6e230e565eb858493d5d04e6d2e2a7ab1f89a3b423311676bfa93c67daafd1cfc7109e040bac52cbfe07c28280bb6acf6e3a31073dab2965378dd77f61fe9247135c1a631b79ad668c9ea1cd4112d8d3a064cc21df32aeac7dd718b091fb6915b8bc063bb5815c376e01476312a2e5433417a7a9315d65999b02ff464a474a597e53988773670eca46a6e26cf96e9488e9e6344bc783ddfb535e76bb3b9a603ff4c59c7dbe2d8b6198d5b24490b4ea96c95959ffbf3d8218e760daf20e01e2f36c84bb097115abddee92bed82d16b15a9e192e9893ac638461df507207b0cf595884d8a99fb9c7045f9bff7b73f00ca3fd595a5cec292adb458bd9463be1204d01678d2f4389b8720115fa597c402b4ff694b71ce4f3d330d5e2f3c3ad6d96a9b3439230fc53a44794cda595557c406ca1589bc7be81e2d79636033253fa7bdd600c67fc55936bd96ce0428c3eb97bad1de0a5fbb9b675157de5f18bc62a7c22c9483e2802e679b5b8f89db0fc37f7c7150ad5ac8722ceb999b2435e6997217092336ef1c8a2292dab9a46ff8a9e10d3355765cac9d6598770f4f01ea639125fd031609dd1a507d96280c7d01a3ee987e9b210ec8744cd48c74f8afee961e8ef221f826a1fe6e7df0cb15ad7c7ef4a91f9d0f4c2e1bdea635d275fac8c4bc0601f490dbdbc734
SIG: ec35ec32c8a4008827e178492b3b8bee22a4954fc6b25f4f225dd7ed23698900de8156756a8edc35c51d10f82b830a2a659676eac911f960244766e0c3c60705
TST: 495
SK: 9bf3fbc7308b46f6036bade0c3ca199fac662b07f103bf75181d52ba6a58be05
PK: 2f6ac6fc33bc060c1dc3cb9d1a2b9115845addb16c4b84be37ed33adb3b3d3a8
MSG: d65e36a6a38195ecb91de3c848b51f639245fa2baba8a6f85947159dec0ed3fae80c5a0f8c66ff24793c89c0c687543bc633547a1f37f730d97012ebbdc7ac339c4890c0856bbfe2ba29b25a7aa6b089c033fecb76db62dd3c00f6421b9e76dd0ea366eb2d4a052ee6cc736e3819191d5ad7a66d2be042cc6539e5f35652b155a727f3888d93f93a9102598f7538a9ab7c777eec79426a6075d6f38d64c485520f6413ff4d358a8a9cbdab01adf4db02adaea26494d1f5d617637f277f8b0e6e7e61e2eeccdd337de2baf0ca264c14c8cb8368000b9c714385f413737d6816e212cae2aecfffc32fd16d46c3ecee6ab074c0d768bdfe99b86cbbc8df9c47cd586d465871268d4a9d1c877236ab78f8859c114e251cabc4be0f8bc25d148c5f543e290745d11803e49f5b53193fe39969c039b3f249b32f2b8598b6acf4ed64d5752bb772ff4ee00ce0f85ecbb4cfc4ce07daf2809868c2903b781e12a274105f06181029e47f2bfb21f49480aa1e444715c0b9ff07ead88975d93585d2ff424832a9783d94906a60f877ae1c85ff15317badca1e61317433c7ce96279b678ec9d174dd0870080b234154f626a53462cfd547842eab8705605b8ee885729ee78d1833aa43f55ac22731989fdeda7dc5fa9c01985f2661e6c7326d346e6db27e6f921fae7c93a2170e10dd0c460bdc
SIG: 0c3136e01f9bcd99e10d3d124b0cdb0772bec18a864be81bd1daa44d818c3d470dfaa8ab6e9a761cf03f93ef9cc78291096ed6d10c08fa2fba3bac04dde20f0c
TST: 496
SK: 64e89304a335e903cb36c0bdf1a6412ef368468006b73d3d2d61cb030cc5f8d1
PK: a180ef3a661c3c479d5f69807c902748e35e7f725121e37a5d91b8bec88d83a6
MSG: 2f51074d981bdafafb02a40fe826c45f3171c1b3184d8c260b82b8411fc625cb02ccfe755dc29dc7895bf759e61b2450da1a656a38d4f70d2ee748c518c6420306e5f01ec7a0ffe0e9dceb93f6c077b12662881584f98ce6ab945f87fc6d123c45d6cdfd8237a1ce3635b623a79d020df44c74b89ac14a321fbf33a8c0a2559fea1c2b156076b813908f842ebe4c2b949089e52b1ae40dc6e4b2abbc439a0bf72369679aab6f4c00018be147f7c0a67b9679ee88a53819c49f7b675e30a8b5af39661ee8db21010411294968f88e5d604d0d88d76a7e4864fad3a56f5f624ba1b34ea9cb720850aad3bd4f0a882a7d25fbec2bb7ca86da616da96c1562c6d6a1abcc641e1b58b2c178e1c3bc8a3b36ec9e144dd2e75b0bc8c08ccb0d6e3427b0322b3d6ab93f3f60b9cc5b61dad02385a14949f9b87a8e3af1e0e0fab7a9a928c753fc6110444af7ccaf8027ed641b9ed87fa5d8e1f76cae465d57a70dad9ebfdd3ce7576ac4de89d98f42e282ad87ad6a5042577cbbbc4d951e2a8676fedc8cb1b1bdf76c3a38846385a85aa24706c20a8b38465fe2ae0e41f78e614b8e9642fe2471a9015747db976e0c7848c23ff3f417cb05a8d5ef40130adf855c998a62104d7e2fb7c0f9aa2a496075623ced2c0f7eec10147ff9608a8a042ef98117459b93837fd1b8d5ef03978eada74cac
SIG: 92eb4454814001ecfc18025d6421f64645a5bcbb5cb8fd85c14d772617c503e8be7d3bcf117f5e6801d1c3b96f9090a66ddc67f8cf8ff0f1c125b16b15e2ce07
TST: 497
SK: 6f634387ca2c0cb167a740d6afd89e2a28f5307184e81cba3c037046a5ede23c
PK: 011f2a9a111c38f3490cad1685be78eceedc6fac4a3221301c69c84b1ec7b3a7
MSG: 865c20a94ac3f2e3bd5cb85bec9d33726671fe01f9c537017d59c8d5106e43360bf76fc06186705980c8a87ba3633a4a170426ecc0defb6db2670f5f592533774cda50052ae597d48deacc2637063bfd519f2e79bac81775beccb1ab2f5b39712e2e829469b75a2d2dbd08aa6d24723404b25eb948a4834c55246c8079a82ec64354e8c2388f8c5a616b3cdc371e6263fabc9f6099219e861585fe82a67d610dd1eb5c81c96b5cb354a689fd8aac8db76c433f0cb0b31cf1d855b6a30a3d2a212e9b4f7d7afe619951f98d2f1ba2c101085ba81f49b36037cd6457a7eaa8f4f3bedf68d09fc9fa25a9d754db65360285412d1a6da53788905fcf4efa8a80cd86ca48b845633d8c31c2ae06f16c4c6bbbe9cd1afb59e101be50e03535dd8a65e45bba46d45cb14badfc8e93ab5267f4e492ab1f9a95e61fcab81cbf2bd867a3ec7b4baa189a0f08567075596129dcf9ff1c502d3279e8aa6ce56eaf134582a9e430a5aa8ca10c3da8bc793d0256ad19aea7149f0ea7ea95facfac1c5cfd29d7a3fe1a417975739e14da8edc819900472ca8c69716328e8a299f974edff741aabc1c074a761b3ec8761dda2e7eed7af33ef00409849d415497c5ed5dfaa2259a31d076398170b2d9d210208b4a4c7db8c626d1c533562a1f95489f9819e4985fc4e1d1a707be5e82b005481d86377f424e
SIG: fd17c618cdbb5d459ea2aca886f0512c623251284aae3a83eb5d7f60da1d9b2ba083c455a5e2583a3cba736e7b961ba19c1cc8dd90745da82a15dfc662e8e10d
TST: 498
SK: 4b2e1ae60fa5d383baba54edc168b9b05e0d05ee9c181321dbfddd1983959154
PK: 36c020b18552345619ef8837eb8d5494840e85f46809343b4d6f406125da557d
MSG: fab98b2bbf86aeb05086812a4b0049a1042abb76df9cd2908755706303efedb1ad21e8bc8d7562349e1e98ce0d752f4b3d99e677368bd08c78fe7425ec3b560e383bd42af6499886c35add80a5828b61d6644d7dc443ba2c06f9bad2eccb983d24458f6ada1b10bb5b77172c5cdd56d273d1e41010b25cf48a7d58d7255702ac12f2a6fe2918466395f460d15236d035ae9410ca86c4605128299faaf09015f1adee7768ee1a8f8ca06d10dd7f95c46fa10253065f9d6f90295908809fd779571be29e0ae66e0bcbdeb7913d2bbb76ac302f3452c55ef199a48eceb0e3596c7b4c0386dae7101ea244a33c4cdc830672df83655b35338052307b94d223cab1af69e07f78e58cbb0cb3c5351e3a6b0c4a927f7562c598d2d3df90569f61db1a3cb0140b56ea02cf7745fbeec2028673d67f1ec5f7daf9715f754a9d8ed46a7a63ef722ee0d5899331b63c974fa880429435767f96254ef46c9968f3fedaafeaf3e8f45634b54f5e0a5fc2d2373ab9e98d9acfe3697e642a18e0dfd9fbc2f094866d401f0a4ca2a456edf6a1a77b9c296c3922067eb3d5a5ca0a77f430e4c8611d8f05a1baac1635ef7ba83dfc69d301949856be4d2c8ab61de29cf39250c5794cbf5750cda95d0468afa2b7f23dba4ef5f5295a3bf4140018b7ed061884444f5bb1b7d239312dd739999536c684456ea06b
SIG: 2220119e83d69a6a3eed95fa166d1d1128a3f232ca1b78bc94b4d476c4779443614b8772aa2232cb0720a055eb71d8407f3ab19baa1d962c052c84c0bd589608
TST: 499
SK: b216cebf878024c20dfc86ce4b37bdc47aa28f29203b5b44925065d993a259fe
PK: c36edbb6254a913f08fe259e238780638f72ec0b3007264bcc60a9e81ee9298f
MSG: 9c8717cc86fe02480bfd9e922bd76bffee2170c4cb1b13df834ac01d45006086297f1b8a26f2ba674d33e1d162f19367feba97352b7df2e75b309d4b6f8b07cc0eb6777e81e268e02d07f2a08f8f39d5a8320bfc01fc8c9227d2cf05e12891ff4de885a1c93371a0910ba53392aff9ba2eed9a2055977ec4157bd65b34df79372f4d50edbc48924353cfa1692319d88a7a5bb726254c209291e9b1d2c1a6c8236398109c59ed42a0ac9e7633c520734eccfea4fea95a47a8f0a068b4275000439cc97c57871e105cc0790e9dcc9c25d5af7063ffd05c4f3780e7bca4c456d0170da709fc6cb3faa72bdcf562908ae9340aef4d0c8b91f0fbccbcf1cd898b1c716f4f1474c3aa316242abdf6368e57a247ff2fd5ce23d187f694f11e38dfbfbc3d9db20903b4ebb449b9049ee020f6e2f508e8b2b165bad7464dbdd178cbd423233765d371e7ae1c3e878cdb5b824b20cb309867c0e473c067e6744008527b6bc076d077f4867622aeed1c253dbde7c6a76c7015962fb73391698600bb318ffa7b0136ee4ccb07daaf01f40ff9c194f98681f9faef8b6f9e99f95df0080da8966a8ba7a9474c537b92df9799e2fd16f788dad7a7bcc745226e1e6371f52ebcdbd144044ddfe632dfc0a43d3a450923170ebc7ae219e50e078a511bc12ef14cd14b5309f38abd65db2b2a7af2243b229c9fd2e
SIG: b7389ee78dd9763f9d2892912edcbe3e8a236b8bdc25f44b9cfdc8c47cd58168ab56eb0402a5bd752ac8f4978d2ea2b65d2fa85265966b9f57227ef4a59ae009
TST: 500
SK: afcecea92439e44a43ed61b673043dcbc4e360f2f30cd07896cda20cb988d4e3
PK: d231f69235a2e3a1dd5f6c2a9aaf20c03454b9a29f4e3a29ab94689d0d723e50
MSG: 0b05f89ebb3397947687afbef0ede87cf3810676277037521d952a3bbbbdc8565988a095d8d4f6f59be572d3d821dd789977ef77a2fd7110ceeed9f3756ed8e188267b97a30ef8957c78aea3a2963deca61860545e0c40824881ebb1db10f607e10ddbddce400ea236ba4745aa99a05641976766789ed0da7db55fdab459ebd4b441a6282f7cfd5a20ea06effa335955e5fd29181671bc92c00052f7f75c39277c9a43b787ac9fb1516e996232a509774d1dc21d8c0513f7844b0a5b5f18957581f99044a14223ccda8a284de12fd424265fe57b270215f8fa9ff2bea517934e4800a47d346fb6c361cfbabeffabd9c4164f45156e245c977edb473642c3940be5ad6fd1a7119a7b18e98d6dc843e0d254c93d0146d18e5c62ede1490f89a605eb454f974778cfae20932e95477bd03bcdb97d5bcb76335942e92ee668f231e69c570ac5446d0f774066737fdf49f10ceb1b52d6d8a4639846a3373a7c6f3b4b3159fe2e7af7eee2f0df172d94d255d017651da3009005e5eac3176c09389ee40d70383bd37117eca083598a1801f592d057186e568e247c252be4b14f723ab7ddb97ae9768c2682fd63acc300779fe04e2b88874751346c9e0f97a2a216772ff9625c33bd7e29fed8003a08dbd33b5d17899c943c25e95ad754fb632e047c112af7f7ceba72362e1a3ddd2935aaf7f818a27c
SIG: a65545cf3df456b28d83a6d94c036a19d0d29fb065edc27e5e93a1f40279897e1c6f25959a725ababc87cf2ae727f3467b79570e902711917191d9cb0d2d660c
TST: 501
SK: b834c6e0facbff580dd3b23753959a4c2154c219521b3d27035d071f6599bd02
PK: d1c384715e3b3d02c13e090605534c7db740da2aa560f53200a3ced8beae8cf8
MSG: 6cf147b1605528a36be75716a14b420bcf067c03f1cfe9c4402f14987fbfc9d3ecc3ccf4f8d2d03a55900b8dc79af3b6e77436f69b1417ad4b68fd44e5e333ed90ea7943fbd1122609ec8ff6bb25e42e9914f5920fc72c4d013b6a9685c996fbd8352aafb184c22d9e47871a5280e4ab7dd6a5cfd10a5994a200f670e0b622a9394d4793d0a420e7d8806cb127c7ac690d45a2e94166cea672bcd982b0e9baad56312d2570ddde7e0b9e7f47136f0481d00f66a2aaca4d1b09d7ce6c5a98a76b68cd97d5793968d667073f8217f9054735340f9b149c0dce845b099e88d0709680f0f77603ff0a2331c558fc36d5f24da9a62d69af5190d21b5c857a1e08f014c6d456468665a7f845c66f9111f9c098c68940efcd87b657070cb9164bc9743aceb7439a0d01c0062a11af2e11349397f5d152872b13c5ab32f51cc58f1475ec82ac671561dcbd343cfb3c5f78d0fc73053c6004b0a4ca3f2043ff4b0c54275c4fcb9cadc6baabe57b1d5acd531e972ef9335136cd1d65512ba1f5b6ccc4b66b4250aafa2967dd4211a2742e0f177d8f4063899f61815cbe6d8fbfcdf74812bd40cc10084e46a99ac128058eaf16a49a24b6ae228ecf0109c52dfc06e37d6a333bcb24aba312164c6c0290485d251280538ce9541c0916640e36d6929dcd9588eb99577f5f6d82bcbb198826267e49f5daff2c0d
SIG: 0f19b7066d5792328a9800d9d4f8f67d5b089b541226a167dacd439fa485b0025a5dc7f2c7e23fc4a5c6869e7619d356399700c93650e89cd25b90fb9925e304
TST: 502
SK: 2269a5d8f7ac2cd9048f5f49e349e5c435a159b319fe3b30bfac8d0d505943f4
PK: 1c817943dc39c24b01da38a487b175482460c609e4726349a9aa7aea9bc0fb34
MSG: 7153d4d9e641aa61920db0ff4bd537a6d6130a396554cc94537698f9cad16b99eebefa5f2776f2feaff6bd9a6904120c67e0883f6b96bbbb195e95aec753b699bab3d03944c13c72fc84e3f2cbf6296f645549111c93fae1a759bfcd16fc09e60bb9785535ad27da244ef2f857f2de99a6e92188890e452c7f5b9e3a4b968e11743b6fc7faf1275e5360a5468941797894d770fa7da364a337302239fe83ae0b0d084aa12acdc63462524e0eb10fefe81ba96f71f275f3449a3f8db21d58749a38853d39b0ad8e69891bd204dfca8f6c239dc9a0ac27f54db4238d4706df11d607369dc7f704da1d39f2e82af8c283d220c12431f56d803069b4acb77081c031ae3319fc77fca7845097fd727ad0d080895bba23e873d2def8cdc216c3eed61b08761bb9ebce0282cf502aaf6ce7e8c058637958c3ea1b72fe6e8df8d37ac055db6992587fabbdc467f52475644f918863af620492f34680f2056cbcab75e2323626c094759c0e0e99ef19759527250646ad760120ba386699d53934f956b8bbc7395bb496ceb2dd223c7b501b92d36a95f8f0a02eb5ba4dddf166b9b95b4a59e72a30c63cf21e6085751923d54b30281e52a09618e6f023ba0a21675e7f989b8991588c96c2b56a78f5d2945a7baeb6a0c1bbd5d95af3ee830f5809c794a15ab4b5f89dd2be2dfdcd8fe0520fda2b3f02a1ac0155
SIG: be0fb3308a076a61a4a92a97f6ac55327190e1341d6dd410d86b41bdaf2d3374093ef720bdb77feb7014e0f77d3b809623c7ca53e2ae4b097113e96db77a2d08
TST: 503
SK: e965b3f257356685c98b42b964a253fc495399cc94b099c2445fc81c759c68e5
PK: 689f5410c8e0f4d37bc07c85d7cce6c9b63601f9bdafecaa448a5eed64afc8c6
MSG: 6f20a9ad27e30dac76b30d4c19a5bd6dfd6d049213f4becdd963d72b8b2dad687b003808201d50f7dd6e599ef58ceb6068c545ed99b9e763f9b0ec1db5fcbd7d490a121ecec6bba1eb5edbd6de85364707c55e300c8b16bb2530f70898136689c988591d5391d9cc347d7931061a9b7696e2c9f35bc0d304a81c2cf954d9c3a88a22e1d67bbe0a85308477f62918c25db504e4762f0e3b4246007908ac701779006b77d72510edc69e17d0f6394c77e5551875a446f81233415d0a91a0460b51c413d644e850f8557281c46699e53b22a7c73b068ea38652cff3b0a7b8ba30971eab18fdbbd8739ee1ee0cd5cbfb7d5d41757b6331271fb7809751e203513c9970f66d91bc0ce062f4fcb28be0a699867b79594c6458a0d307acac91f413c4615877dc53e1b018da5cfce1b63f40be1e55274c4374cdfc21524499a683a231adef779d1921440e5d3fdbd5033dc983cfc931abe638c35d5a95869e9fe3d93eb90bd1861f855ce1f608b7bcad6b5e1bd97edc95ed5ddcbcb715d919f5ff77df2da438f7a3a98286dbd5b6e043fc7372f69704f09d865530f4f0edd3300f185b6d73d8716d32d32b1c9ac2ddf4f902d3f216d35a33f368095ded10be94bb53d6f256560fac2f4af0edf5c5c702143777126e7de32d07493932662129ba0e7fc7cfb36fd2ca531646e8cd2211854fc510af3b1e8cafde7a
SIG: 8d2bc4e1cd256aad8a151dec010dc93a5e5cca58298dec49cbc9c4717b5cfb5460d430be726b0f302cbd926beea19aa3c93aeb452a44f6007af49adf2f05bb04
TST: 504
SK: bc3b1e0bf8d69ea5b4cbbf10bb33fc955adcbe13fc20af8a10872ce9df39d6bd
PK: accd2628155919bbc7f9d86f91dafec35c711a78c79ad360eddb88fa8a180b2d
MSG: 4c73e04abe0819de1f84d70541eb1bb61c4f42920e1f2d1d9e6281a8a2e8b3eb45537d83969027f99ef0ea27ca085b13f9db480f00c02f3fd7429dd567708953bbf3b9e8e2c6ac4d321ff8f9e4a3154723085a54e9c9573cc7350c09f8973f948b08730373597a5fd0349821ae0a3cd6c84992b189128f3490987e1e9ad4f6574ca538fdfd83284c1eb0953f24c08f74932d4364dbbef922542440dae80424a92eaef27c1889bd08c44f9df03a3af30dffb48fae445e625f4d9265cf387a1da35fe4c231504535db72ea81a186805f856ebe6a6a65241432530fe6c960c5f9be6c22957060304e9dd8efbc1e482e7ddbd8af03bf2382899c986d916611e4f27ae52f817ef01b6a141fe4f685d94dc8cd52830043934587704c1e642e8fe56be6d6b85bf4a6feb2b6858f1f007f99d39ea04c9fe5fa7ef1b91f495ed0e7fa4213dd68cea42b6729f95031907e27c44098094386fabfb04ab9b4de3d6861de462312c59b27c76f7b6a4fc71ea0d5daf6b7320521a67e5cb37504976ad73dae2d649feb75e2eadd3401a7f2f36e16dfbfbdb2af5716cba1bce20cd47ce1c1d7be00697001fbbeb4915aa6e5393b5ab20e0f31f5119149a2cb4c4d452c8156113ac7824f84f09aeb81202e8dd3dac0aa89399b5a38b1e218301960a37d52632eeaefe3687455464288eb17d9e19a3a72ed9de32c17be79a3b9
SIG: 6ef7f0e91f2cc6715f8e5a98574b4400c261a643e0545ff26747f8e1739899d76640b6451c43c1d03a4775b54fcf9bce18ed3fccad338b7764024fdfa2de8201
TST: 505
SK: 10718fa6e2d7f6ed38fd66cb6dbfa087e8f1e8a8a24fab58d79d7954b8720c3e
PK: 870d4f666d06fda9f9511b58602eec050d754ea6d8e79cdd19f601c477df1aa0
MSG: 41259b6eef13d6ffe33cdde799b995c40be782cf978440b66be51c440582abd42f526696bb3cb92265b1ed0e4bba764cae2839830a252635dc80ce5f73d521b3d6ff03ac30e198ad20567e75a34fa825ebf9841508da84cd674236ca7b43de3564c94ab079408fd94137ce3f90a5dd5d3ac39a05ec86715a8f025e4539a7640ab88836f4efbabd5e1652c49ea21613acfe343a880ee5a42f2f9134ef4e3716b16d134a9c4c71c39b3c1a857d3c89439783eef1edd71bf4492d05fd18673a5242ff4187b9de47ad4968da49dba5a6092e95ea27ddfc7448dcf5972d9d228d63e5291ba6e6fbd07e3241f9366ca4976bb04b22d01f0dbae794fa9c1d9029f88a83602b0e0ec55e22c37b201125cadb5341ef73f6da1abbe2b1c475f0750345b1be4259d8c28531ffe7788667c410dac339918c869b00ab80f20bf7990d366f9b3d5e8eb2f48d7ed0e64b85dc9fe3bb998b1eecd1231e902d2d152e09da2d2592bdb32c8cd2e2c489496b2980c03dbb09ec7f8a4ea2c7020f2a0faa657cd6ced48d6da27864cf5e97eea9b3c2f0f34abf8d87bd2adeb60c7272fc4306d955bdc8023d7d3dc2f3dafe9ebe8a8d138965a7f6ce93517cd2099663f67c34552176ddb595ac6ea5609febcf24c7d69d412709e578670a21ac8afccb8bf2b18ff3af7de21dc71d50d60d37b6ed729db04beff7d34b2920d87551ce15
SIG: e1659186f1f76fe43ac8a11703360fbeff53b5e57b5974aaa08e2575579c27084cf6802e7c206347314475b603197494e7d61fe4b1ee7b78e18d94469352df0c
TST: 506
SK: c1d4724c6cb1bc6723b2b43034278b3c5b48fed7f8a3cc2318033e7552047351
PK: c27e392e7c3664b9061ea76d2575dd7c41eaf1da3a65f3a986e0a57f6c40c17e
MSG: deee99d7a77d4300c17aec1ab323c571c6e9e73a43491a3c7888b76fc03ec43d07af42a05a2aa322d00c8560acef314106b10b9bd12654357ffa26f2390050da63d668c9e2df548f87639e096a35853f82e761fd711d2a265438f5d4db5e32775708150da6cb686a2b4ca211d7f00dc0abcb2ca150e791116a10a5efcff3514dab8ed80a7092c3a015152cb25d9f86ec0d1ca67ddab44d64eeb1f931bfab2ab188956c743db4814808c5cde1b0745b3edd340eb03ffcc80a78f3db310f4f5c20009fc0279c2c1bcb3cedf990bd0e20c6f9fb7515ad6e933b07e99da6ac32b97141187ef63bdb1062e37220a4dcd419d6244cdcc34ea41d0bcbc3138b1d54aefc0190e30b187db073aa7d6cfe04bd3fd2ac00313e3ddd64a181935ca4b8b2a85d36bc27d97b7626767b93ee38def8b6b2c8da9b00263614342faa9d3e738d2713c45ffbeef8c84bcdbc8da4309c8445530f5c617dc866251f548950a14f075aa3117f96e41f899dbe7340b1d90a1352d3b8fb41b79f16a82bc2e4a193b8a7232400996b73b1fc00b2ec1c667577f82824d39fb7f6e7692dcd97b1d8ce94083ca197e9a5d40fadff0b9ac57e9de761c156e6d31d52c332d513e9f58697dcbdd80a5e42c551702c3de7beccc3db845b1a04c8cbd41695ea7428abba89e0dce3e3d9e70230ae9147c2b88559dc695d6809a51ccbc1dd9e089c585f
SIG: d37a6ec82ed45ca9b4855de9cb942564e883ff70a79b8e712d5f604ec8974de5363ac849cbab28e7aeeff28ed3f2d14b608b3146c2efe0735ad815c7d75a1a01
TST: 507
SK: 37c070d4a53b13be760635110d1bd4f01920225afabec576faaec910f2926d1a
PK: 0aa85f2ab1dff895d1fad0c119f2bf57126aab601c528d37698e97702d35f525
MSG: 10c646447f81ad94d015d86d0d98b2452dca60a47ab35264035e33a0942b954e3e23b91d8123b8593c6af7c8d3ecd290e0e5ee36fd4e53b7be633a6cf027a5ac3f0f679eb1bdd210a38ea6e48b0558e303010af474e7f6df2a4e457699fc38e36938b05ffcaa1b694e32f3d1b2cc5d00cf256f12184c873e519089ec1df15b0dc76e7bfe90780df58136fe597fce894ca563e08efa0f2d4d208bede9a874882873d251baf019fe46d1d6504b3bcd243b795351f34d2e7606aa975528ee50d59efb6ee6992a89b2426956c2ca4247e0df0129852983e9767a8eed1bc7335ffca8d0289f04807f67ca7da971f58db8b9bc9fdbe4f83cfe9a00f1ca584798bc71d851ff7cd6c51b8990aaba4d38b416b92240dfb70ee3c12b5e731057762ef90823fbf683ca06d05c20d3ae2b97a83ebe70ae17afff9d16609d546d8d3c74bc281884894f3d49e083f10ae7c11c1dca0effefcfa6e0f1535081fac3a2819fd2e3265527182ae9d391b232bb7542e68455cd267760db652d19e22fb2ed11cd1305ba8d98c1ebf2d1969b24d64f3e319af74e092006d2a3ff744872a20ebf18d17748ab7110805096ea136bce2f968b205e650b803c531d06775ae5ceea28bb92e9a0edec8951ce2009a88ee1b64d9b9e89f69051203384210a102a44d2d6703173b68507dceadd3bf6510df2a5cefd9c80e4f385b2f9e6215813ed32
SIG: 9da60cc4a64d07dee1346bd3d3010995ce2738208ab35b34c2a8fd1787ae3a1e207fe784525154fae4f5794cd8503045fea85cf77fd92f6a70cd0c5a52c0810e
TST: 508
SK: 1126496a582ce58d3d618dd8a3933547aa7a8a30fb54063b8dfdd31671c6c73d
PK: e10229c623fa8ad8982c3e4c36ff52df0f219b57915b6e980e5fe72ea0962e22
MSG: 6a4b52d730ddab829b2a179590cbd4c372498e9f439977c0a10dc13c0ae1736eaaff063371434fd0da80360ec5890607d2fae1c9a2e1ab0b7f3d667f5b1b9c418f18b10c9e6fd669d3ebec168efef44163e577a2ebd0f2cb768f80c23188e86069e4d10f410306cedd7a341a61e0f4f3bc25041bc2f922ed073e1e2f1b709c579d10630f33071754d707894a1c62190de18882c564dc4c01dc545dd8966404ed78fa3267a9469f63b6120abb65f9b3ba3eee28d79c2eb4e7020cc6987dfc5c29672f8c0fa3e690d584fe000c64f352610179621bfd5ff3eb30d18f1a0250416db93b1c1e93cf8a3646517560d1cc8fff822b51ef27b200e987b592390753453ef138bd3d29db7cb1b5f45e4795b89c53f49704192752237c6ab274849f9594ee9777f6efe70483129d067f97199d9ae36090703864f7ca4750a6f3b6ff83824c910484394d1e2eceba18446fe4e994ce07433a740ddd05f0e396d482894e6f14acf7b97bae6c7eb88703039fa785d60a3af78b13243a4f88dde1d998617f2e3fa7eafc2f435dd4ac1ea9c238407aa09b4eea8ed434927b406674ac270458cfb3bf29c347f94559613179b9502192321b88e9af0a90e9a4ab9eddaae382e3734d1415ebe32499c34e6fdeaf15b0d9787985e08dfe495460c54f6743d81ff16881e5e30c51f4b092373783f12423c3e1ae8591130a269980caa1cb5c
SIG: b30eb56ca9b120bf849a3a9d56af033de8a590c9e1240c1e36dbc6cf0a71b78a11ec143fb9959a8f25b57711d6a90a67e01be3a4da2b69394869bb8d64b87e0f
TST: 509
SK: 9c167aff3b1b788f133d422de8ca9a64316409f9e35bfe22032ec417ae9abc6d
PK: efb534f0d47c068e77b28a906d95ad8d213a4d4fc1c70542f01e596d57b5f019
MSG: 68ac0fc2b607ba38e377fae845c808c8f9fa614eb1f31158a9620a937d3e301e85acaa69144bc349a39dfb582041c4a197ae99b4d4d59b7a2ca3d16228b5591cbf57c18a781efd19193c47b16c6023a3a8ba3d668f05a37f1e83b0d7febdd10f63e48ef7a20e015b1c6725d4c300a986c60e3a115469c8e52ba05b51c05d0af40d89fd9ed76f36950aee3c7819898a903cfe0361a91c69100b495141e86ee79d63d17403fb1a1629ef63cb7e9d2720cbfff0002b190bcdc26794124dd38d42bcaa7175405eb0bbcf8e37d65d05a37195b479371fa2bbbb167d91cee88235dd72ea88fc73ce3ce43d33b715f25f192ec215dac124899c5e7586e86340d8cbe53735defbe02e4cc9fde69fb9794d1db72b98c0f19766ee5138bbfa78909aa299b4913c499deaf54b4841d5044829984936700dcf92f36542b2fc7e86441b9925f5d0b78c17a85cfcfcb20b0fd751349c27463abde4d27df74265288713f96dea013b945521808b4996b1b2dc0338b6d236efd6d2b27dafda46ec5fa32b965e8bb5e8bb61bd966edeb774681e0ea8c17b8c99fa7d660f0f66c9bc6d95cbd7dc094724098eb05191b53a3df6566b9c90e0d7dff2943848b61a20d48c22b6d3c958e293d709c8f48110230ff51918562877daf6d920c85a82e07c451fe7ae9759c0a77e97bb298b5d0592a41d08f67a4ed5a1bb41e937b6a68aeb38fd5be9
SIG: c9ae67fd6415dcbab292fab394ca6c3b7d90ca244dc6a7764e74fd202bf4b2905bd2030e6beb914c3c238db371b1cba6d9261aa392ec871a4b8b12fe9c1c970e
TST: 510
SK: e9948805eb341b2867479c668fd3532c309941c0ad4cb2e54231756e6a1bdecb
PK: 5447a8e34d6a640002d8d60bcf1ddc711e4c465c94c34b50bdef358960ff81f1
MSG: 91cffd7eb1cf6bd4756bce6a30af9dfba26ddd1cce0394c194a3e39cc3d1cbc221b7eb70bea18d29c267457176a3c9e53c18e47d10a67c464505197702e6b2470d38869db5174b158f9992e4435d02246f540258dedd3ce33df582555a681fb76ecaccb1c2989b177e3b7e454aaa529de59bf5a03123d571df2e7f7cb830805c58b74a653bac0e5a888e08dc2236d6cd496aa06d0d67cf3b335e218c49dedad82fc1be9ef20cac61905c30eb132d739b16ca8a8c906619c0e0d8b33985327e36f3d4b8fda387c186cc50443104db761f7ff9301270204a713e58902101fad000ce931647c577fdec148dca95cdc08918ebed037c60332fadf088f036083ebc92e173b7ddcc30c493f27e69cd17a20d30b78f83a72e4f5a747d86d96c5e1bb7a438166204013e2164d6aabc0d562f54015c365c80445607145e5692ee34f6353077fab7452d88ce3eb01d2b3797dc91b341a3a726301516baae18e851f74dfbdf0866bb2376867de55231e362c472c52116544cd4f81e93571c4ec820e7e653f4e21be0a942576c9de91e7d1251683d859de448f822dcf3d2cf55ede2f9c71b6063d1373061f8f5936b698d1384e65459ea2bc26ec96775ef425207432dda0ac1fe28526c5e4559349c3d8df9918230f4044683cc2c1b858d141ab8d0805bb9336067522aa89c810f3eaa7ac2d8dd28c3751225a19ecec8bcca52439946
SIG: d3dc62d6ce9c766f2abaf9a7fbe09d6bdb07a4747b56080db09beb4a4e804a70d7ddf4119475c7be834f31956f4a71dad029cdf2363dd0365ce22dc27f078003
TST: 511
SK: b01753efa73bb3de7aa778be7afcbff66a5d3e2c2f8b5aa2b048844050996965
PK: d0cc6cf109c999fbf6d16f471fafd0232b0a68d4c46406ec7545dbaba8194158
MSG: 684e612f27eead0d34844cc81ba911c28aaf6d66e71229e8cc3462f7c7a050daa30cb74471150f07dad459b5a91358476c0598255d8a642dd7c0802811bd88e4cac597efe41ebd96cd0f3b5ce72db4be1a3dbd6b84f5446e3da600d3b1d2b460a009bd31cacd98a91518ce33e9a703d404288736ccc43103fc69e67974f31652fa3dadef3337f6c897a3d201303c8f03597b4a87c98f291ccd58a3f1e898332aa5993b47fcb5ddaa1c0868b643742d0e4a4b9cd427038b3b74999bc89ac3484c0ca13f25aae8e78ae1ccee6218accab81a4f694f5324a347629d49b55e4037504a9acc8df58c6841dddcd4fc4347f7b6f1fd9de0564577e6f329ed951a0a6b9124ff63e22eb36d3a8863bc1bf69cea24c605967e7d8948953f27d5c4c75f0849f872a3e3d16d422fa5a11e1b9a74df6f38b90f277d81fce8437a14d99d2bef189d7cac83ddc61377ed348b3c4fc09ec2b9005925d04a71e26d641667bdf549294331c6ea01cd5c0bd1b6a7ecfda20b0f1929582b74697cb262c3927d6b223f4b5f3043aa6eb4571a78e9da11c2b36f64552580caa7b5fa6b90f929e0162e608d1240d7242cd2f47025c03debe059b1dc94770232bc6765148480bb1d9f50da1ee6448cf9c88b19dd459932c06ed811c4a64a12d5938bd1c757bcfaeaee8933fe5fff21763de740482bcf1ba59afdc8fcf873c3d507bb394e32e45f736519
SIG: 16b7421227ae09130685cbb1a0c60aa57a5e1afe1bbe6bacea0c281bcc8998e6824a772c3208a6b6b4d236695505c9be82700cf93a783985a39e16e377a7410e
TST: 512
SK: 4f4b20d899366f2f23ee628f229b236cf80f43ba183177c97ee34829546f1742
PK: c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357
MSG: db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb
SIG: 0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02
TST: 513
SK: d2e01d2578b625a7060aabc25765f168c680cef767aa97ca0e5eb3d667474b2a
PK: 191ac223575424aa354b255b812dd3025d70ed829e0826c01629f9df3545082b
MSG: 20d5dd699b2853302a6817094d5ea512bdf8534504cb289c602467410740ec7eb8ea6442c80f145935068f9122fdf4a39f2010f33db55b814d97bf2e5872329f1126d4eb95b806ca1973113165b116be8716371f81331779dc79a5cb3942081ab5f207f6b53db0e0038107d63ca97708181982dcb5f3b93010ec6edfb2cfd31cab00090b3c38515f9781769686cb17ab81d54a8b775754d42fbad086b80b28d636f78b7eb77ed9ca35b6843a510f0ad0ac1b20267a000301b3c707a20f0214d59b5b8199c2f9ee25d32060ace3e0f2594650416a00716cd3f98604a5e104b33310fdae94c314013cdca5ba2414409eb7f1901394f007d6fa0a29dbe8ec3df98c393c8d72695877cc9baf491ef30ef7db3371608ca97cc621562520ee581d5d1cdbc78232d6c7e43937b2cc8549e6f1e08df5f2eac844fe0f822b2483ad0a5de33be64089490e77d69800fae2589ee58712ac15a3f19e6ffdbca42fe1894e889b94c04b04240dafb0b2730c236b8cceb2cb97afd1d515dc19d1067fd4aba8ce297fd6d110b35a21bd3c075c577d93fe1df77d648f7119492099b017af44eba09c807f11a4c3f4a11a2fff306a728ba78983323c92a2fd5fcc80c18d423426f823a73fe04094955284293f5f6b3ca4ff1080dbb1e4c6f74c1d935ed21e30094c7de336b82dd8200b0d659583c5bfd5470f9db342e70ec4000742c5640a214e3c2e
SIG: 87a010394a9f2c904effefca9fb4d5ce13793301a4925ba51db119123a4d730abf764ce065e48d90a79d907d7254c40cc358987a46949e928bbb3cd085dfab06
TST: 514
SK: 7cd7ec99dd03aede1ff1073ec2ca7010276e947e2aa9b0e65f877e4ccf1b3a14
PK: e4c39dbe9493176b8213f1422a9de7c74fb6a59190fcdbf637c7ad5ee165c04f
MSG: a6034aa3c2484923e80e90e5a8e1748350b4f2c3c8319faf1a2e3295150a68e1eeca1bc84954cc89d4731a7f6512af01464fdbce5df68ee8066ad9a2fd21c0835a76559ca1c7449a933bcb15af90223d925ff61cd83eb935698347a57072709a86b4e5a7a626e07a3f2e7e341c7783a540f84aa73e917e867bb80bace6254705a9d1a1185de56e1a4e78aaf539e749b8f765bd052c4cd15b638bf8ecf87d9814606fed5a69f4dae9da47f3806dd90be64fccd3365cbe9e01c588fe65d6b603280740962aa8ddb95a3f4f674c03bc4043092c544595568270a2c2a8aa06e3f67c31998c50b9a58acad00690d3848114cb193293c8ac21016fd996f5c64214064f82167b2c920cd8a839755852ac77c3d90526dd3adb96837cf4e726f34bd02955cbac5b82c92cf4aa8b54bb6e436dae9bf893ef050c6f135a7e62fcd834dac1d2be8b8e59d696131811701c4318bb6e9b5a20bec656fd2ba192e2732f422963bed4a4fd1ec9326398dce290e0848c70ea236c04c7dbb3b67921440c98d72753f6a332eaad59fd0f57742923fb625fef070f34225ea06c2363d123666b99ac7d5e550da1e404e526b5b229cb130b84b1903e431cdb15b33770f5811d49fbd50d60a3474c0c35fc021d8681819ec794cc32a634bc46a955aa0246b4ff1124623cbafb3cb9d3b92a90fde648e414636192952a92291e5f86efddb89ca078aea7717fc7
SIG: 6f99202770964535e483a0ee01a529442eb321303fa805d475604d7fc728a9103fb7b558b955f4d03719eefaa3b7ed5b0da75710bb98787f5c2282ed66e9f60c
TST: 515
SK: e3ca3713a2fd412ad5336bc356b77be027d5b70815b3ac2aecd8340ef5f889b1
PK: 1d516cb8bef116a0c1b6929009933f6eb62c23050745fe7e8d3c631623778111
MSG: dd99baf295e013eed107ba8af81121aaf1835a3cca24f8e464b4cfcaa3c7bffe6f9536016d1c8cf375038c9327e8e21b004066f5eac0f76a3e8edfb07be8bd2f6bc79c3b456de82595e2c2105bb1b0aaba5eeee1adef752167d633b322ebf8f7cd5fbf59508fdbdbecf25e657a9c7050af26a80a085b0817c6217e39acd54cb9fa09540fc7bdc5226d6a276d492cc8a3dffc2abc6d0b9fb08cbccdd9432e449821a5dc98cfb3a418e539c890fe5a0446b9f81d306700927ade61cfdcc0624f13b5840748774604805731d92e77d5def66be44cc817946f1cd758196cf480f99e7117835c4c87cbd64077a562a80cf11d8ca65be7a94d92b9ddaea997e93f1448577ed6d8436b2f3144692c1fd7d28a03e9274bc9e8669d8575f5de20cfbdbcb04e9f39f3451d7048375e2698e722846cb4f2d19a810c53d4c1a6c3b770fb402df0530e7b2907223fd0899e00cb188ca80c1531b4e37fba176c17a2b8f5a3ddc7a9188d48ffc2b272c3da9c9b89dfe53f2fe7e3672f91d11818491ace140adcae98502e114f4b352b90e2e7fbd333b2459e7f15dd0764c9c34e4cb7cc095500cda035e8e2e4e3c8fd5df5f3aa579a735dd8a9f19ef336fa971114e46618734a4c13d30c81128ca21def47330103d23d80ffe67421a6ccf9f36a93f05603c599ee10b03451f36b2133c187a79ad9e6fdfbb12595ab73bb3e2e2e43030fd37e591cf55d
SIG: b3857ea61baa9e62838c4e3a996502d3364fe1ec594258355073dd10e497c600befb1f8f233fd6e3b2c87f10dcb7261aaf3481bfd0902605accc900fef84d407
TST: 516
SK: 29a63dcd48a351771411fddcab46bb071e91498576e8d02f8b6044f5bdd3ed90
PK: 3923fdcc2a9fe5cabf6e9932e46dbd2b7f3632500f9d95552db2b045bc41166f
MSG: ff18ca0c204c8386a4aa74ec4573c7b69216b31470daedd96a4f2302116c7955d72dacc88e3714550c09e6f7b9a8586260dc7e63da4c633bae0162e116e5c1797b78d87d47ffeea3d7819df9c852f0ff30936a105d3af5531a8f89549711c14c2d3ee11564e7c8525bd58864009762a05541d8e07ad841a55a6a9a007ef209ccec4b5640babe35651b61df42de4d910ee73a933c0b74e995757e84a99eb034f41807183c90ca4ea8d84cdba478613c8e587cb5f8fb6a055081da6e90220d5d86e34e5f91e488bd12c7a1a6b3c9fce5305e85346658effa810d0e8a2a039db4a4c94965be4011f9d5e5da266233e6c4e18ed4f8a25a57e40a591c7ed590c0f8b1a119c7c9747f691b02196cd18e6945213f1d4c8c9579c6e0a2ac45924128d6d92c8e4c66065320353d48d1d5e13194d905f837078f8dac0b68cf96ae9e70554c14b2fa29b19630e4b0f5d2a767e190efbc5992c709dcc99aa0b5aaf4c49d5513e174fd604236b05b48fcfb55c9af10596927bcfad30bacc99b2e0261f97cf297c177f1929da1f68db9f99ac62ff2de3bb40b186aa7e8c5d6123980d759927a3a07aa208beeb736795ae5b849d5dae5e3573710aaa24e96d5791e2730d0270f5b0a2705ba515d14aa7e6fa6622375377f9aba64d02569a209d33de686e089ec60118e4814ffc6c0778c6427bce2b6b844cfcd5a7ced0e35303f50a0dfe5df5dde1a2f23
SIG: 12bf629593e2caadc910ec40bfe2b7a62514126b16ba3a438d88e2d21f595aaee8abfa4af2ec870361d0ea04dfc8c6a330fb2841c2d8211a64fa1e7e7d273800
TST: 517
SK: c7188fdd80f4cd31839ec958671e6dd08b21f9d7528c9159143734f94b169883
PK: 019752ff829b6859b9058d00c2795e835655440675753f37e85eb7bc5839c4ca
MSG: 4af5dfe3feaabe7f8fcd38308e0bd385cad3811cbdc79c944ebfe3cd675cf3afbef4542f542975c2e2a6e66e26b32ac3d7e19ef74c39fa2a61c56841c2d8212e2bd7fb49cfb25cc3609a693a6f2b9d4e22e2099f80b777d3d05f33ba7db3c5ab55766ceb1a1322af726c565516ce566329b98fc5dc4cbd93cefb627688c977af9367b5c69659e43cb7ee754711d665c0032ae22934f44c71d31178ef3d9810912874b62fa5e4020e6d5d6458183732c19e2e89685e0464e91a9b1c8d5251e24e5f91813f5019a740a04b5d91cbb8309e5161bba79dcab38239a091f50e099ff819e3a7b5205fe907cdfe9c0dc3ee85e32d7bcd3ce02635e2058388031e317fbf22ab9f39f7f7e3cd1a11a9c1f45f4e1e42d2536c122c591837911847108ceafd990813c2b6344cffc34be37161dd815626900e8fcb85c21afb4f6be8ad01516a31c2a6580315857c6a216735ca991009dbc2ea5034160747a869d5cadb0b47ffbd5d3ac97fdd0526cae6eaa35cff7a16eaf4fb950ca31511346fea6141999a3f754e6281cfba15e8a826932c589c5d247c909d94b4eab7ebcb09077648af065c2d86611eb588453ed7c24780d73c689c8744afd533a86d9ee9e3365732cbd0c351e436f898b7043292097e03e6081a23ac865e19dc8858969b999d01fa65ef200c3f269c818e30b9365ecc683bcfe69c203b4e0ab6fe0bb871e8ecaaae82d3acd35d5b50
SIG: 35c170dd0c6dc2920a595775d8e2dd65243e9c1bf96ef42779001ed45f01b7dfebd6f6a7dc2d386ef4d2a56779ebe77f54e5aecfda2d54a068476b24dbd78b0c
TST: 518
SK: 38ba0621704d2155fc2f78555196575de06d80255c35e9dc965b6fe96a4d5389
PK: 4388f7f68a9effbc366e42d907015604daced1727cd1d89d74adcc789fd7e6e1
MSG: ed4c2683d644b05b39b048ef1f8b7025f280ca7e8ff72cb7eda99329fb7954b700400705275f20b858cf7e349a3510665b630609c5e2e62069263ab9c55e4123a564dca6348c8a01332075e7a5bec9c20a03807957fefa910e60c35ae579778ce2ce42e6a69a1b647681e43ec4b63bd5fbefabb31712cb3d6419ead78dd41c8a92aaceb63cbfa89d2af39606de010a397e302053a615c16e5e95ad9935c079a0b8103125789471a1e3574f429b29e4d225c7723fbb3cf88cbd73823d9f0b6c7d05d00bdeb0fb0ad3d7132033183e21f6c1e8d8e4c0a3e4f52f5001da687171345c6dc8b42c42a60d1f1ffa8fe3e7bcece59a035878f9d4d81127e22496a49bfcf6bf8b46a80bd562e65255071f9d11a9eb0481f4626d4d71ffc38afe6e358a4b289179cbce9764d86b57ac0a0c827e8ff078813306a1d5fadd32b46a1fbcd789ff8754063eecfe45313beb6601c3a3010e8eb97c8effbd140f1e688311092d273c4defca47da6f1f0825744676f9a280b6c2a814fa47fabc1980d0b37f087a53ca8778f39ffb474ff5f1171b442c76dd008d92182f644a714a0f011e215a78b97af37b33520ebf43372a5ab0cf70dcc1dc2f99d9e4436658f8e07cdf0b9ea4dd6224c209e7521b981ee351c3c2df3a50040527fcd72804176046405db7f6734e85c5d390f520b0c08dcbfa98b8742480d5e46f9be893f6d6614340f8161611d5053df41ce4
SIG: 42bed6a98786f664715f39bb643c405ae1750056460e700469c810389504c51cffd9e1a94c38f692fb316265316d8f4dc3ad1cdd8a6d5991ef010cd1489d7c09
TST: 519
SK: ae331fc2a14759b73f1cd965e48514e12b29f63b06ccfc0ad49f36820e57ec72
PK: 08803d48238eda3f9cebb628530121de00f0f0468c202d88528b8bcec687a903
MSG: 5716003390e4f5216598a03d7c430dbf495ee3a7557b580632ba59f15198b6180a42469c237db5bc81f29cfaab0aff3c9966309ab06958c9d7126add78e3b32459ff8a0e0bdef874b58e6083668f38ad7d63aae1f12e26a613348f9f03ea5d205f045d78cc8902d47f81e8b52293e70e86c9803d4dacea86c3b67458ae3579bc11113b5490bcf3e1cd4e7979c264d835161fd55efe953b4c26395dd92ca4930920e904fadc0889bb7822b1dfc4452604840df024db0821d2d5e96785a5c37dbfd2c375983283e9b5b43a3207a6a9b833948329d5de41e45008bcbad493de5754dd83decc440e5166edaae0208f000c5f6d9c372153209e5b7578116f89cf2f8b1004d1307ea79ed37480f3194a7e17983a230465ccc30fcc1a62d280fbbaccf006dc4dee0ea796b81accc61a063e2c083daec039bd9a64a77024af82ec1b0898a3154329fdf61673c36e4cc81f7a4126e56290e4b456819bdebf48cb5a40955bab297c2bbcb018adbf24828660a5d12a0613bf3ccb5eeb9a17fb0a0547db8da24d2efb87ba1b843142a75e4ca0b0a333e4a14fab35a62669329ca8753f016ac70cd997e8bc19ee448aeaf0f4bf3ce5230550578ab64c19019446ce2d9c01a03d889a9909860aef76f067c50b61c3d0f12cc8686f5c31bf032a841015cfeff1cfdae94f6b21dae941b335dc821f3284ce31508f5db5c448ffaa3773e9be1a4c85a1c58b009fa3
SIG: 75f739088877e06dc56daec8f1e4d211b754e3c3edbfa7eda444f18c49b69c5a142db45a0a7650e47d10550ba681ff45dd4463c4ac48bf44b73034bd5659220e
TST: 520
SK: 82435f39790106b3af72f91f14c928d2465f98cdd10084c4a44d19af71a1927c
PK: c52a92646f5adb21c6dde0de58786837f8a3414c09aedfc27c812218a7e7239e
MSG: f3d6c46ac5248d5386b6b68462597d647039f544bb01ac2d1067daaaa397d2dbaf125a1cf8fdf280a6afec324d5311f543688a156c849819bb046b911c42ea3ca01b99808c4d1f3b8b15da3efe2f32523ec3b09c84b48cffd13c17c9e26c912d9c3e9346dfae3fd0c56c8858780782f61a4c4dbfff1e9cb4b362cd8001f9cdfeb1a72082dce9c9ade52effc9744688ac0b86c88266b53d895c17ead9e89ed8d24d40642f3ad3b9bf9bbc4dda7966ef8328289fb31e17c81fd028ef1bd9a1d4c792e86ec2dbdce3f937eecc3eeb5188d325941919bbf75b4388e2399507a3d7fb387502a95f421c85826c1c9176c923e316310a4ba45c8a5ef7557cf87b77020b24f5ba2bfd1228109566307fea65ec015019691217bce69aee16f76249c58bb3e52171cfefd5254e5e0f397169186dc7cd9c1a85c81034e037183d6ea22aee8bb74720d34ac7a5af1e92fb8185ace01d9bf0f0f9006101fcfac8bbad171b437036ef16cdae1881fc3255ca359bba1e94f79f645555950c4783bab0a944f7de8df69258b6afe2b5932217195da245fee12ac343824a0b6403dfe462d43d288db31f99097ec3edc6e76547a3742f03c777efb158f58d4053fa6cc8d68b196af4f9de516fd9fb7a6d5d9ee4a89f9b9bce1e4dee357a1e52c0544cfb35b7092d1aa5a6f7f4c7602610e9c00ef5b8761bc72279ba228a18b8400bd76d5b2bfd7c3c04aac4436dae2e98
SIG: 1daa44ef06d4c10ddb48678423c5f103a1b568d42b20cc64af110fce9d7679a2dee412b4980585c26c320dbaa601c472defc3c85415daecdd6d2d9eacac85e07
TST: 521
SK: 1bea7726d912c55ec78b0c161a1ad3c9dd7bc329f85d26f62b92e31d16d83b48
PK: c9ddb42106ccef4e0ef4794551d21df94a6306872f231663e47e241f77cc3e82
MSG: b11283b1f0ce549e5804730ac3207ac00332d2aacf9c310d3832d879f9634bd8a58adf199e4b863bb17481d28acb2da0e1557b8336a400f6295625031d09e4df4d319bbc1e8f6e9232d23053bb3ffac4fe2c70ce3077fc0060a5cb4692a1cf0b3e62fe454802ae10b83ded61b6bf454ca75e4cdad5532f20b70654f12ba906f003a8b9e986f15a39419deb2ea1ead7598290eeebf9252b0c27605a7a73a6abebb42271d71a3c197a46bcc8db11d9242842f378364a37eecaa34e982135be34182c69ca8e6e3c8c90e1b4b2b475815a178377ae0165a764c8ba2889b5ab290949d8487a88e0d3d2bc7e2520176aa6ff9ff0c409ff80515f4f0b83c5e82c23fd3326cdd6b76252e7fddcd6e4770978cd503ed2d6b480101167d3f191fed8d6d74d74a2007db1092e46a23ddecddcdb984664047b8dd7cc8a576e1a806f52cb027a9480a95cc44b1e6f2e286e9b7a6bf7b396fa5496b7a5b1c03d9c5c27da1a42990d10b12fb8640e1596f26b366d270ba64f99afffe3fece05a9b0254b208c7997cdb512fc77527954a1cb50fdab1cc9a45162741fd6f9d3fd5f2e382853d7335dba1e6b2959dd86e125e67b53dc8e453c810bc01bf20bce7b618dd5d1ed784106ee06a3ecaf6b3bee0b56833b0b813139c5a696000a449c97906a2fbddc2d9de9406ea282ac4ee5ef8bf3854c74a6b7173dd2f79c7a126f3c7b0433fd4ea26e877a14831dd415a19d
SIG: f9b04517bd4fd8ef90f2140fc95dc16620d1602ab36c9b165fff3aba978d59767110bb4e07a48f45121447ac0c1abac585d391d4042041898628a2d2dcc2510d
TST: 522
SK: d01a0ead9d694833283b9cd7299a7bd75fa90b1d2d7884e4557b33c998772a68
PK: a0f757479ba627efef95d6ec7a931dfac4373df33daaf4ddc4ec6894c8261ed7
MSG: 7627534e9a83d1e406ab948d30d1da9c6a5db08e0feb7fc5ba5cbf76849ee8add4847ef5ca5a0dae411aca097451cb4c2b498c947097407007640dc19ed938e3b91bf51c9581168df860bd94751668dabd721dc73998400be20c9a563d5051ef70e3546fee673312b52a274041057e70848eb7c5a21644c97e448abd7640207d7cdafcf45da6df3494d3585b0e18ac5ac9081cb7a407a39a877705cbaf79a01b915f736eb025c58b4b5d807fb7b7566c5969787c1d6ca4eba97d509ef7fb3550d21d377eceffcf0eb6681895adbd246ee7bf3c935a006478b832ece46de6118b17e466a27fc2a44a896baae272f9ecf018c65cb50cfbfc8d260994a18a832d971928c449675724585131c871533c9897d8f80f9c0416b718786b10fea8eb5bd813a269a1b677b7a2507a44b713d705086530995e59335ddc2855e847e4f4db06c91f1d54023d8a10f69f9e61bdce4b686fb617bd5030e755cadb1f644e1ddd91619b96ecd605b00198b9a6eddb5a84ebd3692b665979766637c677378c1c77041fd4a6b3555c1dc8a83fe9013bb6106cc18a2b037c9377b7a1a5a5d0dcc54918eaad7e32c880767b26fd2ea2d68b0405f5e074f55a19d8a39ffbb7dc32faee6a7f9532aec8a0776c3ff83ae3a4627738496a371eb9e090b74e0eddecfcd41bed0c0ce581275243472d26da8c998e4b6d6b44fc88ba2ab54642225417120294417805742bdb33b7b122
SIG: 9a0ff7f35174ec3f66d22a6f06df60e09c8f623a5aca810e23a88d0e6a31cb6f1ce1c1f9dccc9e1484b68dd004ac53597e29ad6ab72e8ce2b75ad5b80eb84803
TST: 523
SK: df648940b578bc31d2a652965f30391caf06d5f251599a737ce10be55f4a9d0d
PK: 27de920419c186b01be54279fb8f9be4bb4b2cad75ca7e8f792bfa7bb97c7f41
MSG: 1ae520beeb4ad0722b43067fa7cd2874abcf34dd9237b4478eae9772aea297a67fb79b33070204baee440b9c87e2fbcbeb76801dddea5e4530d89e11583179939a00a32f811332c52291cc7ac91e5a970cd5aa708b1da26be9fe432a9bbda1319e31e4bcc9f1666a05b5c05b876bfd1f766687ccea4e4482e924329aface5ee52e9879fd69b76e0f7e452ec4713bff216d00c82599d27ca481f73aae136f0875c88a66b1b6f34c50523ab602e9d4ebb7eeb9e043a65e41899d79752a279d2ed46993926f3621e7c32c9a9b3b59d8dd57beca39285434de991cbd2dfcbc5ca62a7779f475d0cef2f3e562f29acd474f3c99ec5bd8de01101bed2e0c9b60e2d70fd432c892fc66f8d4619a911b5625163e9a42bf9ea38586d8e764001564d335411225fcb0a06dc2a82da0779a3c444eb7864201b43ebb72b921f34d3c13089df2f4fac366ff1e3c0b96f93d2b4d726a5ce4d6916d82c78be354a1230c2cf0418c78a1913e454f648cc92c8dd0e184645fe3781d263cff69f5c60b1ebb52005a8b78a515c7e8886ffe054dab428e2e221d9d76aff42654168d833b88178293e1fedd15d46cd609483129c4d2d84432a99d31ffe9bdb566f8c75ce65e18288e4df8c16731a0f3fdde1cca6d8ede0435ff7436ca17d0aeb88e98e8065cbcbfd0ff83043a357cd1b082d1703d461881872cdf741e4f99bd146745ba703974be40f579bf5c4dba5bdb8c941bce
SIG: 62bc991c45ba9b26bf440116264162c34c88597885e9605083c604b5f5d8fa6f662ba214f76e6cf84e5ec04df1beefc5f25d3a3b72f98b5069831916a6329601
TST: 524
SK: c8ac234558aa69816b368b77b7cccb5c8d2a33ec53aeef2ce2287143bd98c175
PK: 5364baf1fdb2c63840b30d4031cf83a2e18e620793bae59d1035c0ede55e528b
MSG: ce488d26975c1c9328b47fa92e19561330041b23a0e57a4b8bca89eb5f615e73dd7fae69c2380e3212f9b73341c356db75a6256d7a20a97f759d4cba7197178ea724dd932949360e96c50a4b3ba55a953372c397b0969c2b14d3609e0a852d484df70eaab11249ebeb3237921f0a39a55d7dccfef205d94ec80d9e1fd6a2c1efd29844101dfe2c5f668adb7975915dedd086500cee2c1e233e8e48855cc1a6f287d63dce10addd13cac7b7a187efe47e12d1c35bb3974052b23a73668d3e4c87db4841af846e808672c43d0a1522e2965f083951b2b2b0c409548ee6182f0c9850514c9e6c102f54ba4124c92a90274f405891e662f5ebb3771b85783156e9e5836734d09d1baf5b2134c93162eec4be03bd12f603cd27be8b76accc6e8b8bac020cba3479651c9ffa53ce4eb77a77313bc1265ddab803ef7a6563ba6f799d1ef30ef5a0b412965fdac0b9dab842c78ee2cc628e3d7d4061e34ede3797e154b06e8c66cebdf2ded0f81b60f9f5cdda675a435277ba1524557e67f5cefafce929291dce89ecb08a17b67a60c582b487bf2f6169626615f3c2fe3b67388b713d35b9066669960de4db413cd8528ee56ed173e976a3c974ac633a7134cce38319735f857b7d71ba07f477ef85848aa8f39e118118779ed87b4f42aa358a89f7ec844a451e7e8fc0af418b85bc9bf2f26d1ea137d335ec7ee757b70ae2fdd9cc134932f0e5425bf37fb915e79e
SIG: 32250361df6ed283485f95f3d357a4f1c33a8cf91658327cd453d49c953665510870aa454cfa3b83245220a827d0ec7477f9eceb79c4a29f301f953cc8caac07
TST: 525
SK: 2c47f2b8b9d2cee9e6f654bc24658f9eaf439c23beaa0a79bf35cc8cd2debaf4
PK: 444af2f34fd32e5a19f61f87d03e107627a3eeb8bd94d2faeaa348b05dea1980
MSG: 044c8faa8c8aaf9f2b8186a6b9b33847ec7b452423b22a91743d2e597ecc1e1e22ae60053e9ee6233b044e775920e4e3d66719901325cfdd39bb532f8aa469aab42e9608c21260c04c27413a7a94e466f63c4952e90ef90c12814b3451b1cad7da9147f8409220f6498cc0a67fef4bc04fc06e1d898a5515591e8be0c43d75a6fe425b7cbefb1b91b1bd78b5bec7829056982efdc5be24af6678006adc6f0446202e7ec3a2d6979cb0df7e25d74233914d9c58b81cf55be06967d3a595c1b9672869994cfba67162833a2143aa91cc93acdafa5b45208df3e88ccc01a2a4d220e360098d9154d225a7ca5f2f1e52b1003d106650a77b283b95e4baf1e7336fa9a747a2b3823d360910412e76db725ce1ab1e1d189d0d3abef82d7666bcf1b76669e0643b44f74e90ceafa0c8371b57c58f3b370a547c60958f0fcf461b3150f848c470fa07e29bf5f0d4b59efa5ab0d0341e0451d0abb29d7414cddc46cc6d74cf3dc233d0d1707387bd8c7780ff78e546fb77294d58a5dda5f05c1297e3d1771156d285635bf7ecedb38a9e5e77449804f3899ea46a50266b255aeb52d18e0fa136e535cc9026f678552fa3ee2146081d999685e24bf7807cc47c130436c544d35b4b875bd8afa312ce3ae17cf1c7f5ea1ececb50f95344720cecf088434ff8e0ba044ec19c98ada7782116304cbeac1c3e35f5a4f44313354dc9a40ece5a0f9ad3a2025acef262c5679d64
SIG: 8554b01d09ed86e61395b91a2b1ee18715c42f9c7e7f0700d79ff9fb5781293d61c558dd5b431c93718dcc0f98fb652b596f18c30f82215e8e63e4f6568c8800
TST: 526
SK: 887fdb4870681d4fb06a936259f75cae0517f501af646bc07a4d72bee7fb1c73
PK: c762ebd48b2ce02d06384e38554b825ad322ebea74d259df1547a4d547ce0024
MSG: c5dc779f3f3fac06dd28e5a67e0e524af5b5dc3b34409657b63dface9471e9a41e1132175a0b569c8fea9d2eef2cf5d5962c7e0b6145a9e7a0c1aa33772044f9c3998c5a8c4886458b4e586f9307608361f511e7ab5092ac41ec76e0586ef5b9c236fcf5ca2fc8dd6aaeb789367f2e7c990932555dc52261e44e49423498b524419183b6c1f1d42c45464eccb0c2f7e25177fe5cd463502b403e06d511fcf9dcb64012e0f20b34c2ea7c004d9e484a7ed81f3260c41c8b1953529f47f71e867843cc3c332ad0366a63817ed12dd4730d3dfdbd7572b9ff798045940dd19fad0c8aea0b4ab61c4016de32799c73aa2b92d2c25ee9b72d46fe8f0693c58775efb05e9e17a5c346a81265d35be69a22d095de186066a5c6d8c07a3d38d002a10e5efdb866da4a9bdd54f5092661b6c2d743f5aeaa4c6c318fb59323903057e49c237b45f67542a4f27caf65b57cfcf88b71203d43d7f95322160f95c232dd10abb113b721ddba2226b063229bb44102336b10bf1656551161249786d454f4e0909d500017f6c7564f733c831af4e5ec94dfd3bf8ff5f3021b70a5ca5d28c6dfb8a2c18a1a662a33359f264d169698c1ab55783faca73bd68c0f79d1d04ae0ecdb52ae761892c02493ff35f3d84f66e236fc58134ad6a77d92254905d773900d9ddf2654c70b46f341dacb4793ca51eede45533eaeeb6e3323bc3e6c85a7940651c4f6f98191c618c891ea4e220ea4
SIG: 410a5af3c59b7c6bdb214b166cb79d96f830cf98bf52dad7b6ff2979c97fea4fed5ef7d3d49f03097279b9a099226e2a08dd30c60786254e2da8dee240bfc308
TST: 527
SK: 88b3b463dfc30d015eefbbbdd50e24a1f7277775bcef14a6be6b73c8c5c7303e
PK: f2b6284c930d4ad32d0ac719040ee7886b34722edf53da801acb5f931969e119
MSG: 17c317fa6bc90c5532328f02ccfb6c099e6fe1000174f2af3a3a9309428506717c5c4335bdd7c367ff4e448a9c047503afba68fd8f7987237be7f7fbdc6d73f24c6421cab422b3fb25f67b2d71042e71570df2af37bfe5c114211fd5524b6c1c6cc52fabc3cd7fb464cd580bb74071cb300f8c9f8a46208e5aa5ddfea5fe90697aa2f14c607950c98f2312a9e16ef6346a8fd129232733827e1501a660c77c29c56d2fdd1c5597f8bc89aaefe3713734fe82858201891a1147efaf1d78a471f920defc880344553eb716cce3260e86a1bc0be28373a6a066116e8ecb10a0c4a70ca2b5364e119f84aec60deced3a4eff1fe688c5e3e251470ab516fa964a4b6f28368dd1e283597934064dc0c5b5691062cb2e267bd15fd422bcfefb83ccef7aa9a2275ef57e473149988c1578fd18708d2ff69f8e5980aa826a82cab7d8b92bb53bdd46db046ecdfc8cd7ae5ce44f3c5b8c0565b5d3c072c76b95ce900ac3ee5510db0e75d3a4150a98f3ccccc69e930c6ba741dbb0eb9fb3196871ba206a58e0dae39c8d6bb72a82399c4b7b9da38577ac17ff1524d653c0bf33679323ca7eef4e9228729031560ed8f2e5193c640b2f5e608075a2ed61428dfccdc00050ba4b99ed6d1536d5ac1e939674b41d16312ae5b07def1bf53589bed4400602ee11b850330f38aad33ef04170a3905c28b50ecc57dccf4f29d0c00f713d32ffc857956588a6326b9549edb0e4fe6185
SIG: 825aff71f79303bf4592bd8da4d7d9437ff267976f746437655988ddcf29379465a3b48c9fb0f31cef03e6368861c369b4364fb8e4b0c72e26a9a9dded1c2504
TST: 528
SK: 427d6e423917896831601b8f4e21561db6108571be009e29dca49a5960ff314b
PK: 8d9e6360fdef249975df27b3106a71120587722df3270a85a13a8c3bb8c9809e
MSG: 9c2cc7f2462e09c4c58c2709ab4259885a4e887d9fa531881505aaf203c163fb3a0dc028f4ada60670638d4a9727a39083bedbaced58edb779e1ce6ccdfb428c362bb1db0c1053006bd8f4bef89a1a9de01c774e357f910e5c39b22477555e5f7c0498b5b28f369e5d3fa42ab360e4f451c69f81ba0f3cced43a559db600104278f868796b2c911b3b032b729f4b22ac149dc467a0cae48d19e9d985b42b62549de171ff566e1d1e9bb8e56cfd1ae8f7bddcfd8a2341827dbe89c882ab3e498339ff681c7dc1104de738b480316943109f703d471ab86e4ca4287e4cd74c312ff7d037395606fb25f871e7277078a787d02f31cc9e815be8600a7c47c6fdd82331ae9c496a547bdb235b8a56d53259e6296124a32c3b625d202419d064b9a4e83efa87f13537b4f513b916a84fc866d8a899804c7833eaa019e0d7e0e8075bd6b5cb6ffc766479f3f6e20e481e6ab27bd808ad906cdcc7827430e312f740f275ddf51dd83248fa057c43c9cb77557b2fd9c2d52824ff9e146deac1e6691d450213bc590a49bec72d52e38f6b4dc6cca951eef2184d2425031ad59b242effa68b6c72c54c9dfdb419c02eb43ef3f34d338d2a9dd03a78cfdd014098e249259e77282e0c3fc1010b02a67ff851e9cfd9749c1cd8f06cf462e6ade995ac466fab5c795e9eff13e55b4350b94c7316aa498df9fdee9958047793e3bbb89fb81da85f4b9d43e4b0d43b381b94cdc9a99d06
SIG: d1c9a01c56e33960f49df37eab963bc5a99f25c600446ce2ca48d9139da5733b718fbf1a987393f6e5823c2d130c7ce60ea3db3543c8854ef12b98d33adde705
TST: 529
SK: be935209f62dea6012ecda6a6156cd166a4d761150deed456816eaf0ce78a7f6
PK: d39a89af72293948b13421fb883bbe372af9089c224d42b901979f7e2804e1c0
MSG: 117f427cb68150cafcfa462c42206141427c4dcea1c8eacc2d30bed1e90207d5ae305e1fc16c54e4c54cc6878cdbedc9f51fe18461ec37c557b115d13c8682c4e15f505296a1760e1e75f5ab27a5c15a1357d2c8c40dd5355f7c82fea5d27e28876358c12e9113ee2983ea6f09c64e06e297dd96b34d9b5ed49fc47a8839549c66b002fe945e8f94e7d2315c50ca4dc098be4b3289812fbea96b47ce604540bde0e5ab0b1bc036be9b6a95e09c81e898640c8f05d60ad94218d0e66ceb85a26b78292220bfd061dd073512923b90c79dcf5a1935fafe8e01ef8bf81b4d37c5a571b50c421f9bd2194bef3586fcb8584877bb7e0481655b05c7b643b1e45b04036272841852e31940ef8f3b6d4feb5df079d176f979c18a11a66d1214e52f687e9063c1c2b7277b685d5c72ad569f7873838f910257a053131c83ebce86e69d736362bebc96bbfa35fcba1cb527e748e5f579929fd40c56b1a51a222e863302705c86f7b54ebfbb9482f7e280f7bec8caf3a6b5671ac30cd1be529288797c013ce56bd186de7dfc1828691425c147c5174a290d80cbd59c19da7adf77918882a7b2a9a64e6d76b48b92f2a266eee6e251d2e817652b88b502de7399782d7529a81d0a363996b9df68b15a7630904c8c246081fa4f09299f15757958e089a901c3564615c0f7cf2752b8b9e521338d836e3dae4ce2374642253c4c9831974e5d8c2842f49007b71775093dfe57f44492f0
SIG: 08e098a749fce6d12354395878a8be35fe9edf72684dd8281224899b1caea4ed687785dff55a19989e03636e1666386f22c3f443ecf6fd34d599ff3ec2faf101
TST: 530
SK: 6818c60bb6439ac2eee2d4e128e9d8691d4ad5d363fed7d6577a62b6569994a4
PK: 7345ec11bccc056fc4effa3e4ef670996aa26a1bb1b83391babc39a1a59601f9
MSG: b2ae658b3c13c3cdeb1dc993b0f45d63a2ea9abd0b7a04f1f5ce5932806c2ca9b7a204fbf8d066b7f0fe6ae0d1da68c885ee11f6f6db7e8320a2ea650b533851cdd99d903aa0b3faa3c950f702f04e86b4eeb3a1c7bc854b2514fa5b4766d375b4f1ad61075378dd92fd626c2b47e01383ea72987959262c562862b45b7557671413b66614bcc9f7bdb9ee46cbed8965bfa505315090c7204bea89175be5f20802e3deddcbd8dd64cfef7ee6a6e3860ce1e5799df5d810d5ecf32e615d16dff87abd4a636ea17aa4ece5b6b2c046b65b5af749862b45790c39176820b36901be649cf4169df7e923956d96064950c555f45acb94507cfd0c3b33b080785e35c0d2b0addc4c0ad3fb216ac2e601c9c7e617dabda333dae603cc9db1fc62ae4e0e45e3ccdd166a6781e243b7daa138806632f538844ee3d140b7a8bb2b540100778c458e066170705e5fb2c88029098b992c39bc9ff6330bfcfe7752320e6ea0949d2c871aedc187be27fef7db5f72a6a773edde0dc52ae2ed931cb26817b85b1545894d92298aaf87ccbc783e8dd6d16493f56ead2ba852ee9c7d10074406440d2a279abc874f15468dd66a717bace37be7b7055dd9681f8be81329ee7af97e3abc434ac1c93aec582f23fd1ec0fa5aafcf7bfbda00ffa97ae317ae918d349d21a7f4619142ba23dacef7b390ae26a17e2e2962ae27005376b72d4da9e2979653a66325a14617638dbe1a5540b683ac0017
SIG: 1505967a27b9f86e9242444002a1e3197d74ddcd89659ec5140202aac794b8adc193e7d30f3382642990f6fed7a999cac8c61eaa39b7d90816f1d738744be101
TST: 531
SK: 6d1da5b483e64b0365990ff09381fb1702fd8ec3a1a369cd52e4c56713a314a5
PK: 08055c261f26e02a658f66d9ba01fcde53e9ade3edc6bf815e4a6802e1677ab3
MSG: 79a2c37055f189f3247f1f8cea19b2ea40d858db1f5d1392ee6d411c7802ee23de52ad02811725a94d76675da89a96b5d07abcee233a1a2e1fa324fff9e78a4c196147f8570b0b13713d96aa5d750a15d7cd162e7ba2e75333607dd698eb4773c7e91f7668ff8b62f04640eb12ecf122fce6b832e0d0df928eefd2c2002364af6bb55291d3f54929085be338342f09da73e279c87c8324555819ed57e78d7ac40951d33f65b94aa1e555e92a063d11f1ff7b12694341e3fe444933d01aa36753ed3cdda890bdf95a8205b5d893221991c795ad0a4a946f58d40a453451af214fd465e28d3e2f0a56aa56def8dc04aad35713abfc8bd7856d5a9dc3f60a3f2bd3e6366f1f244e941d6aea892f6a88931fe1c313e09078e90bc6392d490533c9ea3ff6deaf3aadfa8dfdc4e90f64af47589ea65a87acd2199602351d3afc2103196e0394ed523aa799d31e11d34fff546d44f436b34859f9cfbc9ce403de5a9830ec3d453f0d45970f572c144f191b2fbb2d0ea6cc9c8e24d9c0b2183b278072ebb0be2d70d037fd2e8ec18dc4c9b21abdc6a4ce8d4668a220eebd6934f04baf0e88a488d2dfc735a7c5a70dbb0166a21ae011fc6e7da10fc320336271d9eead510a6f7032f2296692be508021bc98c170be4235f7ce31f2bcd6341163683376ae2c5662cb4770c96e018ef1bf47913319c9a09b9e965ab5c3e97bbc756a5666b4567f2cff2d0c3a6a4026158cb9f90f950056
SIG: a5b8b44a91444c64374b523cb4dcb0cef4ce52408b98126d7e1ae8bdc28cf51470ce4e253e0be62bd68ebf5fa6bce1585eccfa9256c073ee03e54c525bbe2d0a
TST: 532
SK: 5146f5b7f1baa19fc8cd785c896e0f90f9f659b77b1b9bb4adcab5a6267205e4
PK: 688a8de64eff33ba6bbe36cdd6a384bb67b3f42636db234ff5efe0b31743c7e6
MSG: 97bd99f518ee0788d576d99c043b449dfc242ac5eeaec344a19432b345962ec412ce55362b3b851d98119fceb9328347f6fcc68dbf56a2814db09e9385843a931189ea3e72da9d79a45693053c035701dc5551240f95b303fba16f89aa53a43882b0f1381202c78f9c7419899f2351eca95e20bfee76351c48d00499f591da56a99524bb74fe1c834ee91077139f1edf67315c07a3fd97f80b7c276b6cf6b5cc36be363b731217f6319f5129ba7b14d054c8d81d8e3a3f3be62ac31ff62df6a3b2ee2596969b991704b31c689997ab4628bc2660c67872132e85da0c4fcf567965f1254a8f432692a17bb86cb3c1dcbaac939552f09e50ec5b0de2ef85e0ac253a4165655db5b5c49803821d859c60961e061d58278b827dd4d3bc47f1c22de094906bdbbf3badbdde22ba24255855eb86d1d7f37082059311dc0728ebeaf26c4473bad1fa9e614b533b811b6bcb0650c06d879a5245788f3401b46197300774a9aa73cd978c0530c81a53bdb3fc932414b3e30440dc127441eff1605e7fd9ac8c632e82bf1b453d4f33a57e4b67b0b6fcf6ed5555b5f5a300a14a00d0385a33750525b00edb312c6bfdd64edd3b5316d19f958c517634f013b008936d34e9b5e1e9283a5f0fd7783377c0e5090641bb9d338cf3133acd0b971e537904f17af92911afad72ee97f9a8283a16a7e26ab428416c1017dae9b1a99c4c3320ad163bdcfc328bfaf9b8d5d7d26d41d1ef21a5208f01
SIG: 4bdbd7c64f13e278c23969e7eb386bbe499dbdefc3ff4e30cfac5cf86f216c24c9e6cde20e529d147fb7ea08f2593ad50903b5edbf86b4d28f2eb32ef137f00c
TST: 533
SK: 5e6fdac9351a637b99f33a264e1287697e2abab0cca16621792484f5606f44c1
PK: 57e5f88acddc8cde7dd07a3146fb1d4f7a9b6383a8f6b2b8d9b07ebc3fc4dd20
MSG: 4d6cd3bc2f86266b8bb1b61d0e1caa9bd2d4a180361aef3a18d390b10f7e860f697e247eb6c3e51d3b976bf0ca183d01a69880f15c94b875668ca30dada0895bedd4d705a0e03304d063dea87c7fdec98b89c06f130dd5bd586b54d9ba737826bb405cd8ac8bbc9500acda3c07461d009440af0b2531e72f3ff5016ae2d86d69b87fb273d1e8dd5f6a264beebb2f885996741ffda277a0fbf8ef08f81f22ee5961d9d3fc938362e1ca12004a91d9b5f7a6833a6c22955ac0cda3390671910cbd51e685fe095973e415fc2db8adf10b147ec7080c3b8ebd07d21bb9556da85430a268eed8486b1e31c94313b01649fe91b222f85adee15eb77707d78ffcb660926544d33be9994a297620dc7aed97f392639053f388b0b3aa3bd0ac5b033cb414be520b43df6826b976890d0c53b97b6c92e7d1a1573d0c7494d747e0cad9bd8ea538d62ad59801ad0716f170193e3009d9959c55d2ff64799bd959359abb94ca9723b5ffc24c9507f8c5fd6e88eaae7a70add84d744ccf8b98363788f0bfb1a02522025751e534710d40a2d38a791194eba293fd2046cc14dd3876d168fc6e236cbe146d6369d225bfa67e53979865f78873a9fcf03c186fa8521f0a5545accee80d1e55107221e21f0f2291c143de023e88d7330cc87d4c51ff29a3090605e9739490c1dcee713495f231c2a36b11ab235547fb6328f747336d9b1ef25a8ab99ceda957b2dccee4075b0d03381b94ae18d041ea
SIG: 987e32e00a8a1632f47b503194355c980cb22adeb326b4e3115ecab04b704d186cd92e3c3ac7b4e2936cbd07cb794ec0cfe91a97872ff2b41376f5f18f55b805
TST: 534
SK: fcfff0932dc86ea5902a8d33073329960cd8188a075dd0bcdfa8382c20b0e78f
PK: 0c9205a90bbe7f2d505e17fa3d080b522a1d7a152cad2d85d31b34a0471c0d4c
MSG: 3d4b76122373e212a346d19a66bbfc4b623292649bd0ce5cf6bb135648bd01db7403b3d0bdd1697ff4e6e908904116754d370c40d700cdb664c46a91dd84a358b9d2381443e60f2c3f5640261b6b858ba8f828b0971f4122b20288a26ba2090ba14fd276360cc68679cd8419ae19c6d4dc7b6614c06df5e5c0510e2cb686de0ebd75e5210a215562589b28c9ccc7d272b98bd4bf93495efe4fc5b78defecfbcaa9fe126bad30e89b3a389b4256f6a48a76c345de5a36a1449f08345b9a5e6a001da1ff9cd433709348e9aefbc78ba52d3ab3b46986935eba8ecf81edc43c5b2e3b5eb38d9a165e9e7f72f617605463bedba973ebfdcdf2b0889c71412f8f850c7a3b5518ecd89d2e25c0c1c30f085a0ffe540ef9c0e88fc7ec4af1948a4e6f7a6e256b307a1127b71ba686efeadca0e4860947cf674fced6caf7310ccbaa8d9047daed30fd5585d41ddeae4df2fed4b6228032c3e4ae2380e87ec6cd72e4d74b8b4c3813fb043389391e9c13f7d33c3aab5a78fc4c6a634c61a70f02a940548da177c65df6ab17cd9683f37ea821c740889d82e88c834e7d5dc11662ea78b13c6a4b6218d31784219a4767595b1a56216525cd68938b22bdb1f8c5a7f1701afeb961888e2e0ec0c838cd620cb7dd8a1493a02cd56b545125e4700c0889fa2644e644a3af531d1cd6bc95e5df9175f137f28408cb699c7ae66f65d1d2930fac57ca8a60e6311a4078488c9ea404948a9debeb9d5e10
SIG: 37ddd83f98b057b7cb3208a832c58aa90694563c23548d432291380b73591301f274b04cee2ef78c06d96c3d9b7c17521aae1a8ca50d347c09c3cf703bc8830b
TST: 535
SK: a1e4fcfde044f1bb0e7bbc631a831a8d07e90ae08a966ad627b620b1e28c42cf
PK: 25560f31168bd4b72552ededd08bb6bf79a94063c1f1e1d304869dd1ce049b95
MSG: 8c1454d4e08a1401646bf7a8859e8a145e85eeeb40db38ff0169709641212c81b67390749c01a79807f3ccadbbd2256f36ffc180cf9ba44bf4a7612d441c23b2e25d33c48a73e16ce357562758adb00553c3142fb8176b6ae8fb610a60f923b0911814b10f5679936c3677b70e846e218f587567f2019c7d282a107f3cc84763adaec88993c0cc5003e77af60d67db53f8cb727aa6672de004498c3b3e222aa7082d91f98a1a068374c510ff53a5e559cbe2d6c7c3442d7238907c811d58aa7f5a46b8311244f0dbe1b9c0e944dda1d8010864949c59396c6b346a11f3aa866d6bceadfc909038d22efbc8f1dac810a9f2fafcce7c0389eb0a56c0f68cae24ae3ddbdff7116d2fadeb9b0e7509536fdc3b83e71354da6a1aed16887490dc2f4df57bbaa7244528fa3094b99e867581acef906270b2cf4deda6b8fd9dbb79add7bea8f86fcb1f64dfd50e385b4209ec0b1a9f6d2e519068297a2b5c405c216b4a2ed983ff69c59b530effa60c0367051267dd2bbd1e86a9ab5a114dd4f69b540bfabfe97c0403b8fcbb27625761eda3e2ad8e625cfe4b615b7025531a498918c24e02a00e797bbafd14f9d3f6827e390063c436080688d037a6e2993c56d3a8e95f375c10040bf04f030c972623d9e3801c13b4ec8d01cf183855f5935f10ddb2c54c51c80cbed0c24db56e1ed148931d89161c5ea37c2f9787f88ef7330e5dcd0e43d81bfc8bf23ddf7983cc1d733843a33ccb395dfc
SIG: c8001527bd902c15c3dd5ae18180525b5e8202be66711f82885c8222a15f060092a2a6e2f7d7e980311209191b32b8ade48d3ea98cf245f0fad62c009c5a7108
TST: 536
SK: bed1bbcae18643d6f6aac34f3d9b6a1478394d02b931cff006d85f21b7dbc747
PK: 4f528b38185a424c6fdece46511a0c29b7c04b32eb0483abb52d5f8eb6b352eb
MSG: ff7c6413e618a056de401ee10c40ade3d7c0e6861495d97c2689ec6abb69dd2ae701fdcac8f08331ea5c5f5d805b5789ee5e241ff4ac8b960f4f2b9fef6a727fad86dcd432de9fad6ba45e00aa3687b0ceeb2c0d430b7d5fde63b4f6b982c4f9e03c430abad9044d06dc49e89df481405d8febbb0653e9686948aad2d9072544df9424fd487f4e24ba7f2455ddec4105828c3981bddbb1b7fbdbac155903e960fcd94c0716e736f519867fbc52c51260f571d7edcb081a23550ad8c70bb268864ab276aa2cc2dbf62383bb66030ebe94354174ccec2d2a907578556444507cbf8488bb23c62423a3a98da7cc968f599d3dc84dca3afad7f14ec306e1db534143216aa22ad18074c719570805ea46bc86b71a8ff58e41e73cb29ad5750fcfc9a1c54292b64b47ec9538f53816e36ed0d0c1ae5ead06d477aa975ecebaf62d9023b77e50e7b6d4abdaa485ea34ec766beb1d9ba03c9c067186e2e38266c6e2531e97480214638a2bb31431ac2086797155fc775b3aad8d5a0b904c381edd0c6bc23c66a1904955ed450a9cbd16459c32f5ca354bbc2da7b1a4d814f1b8710aadb2ccc4f397758b7e9d91f3a91e5825ab8682ff5e41702e07841ac7698c3da9f558edd01f86ce2c506bf4c2149ac9c195a59c7dd7d4ecf93c90b4423b4350588d41672cedc8510a7ad53b4b7edcaf23e43e05669d27a1fe97b78730d3fc060bd4edd9872cffb96285351bef148ef783ab392116bd7b907bad
SIG: 0fc99dd3b9a0e8b1fc6e635af5c64006b67200fe958f53cce1b9b091a4e70669b593f15594bc0842e5576259f9a6859a0db22d740f9f8024b5baf1ef6f958c05
TST: 537
SK: c718823f43db2217c66ab2899704165d208573de60f33bc0b9338d880f193fb5
PK: 2940b879b63f2cb1f6e3ef9c9d333ba91770fe18cc5a347fdf12b0efc5ca2ec9
MSG: 050e6877f65ec726eec701863fab140b994aa1e92a487db1a18701312057db44bfde70911ec26eaa28632d03794d545dfcb2aed4340cab7d092595cd59ed23994043f50ba696e9802bd64990121397286457ae69d76cb8e34d7c1ab245cb07b1b408f2bbbfdf33a1bdd559636702c918f982c2ac0221f7f94db91edefce28118259f89d994dad5bb013c678c1c338b65396b15e8899c169921f278859ce0c856d889b8c63418ebc573d2d625d5b5938839f2b169b6916d8e40dde70d3b72887ad2478ef6fb1284fa0e4fc524e3c6fa1dd22ba6b81def8279f382bcb45048851b17cd659d59409f571fa8a920a20934d9dbe1022d635840965400240f870aceffd5db7c7df08af89e47e1b9e20bb99f96ab073edf53694c7482890e3631340217e687ab27c984b60825169457d435a5409ad8e42da0aa63e20c2bc67bd8b9a267f39673a77f7f3136dc5cb2d24948dbe7bcd7129318c68c6fe95dd4dd4fe942286831ea53352fbb252a1288bcd838921356785d072134cb820f6279cc71461f431be9d3014724321c92fdc576320137705cffb2c23664b705e9be60ae1a190f3e3484f70058e702407b056d7fe5d31cee9c2a6ac6eada3516abc5517256df1243780a03bb00ba00ce248076eeca6fee91d5ef9eb907b801af097f3e9eb256bdcde81efe4baf8189b0399e36f1eaa3ab626617cf3b47dd89caf69c64c5b8f68bd917fe03e4668538460a1be88d9a846cef39934627d474734f
SIG: 4c9cdb1ad46509560d871d3089afb8734648201b10acc953e8b61f2cce2dbae0fb9b868ac957432b7222dbf7e4cf0bc75309bea360b263abbde188532dda2504
TST: 538
SK: 2543d166c9f5f7427ff3034ffa8103cb117bf472331a73d9a2f1bc0a02a6ff1b
PK: 42678cf3857021aa5567706db031e792715ccaf8abb02a042bad17db3d5fa103
MSG: 746d7abf0bfb2662c25ab5c5e4612c306f16d13e44d0db394a0015676ce609784f0323da1dfa94d2b2f1f6e02444a936d019b143021f73c79df9309e7bdff39daeec4caca00cba4ef31c8310c1a08ef4b36f81c377846b5b90acd411aa671ed7af278a24229b7893c1b415d79888d7637f5cb5c9c6c631ae5ffa29f1340e444096ab533617fdcb80ff81da0a7c6c142ee0fe5ea82f68cc3ea38b56f272b0d80fd5f4f55ca9348c161881435813c3fa9fff66a2ee6d5bd3edba0d2f9aa74b1c44bfd0e64678d3715124963ac575ffb09ee16437da484b3ba58e5aeb8ed8c5c0f47b59908fe580f37ec1de266b295d6be85e62358e9bbdc78964fb837eea29fdb7de86cc56f48bd9a3e6e2be51d8a1dcff3ca4d56ea934c682772bcafb51497be5d0f2a23dd4970c02c44c09ad897b4241acd7d6ab12d8f00c9aadc334b431fec5bb69a285b7550a639ece96952682b7334b68c65152e893b1c8100c694d8c5cfe26ac03c1f3914e65c84f0e777290c76f6acce340bff66da7220f73175e94af52f9f19e61f80dc1f35716b3f48dfa5025c9ebef7382e055830f5bbf15c6f6a95032909c892c0f89c8c15fc3ea40a20ee1a4529b521951df44d9d79d74e0c4c2e0fed849b8785206dbe62bfa2ca21087a912e9b184551659cd8a587e95b04317192596bb0b7fc9f7bbb6ee049c8b02fdd758b4e79882073b71eaab18aa293701c17d55f9ec46c52de1e886b6750fb0fbcd64f4568a210ae451e9
SIG: 20ea9368a2ccd08bf9cbf48d4a2f7d03f0db08a54b87679cda03e296af9ef378be9b8f04b4065b009da6db016f3df9db64825873e2fb4de30449915cd73c4609
TST: 539
SK: 85e0a80f3b30c20199d9c1ec662e392fdf1546377343f12471db2a0310a705bd
PK: 540a3a1d83672e495034cff408e1fbe82e538f0917e8a1c7d17aab58e043d3c6
MSG: d2802f1596f8383b64edbdc594060bff0e7013d5b7c85d830fae11aeb34dd594959da624e044474c5409c0059673bdc61a671ef5b0b8a26f30100b3b73968d8e4d83a72f25b513448d2f6b6a4475fdf89e31ca9268a30705af3f649e3fe01dde0cf4b29ec2da5436444af091d62730acd4cab608f0df26f088c6b9b9673794f0747dab2ce190f90592009fdce5464b3661b7e8620bad65509a6c752b727a8dc8d3efa584fde0272c451d65a93bece4f59d87dc6fbeb451401e3e2e003c6aca7b3d3f92719150c6778f015aff2a59bfbf2e91b21b0ad6877536eb54567059f587f54d4e2a6fe1fdcdd6a7fdcb8515575bcc3705d77859352fa0b044166e3c318846a5df33563003cb20bc942d30391093e8d583e8e64dec570ee1c4138762f6483898d32e2032bde9bbe07ec2c3eb47d96876f0fc0f024d753ceb34ff8480b4cf576230bb8263dd80eeac662eba31d8a61f309e175f4c0143e28a852b1c3061ce78efbd16a2873dd28198a46ec0a800b30dc8a93b8dbb81a730de450b864dea7680e509d800e82329c261b07e72aa80ee16ec375ddbbb6fe3d8d47b0e3c5a9f23c4d20b724c1df59835d830dd22d10403d8f15c102c4b3769c41666c3ab8c7e80b940d0bbb58652d10a3ffe8d44df1012a3ddc4e1c518d49019f7c5d3d9f95ed93a319746d1e543ffa69edb49bb3439f8a325ac6a0cb4edd65ba60080a0447c674faa72d8aebdb5d2544f2f2d847c72c2dfa6057a690adc5c441a
SIG: 185ef2246aba2b1a568032c7df93c667799b8a521a6f97321ead5866b4cb9c65b64a1c40b9b6a910e742dc32a7e66d11ea45dbeaacae9f09511b8101f8af0c0c
TST: 540
SK: 82a2c6493f11ba80e4b8b3b43841be970e2a10a94d2249d8ac6f5414cf5a3cb5
PK: 4c2ee01cdea07db3635f5d4c1082b92f298deb17d0f905df71b66fb2274eae99
MSG: 09854d13684950419e0bb16464e09988905c0217183aa1e48adb147bfcc2eb57c2300b0dfc39d4896655a57ae20415408bb5f2c238013955f0a4fc782e0c993fe42cb08cd8cf415ccbd6cf1cee2e8097f04e8f09ae5da5f415b16c2cb30cb2ab6652ba50ebbcae4a59e31fe11e7ef3699ca90aafa586bb242c89cd2e332b2bfa2f8142accaf436f89b6453bb4805a1e7f3ab6270f0daf89389e717d1b70175ec5707c8f512c40ab924c457e9f0914791750dc292bb27d6f63ba8ccf54b90d3eba7f19eb300d9eb8f3b72032ba93037f552b409b580a5f65116faffe0fdfdc6db3881386c3cbc16b67eb25763d7ae3aac0b85aa1e9aa22e4959609d4381e4b6d7159ff3e3b2d37b640f88cfbe4f8a77f8016457228ba6d3af5c4e33125d48bcfcf3678c163b698e52e85617ab1a75ff20c690ab07155ee757598578072d4a09dfc6c6c094ec048567d513ce2b1834e163df1545319d8061e0e57f58ef041b7bffc4966ac1660331b97abbc97be21ae2bc58c6c3274a8adad5fd2c3bc16b92e1f8de877b6a26f0c6ab7162e8aab93af8d85918c13d3e235a273748c62f0d22cb1c93e134a495b1b5ef8f1a1134512d53b7a211263177f7a60bdf474691f224a3b5bac4006db345ca6725f5ee703eca0dea10d712676f63ef3e537e63abd2608cb4fbe200e15f18209153496072908044c95a4e9c5356aae8ed5f0959eac091e227a0b81f5803276b3b3bf4b6865a55fc6782f62ea6d63990f9befe01
SIG: 68a91d4f8d241c1defbd5ca9e9e1ed8274419506751c967947b10d50118bbfabc765ffd7b31a0167c4fd8b1175332412df19d8aa1a909590861320923dbcb204
TST: 541
SK: e55b343a0fa1fb747189cb00dbc3a6aa2dcf5b86e57d7693f307420389761153
PK: 23a14460ea983cf997c782eb4582ab3c8aa6dde53325b977b78e33d2dc5f27aa
MSG: 36289b5eaff2a85a7c6d575bd15ea594b2fd8510874a469b52109163696d85b68c5b211d2964efdc66e625abe8aafe4cd9220cdb341107ffa8276ed4b370fe376c1482687167dbc8f7b205a3f3301a1664d9072877d9f98b8f69831301df9994717fc88969242391d9b0517d6efb271701eab3f4a9b1204213e8cd13f9d099048b8207562f2e4ebc653cc65e9d5512d65b41022c79b4eb37298769aeaa6efed69e9a8cb445c7012274de62f509f4e4814adcbf4453b4fab85d7c8fd845e00830ef5b7b1e63c67613984caefe915a548e18e505622cb2b39299f427f4d83983ba2aa00d53bee1f59aec8318c5ea345d294252369792762add3e56fcfa6e7797f028c799479045edb2e205eb6dd6ca04eee56f9496d2bf26099357c973835b9936024911e4655d3e22c811c8d4dbd1b04f78973f077523a389b6f28f6f54216142cb93e33d72b4a5052d27e4911e41e6cec7bebe1b0a5113e6b70b479d2abeedf69b7564e5a573b352d16cec890701bb383d3f6656eda0892f8ccc70940f62dbe528a65e31ac538826c138ac66524e331637ba2d37730358e6c732cff8fee940afd22c39ae381e5d8826739b23fdc1b80aea5a62a2cf0ff1525e446cf31046195051d58503eed1befd793eeae1d5d1b62a5c9845157a095cdc08a1d77ba47e84a5a739980f0f5be7aaec9a215b204b4bb7cb1b386ded58d7aaf7285341907c63336ee3e6ef077ad111b974e7504bd989f566fda1b1b59abaa91c78bb40
SIG: 07266c18650ecf0632e225624ec4c97fc387dc374687a61956dccce72894ee138aabc80cfc90c9eea6dd4c59af4502ee29635a92880786678b14a3931a69f907
TST: 542
SK: 3973038fa2ef6a278d3c1cff9a225669e465a69d0750503de748c002dbf9278a
PK: c75e77c78149d9d2dbc263ddf8ac4d654d1ff455cb1897e1c3ce31b94cfe3210
MSG: 3392e02f3c84661eaf81a5ff04357f212e92361c5c220739d96b4d3d9c22d18df48be6b55126f581601ffe0da63f38e19cbb12726ca0a6aa325567a003a7849d06783992eb9eb92853297d7228dba980b250bb110f63d0b84670e5ecb319cbfd61278f1f4cabf1fcb3f701f12f6ef8d3cc4282fcbe589eb5659503a2ddd8bba38e5eff092dfaf539fd804f21f73a90adf569a00bf9d25a9ad3a63309cc6093142471a478f0b8992286de023c68efd49987ec270bd946f6db48f684f1c2adeee26d68dce95a55e4cb27bc60523080df6ba2b199996b1f1da6920d1559f79bfde9fa1a02deae1480c76f947f9d213fc43bb2880a1b4d03bb14f5b044a0fd83ce0492f49ca3af25211b86faa5735ad7feaf31a1a7491e708b41829d68e32414f68352b71d1cd23c8e12fb02da711484f6ef97528a00d24fcf91d4e06e9badae9a44dbdb3f778041768d863704d736810400e7f2931efb85c8724a593426aa2af1ec5b664f85c2254896fdcf316db0924e11aae8d683e9a021929d0a9d6fecb4594b1b3fbc16b176d29d1efb1819a4a423fbe0ca0559c57e9e5449f14bce91360dafda6a427ce4a0993dd03082ddee066533f6d3bda5660f42fd7757690d670598ec7096f475a01a519950341a831fc9a281c0947a863f1f6e03bba774de77adc23fbe525cae6ccce47a0ec4979e8bec86f332fc6a5736e3b98fb332e9e8244e68a100455e6499ba8dbae98b92ba3d9c6b4ff980343e4c8ef4d5a4aacf8b1a
SIG: fc0c5453839ea99296fffa501d58366628df89f616766942d5040a056056dab18b4405c04abf9059c30868d79c936cccc84c4fbd6fd30b60f8bcbd7a66404202
TST: 543
SK: c71cc10ad2d443e025ad0625686b123503e590193a2bc8cc57a7b9b4158de6cb
PK: fc06acaab53ad08e9762dd11cd2122b31599bd2598ce6f248795e732219c2fc7
MSG: 2e0846536dc6cce19ccf82dc2d0cd21bd4e1ca7bc317067af8d90ee4818c8518bc3ef960ce112a41d2b9979a282ae13d706a005e0034f06b39ff4b0a5afaed70b561bcceb1bbd2ec19f97448eaed4be620e36a962d878c6f80172b9fad43eed07ff93db9b9ca2262d5a3c229c54e30a45e73660892f048e363f37144ed1921f72992b4d01529870cfe373b7e7cbedaf969269fb70aa783d1e74417c7bae0fe03d951fdb8c71c62e9be7fdd5d233e39f46fed057e49b6f34068459148da3d424161ad2c869508602e9c0bb30bfb88acd5f4dfdffd473503cdfedabc4442b743be075e7c6f610e64ffc2e53187745cd719658fc6e62a5be518437c5bd6a4feba94ae3f44f2f29308e831feefed676909ce5e80c84cbdcac47e47d27c9712a01f6bc5daedc02e6414407e911c0a5a53e5328a5a5fd9f040aa7fb70b79b31cd1b6fd9bd5029040bd22ae222fd2f6870d07f435322639cf3193ca5709b882b07a58f952a9963e568f8c5a584a6b9e275c5c07957a4d2cdaa9f1eb444ed1224bac6563b2f9273e80301d44d50ae383b597213b00da5bf27e5d1fe240cc3bb65aa5030d651b6b5b31761d53ce0c6d74a15dad5479f31c915ccf446659853b89a51a28ee8976853553fd2e02fe7243538d00b4ed07d8b8a80b5c165cd46341ffd8163c555702663a4e6ab2952b7e7443d0f6b123b6946721aa63e87b1155eca8a6a1bc9fd25c6762e52742c86bca1ba9d8370415244f0edfdbe0932b5ca0611509c9
SIG: 2eb33bc2d5deb7f3a2dcc377b0c6a862134bf3191ec40fc128ac28abf2316ef1401649b8f4cfa1a936de79b532dc043b6d36024b4c37bba29290ac9f449ba60d
TST: 544
SK: 0a4f5e1670f1e24bfa37b73c994330b36e7daaf930161b78a4a84866ff25e3d5
PK: 9dcbba903981594c7b677ea8002001d664cff7ce8e5cfae58840cf74aff0d3a9
MSG: f4b05b3efdcb1d5c07da950c46565528440bb48835ee4c13f43d7a1618de119ebbb259ea7480a5048174faecc1055b32dc01ac7156344321e8eba698f302ee1643b5f04b8e7ecca63b91561ce3514abe7851b6fb17fc943bdc94da308c8e4769fec20fadf4fa8e7f62b6ffb5f170d644ed29355ebd22cb3aa1486b1e367c729dd3f79bcd40ffd08af28cebc8d776e1a483e911d79bc613e09cc621cadeb034dd6f72374771985127f7a3a1aa786a523ae6e34ee433dc30c375987cff50bdcbc997fcd51c94567a67aefb6ef5edf9bdd65964d464be9ebdfb88c0e231b07ff6405c00f82531e961bfc5ead266bcc08718878cafb1d37536f183e48bf38d3f6be900252d1fb419e6a2ac5896039f63c31401fff932ce9814b085ab20416972a2b351c815a62de509674628b0d3566fc9c2e0a9237b93f9bbb2deedf02bff83bf6d868b6399326d4809d0419f31b2f3a481285b94078b47061ce91dad583dd5b13bd010fb30f2495bb70420183a930159e4db193df6acd124423e039a67f15688aec50c5927fb271822aaa66f294bc805d3bc7c8341878a541009f30da99fcc0085079ce7fc55e0011685562abdb3a9471ffde6176300ef5b31e0df609a54a1ee6624070da99c8776891fdf6aa78b4d55b1f5dadfc061add5af00fd3adedb448c559bfff204068043a5d1d6214748628c3ebc5f0224326ca18ef048425da9300133fb695d4f263165ac22f3619d405af271a71a9afb198bf631241d3459b95398
SIG: dcf353b2b99a4ef45f3fdf6528632e8abdc433342476a8c2b37900404a4e333d387814235757ef7ad03858a0f35d4615e8aba484fd64f1112ec1b1aed2cb640e
TST: 545
SK: b855c81805c7087410e69f96b0240271dc76c1e4ade38c6a9278e3c94fbea256
PK: 6adb025a40260f569884b8cab3752b4f255c373e2b424b6287ebb510fa06fff0
MSG: 85a9bdb70a6c752897e43a91106ee9a99c2ca94ff7b4461a44a39174c17ecd99df46eecd81c3f52513dc9d547dad3721c6d5ee1f8fac0ba5afb3687044739ed535b844008704c09fe1e5d785d4c9c3d0b05889b9c20fc3fd68df12dbeb2c34f6f7ec1c6fb7fa811ff846b5a61fa5fe55379ee63abcd373fed00254ebd06bc8b22f7fbf2f727a5fad88514159e26d78dfdb0957f6efaf51a8e80b585e838b9621d051074a4f5867b4ae2f2ff6d62b85bccec0b4aaa4791637388c0901fd49dcccce7204859f81eefc639fed92280456e69a1509b4b1bd7624447d862c45a0c8b0c5bb2c4ca512cbc037f51b780982b183a5cafa15297585c947a25be8c2240ebfb6868ece5ea2aab2c239c83754c7d594b3725aceef344ba7e6aef49f7f313b0ae82ccacad387a6e9337f05f8c799efe7829b27b4d5b201fd5ae5834351690759f3ea175fd4741be228d807fb54df4a741038faee47edf1f561652598601f27155fc50d9d5011433711c106d4b60785a5cc93b3fdd1dad70c0c8eaa33f1512e35a541745e376c15167fa8f6b3b2c4c3a366fc41497d297357816ae795a804c980e7cbfb0c74d8835d929ae3bb52bab12964566d746bd2c1d132b6233fa34f75e268edee775eb3ce132e6beb2e8d71f0c8762991cde4e26f71439dfa83978f995603861bc0b1d9060bbccaccf86f8745ad96994d5d007d52e83aa5e69412964bdbfbe4780aaa8de41be1298abbe9894c0d57e97fcacc2f9bbd6315d3fcd0eaf82a
SIG: 3caa813273e753542ffbfeb21bc3e2cf8ca7d920faac7c49dc2aa9911768c7ad43b38b0236db27f3eeae0b1206001e665a607078c522ed7a9dc4688534635900
TST: 546
SK: 95b9c8a6ef80ebd5cbd47a04ca54387373df4d67a2b475597765ac89fcf93e93
PK: f2c947b18adc3ea6a23f7abca364b9853ae85a2b0c8c26f0d3173c2732c3c7ff
MSG: 7855bc392630ccf531d3061606ddfc81a0fd9294c54791b5f9559b6827254aa1f25c540b7d7df3ec9cdf14256629dbcf9b725feb3412ebf35f0ef9379e4131cc77e0f0fb6f7459a738361a99ae4ccb2b60a99fe92bd6c3a53d6f454ee9005bcec5aedcfa82347392efcf1175e578396a8d800daba0f4c2cf4d4913b0528620e3baa0f6d86e0628e47c0ca26df3b0c788c4e16557f7fc28df820c12fbb6ffbfecb9829ddb65ef8d63e90d68fc7194b5b885913f08edee84567647ffa3f0d0d325d082600ce71a2345c77d65bd96252003e5c125a718a07370c31b5708075cf1837c6925635cc68dd1b751e40ab608b0d9d8852c18d3069219ef807b76d288f92c29a93e3d75b5b2e53681671d3ae0145ac03ccad3162e44703b0401d3eb167cd8ddc1e1a5a326b728b1e0c00a94d86de61352a661e40897175d28d341e4d1d9962e35f4de18a54017611ad05359ce08b97bfedbfbe3992ed58ed40f517aab01c0fefe8b63643da1a454152730bf99af8740adf98a77b8d73adb08e609e00ce9b1ccdfef3e9a9b05aa56e0bc79b6bbba80dd8e461af7cb202892d89b2d05a4458ab3fa54b474b8f8f581795d6c2739e59d0fe062400bae2d2d534b340bb8e2615777a9a5615bb2cf437ba525e00e7038f22a57882ac520b333e75c3c92a8b9f0e37f671c94b15dd8182a08d7c143e94e9262b3cc5544c294f5f335c2b28ac119fea00f9634db063993988b5f150579c7cc25b6a1fb0dde94804fa6ef66ff79fb9107
SIG: 2c8bf543e2a3e00415ee4f107b2f5a6687176f5d521117759ceb561751bcc77d9b08a6a631f6447cd901de96699aebb168bf97500dc54a0543ef14e4b5a08106
TST: 547
SK: b786ccfb586d43b8c46bb97b96c918731bc2cc119277f123671e30148158d2ed
PK: 90c7004600f3dce409fdeadc8ed018f9ea263f75160a74ab54f4c2399a90ca78
MSG: babf48bd55ea91bd0c93b970241b529d9db43d4927fea5f1a1f7082dd6cb50a52b094b3129fcd903a44fec8bfdb5c86c002a2a452887ca25a60eceb5e1f9f5c93dc59423c7afe747c6bf407cacadeccf5d787970cb0617bb3cfe7fd17563d3a0dc91631f71b84be24ae800113750f031d01fd05364b4f27f86f8dc3ad7407e1ae9e768154e3dde58e867129e2474547b408217964844858d056b31c374991b7f161f52f088b806e0f313d68a15c5401ed55b2b77deea586cb054dcd71af2ab6ab11e84b30c539345de3eb43fb7b3a3b48987c3bfa70655d599f2e31d12ad23cc96e86d380bfda812feff3dd3024292916907022891e119bfc3ed9c25546cd19fc992d8a61e6059ca3ce7802af1118756620b87a7242bd83897c94dd5a36ed40fc0f34c2c93110b37d17dd96a22062590bcdb546742ef7218adccc5ad28f4fce6ecf705835f4113d82ea533903aec8c3820fe4b4715f37e20cebc1e71519aa0b240b4840aa4fdcfb52467fedd8f4d1f9bc33ee114f3ef85f5fdb09ca884af388ad3adf84c793f386efe6ff8a46ed81e5d45a37c25cd80f2d7363f43ae45e3772c0df89f11447939806c096ef933a13944f0890d887c2e5bbb6b12ea950b09b8fe425289377352f35f84cc4dcd4d7a449489fa9251c03113489225809cdf3cb63475f10d341709371c6fd4bb7a949483d1bc2b31ddf4d963a07de7ea5c3fee9a0e33f0769f2faa40612a546974bde0b7339179e4124a447bd42879ccda5c8ad1819c53
SIG: 52ba9658a1a0b3e98ed5209e393e420066a37d3714daa73d5c671d33075a5f5727fe4e081ee0fa3c2133dc953a2da620291371f00ccb57d8792eb596a2ff8101
TST: 548
SK: dd1a9774f7584d8589b19f92ab6939ac485602fe1644cee2f6f3cd60fbd58400
PK: 4bea7d0b0f4bd590f9e3579f0c5fa4cef4d60a49d2c437a0aaead9d43a73d4a3
MSG: e5dc3ed26c1f693cf852465a05e3048b505db5116d9e31592205a9c3d4720bc10b6c20639a0ee2f0e147225b5b19ea511cfba0c21aac10715a2f232f10c2c8aad41112b6b012e75a4155f8c6926253ca2b4ddb7bfe7f86e90a53dbc0cba89e485ceca8fd26e50c7f282a253573cb0a8fa88cc44623e82e8fa2edb6cbc7538ac92c11e4c5b1ea5f68966d15d93c34f396d27572f864382ab76a7be65a557b139766368a207d98bc0c20926370dea27048160363ed85f4099e7cd66d12d0988cfc9e2f16aa565f8f33b39e978c0587371f92db5056317564411bd8a3b6fea09d3487aaf734034918ffed1c9fba7bdec6fe68876fc7360cc5629b92104027fe5759c5ab365354751e7969116c3b9a21b152330a96a9381af730d17822d78ad6ea860006915b5cab447a759372e05d495ebb328e75d248daa02f5d2eb978d2710cf1c5fb824876770e32ca6de2c730564892415bcb53e5981d707add961c5f37fdafa1399af8aea960458d2ca310553f7c9866ccbe8e9d88e08a446872ea66fc308c824514b7dace0334db735e6f14c85b5e619a5d605648a881e876c78dbe0657233d4f7f3bfddf63b445311d6abc476347ec4fb43c8946f9d17c369381d1c564ffcfe2dc7b4726fd57387f0b44db8ef95a0b4e32a7bedf319e53a9e7126c2811f9829d1f4ae9abd9d5f42efef2075f47051c63a4f8202040ec4723686382c6033127c1fbfff4bc82373508752d431dc473f52ddeab0342dc4f5447f8f25738ef65d78556
SIG: 1959bde0a697a63993ec47d158223739fe65871fa05870d7de0d38086591202a51b174d1c6182808c6ce62631d81dba34ebed4af2f29b06c00a57a3cb6663606
TST: 549
SK: 66f5ea8cdb95ee1a75e32467d7c83c59447742c85ddd499c43c08673e149053a
PK: a8ad04b9c144b97fe867374d4fe57d7ec0c249183e43bdfb5d52644e7fbe1df3
MSG: c0d01dceb0a2d17191101879abb093fb077571b521be7b93a117c696c0872f70ea1139ab628329ee5655fc0aa77e8111d2fc884748c1f267b9eb09dc26f57fc402d61ba36f63f4d589aae63c76eeee15bf0f9e2dcde4e4e3e78fc6c29e3a93f3ff0e9a6e0b356645953890debf62dbeaf4905178d4f0a5a592c19294eeba7c21cf8f1bb3f4512187376de72f1136a48ac2dfaf32d0f37de064592592b6e1bc0c512cf4d2d85d16797853a80933b09c2f7bfb9e54a69e51a8e423a91c3e5fdeb4790533e87a4b1c0e0e23a9db9573ac17ab6ec7014d8b7c4486e15725f8d264eea3050e835ae0ac449db334502a6d97358fa859106ad0f6f4295f2344920adf9355a6949d8d145c25628a46a104ca099bd9dde941119c83820cdc2cb2d09722694901043c37cf0ae879be2030d0373158b9c4b0718298be45f630f6fcdc190f7b2926d87655a18bb797ac50757fcd3655c9e41d5163293d9a13d984f591f75b7e4e5cadb64c4c9fdfef76cab69381d0f60b483f804bb3b33364df8cffacb3c9b13ff4c8d8d4ea40766a7d42d8256c6b1c11c191daba1b8ef21593e47b18858ec19d817358678d8548ff1535d5fcf4414b6a11d34a3742f8d7149fa681383a9408887f1c0a98ed521e72793277824d6f746d49b63d444e312e6d9b986611258196a5b012b88faa29f9a6c67ed25df87b2dbf0dbd2dc3080c5b8d15a37d34729098ed0de92d75807429b2cae5d7283c4e5c9bd196d1ad436c7c34f3c9466e5cb3196b443f4b
SIG: ec5c7e8392fa8b61bc829681866e45ac8be4b5b7b6a822c1bcd0f2cc2c8c44c33cf83fa42d43a2f1884141b4a59aaff47f9be07e632e2018759324eac9d14900
TST: 550
SK: ed2558e5c56784bcfb4f4ddea3c0dfbef8d96ff1cabf158ec4abe60aff66999e
PK: 1edc991012ac6f888fa7e6045777e9ba1d4c03c40292d2da6b722b4ad0a3ed74
MSG: 2c6433e9bfbf4cfd4e071f15ce6b129d780a4b3de014fac034e0d44ef772e2c8b0d6a3481d7b3ddeb237632673553313deac1efafe3702a7a4411e12bd341e8d8e96c59c5e30c36807a8385a538e9b66907d6a528400bd9f95eedc5216b28fd7437d8f4a029fdbdc7c938e4eb9812fec05ea693229629ace6acc7af6ba4c238e7722f312f7896b004922f7067ede106f8e70154d783fb41291f3c7e2e4826045b5741bcb4a8838f87a32e0049704e9b53234c224ff898a756e529134c1a9bf50fd029819b2238b60b2aec1128f34d21f9d66983bed398659d808b67a2e501b5a1f25f71f0f0c1eb2fea0ab42d82ff3bc9358bb20c27520c144cf2116f4a49cbc61994d2d710546694c4f602dc406e0b0c27e5f5e64667e95c2ec9df2d6529cf53622ea10b956b345ec55b6c39a1e6ed88ae66e5b457179425d1a849037b07c46cf5f363301095837ce811bff4960bf9cbd15201c1b6740bd70102140744c3327aca9d6d6d154936798ac381fa639db436ee8165667d538a6c74a233c124bf604fdad51984c4170b8200d2df73c29bb1e376affc314dde3e86af9d2c2e6c3a6524d321bce93e21fc965564faf77d0cd1accb4d7629485f564c79f4d8a2fdefb465454028c6dd1428042805370743363bb18476a3f2320db2589c72133cf5e29dafb7d07aa69a9b581bab5a83f403eef917afa14b764c39a13c0c5ea7019d2fdfbd7f3f7d40eb63b2a084da921895fe48f4fd594017f82569b467ab901169eb5da9c40171d5f
SIG: ab9e01166524fd288e5c689e56d730d4983000551030493334a3984e2223dc9f7a5b910c61760c6157990a4c335e348e3a7bc8223e09c10c5e520c8d61aff500
TST: 551
SK: b72798b811e2338431256d2480fe7a3663acecbbe6e6c1b9191e9d9a22447940
PK: ce491daad296b55727b09513df02ba5928a371737cd35841e5f735acab7c5df8
MSG: a5d46298b0790610aedc0970fea2a7075081847266f22f12478b93d7e674c6c517f3c14ed061269d170ac31e2a64f9754a565bac1dd9757322c11132e7bbee5f32818e0e3063ab64e552d09b0fd1757639b9b9d1c770016b677465872b669dd48be038665751674dd2f40a966a26748fd3e5dbfd92265eb936f55b094286c010629904347cb4c526e377470aa96e8169a6f211633807a50030e7ff68e38911b3555e728ed8590b2dc45fea69945cc0c9a3d3e6c954b3e80106a5c91d3d22e89e8c0e1de902058e9cd0f8ce806eac4f893ee0429900fb5487b8fd36dbdcb34f2d54fc6cc74a923951b863da70f1b692bf0438484366cd85eeb880b279f8fca9d3242c558330f1ca57c6a58608cdbc0773e16082bca964ddc40347da8a36b2a9328c2f46609e092fd64b4134eee1d099813e1246489e8ee5b19b3d3b891c28f30b38b6a28ec1d3e9b005dec9c63f8b9813bc1de4aaf995f1779dded15c7a430d70ca46e7cafd4e9a543804446ab0807d64f255e201ef428a474dae8a0a75021b62ad3988ffb81cd8221b243085a0ad046fdc16c67f17b9f81820095953a5b98acbdf93ebcf80bc9c99af5fbffacb61a9251c5aafdb22b1129bfc60c98e0f175263bdf93dc9a08b8efc2e8cdaf0f83d6c49ec901645eac5a4ff63385a6f1af2071897662a372219c9301f545a2ebb8f5917db7f29ca13fc861af38d90c35c03ac9184c122e57b057cde426fd76dca79e25e64dbb41c8414a0450da4905b902ae98d2da4ba792801
SIG: dcfc6fd47799fec772c2099b3c6437246c3ad07229fc740e05311a206b18b02ecdb026c926f49c6552e347fd35dfde06cb639a797c50612f98e2478a92aaf609
TST: 552
SK: 1fe7327ea907d3ff179b117811d30193fcba4c347b90657feed98deeecda9ac9
PK: eef301b16fd7bf3c7b640bf5ee8700ac5a87169eab5f56015b3f499d955e07eb
MSG: 19a832f26fbb0239f0d9d26a2ebded2403c2a406dd1f68318d677afa64f35043316a5efd729783c7f9d18c09824614652091886cc954be9f9312d4586bf36f3035ac703438b0cfe3dec5077813c710d1447561ab6157bc7ad5eab5b0c0afdcc9db77e66fa8071366829c501096c3d3a938218a6e4207109d1eb81f7d88bd6fbb2aefb1adef3594aae57c46b7b984db9468cd962c6184fb976f0e2aa84152deb1c76aea75ae488442943a80ba7d98a28cb864b5e87cdb284ad6e8d7aadc6b75d69d3bd345783b3ebb676ff95d7b4191e599851c9628835c7c01197e7c8f86f9c8fb49fe3e28458ba9b0236219bd46c28df6532496994ac9ba733c0105a02a269a2be8b7cb40074b881602ef9247052de9d637089188bd4c185ccae258a2ae9856a2cbf8451117683ce341f8096e1d91e874c5cb8a4e0939eb77373a9a0eb791645b8f5460472d669d8014681a5e778706cb5566bbd4727d1716b23c620d228b5d4dc2b352b423931f8a7e8fb59edad8ae42458729861a98e0c850a77ed655e7fcfe4fe36f9772df1ac3c643ad31db5630d571df9fcc9c50de7622108411962bbf72defbf49e997059c7311bd9ddd5b338a9851938d37e7a262108a291e2016803bbeff4f9c776125ceb7e7272b51c7c33461d8089f8408d8dda92506d5002084d4f414d8a4d28d3694c88630e31801990d95271cef47aa5c263f97b7daca1788701436329b5bfaf72653c166db087708130c5c0d78cc4e9064f860680271afe4c409853c2fad675
SIG: 9c7fdb53fd606bc7c9c223fe9431e1ad009546d00098812a495197f2541e87f8d6f5da22ecefcbb7da56662a7309d10a6c4a4f7f299278d51bbd11e0cc1b8709
TST: 553
SK: 5f9dcd93fb140610b0e211b39addb1eb87ba97804877afbcc381388cad650845
PK: 182a237d878c581933332b4178b67ec408b3194d44e4e69392ef800b267c2949
MSG: c38b874d3ff010fff1a6613bfa134257b24833cb536de3e74992c3cb01fe3bbdeed97dc3c4596fa44061442bd31a9d4aa8c81e34ad9888718206635509b133b1ba69cb1aa0e75c7a1893c080161d26152acef40f6ef4210e952a49828b5cdde804bcb536cdc349a8e831b4b69d3785a76bd9fb27080565972d0b8fbd16f3f960a6bf3ba0c5b9c404967ec1affe59b8c4ecc650fdde1cb06b70595ad4d325da0fab4c5540a7a8d5ebeacc4e99bd0dc96bde82f2bd7d9586308465e55b1cc388d750486bdd5c7264d54f5614d48726d99e44d7778d9ed0323958ab9858e2b25df2bf994ba3e625e2803b6c6931e7a9926f1e61ed862403ce392ab83b7d1b66085dcc06d82dbf176d016d9f44cdcb5072d004591e92d0459ef05a51b8f54ba17251e16621ebb753e5b1590c02d21e40f4b75eee4602860b9741fbbc0d2e385b8daca83cce68c34a99bde6a60d13ba64347d0a38d64b2ade250f38852c4eda2e2e4f303c3de1a8a9d4ab3300c9e63622879fc8537ffc63b18561fa1fff65531241515a62bb9b08b80af37667a601ae04171793cc83b11adf9c30ca9f4dabc7b401e16a1814cfc750248cc2f77e03f9c4334465ff6a2c83cbb56db4b734751043832c4000972ee3232f929f23337eba5e651e34cbddfe68ba219b632e7acdbd4630a031bf1689fbbc7fbbb210dbf25ee87e2ef2b3cbaf8d9ebd8fc92c3a58d3c05b1385a76c87791d7cd3741b71b6c329de9a9d7508a0c156a9521a9020563099a82b8770ae9a944a7e94
SIG: c1915e052b664797e0d5faadc78f2a009d6fbcfde03f3aaad59b9f4588e7fc3b21990c5208d3d76b4aa95bd934e88d3c98c591930a59de2a056701d9f7577400
TST: 554
SK: 925ebe04c6eac49b26738d6c1300f31fd4828478cbe97dab18bb889642e1e110
PK: cd7231b6eb74e1fe9f926f00d8de2c513d49640525b0795cab893d0c8929e3e0
MSG: e6c0bad23a92ae8b1d85778288157ac6c617c63363341d777870341bb10a8d3dfc89be4f55ad4f64e83bf2499b69fdf72174d2844e6bd289daaa035fec5bf7cf45522119dc7a8c811d79578c5bb0f6d34db507ad1fb6dbfff997b79dacfb3da50a415e350c998c0a02800aa50ffdfe5f4276d8e6bb82ebf047fe48711daf7a893bdc7537bdaedf3dcb4dec5d24586811f59b25b19e83ca61e5592fedc08ca54473cea2ec121baa0e77fb2d9d765657de67980ed57f2f177858b6decf84ff90212d9647f41eed9b9d0ea3d8d621e4bb4041acc5146e96dfcf14ea962d30c8ccb39ea2be958c9b8774451bfeb7ddce716e94923cc85fbd3a3130780e2b3b2bb76da5341912a4e994cafa19bba19732f2ea402d71d3d8a969679b9d104243d9839c69ee9e955e1c60449788d1f4f6651f4bc9b94d73522ec0cf72cacfcf19f1f03ad6232104b55cbb8b5bb1e21344713d482742d6abc5a957174f623b8495272cc1e2b8315e5c80f947f500c83d8544f7cd4f65348949ef4420d7fc831fa4ae2ee18dbba614925ce1d767c177a626c4527a8154b57292186b044cbf92894253b00fd9343f9e697b1412eba43597eb72a669aaa2d77eacb968c20fe19505a38074158621b606f77d97bc6ebe50e7589293db27fc7dfe631a4bee83b22682a77328c36d9d7d1d891d65217cc47864f680dc8b5fd1a01a0f7c34430f77060b691a1ad213d22868e61bbd38f43f0c8b4da68a58318666c099766170c2db766aaf417f556cc9a0a3934e9fcef1
SIG: 2c4d69bed5ad8b9584d849cf3df2bac72282b5f30de266b14f533ca96e9550c4b854c154bdc17aa880cf001a6454ffafaa2e50178de21216ed126b63f77f2d02
TST: 555
SK: 4dd3b478ebdc59472bab14a8cdd0c2fdac5723ee04dd8917c7cfe7a536485c77
PK: 5bccb37e68c234bead49337de208afbaf611811d965859a06d31301247d66acf
MSG: 1cdbd28556ec44e8705afda92bd5a53f95d8fe8b0ffe463373633316c52274c11edcd61551e3199e494dff6d906a739e7b324303fc47827e56def0bdcc46b816017c712305370263babd2c71be478f41ce30b1df63bedd3b2e6a519c53df515852c4137bc1aca49bf4c4631fd6564657d11cd83ea73cc3d0cf9e3b3c3e7ca99b4f12a9c9b67c8798148e0a0dc1ef8bf58642a14f97a572135514c10b19aabec25a9c6b35aa4034a57aae1b6d05bde2b6330f251d78db0993f0ca4c26386e3489a2092833b8acbbc4f4917fd3093df582fff71ece219d3672455582609c0db8d96a70fc8aed6798de54bfb2b3ee6c5d328db163593f58019f38f339fd3753f896a4a2cca8c1400a77ea391935f34e2639c560860810bbbe4be1d16e012c11490aa84f2964c877c293b300f43d379f3eba9af391dee510856a4ddcf76e0a0ae06a6a7c0f9c5e3fa1b8354fe8977b4ea3b20661491fa4613ba62f556d5d5da8213d0121de2c8725df0aae048ac891abbc06bdcef3c3effdf5a31749476f814db9457945f0d91e14080056be921a16aa964a9298221b157594973e32969993310c8707e19f3143abc4fda7c8ad0160acf031aba652801aa81a016b3137039e27d6738d02800a93a86f9f5585c518dfa9e7d8ac727f37437e56d2788386e11653a04e165169f903972a01484751e7cb38632590ec80d5fce4541601a0e095785a9ee8d359edf26b9946e798da5998cbb736f94eb713463f79f561759bbcb4c4ac693cabf2e1e036b2d0b0879a
SIG: 5788e79e843bde9ef11a9dfac970196a567c6308c348e5174b387795046d590a47491fd71d97aeaa78c1615971b83490e8592820f9592ac76269b9d2ba702901
TST: 556
SK: 074d9218c1217e75823c90e010484c2adb88ecccd2bdf0120aa3edffcfcbd4bf
PK: 3735ad1919033d1617b85bda04b16121da1d861b404154fa961d4946e55ecd83
MSG: 6b5aa40e9167bfdb847daa7d2786e28e7533e1d6ac53beb6f69b5953795a2bf59bbf7d141926968f50969bad742a4fb579d3250fb1be4c57ebf4f9112c70cd9f72a00db1c8896fe2b5bda7c7030f497c0b001ea25ba0d447f08c36db8b907c2f2abbbb620d3e8a2c66e4171285adcaadd1c14fe239bc595f098396aa8780ffb80fe1446a07001ec234d82abdcd8100793915b0b3f80d84e20e51eabc797806f3be8108a4f437550b06694050a82931ac40c0a48977edf6ced2428d7cfea8205506de86408065d1a19870fa33a7081037b3ee4491b6e7f3d10b14a30c209159a1c81231a35f0365b47d3e0da04a32c95d98333c44f572cdaaa905d069197f6e861b5dfcdfb9db6c7b0d0cb00f37c916a1c4c0b8985b09f334095e1283edfdd4e62a2941099a2b693696604d994311e3d5f6106683e1d7a1c7e53df7b790947a9a801a0ccd484395f6cbfd9ca4d9804f18d52bb0f946d1a89f97a6fb0680a8c4c057b6062b2b9de7c0374879b8a6a6d2c10aef780508eb28bb569a08350944c82f6ef28db2304db697c3ae1af43a500b0b974803e9f46ea2a02e85ed27dda616d24d6db3cc4f5aed8240b1aea3dcf69dee5f14f95e6e72987bbe6189bc2045f0d783a7b47bfc19830bc7f4e798abe90245fbd43f37c3f036d1cbf1e73dcb1d9daa87379b1106973481a215c1f4f46c1603a5d5cd97b7076f1f5dc789aa6a71e72ef54ed328a4ab64340539ffd164d0ec645f322d1bc37112dc08d8c8079d19d37abb2353f48b5c492f806ed2
SIG: b1f71c3bd1b6bec43337e26dee655a8d5f4a8dad84a51184b775b686fad31d8029e3876927f9576e90c3624875fc0029a5c10a8a0af75d7a880c6844a4a83a00
TST: 557
SK: d2ea2dff7af0ba2a6bed7f6cc68c0df664a6b10ce801c42ed5bbe617bcc8b84a
PK: ab44706344026ed35e21982964f7b4dbbbe207fd27c46799701c19a4d88d1d72
MSG: 03ab5daebc6e70d352977932a03107879bd55dafd0c6ba7ad9697a17b127b3a74a3eaebabd0f8eeebfc0483d63fedde52deb46a3752449c9c4495c51a1c91f57e3ad2e6d01a13d0c470c5291b8e912288340970fbb85787b8b376d72175250e8cd90c07888bfef5ebf5086c8ff2abcdd12d214b9c45d120873b4602e57a6aab0b828d1084dffaa3651ee35662695b7f3433f4ab530c29ac6cc5bb43eccd1b6898b9ef7aec6d5aec68d5c1114bb5df7820966594c994d640891b8f2dc5d25638de43549d86d34306ff3f574575116405b9e8e286ee0cd978a76002c4435feaac6e84eae1654f339a567d8d04fcfa3eb6a04b9adc666021300e9ee5972b3df5d4d0dd4bf7921dc98de82cef2d1b1d61b797fc9968e118484c41342416ddc6adc4ee5d687d94a40ce572f42a2048668c175cf7b1f24c4efd020554fc6f642e14a57baec23e95c2514306d0a6d33648841497eac48eabd96d04731bab08bf5ea9d43e0cf9a37faafa732869d68e7d5fe6954f8a319ef55da1e178e43e84a3b9aa3ad00c29b1d161163df4b79f288e9391d70a2f8813d66622e8ac333fa6aa5311eabec383ba4cc122815de008877efbe6e12c322c975434afad173ebe24203d916d57578bd2bcacc78f6e2564513f8d113a833c2c226eb97ba2e23361a5d02664ab377f964c4300be2d77b62d9240823a09884df307eff3be5664d72d11ad513e1bc5610dbfd1009db39f0cbfe470555ec1b56b871670793d3b704fb06ee950b1ad2a4d7297ca58bbad810c3fad4
SIG: 9abdb9dd2ab77b6f5e1b91ba0b613f5f360efb500d3fe99290ef7ca14bd2b330f405a4f7dcdaef4923d3111d40bf0320353386f634b40de6f04de9190ad51c08
TST: 558
SK: 7a60cdf1870460de8ae7781176d5127e71207faf2f210bd4dc547385b667f2f2
PK: ead67a9cf34d0ff14e79afa46f2dc996e9ac0e3e076322fbb4009767b133f01b
MSG: 9dc023a525d01ba3513798b738c79162926ebccc0adf1e57ac47c20dea6ce1375c3d2aaa1733b7f0c3bd945c335ff3576112bbdc10b6783ba654e8c61047f2773aa229bf846922a89c6a73d5f1051e8d96ed36d7d6747e063a7ac602f19fc52e021a4bbc28b03514fbd51c7b3fd659f12d547d0592dd09f873c9ecc6439c7e931ad0e4856be31c605def2ed9b5d13c5942b2f325397dac6c9760e9b1bb0c06f713cb920c234bccfee9f0b85dd020f7988f3be1cc66e9e51babe2fee237eb84ec7eff9409aa91c194e30db1e065015955de9746bba03f7edf9a587512409a4161fa77ea62ccf431602dcdcf365ed6bf0aeddd32f7c844e3a34d266e28382f4062fd4d6f8214252104d643a9bfd8071716371ccbb54c8cc8db79add65bcbcea0d080d8402803fe232df70f76577247a63d5583bbd5642767bc63f3c5a7bb3a47eb12984e4541f41fdb55869a08fade66c20f69a5a9de25f6b36ba18ace5b4ac336bb2a8ebf630ad03e8bb8731d01e84b91d024d117459a74892e93d53b61e6b8068e4f04b4181f0387b4567ccd45e1b8718a2d7d787872f3dcf87a15935ad7daaa744ed68a28666a51a10d39fc139cdfe9a6873076f7c425009c38faee135e513207b06e7ba35685f5072da34b6045b57cd5d1b1a1fdf017b8aa8ebd27522bc95e47908734e41722a767905c5ecc30c72481b6c12bf4ace94d5bb3a3155691b7075b40ebf5968fdd903d8fd3cc50b8d6464859b10f755132c6d9b6dad1d6f14c4185b264d3497a4e549877fe946e
SIG: b2e08142bdd62b786592c091f5fe6a9b7f30ce134c3b236fbc6dfe6734f88270ac58f6d74b4fd99c22451ca465a42c006db25af215ed241af1189627c6050f00
TST: 559
SK: 3379d25c1117cf802ec79c06575d18e6bece4c7093dd43fdee03685c70b2fa9f
PK: 8525156fe29fc2fbf661ba50182be20c8998d941493d5933dca4d8b41fb442d5
MSG: 7acdb39f1226bd3abffa50350a1497d761f8f0aaefbfbbbb925ff563e38976aa172d407b61ffdfb1cd538a4cd000b57818a0bc92c0e0cd0a5abfcf578300f5f4e6cefa267275d17845da7066fd4e18010027960cd395e682ad71af349bbdad5ebaa0f11a7761e19ea1bef6610743164b17141453b472ae2c8f36ce6b080f1c0745352454ce5aeae11c9d75de3c08004265fc4ca80d33b26eae1400dfd8977bf723a616daeb6d42199010b73e193ab72a58bdd248a7f4111ca50c1de646bfea7b4d5baf0f93dd973ee93649e21ec0c6c4fcca8cd6ff69df761612021d85ff1fb2a95337da4805a76d347ee71ef19c0dffb59f15f650293abb9721053f7406905ae683f96c83a3a7447b1afb14e1208c639f37a9750ba21da5552cc204eac453ca036282f7e0961093c39ec118138dcf71cf2d28fb96a24962b52d3393f880653bcba2c9b9d57b77c522f421fcf5ad75fba9cf3389b123aa97521713fff88467deb8c8991d4b57c1438170537cb50cdcc657e50e5c480e12c0d44939b6399944e7c71e186c2abb81fc57348836d5e57b72b224a6b71b6caf721aca73478cb6cf5fb89071ae3a398202dbb38c30812563bb9a23406657a956d305a3449a60cc8641b62175a7170c23bd5a25f0f12e15a7ed91fada6a4a2f0e7b155a3d6485ec03ce6e34df7e216240bb28a2dd732ff790d2286e200b33c29a31a5e19ad2cd02974badc4bc22deb7504c15241fc1060c8acef4fbb25ec7602fce36a27bb87b6e6423e6b4f6e36fc76d125de6be7aef5a
SIG: 4c36bfc81eef00b9cb3ab514c6d451b993361e09a4be4b5040926feb0e0d9b52f03de468e7bad83f379154bf2c437a71f754f3f40798eeebd62e55f2be771403
TST: 560
SK: ef38c3fc74f054ae43e8d29d6ba6dc80b5af848270d4af58844d24bcf987414e
PK: 0ae1478b05fb329965ea0fa928dcbe81a0bdbb6ff66c811671635e4388888051
MSG: bf290db3dda8763937ae4c83746705327295c2c248068f5ab85c8b5d756f4e3e34062b5549387261476bcbd1e7331990f11910d11f94607c2b71f65b771aacabdc10f42ae918dd2594ac71051c85b330779c47af00a5b98191b56cbcf7efe41a27e87c677168c8abe9496eb2e7abbd0b1604286ed1a1b18d264d733de87d0d3f8055528c4d426d7f8e6ed024a74140abd354007962a2a97a5c2ff976546a8d1ac4924c09223d348ddcd8710a3799f91bb870b3f46d51f1e7f6892d6b08b991748a037a867ecc39ee8d6462a7614488edd3c2ba615ca2e37854889441b13dc835c36b38653f6598616f35783e2e158384bb931c901b703acb3991fb7aa5ba69d9a5bd0570242961a71a52470315e982e341a61c64a619bd16fe8119aae0d7503ce7d7e926146b91c2892f131669d1e39e5b75e9c72452618099a57dc2ee377be65875ee01bb88ed526fc394e2f5c8127a5f69125e67385ef94b1f33ad52629d720e31c02ae0b582339ff0f0bb07ff2b030f48fa7b692716501ad7773ad3151204a2a540fa9436bdd4202a157309ec36cecbe58b33eff557fd33e03fd3eb19009bd7a2dea9efeef8785567aab2a4c98bd1f2a81011b343a9f20c44c577a452fd54ba21029d4706813b2987c76bb242ab2620843c2260b669ad358efee7f9830dc9c7d478a2de4a2cf8c43da770e288e2edbb6d73bcf2ecb023de6b2dcc6b166e87a385eb0adc305665c5bfa57f250fe223ad7ff4518de39c79e87dc101a9faa6821a74442bfcfdf0a9e63a509e2a2e76
SIG: 1d3ac6b6bf18ab5309148799485b276d20401c6af5f9b2f6032395a3c2f4b673b7140c07cc26f4fc56a5ee00b0746b2a80da6fdad17edd114920101d2c89c30e
TST: 561
SK: 7e7b39af69380cf44660e2c1ff308334e8250feeb88be0d43aabe5e68b8ef171
PK: ccef9daed92523533d4a2dab6d2419f6d08604db64ce37e32904ac77b9b4a01c
MSG: d4a3976dbf8320185667b5a8236640f2ebc9e45e6d5f2a8d92997927dd9bc5db95f44634bd654eefece10d99d92b46715791645004accc6d140f32a1c872e54aa9a7493af94588b7bb400d94d458d43292307c5a1a3882a1c8a6a78d9a945f79d64b3294a28c3d59d82022b009cc4d2da93a16b071c9ab8ee9a3663d72ed344f151d68c666a4b49652d97a46d142a4741127f3c57f1551c40976cd1381a82aeae7bc5adb398720eb433f0899487ed2378446b1a8dc6a33fcd4537a05fb603ec0a90a27532300242b2000108621b65ab000bc06381530f690d7e56f81604dacff1910715040410aa1f944c92dd9bbaa5bd08ea00c8442df94f085eb3de97335b6005e6f84f823d43470ab1c67da12ad449936c6b55f9ffd203dfd6e3f33309e8a9945a59320e66734c79c4814dba5a1c14095c62925a1e1733efd94817a25ef9e479dd9ccde6ca8adb7a8053c1b55134697504af8053d595b844640b61e93168075468450eb5de0358697c104afa6a3796a509c26b4c277c23fff42df146de55e95d0d4b80a7aa177d99227ecb2a0594deedebb9cafb1a458aca8072cc7d77c7175f610ca300efd7af9388346498c22991564500e0b0aa4d2946f18e6f5375a848286f36954c1ca22684c6928c2a25c7fe21aba4a7111d7e05bc8d70b3dcb4f6aaec064845eef5525f85024c2570f3b78698c4bcec0d71aad5378d8819e1fac44ee416370212dbaaae54d2af2939b82cbaae7f42ff485d45b3acc21090f5ba41ec0da309e52ef2838d1de471e0b7cf985
SIG: 1062a2dc9cd5379675c04f5e21338dcfb77dfbabcedd62b2607100d7649a05e80871e96123214f80f4f73b0d9b06e2d31f56119cea69da2347da84a275b7b207
TST: 562
SK: a9048af0c20a125f5d39c50f22b805ae742cf64f1fe8dfbe8dfdaa511aaa576f
PK: 158655db94b15ca72983877b6db231a5843df5dbca2810a7e496fb59ab7104ca
MSG: 8eef2d9f5d59709959c924f87c22789767393a155d5c87de488cef50b7bf7da870e3adc300aee6603b2ef08764d99d9e7751e5dce92aaa71aa18a69cc823134e8552d959a0dbb41117e0a593c31833b6ec2172ddafaf7848ddd18d28d0d4ed33237ec804f65938aed8e8a3280d42e353d01be0187b1301f83d89849067b04a9031f7e0f33e3416240c53d9265ed0663959971f417cb5f210cdc5aebcb5e1db7dfb82df435876a6e98f415b0df869f0d8851535375645eef70faec744ee0dc3acbcb040f68d502c2c62c8db45ebe54854a4b36f43feb49a6d1c2c2ea79914a7c23c60baaa67cb47b2178e12dce76b004c87b7b8346efadf380b9e1e41f63148da51781d75cec040e4268820211f3c462501d80899894e79d618de42461d785aeace53ae14b79d33501ed5629bbdd07128156db0725f5b4bed593a952947830384f61df00ee0aa099099c3cd9765a9c1c7e8a6a83430b8d9867c8e17920ad0ff64d8cd2ff5f114388ce6d43eec1715d035f022fa97969e1a5dd9f58d896b17c1221c9e6c8555597235eeda6ec41b0c117612b00c5f0ed1816b057363582707a8aa0d98d4d4be5e8fa32d6c9d278221ef3067b8ba1516d9e051d2f68b7d1b151f74a3534e7812c051e5f2b63b3035f8e5703b5f68fd2d65bb7565e8aa67bfd2a12caf0bc5481197a9ff89d77df7a0e9655ef029b43dd906d0b888e313ae9d1c7e9368a01352d00c6680dd0f1f574a5877348a7ea2c0b9e8e2727510bf0c9ef744f369eb3c6c4fc16adeb6e1945be8287d0f30
SIG: 18a312b20d86ac339a58ef2b852d467c23bb2cb1227cb15338af07fd04b9a711e856ee5b2c82e366c17f861713d1088c1b2144d1c37d05bdc00d739673852000
TST: 563
SK: f8c9183f23105fad0c6e5103358b583288f9ff6c7dfc91106d07987ff69ce1eb
PK: 4c79628c958cde0cc3cf686095b8a2f44b7193c616f51b21b670b038ce6f67ff
MSG: b1d60595323ff3c844874190e1836e4101409cbceae28d5da81fad298fe47f6bdf44745b7cd0d37131c3ec365b92f5a1a69c09fe2d9e81da10cf19d85ff5ff26f9e7db9f0793b25ab26e6a74f44eb8c4f078eb7ad18e65a16210d5c844d3cef75f1daf44eee558f90e524a032b6cae6c8d23367c28ce1c75fc25ac87433977d597533c92ae65f2913a18907ac7d9543df24127743943fefd9cf83ed833f63ec8367233d897bfa12d466d2c4a9ad70d5a672fc10775ea2d204e636de7010788da271df03881a25c8dfa5af73ee559f81b529b35aa127fdc0ee8fd369c7a0436623986aa6407fa67a1420c46f3211ab84f84466dd58bb79508a1feb0a5a5dc3bb0c1b248098262a064f37bb2f019e290c60afaa1206651a2697caacc3ecc02ecfc077f272e8f75cea71c3bc3356d2b5807276f1955001cfe10a61716b4082bd6f84cae4bb0d9a4b75a4b5762f81079f19d7d19eaff8631c924885bd3a64e129f4cf6b79c7a9829665511e9d85c745eb22c1b7cb2a17a49b6285cce37b3de415940328323efe24a1a07ee87468f6510e42dd206fe7f09e3d433fb52156ae348383115648863e45bf6a371b17e70e19f9627d7f0a58b95c6a4788d5fd7862f1612c0347325b797651be30c3e1e60ea4ae60b5745a38b6a9d4eb4935d6f3cb8d71ad3f39adda5e42e2219de0d381909c9cd317dd4379421a2a84268a7ea7180a64c129be1e5e8fcbbf5ed659e9f7e763ce84f630d5407954f9f755750a6dbf9f7660717de8e2adc1e9ac9ee31654d1837cee39795
SIG: c6a8bc7a0d5c6185b6ecd6033e42321d5c871bf889be72bd54cc0083ed60a470b2cc0fb4682c894c75b0df95f1ecfbba2d5acef3e1aafe54b9f7e803a1d0150a
TST: 564
SK: 16089a1b932f8d14995688b48dd841edae3da5cfd2cb16555306f3fe8bd3edb9
PK: 9ecd9fdd7e0b923deff5d887b242585d9d41cd2c7c10f9c345b39f633f4ab903
MSG: 58500232388d9aa4b5faf85b0233247e717fd16840de9bfd0ef86e01e61302775513e224125e0d20420ea949f6c26425f70077911f9711310cd6fd8bff27cdea11480c73e8f8b3c37641e7e8dd8607c1640218fec80a020928b93d4d557ebe82ec0bb17538867d2cb14d44d3ea727fdd52820b0da944de21cd5da303d776fe99cbc2648365e6a0a98d4db150842661768be84c68507a5c45d207840b033537786cb21dadad5fbab9c5cfc1e3547de550d313631dd4fbb7ca8f71938627608d2ebf655db4325abf3ed504dc183058f9de1e449312d904c846a184a028f364c028b27eb4946427e31c21e1051df364d499f477bf51e7a8893183e5ecf77d513a1a76b1a6fdfb16be90d74be4c4345a4f9f87ee441a1022d67ee844789f21b0c31adcc0d95663cdfb40a895b922dce8069b932c802fd3ab1ef0ce6bffdcc5653b1cd5257e19a0951687e545faf4aa66065a55c4b4191e34e8047d6a4ab52d1b06c369a426ca2d16b51a0271f27f8d744c711fce3aad9d4ac038ee700e4e971b21ca489ff2b8c778a3721adf47c1ae5a41b9a27fa742fd0f18164ef3c26b8ae7d1fa29b7c0cc4683be65025c96537a12d5fcebbd05e930c3693ebbba0a78adf59d8a3b598a348eaa9f47caf531fe449652db5b20d68994e35afec2c25709055a1de26082e3912d497c647720a3f873621456e6a5b9eb613acb43b66d47d0b954c69e8fbf2c5e634c486e5724930e0b56a516940c8cb0e775274deff97cbb7759ce90a2b93e9efaa624e6b38a39849dca1df612736f
SIG: 7878ab741ebae2747c7897cbb1d105482f37be2f5f91795232cdfbccc526608918e2756ddb7536b3680c162cf8a1ef38a341b9362bfe5d468b4bce21df234f0f
TST: 565
SK: 94d50915144c7e7dd0f85fef87eddc2206c1569ed1431c8c5a153e32e1cb2fb7
PK: 3bb098cf160f3aec3170b57d6add4f56739270e4b3a8ef7966ec30619b299102
MSG: 4d915f27332dd75051719a24ae8d0e9c30da790999e22d9b587ef20321bee4c07d0a12494ffe599f47f96925f5d92517fc3e5f041d0c709f2a9783125eeca6652997201c429aa6f1ce2f07a0d4a0a18cf20b3e9a4f7663ea5262cad8f949411b05ff5c5edd7b30b217d75d8c86c94e5f92c16734374e8cead61b0b27bb4bf5f43a313c1dd5b83e0ea933b6cadfedd7a64aa5dd5b5d02c695ea20e091fdaa72ef4e7ca40f38395be8bf7a255c6d06a632d7d785d9e047f232aa50fa14529f986f9ef9d7b580a03965b0154788822a225bb5ab3438b89a5c28744ab0bc0b2014e5796acb4935a81b02a04632acb88caa7e39e069c7c8e1758291094a53e362fcedaaa583eca766efebf69b38e8cde9ce58e012c60ec88e8c42beadfa838cfe440fa0c01d659c9634576d7d7a2d3a044f99c6e4263d4c0b374a388a2acf38eff29c777e9daa60d598035a7d9edf67a502c3f573207b119cacac3fa71e2a0207c601cc0dd637ef562bacc35c57042738f1f55815a5268082cd6a508292fa29e34e9645d87a1a2b6e58adb7f4a57fbb53e9213ef3dc873f29396258a1ea546fb5952ce343cee9bbb90c1cda72c65a7c8e40312b328e231920c233077dca34d04f9d89daa9a2f43459165fd102ff5643c7175230b39ec7c3c475650ef131609d3220f5a294a403b1e1c42cfa162cd426f0ae43fd6b7ab547a62b7d5f847403c4e5987953877158cfdee23c04f751c7c86d078e824ca63b5e65543e978b6b0cc689ef664412b01b8ff165e7dbde3c099bf4f34ebddcb4c4
SIG: 59a1ce55f5a6badc1b9391263620542cfcae87a0f2b9502250cfe4bdcbf76c461977c334a48d916edebd56c21ce217c35a6444cfbfd3b11a3d48fa2edb6eb40f
TST: 566
SK: 0d81926f513db4b25dfa1e52b5dca678f828a61c7c913c828247c2eb0422b7d1
PK: 0f32411ef91d4e4b6941dfcaab142ef3bec160983993a5262ccf27fadd2af890
MSG: a93837522f7ec2e93a2e4b4c8b46de926a81ada2d248bcd33b39b6c95fb62a61dbbeda1aa85a21d9b96a08510d8d3a658cf320a10928695999d2c0d605c7f95a12f56a8718507db0f497e3ead613132ab092cbf19d2260358630358d9b26e68d50ddae37c8af0bb7d2741fd2929c21279a78d10e2c5f3c5bf4a42a3617036d54743647765afd8cd910f81b38ced72390630ee68944a37d29c2fecada1cc59ec544075bdbc14c63c6234b884049000c27c73406035604fca8760b49a5e2109ef91285adc4ec48c819d62d948faca90f62cfaef0b07d6fe576d762bfd0eef94cf6b5332c4d422511607f2facc7ac046a59b9617e8383d1029cc91ac592b52084413032be841baa9bf96251a6bda671d4cd4b125da658a4e5a50f4428eebf2614fb0ce5febe80f721a5f4c0325506d27a8d31e33d86253870dd63c08edc7302b280e9b9bdc28beef05c7dcb30d4c162e9be832e1c785e37551218421eec852c4298213b2f27f8f8c706d391b9c69a56db7ce5d81548fca5fed456f2d8afd0b75f79f85868316f4a0921f0c6639926516b3c3e52a9cb22554546ef70e14c77ecbdcd5c0d59a81769b30d5d131f2fb449c996b8de8ac7f8084f8499e1a56f7cd29db6aaefccae8a60e75616a1f702c3bc8deaa1004a8dae0392a59cee54810c6e940eee25fb2e5d573267044b893ffde378fe75ac2613373d84a0ca8187af4a3358e50a994ed03367de645e10390fea4c33bb1a6c0c39858b8db4a69fe894a4223d45af69b36c6117c4dc25de49a63017002ba9ae551ef9
SIG: e0cb6c71ebf8d705e50cad9f0b8cba3ecf4b9e3793400092aa5b121e7dbbc8bea71df29528ca9b47abf87c198a8dc4e14d5180ce932dd2114a3cdaa5552cc205
TST: 567
SK: 6c8c53b56bbcb4c0a25dc40c18240b6a5c7576b89dde45ef13fb158ea17f8ed9
PK: 238e51d6a44fa7ac64268801261ea35b62638a006cc452bddb9f16fc5803060c
MSG: b60df2944ba015759802d3c587bcfebe521a7e77b9985b761c9676454d24a664af0b0d44225a557512e1c1cd7dd8335c8f6adf928e18f89fd5eedf6f411dcdaf996912e8c3e23d1cb95eca4b9e24e7539c3b98bf3d07ec251392096c19ac5374dcba526132b6d9bb8f6c859ce985d584c7bba5b02a81034b6d8b521bd280e50d77daa2b2413ed679834f8161d5d0573bdd476ac3cd0a3a7d8db45334e89c00ab66bc368a07b423e246434636272aa4e4637a5306b2c3397992781f30238de79ec104acc7200defad960883d391443e70efbd22f1cfceec5112fe9e8e13bb941c083468dd71ffca976cd51ce161793110ef00aff5ee2ccb7706a512b85beb94ac49d19afb6333655cf3aea535a6f9c75e034841e763c5a249b4704e1be78b0ecac6802c343c1b7e7b5770de4c93a3a79c46e6835da8ae5db3838e1796b564a480a4f290b60a1c63a725ff3fef434d2a0b3d8931978742b525c83bae6794ae64193794b370c289ba35ed79d37072a8dcfcadb46d5ffaeeba1bfd4f87d766b504e62b4acdd77446e79ba994d6dbf4765ebd74b0365100da56162c36fe5a95077f6b4265e81796b4a57443782970b96cb4569ba985c55fe3a718380bca39f16624f8e47cc63c1b6fa1bde1aeba9c51f94b702b13108cc1481d42e6fa981e3ebfe064d2dca7420c74595792312ae3fb9101d4b66d9916dfd6c13ae883e661c628228be9794cf60345076db26184b617e272298cd4183f27bd52d40510bb015d2097d4cc76e76c0a62bbfdaf53c7268775bbfbdb8870eb9bab
SIG: 4bf1e7d49cd4d5c3c1fd4a4bc48ff6b6e52fd9510a411812296996e4fec56be44514c567d1d33477bd5dc083c3958bd95bfe599c153f21ae26252967b7326003
TST: 568
SK: 69b320fbd4774030a29767a0cc1550d10b749b44d619d41dce1146f7ac80a755
PK: dc508a79c6b8ab866cd117a5a84dd9d931fda450bec29335344d0d219216d65e
MSG: 217e33f88622c96f8d092c9e26664fe9efc0d8d2eb59a036fa464cee65ce4489caf903dce17afafbc4f18dc9bbfd6c1a4be7b83485a6ca947defb1d35125d0773962a344a38b6dca9a40c31c1c4eb2d7f6818f978e573d66b990921b92b777471a4f6f05477ebc353ace1d86b00cc251777aaf6af3aa1179bff78df5048e5ef29968670e535483568d6bb16da829568f81c799b9afd4aad6ef085252c0ce3ac01ac21a9ea69bd58eadc66968f55dee386b653f3334efc398ef3c37a38ce93b21f107cc54dec26f53fee5604eb09a36afe6b665b6324a84c7da7b7dd01d9278e472f15a5ce9ff0fd93d0aa0604dd2df8d5bf6a912734ec51de77f0ce099ba11670210a6a206106b0ede2ded858a6bc411e7613e6f80e1aa52c323e30fa849951cc9b776e4cc58c90cfc8f442df64151a7fd4a3dd61a4336da21d03944635d3fd667be741ef45b1f7cb276d9f4de8107de64582f7917c6eab38e0a8890a4bee48bc92617a361cc7b1d25e089453ce0a52544f868dcb3249de761e79df63efa0794e3c4618c554753ee281c52ac8ad78d5338f0dac360a769381bb4a39f190b887b4723806ac4a4f2ff304bc6f9337ab54c866e6ba51df50c43eab52e2b39794c9917e0c31433f03681d2f1d93a0436018caaae20206a3458ad6c037acb511ef128f6dcd05305f07049a13b6c6c3c5b8170f158c8f12d46e160931ba18bd59ae129ec07a0655fa482ebbd3b850d36b832bbb775f538e3c1b3a43ecf94ca630ca15d502813eed3e35e8fd23d2ab638600427d1597cb29da2a5
SIG: 697d4d897e0e2cc02bc1c2dda57f0dda620b37e861822bb7f1a701935e959ea0d8453f746fb92c087ed65d980eea1d6fdbf23e99b289aae0dcbb128ef836640a
TST: 569
SK: 66da8b254a37067378f68138afedd66496596a0585524c716bde2b3124c3e7d1
PK: 85bde28a922ab5eeaa4a6294521a2ccac0ef2303dcdf8c7fee228fb4552012e7
MSG: 3fae36638837d0edc8dcee517e43c488ed57fa6c9853a745aaedfb109ec1409fb8a2fe51d23e0dd9fbfd94f91c18e6114d808901bf617d2667ceebd205c5c66f5d7534fd2ec33dbfe580ad919f504204eaf242af8700b138cfbe0f372919c06b861a27d720d09df20f4fb7b748e718b0fc486dbdfcb694cb3f1420035ac1be55d31f30f997a043d04708a5c542ee37c0f7fe0b3211d18a87033dcb15c79e6681c4970593d32a13c48f0a3af8bfc136e0f9b56a123b86c4c640b650cb7dee9a89e82aeeee773b5cb032fca41c20c407328bfed29244e46055a83114614d3db56581604b115fba14f618e102a1e16cb036ea69df9275b977a0858118c91a34b9a8519bd0dac3b61434ea088f381ba08bc1583189a4a7c8b6ad18f732d74eff3acef4b6904df58c6469432151372df9327ae71a0f356c94468dcfc2e4a5c0e4ec0b166d90cd465f9260ebd6a7a62ce6c715bcc715be0c7e1f28c4456012d33177a7d4113c9a5a22acfaf2d6b63309078fc1b1baa8f36c7e866c1f972a6500a5eea79201651a7305208b6c93c492bc77cacbc99c9cded179e664a2f4e16938cc26fca8b433eb8012f7b3ad19ba1fb858fe4a00fb3d1f8fd0eddf0c37dcdb2e5d35c2546f22e8c0f8ce90e2df8abf24827a019b2c33fc590bbe712f019287002bc2217c0dc0931dc8ed8f50bb442f8b2de27857362ce5a9fd97f0fd1b2b9251cad2a4aca1a94de2e953902d7228142407443b1d517107648a7bab83074987d0978bc61d419bc84591c969c3d6f4e86fc4738737bc0558755c110a
SIG: 4082a5bc730fb54b6bd0bcd2a044ed5d3d327dc19ceac8825e629b9e6423cb1c614236f097a6b73d473947cb81c4e270852ee5f13a5b03dc18e1c9c27a9a6802
TST: 570
SK: 276548290f3e0f900515dc63366c03fe0fc6ee130c21fb60a4df9cf464797cda
PK: 7e2a3578000a087edcc9e94fde509fc4be05ca0dd090df01ae1121123536f72a
MSG: f0db442de29a7a1ded550d120002cc12abfff98b1f576d65bde16deaba687e4e0b0d5a8748d7503da2969c64d6a7c28d27b6c93ad257ce32ecdaee375f43fff97c432d453f7196c709c3bdfb7388d4d8eaf139f182940ce17b4552e2d20aed5557ba4d2acbf845730c0a66b45b40950baf6a946437af6c9e3b33a79e04dceae57c2a549542eabd216bf13948d41ffb9483fe29801fc8c1782840deeb3fb4da3192785bca13ed0a9eff57d6136bafbf9dec697b832447b2b6e730fa7f9995bac6b7832eaa09905ee49d465a5ee450f52d1a6d364c618144e886e8ef633dc79d0af893d16b3eeda0fefefd8759f2a0da1930170dd19eb78f0d7a7b74515403375a95bdbcce018bc1edb08d897bb798a95e7e86a52af3d9b8a4a14b0371d63498dcb2016248ebd0be800e9f21d549e5e0e7b4895ca5cb725a0cab27da8a8b1299be38a4260900ae10df5baba11ae2bab7179dd8453969429ccc4d416055f2bcb93c1cac6d7e804cf812df1462f22ee9e833a9769e8e677550402c4094df212fd2c5fcc09a72c7ce0077510073090d0e63db637d43d4c21f8619d34da5db08033f686ce8b8a0821222f95434ac4e6f703094edded6fb1b846e979650979d3c77453f40f7fee7c3e88a96fd1d702e81c2a4f3f3753c7964842dfd9d3958a743da063d1d648e51b210a28ed2487f14d5f1bc6f339b2dd17a661c39736da99e4a4f07360342d237e3813ea3998d66eb31a2d708af065c32b927f757c37a800660674e9717ba58f280eb2aa464fa74402108a5d5662e8d0feaf329687a
SIG: 88a146261ad111c80fa4299577e710f6859cf0d1ca80e512a552c725b8384037eecf6465ce97585c9d660a41ab9104e5f7c9b2f8ec6fb21f1ddd50d65b9b660e
TST: 571
SK: 972c0616556ef22c214868fdd822c55739e1f96a93ae83512afda9ca7aa74cd2
PK: 9e1c6d4107f8ab8161c5db5b88a37ca1de9f4e291367abb1efc84f83f7076953
MSG: 8689e2f95c8fd50dc44664a18fb1a9f2c8f3ee73c0f9587ee28bfa35c9231c75bfd3d9534174e5ad3fa9f092f259942a0ff0ba2ca2cb59043d192ca8e3c8869bedd2354cbc5ac782d727c0b69407f68d1326df65a60c4d32f87f19a10f3d765ff923434f5511d134d397c4fef6bb1953abfce60827c359aa4b54f912aa8b17b83dcc7e3bcbc505ba046fe57c16dacf4ee2fad538bc06817c9b9d8dbc5f9d9bbf9f4a934f14a42c29e0e2f3a49f46b20ee76cfe20dea1e97450eb6a8fda048168dd827810207f005a3caa93ca11f4ee608a7a9355494313aec8d7075afc94c7cccc75c2319bb458c0ce373e9d007f753b33b52793d58496b2d25cd1dcd7832aac5ddb38f4db19c427219e1a0420ead47ba95ab6d89c65939041cc734c08eb6b476caf7fc76c598d947ff444b10770f62945ae65044f78098299e2626b638a7328d1b7daa5889e8db94bbff2ded62e14463760227c3f326ed493565ddf0a1761b8e4bb7d2410fa0fdbf35684397eefea95895889a0a9dffc5e02c092383b7ce74d2d90939916f26b71afd265f8bec74f0de247c9643905583df3cee23537d6b568c8338ce5fee42f7dd15dad5247f009acbfd5d769b6366959cd0ae150f58f7c80fa10d989ed90119372e5fea5da48a4e8ea9c727875dc4a2005b0dc2e3f697c0ce0a4bdb2f750c04fbc0c27d02dd8286e54c9c3959b6ffbdb1de2affe9e782651e5168a500afed037b3e1790ddd593851a6a6ccca9fffb4a99e27df43818871536ab04f14a06a1c7cb47bed6241ce7430ad3e640a726752fa06a9
SIG: 54dd06fbb3d7c63f8cdaf783c2d7bac16b4c826e2d1b1807c84e049f64e271b21cfa3e37c344260287805d718806b62c56b47f6d5c508125c9fb5d5ea35fd501
TST: 572
SK: e0405d37893e89f53811d6d446e1f193f51afa1bbba725f95eb48033424a2509
PK: 45104d595e443e8ce654de9d655054bf0a99d35613d77d57454ca2d1c899b517
MSG: df58c4fd0702a20fafa3d1d4fe7d85938b120fc11e8d41b601f0e60e42236a49f126813bd512ee71359061e13eb314d417f56d6d560285fa8991213284c42bc2cef2dc937bdc0b5e9dc2269afab32db30e6849855951cfbc53ecfa01643863e0328995fe850c0db55421bfa564601b8c9db7552c7e6aa7adfa15a58021a84266e9595c65fca4a15fa70f55f5d212c9e277ffb830f4cad1861f3f495a9d672f5691310639c12dcd07e3ef17a23750bcb46b7ad7eac462eb512225f3be7e32f8f4987a11df341166062b43c63ab858a600497667fbb88e93c7e2e0aab41c09c023eb902ec3baf679e25b96e106921a914fd5de200a47889de23e7b65d0ccdf0c29036467a1210c0030309a2d04ec256d5a4d8b97d46a3e15f345b667170803cdacf6cb48add0a13462dd30fa062bd4566641da07d7f61e063686edd96bfe8f97b986b7c0e44249cd2d7317472999b8ee4ea80c902f3b188936712e89d8bf02ce8ae77b6b31abb0632065455ddd9f9d1cd953a4a49aac1a15169e687d4fd3f7c2edfb3aabc3b66155f7d315f8a294faddffdb4951367a0cb870759e85a838af66ba3fc103da2babc3f381696ef8882d85a8278d5fac3a72f16eb119ee9900b1fd986c2a9f94eed8e0d4f273697e4363a975ff6a7b80d5b4ec5355bf63b42b71cd4842401d38b5e00cc97bfda40e456653683bc8e6dade7dcf985a97b0b5776c4d72ca13a1474e4eb2eccfcd428786ddd0246d73a6377a79cb8da720e226c19489bd10cedde74b49fac2cfa207129c6a108aa164be9d809c4d31147360
SIG: 77ddd491ca662ebffb12f7f492d7fbc1a1b447f6c85998f2f7cc9adce67de63b6eebd08117845a0302f7349714ba9db2af58048b85837d7660ec3debeee2d00f
TST: 573
SK: 5756e752dff69e3eed848e4a49c7a8baca12154f9431dec35626ef8d75a44514
PK: 5910ef00a5b354143c46561da62c41aa13d29c18dc6153bf8e502e0114007728
MSG: eb2190a3219c792b6666b2752733ad9f86fc390155c4b438be196959383b25f3a749530d5a4b15ebe2c18d99178e6d45bb4aa2120f95a352e0406c63ac867248d9efba124231064873c82fe995dd031c7cbc7d15ec191fbb6c474dc4c777e8f457841eb4624841c152d15ede26e78479a6a25ffa335563f1064ef09558b910e2608418820f49554b670c6bab34d1d60984dea50ed6a375f45a74beadfb04bd9300bd594e2e20ea5d3052bb7ddc51a949a0047972682ebe66d38aac62927270de42150d58221d03b8ace3589933487bf23d29c5c2c843aefa2e1ca22f9d1680f80c766d143ce5ecef253a745cb71e72f6504ad911f7cb4a819cd074863a92706929a3142f8db7ac164102ac2ca0d2e19a725e1b5f81f443c73e0484f26a45a3aef84f1f3fa04a4ac695d2dab6efba456a281a3973cc186e680a66df521a4d1f9edf4dfb274a427097bf863281cfb0ed80f8d7676638d6cdac937843efbcfce91de1df6c52b594571b9315600e4b6552defb8437a807ba21298e3d972212ba314692917f40075311acd009395241b9f1b256c515735dc674f8e866d1eeb4c328548aee71231c4c9d5bd22e39de88d19fabf49f0b9869cbf835214b15522a93d3a5007b11f0b50e5228d4eebb4571b35da84f4f687e3f43793d54f3825b37a509ea564bdf217ff4adf6847bbea4316a1dbcc7448ecd5363eaabc128decf054ee1a0ee2d871979f8a63b2692b09f6e986a138e7f68f60aa426a1c9b01a4902e13b17bc8312410c28bed29b601b0fc9f3bc2d223f875251100f869c6b5844
SIG: 8157d8334ded1a32699b350ac0d4120028cd8ef8189448934850e50ee4999d8fa2cd257646d92fba5d662a823e62208ab4fbe01714a848a0b90b55adcd246902
TST: 574
SK: b904acb19e5cf872d3640cd18ddf3c0b6657e0117ce659dbf50259015d3fbf32
PK: e04a8aa56d1818483b10d0a7c919e1d5d8001e35510e1ec62f7114dbe81ae0be
MSG: 83f4124d5af955139b1bc5441e97c5fac491b4ea911407e15420a0347ed7fa1f8819e36c8ed5740c99d4505a78b619d560749af50b0573510816d61322cda976a5d4ca3205f5f0e60e759a5df1a0bdf36dfe9717906ac57cbfc970ab43b6fa18e6c0006c84fc7254470a0b774727bf5f8e679423a531e41cb5310f9bcbf5a5445ebc39fbd909ce11e97bc2f66a4a1bb6c2f167f2c6e80eb9b8b72df3e8cfd4e51448dc14c0b837f2949693d1d054c8f95bff7f1e364567d034f2223e1594772a43dcfe0597fd6d133b3f2e96ffc5667dd5928f23ec3c750f845993a34e9776159a6830d6fd9013ee7aeaa1fccd69b96df284704fd08888b15b64e2e90d578c5cfc0f95693f6ab65c6947446a857c029c7ca66080b754c7734b78998abe9b7cc6efd09a4418194d88b34ec6c33af630db81de5b99fe65aac8b73362379119c700d107edfc19f270760468ee8e5f155d9a347e57b5930f327a8d11c6674ddd020f9e7d9b761dba5b83a87302f1833e5abd49526d66391e5bf0e35b4453d630bf7d0adbfe501aef81e6c5938f92cb752f5f14d2806f90ae1546051ccc7f913c5d6a38ff3b7b9a23662ef1f00808edb2fa31ecba5c8d3387e87541cd0616edbf3aaa35a537922861f44cbd9f992b8246d9c64c419881701ab43f7fd464210d802ba656d95c0f24a34599b20b1ec20011485cfcb3186b7bcf69d74581a7a3eed6134c4eecd65574a4320d9c57a849c4e78c8a5ce82505004a54f19d4bdc8223401b34946b7d66e47e63cf9d0f57d0945491384bc6868c4b478690e550021df1
SIG: 9aaf8ac97140d5508d58f5ac82b7fd47e6b1f68a7c78a2ac06f0416ef8e991953f62c47fd5fbc6c1e01bae1c92a33ef52b7efa5f17bb8633bdc1aeebce318f0f
TST: 575
SK: 8a3501b76953603c9033e3bcbf3ec378d257011a6c50b89762d491eaa72c5e0d
PK: 778f2019dcd8dbb86c6737cc8dc190c5a04c50b5bf4588bc29fa2a47af252672
MSG: e609f1224a6a451140cbc0254d432ce5fddd08a8e912f81c412fdfd5182ff6ac2f13c576c8145b15f25b409d853f914409e4e02cefc39d9bef4a2a060498570b2d3a2838c9b0b8e3af4fc37e1915f804a80188585b30b68a3ffb2e960c7320e827d2fe36e6a328cc6e7806348adb0b773b784de529bb6f64751b2105859494fd49db0bc7f62df46b9d7ce676975cc5f43856498436812e04f26fb8b8ab7eba12f1d56722eb82ebfafa4735977a26681cb03fa4bc6951ab9cbdf787e3278f2f57f29e12095f8ca2a178cfa7571337f0274237669f97657d4badb39436d786492580fd55d86be3a0cd17d16057017baaaea00c1e14552159bcabc0e666bad3418e4ec13bfe163be256f0c89bc2344a8ddf99ca8160b189875ad322d90f581325281d5389965c0a7b7bcae2294a3cbe35a4e4e83b54c4276353960fad118532d49b7076f25ad190ab5694914f7108b0ab6969a19128fb0aef00e65a04fc832d07696167b9342b355ec57737ca37cbff3bb31931cb58712a4c468952c6459d567a26e79501e4e31b1b0953537632029e9b490f72e5a6e057ddb4b31756fd9704218b1b8f4dcb5430c025042f47169bfc7c80d71cab8ca07f340afa008abbe2e3a0abe141da8d41ca6bd69d36fdb11a41ce0b72fabc00d97ea605270010b259df8e10dd22dc17c13990a05f0233e3ca856b40971cb3e21c8b3950b13fc84e1f266c2a6fbece88d59725c3cfb2225dbc1ee95b686db704fc937b766f0a9bfe95a42b9010f1229c610d7ede095712c8f0f1fb0047c040a870306cd8dc74c4da51bf
SIG: a8a309ba52125e76a4a61eb43fd4135c41ab11799b91cc54ffc9c6a20f050cc595b28143c874bdb928beed261d9c0f12aa192e6640bfdad54ba0d478426bce09
TST: 576
SK: 42b53652d08b5d766e66ad8f3ebf693cfd77907cadd98b5466df77dfa2c637ad
PK: 88463bb8a4b6388d924cb86209834195435d79d77f8c02f46bbd16d82efe42b3
MSG: 9ee913c74ee3c5e8c90d64b8ae3a60049fc765e176060bcd1cd09f0eda60bf23badb8a1caac3d66ebc5268146ee4a54e1eb231ed25eff95b90a6e98337a540a3f48449794a4873bfc2e84728966bb7c6ff676a2ff57311c1c25e15fbf3d40e9f25ab5db91fddb7a0ae436c8ec070754b6d743aa1d6048fb5bd7f5b8e4ccad20328389530f11374a489b1d50531a39c9b32b40369626006d264a99eec4fac1341f4e74679457b418e6bbfba233f1ca158f7b29d40d50301f9d92536fdc5c23fe5dee4d6df0ebf13dfa3754a14c856009adea1dda409304c1f60d25330fb10957947a00508f2fd76422eac694cc39fa8ae7fcc77a02fd9ee5f910d93e8aac68f145dd878876ba8eda0a49fcb209c34ea220d4d0605546fc4a809baf010d533e45d17b0e16a46e91ea6fec2cdc5a8b3ec5014b25e92d8e5c928ab06993d4fe23ac8d45c890378dd133f00edb937c071f75cfc13a402e3e429a848652a175c9b6f6eac86f6188a4448a96ce2872e5f65f9bdb87166c9b87a7e958e80bb6566e3fcf871190cf4a867e612cfc1e4371d2b73d2a0ad0aa400ba69e66336233b0f3c52b8a68bca05125601255046e6f49d688d2db85c7b821270516e3c0613f3f23f9c57cb4c8714285cdf95e106a3b5afcaeb81b72f343e87bd92f1581dcf9aa90a024fa4a1048059e30de8ff0d16794dcd745d2b2d534c520f8278538674a934c6f14a8428e3da018a36e45aa5827cf4b15284346fd69363149219bb0d1bc927d8d193c482692f97dc88d8ed337d0c9dc99c7a5e111dced42250d580e20692bb7b88
SIG: 30c4b99e68ec3351308fbc76d9caf0af6221b596b7017fe10cc633023ba97f023896fe322baa347660610e05fa493d218fa360f18d93e275d1eff666b63db204
TST: 577
SK: 14cfe00fa7190ae810888ae2bbd0ff6412cf1fd408a308294383a19453b59073
PK: 4e61afe8c174b6ee1a29fa09cf87b4008139f1070bc8531b6d06f54c9562a4f3
MSG: bc66f801daa829858e740293d4d2187b8e1a5afba5fd67b10956c65346aca94429d32e4cfb3584ab0e005d0dd742781d47e89447c4e1d81bf7e6154f8f73af03361ad56ea3c06000754b9f327d4edeacc4d348afb54823e1c9d49cd8ff2b19f42021b40d580c39ce3d243661b85421fec915ba9dd2762f850bd208fdbf20ffaba56a468660f17c00fb1c0f4e8527a509dd4eec13360cf6e3cac542b875182f2a7ce7be0a33302fe26d3629629384e35c06789de634e90e964fbda8cbba98111e22e8d0762684266aab76aeba4a380778696814a1e311943cb3505892640c44e3aac4530c50ac604a8d2ccc7ceabffea4aa3d7f48a66dcd7588b80209dbc173f0c663e8fc87a36e892ec9a3ff8f60d2e0d8704e5b6cbb873275151ad4cc0057165031905039651ca10a95c6fda3b27827a657ef9a5fc3eb5b53cac61ddaf5a41704c878570cbc3c41c475b117c05eab0bb196bcb7c43334debd64b9e37450d23f5c10161ec5ab4fccd7cf308e2a9995cc9e578b85e8285a5208b9efd42af9cf2ac2b3b7464254889a2187317e32499709b913953ad46f1c23e1b6b56f024c4a7d48461192c01c56c54c564791ec0a67b61acbf957e6d0d7da8053ed13a41893d767fc5737cd195553da5d5b07065f47d72a35c42b001eb6dbd0f8e77a4b76a6266192647f4155ea11bd1237ba77c87c62bf4b01149fc58bc28f0b5a286485d3717d323964046218e70c7e38b7d5e74ba6b12b022f18197d92c13bca89335c856cbc5756aa3b64ec1f46e396b1161c871cd2dfded1a4ec9192742937c0704531c7
SIG: f785a46f69bbd099fa011124ba9032c189742c9e001dbb8781d8223345a9569dc144ca694d90245e0e513e88ab023f7f0f99b7416159758dd034e7a89cff3600
TST: 578
SK: ac0f7f0418de67e348fa6d5686c46d21ca72622ee69eaabe00d5c9075a34f179
PK: feabde08f00a2b682bce9d45990bf45afc958339dc44106dad33b2c490ef7090
MSG: e8d0e8325335e0f35a85467beed1e11c6a2078c35ae4a4a10543ede40c1712bc952012d2f8fec105aef7c6c65b3634b4a74b22b498b913507d1f6cfde83858e6830c0af4f464a6899d5c4e279aff36754c21da80a1bbd1dcf46220375b1e112a5a72f1ab6e8f641942f66d9bbdbb179cf0139ea8deb0f4b814f50c513329a1a0e267c4433a233182bc4a2acb2c6d4f00b24094d3bdc0eb81cf37d38260c2107dd9490613d276ee1f72266c6e4acca5249811a0f8a7dae66aedb75c3df4c8ca3cb5d9c567ba541ee5a9140c50587272af34530ab8b08b9ec032eac06039e692630e2d554df77c1a0388b3caaa3be3754a84961fb299e402227158ce363eac26478d479775e5685adbf828bb355e3c89cce241503c15366432ba94cd3cd95479144b636e0de70b3f16d1a3ca518e399009a4c247a7f96367c7146608aacc0014fc35b84af9933f09babb89937abb8ced111891343ddb79f60b78898ab5938f8ba3814bd8002605b1dfd297fa07c475a0d4f8f4451acd707de8af6c0e8818833a3abe5c96d1a8c6c96e2cb63328eba44dd1d34684e412f288e065209d11eb8094d22e4cc802629ccba33926bf1ad36a6285138abee05c5a39a475f3fdd0b3ec8c370cd957a8379ec2cdaf03e895c1ba12b449d6cd8be0f35d99e2b7fbaa92dd54e64e7c35ceb88a71a680527cb373afe14cdd158a0b90bf2daec80d2edbdc3128cd6b63fa532a1c278cdfe0f8ebb4abba5e1a82bc5c3fed15c5795bd9ffb576082cc479fa1b04c5c5afcad269a0f1addfe76042c3a8f1f25377b6cb72ec1614eb6383
SIG: 7591cf8257bead39a1ad3ba1918d518e6724356bf625a573eae501d1af946c13c290cb63156ec9d362726ee50b39fc0a7a2bbd69d4a81b75932a90f8c7ac7d03
TST: 579
SK: b5a7c767936380b3e98751cafd3ea89b388a32cf828b321c5bd0cc8dd85baf00
PK: be7fa65f1f6be51027f8b848db7a8c404961bf1e21a23df23bb8ce05850cdaa1
MSG: 6b67c795d66fac7bac8442a6c0992cb5758843b3e3939e3c276c6e9008da82007677bf9e67e9ac5a1a0f486beac0d856191fae25a127392bed469bc78deb0c4b893f67f1716d83509077e4a1bfd4136d03152dcc3b76d9524940a6064c669fbf51f6b91034b6d5f2898678a13a2470f6641ec802457c0102c3ebf6345c327e741b80644b3a99bf72b59ab8016f35d25188a085750dc060e5a8d524ae213f078f288c7b34bc41f3ce356bf2dafdd2e0db4fb8d7c2c319f9906005971702e49ca62e8050540d4121d242f2eeab1bd134e60bf11b3ec71f7765a97c0e098455e59d2235d6b37e7c9f5b21fa112c3ba39e4ea200614f58dfb3eb7b836f0bec1ddd438d1422450ae7ded1df9d71e5d9bc8fa3b6e6f78446ce7c79d0bcfb1c2d26c6fece68682dffc60a9c6e0ad05f2a09f21d7523251cb0c3d08efbbf8ac16339d717024d676024c1ee3c1f62c5aeab7fff937c57454df7bd96f9844a2a399958418aaa6f1848bebf7bf1292c24eb5cd8ea56340c5beb2688024a6953275be6efd1b71ba8be6eb77f0c65a7c5111b96c4c1f39cb7aaf83fdaae8d148d7a8af40ae9e651919f7ce28c8b2b6e45e4d3d56fdd54d00c2412790cbd6f80e10819e0b8f37c84fa004988adafccbbc21c63d6bf2e732d9dd63bd49b0412b9674e1e88f6142f7f867f1f26891b22430423cec4db91b61c2abc5c8fbd46b8b93596fc5160683136e21129822796eb5ea088e0a7d8121b25572e3ec37743d1ff6d8d1c3536439a10e84a665f2c75ee73cdc6ffac4cc28724469f7970b47507df3e1b14d477aec2bb20
SIG: 60e4d23f1f08fce466c9915dded93256b52b327e5f81fbb31d1d10d321c390366ef001fd759aa9d0a55162d5364d918b48c7327e77cf5358bc4319e325cdd608
TST: 580
SK: e136f398a605d13457848cead07c7286f42e2f28df8c128a3d0bb72b29aacc19
PK: 6aa5045a66f772a571fe3e42d117efcdf6c49591996186012fa98f7c48e0cda7
MSG: d328579de4c5372f3b382c48011b2d4c6029f904f3a33e07d083d7e2b03756af2c4c97a2d66c10ec4154d874792042b646e4aae5101d501bd1bf6f511751d0aaf821cd7c0b3ee6d0d7c690a2777fe16bdc7e49b7da4bbb4cce3b618ee9b6f2e3a19240cdb70733b984b1c940ec66960b728cbb874b80643123722db9dbbe88322008931b1c894ef5d21099e63e7c65007acd61784db4994a2fb40c3efe9c47fad63763dde06fa017a26b82e71b9daabc4ff0f6c79b8ca7ccb4dc2031bef1087367c7086974a00566de41a71e11d993abe433569892b8f75d7637993245c884478abe3f95f44b0a4bbedefef8906b75e0d34020ae536455b0e06f9bfee11ec9b8604bac2cc6ebe08c8fd5f5cccccbc1617b7cf69a3c512e1f0bdb585df5e12743061f7c2053bc37144361c0b35fd39d56b1efaf92c610360193ec20598b82858050a6d99e082bcefdbd5318ee5efb3b260f3276f3c73f9c24ce0cda33c7acc50ca5dd61bdb85d793825f6732a6e330ce672ac44fe6b2b9afe6e2e965c02d2a1fe0b57cb1b317c1d313efdc356492fe896fd149dae51c95ccdbb7d11f7d610e0c6e2fd3e57fcfef1c57c7119a0af6c7821fecdb89d80302b49fad41743f3d2d7a075154b3143e51aeb947d4b5e8b7e4ca86fec3e80bd9a786e4e46ed1e6e9f7e0b635266d9fa097aa9e20f32e3d2772d7c1f008bcdd3f92c7283c57790c3622cbad3ca35803c45c869dc377ff36bd7c0e6f1bb892f7329a6e08df1dbebc81dc7b115f852e36ae5d928725fa7c6fb9f28b0fb394f9e38fd87625c5fa23aaba47054e8cfea
SIG: 75a45c6b9566899829b41ee517b7045a473a4f7a2641439b5d7c5673e00d8f5c066f1291f85deada0502bd16e9709f827d4751f2873862e8219e57746a19a900
TST: 581
SK: 97b6702e246805dbcfc7fa424a8caabcf262d466a05e0dd2d4e7c374d57d5251
PK: a716c3d5ce78f4d9c5bee3447ddaf4881c986efdf667ac8977b4fb69b5a7110a
MSG: eaa86cf76fcb65c6f9fc208ac36f28b200d3b403aca73207461d8d96afa246d7c69d17a7a9bf77f05543563a7d3eca1d4079e22938aba1f6e9e04b49fbc8ed6f63b599730de9979831c02f8cba61e55560d7110d4c6e61679706a7155d5a673c54d16fe4d228c2eca7546faa1339f26d7a0bb4ee339611afdec9a68f5ff5b5d203b600533ad5a3b368c85da11563f098cc26871e7fa99aefd38cc26151db3b0bae38db6a87b6789e5840b10884af511f3ecb3ecbf94ff86fdb905505a8c34b2aa61ff2ec9ec8febd1dfed0965b6fc5b9f8869dc3a47559974a8822996706daefbc6c5bf984ce06b0d32b31cf9d8ad136aed4b052586dce7073b767b234e4a37bebbc393dd2e0f7d155173548c38a1583ef94e0aa84e7fce04fcc9b4e300ad099449a49232abdcf3d1a6e6fcab696f5996f9bd1b9485d074755ac5b4297fee3124c7c03976a40d570beaec2fac992339f885f74d40ed4ac87a4f40cefbc4864f44c3683aa8f1026e2c37aeffcebfdfe24dd0b019c36a79888203004b2ad83e89221f3f636f455bb64e17d1754c7c6dd7fc09a0d65dddded4622fc4f9fba072b45103435e10220a586f15226d2eb377f4064d3ff37cbb4705a1faaf5b348f8c0ef7fd1564d428688f58f3392967cf396a8ff2fd9e7b517b7d6a5ede7440373d8cc1a839900e84d42254283d9699c7ca37e477692a3494008b80444c5cf614cbbc169bfb9296303c645e2ce28d168dc6cbaefae9c73191f57151aa473009d29e1800b10f4c498609ba11520985c78092058696fdbca9c020e2dfb8a043a3de8e452d58cd1ad
SIG: 90005541dcc1d7ab837f4de5393fadd6a92b26a7d93af3f669e0f1bfd621cbd00c8a23056d2da6786557c828a49be1e4021d99311235ac0d4d56eefc7c953605
TST: 582
SK: d1528c1406a6e494a02f635305fa74d745c69327fd31b7d2c2623de2c030ed85
PK: 0cfe369cf93daf6d53ef028ddb9f000443b0972fe2532f83a41ce657c1836ca3
MSG: abb3673f3fa17a33a7aff76eac54e7687c04bc84f766651a8b24ba22947908b04ca459feb98ace7cab1e7433a6a6beffd8d9504e2991daa0644d61b8b2e45448f54df8813f50c418b48f49e1034e851cbec3ef0a1850ef726733afaf68e1a461041651c138d54e4ef78187af9a7342f7128727f903bf4fc5ef3e40c64ec26f892f59add98fe394765aaa7d09cae81b9f699a9dd8bf2e2fe8e1ec78fc884eaa0d2dbdbfb8c168833ee0d21803cc35dc628d7c07e04404fb60e8c490a8dd34edbcbaaf80ccdae3f7d3739e0e897023eeb5b1a8c00a9673c59258240ddd4420650fe5771f7e28cb2399f5e1e02ad0b6432d9b49608fcf0b1c0d7c412a445255b8badc5321c24c1ac92c79a0baccb9deffed02d12f5536cd595dc66083b33a3603a9d16ecea2bf38c4f2aaf570f30d21162b2efd7e4d5ebf1ecae9588eee36dd9d3d8e3be7bc6d4bc2185622f11d1da7c49c93e623ac56fee7e3706db8313cf926be92e5c8a539fd16b0f438da8e51a51f2d27640356124ef7be2f91ffa1796a91b12301934ddef0c7938a7a45f36f53b6322d9c8f9d275e1cd2c0f129f8ab8d74155b5d9e5c15c015b0b00003b2bddfa0bcfcc693a1dfcb4f53daec126d1669f33f39ad05519ef7c5ce40e6f4573c247a32c4a0162831352f6d558ff5836a5317dbc4515b3df269a8ac76d6436f264b64561e7968b5822108487b045c92d6c6142a1c2855b38beebd642565123cc827cb1831199e6f12a7e4236856b94dad738f69d1106e7735d711f7c6a3a3378041fc7a21103bbf866907d4edddafa0e7f1bb5ffd41a60d64
SIG: b8399bc3326cba0a93a42497168bf57f9106ee43d39bf0fc86685199dc6e0a13b9c724ef17e7882af8c2eb70f6c9e42dfa2fbf0c1cb5002b58f1086619733e02
TST: 583
SK: 512340f961f142d1915e85fe4fa0f551f80892e75accce7cd1869e6e2c9e8015
PK: 0ca02604fa87e2c20506251f0792cd2125856f0ab16d663f2811963b1f2d8172
MSG: af37b2c7587a8d5bc895cd357746ab03552a0a561a293dc7164e39b6a1333a920bb6daca6006676e99bb7e928f9ea391e54802a8d31596289fb9bfe30000cf52ebf0c124a5895bce3398c1bf5356be82619b8ddc15a77ca922494bdb04f5c2e1b6e8ff77ae749faf2b8a41d822c17c06dfb7a5f9434d8bd715ec8778e80b81d2e8d06298748690c6555283c98bb9b19b9246667bc41046ff98c2c35d161e1f4d69d254ec5a076f25bd5c7e2c98ca3c09d80833962cf9660287884096eb30c46c54174106af4e2979a112f3e8944eaaf7669c40d5afb91a024abbeb14664e308903e4d26d7009446ee2e830ab5eca0dbbc513fb4e04351df2f6741864fb2371b2502be43dc15fc04431fff5eb8d4b68d72462ae322e57ba2d4adddf15a1902c2113aebd3b5d612917c1bb73e708ad5418e7d45e4b7280fc8896ab80853ff5f8e98f26553fc78e30b3b0d727bf6d064a8f32888768c51ebb61b2c600b4028a77060febbb02eb3d201780e74566c86a34031836bce9eada81e5d0f33960cb2df08aff3c974921fc9b7d3aa7c81e9c671ed6d33e7ae5ed03a5417d7e5cd6faac91b54b8f792f48283c60647de3da816ca9756c5bfe1bb8b5979e575401bda34e9cbc4d77e711d6b73b82da19da473b55e8e72d341b2d8503e48609be0fe291444c283669e5deadeaf52aa8ec48da83f5328cc099fb41f82becdd58d04b1d66203d737bed06cf21c97819ac13ed711ca217a57cf7d80ff082aa1a1cf8fea555cd2e47e4ddab5e3f9941ad4f775f49419dcadb5b004b68caf45b27ef49ba14fb52b09f1b185be9f9c7
SIG: 6bb4d975afaef41ea9ef085a68c568a05da37ef21dad464ed86ac0d4080e7d0129fb023131eca5f7adb2586a18be40562fa2764ca807e670a0596a5c547bc001
TST: 584
SK: b1b636e957574c21a957a45bd195c6f9fe4cc1c57e84134d39b42e1a84329edb
PK: 95e77b15dda47caf69b72888dd69961bacbec3bc75353003e8bff0a43ddf4b7a
MSG: e25d329cad8364d2dec24373e92d9d50fc7abe8fdc3d0b4ee57e1cfa5b7cd58c23be918f05179ba841b61e180034ca7e74d49b0a1a2cebb4be65344c913c46d32652336e6bda4efa3f58730d39a633a14ca3d9a62abb0a7398cc29aff916eeea2e7caac80845562f73d4030f9cab0bf1c6407f5401513ef87fe6dc099dbc5dfc3352911c07af6c523bef4cca78379659e8803f585904ee6ef6fde77366d96d2ccf248a5320d9b8298b2a73363879107a02b47f57213a85203abbca5a4195f8af3e3593ed2fa3504bb76a3e1be24b66d355662932cb67dc88503afaf762bff741ba1cace97ac58bafad5d36c3aa02e0cbe20e5f3dc8092c512eaa9c4943474aad41990076721ad3f53fb08ac22982ed9b15c751a9e23382f6a69c72e6e244e0eb681e6dd228d3774fccb37eb6232f825d169a2ac8b7e18a42cdaa4f2cf05890bb0c598cf8c31f829ef8ca2435bdcceb0e6193ada7841ee692f30aedf88b627311b138ac78b3913e06f7c321cafb39d901dfe17430b1a20bc437a555a578fa31e4b6807954456bd4b04d5d887987bdf04e0f14af3141b24c3a7b9ac75aa32e2fcd2171a12609e15e73094fd09221b4d27090e73219b648bcaabf3807c9280b6c4ad750a468be0e1ad3e6e63016cb5cec3aaddc5689c2955a2a8d5b8984d7c44376fdd94d3f5ff1298f78172b565913704e90e5ac038cb1720e19b080f81b53d6a45d4528530711b63dfe1e4781c24d74aeb2bd8a73fd2a993c5b0891392196ac32c523699960d8b23e01664cf9021d93928050caf97fb985554580e33336a4563247df59ef6cae53
SIG: 763c7d0d46878e5c7ecf7104fc1f2230e46178a27c75f196169c0279edb01c28fcde3b0d5b8635cfe339fb232774b2206dab8a460ce417abf490bbfa785c0205
TST: 585
SK: 10ca413d70eb3db6e337f0f11abc075c95859e825f876176076952d2f1888030
PK: 5028ba38afecc242635f6e353d5f4afd123f860a0425220e966552a057880823
MSG: ea7faf79f6ff5d78a823a754347134f1b3c3e91ce518fdd633feb4f05d125f05cb54336ef560e92deb685112a5ffcd3dfd3964b2758ce4785f6a34bfeb39784f0aee55955aebd12ddda641d05769f74402f706dad201c44c91081c7d7f65e7aa4246de6dc3ed6496d10f4a412060d493bac9aed5be4f6d74229e3c55eb6876e3bb2ed41fa4504b6670dda8c798f6daa280d1aa72021174f6c01aec49b321d87f53acbcadcc4607d5b1e45d63fc481a6d90576c87c1880b2e8ff3e590a96beee1804768c756beb86bf1de8adc408b1b8d666f74ba28630822f92d18b056ae37ce0293ee61b9e80f33ac269671bd62a4059b24f7c1a440807440d5d538a65458adc8158724b25c12127aa0349e55f6e55bc92078fd1ef274c2aa791905766be394a2628f7bbd1a32da5e487446bbefae88fa6cf3f7b499f131fa19313d13b280adca50f77802d17331b381683b5e7edab99473edd31d77443488214135fd6f26445093e9e2aff7d7e892337fdc8779065d4d97d6d673576794958dbfa6c50b1b13ac39607c1e66ef9629761071155fbca6f36eb02ceeae16367feac07476908c847c9a533ef68c94311fa089ff28fbd87809b0d3876b431d9a18b202f9a4049a0577b8177610dd02e5c520eca955e803c3ad4f50976f7c2ea8aa3ee4836a1985df0a4f16ef46981595419897993560af82651c2b494e680b37802e7537ef68a575c34f8588063ee0197206d9a32bb4890e7c216a4d33feca36b549e532fea68556e7540a4fb169d49fc553b2e6700ae42d9a516e68160acf6b270c77ca5ec26e5ad5dc75c2c393e299
SIG: 6aec02dc6bdfcb67f0efc1fd31e23e69e371ab3802505b3201a95dd525417ed1a128db4e182cb37c28f62806667099a8ad480b0ac9e94c2a7d5a0e96e2a7360d
TST: 586
SK: 1f0a10a2cb111917b9a67a2a1f38fb86f8ed52607d1d653a457d7f4718d9a7de
PK: 70c075b2e94c4c02f45e73044f24399741b161feb6f69eab635417282a4a9368
MSG: 4f6a434bd5fc77f0f1b7049c91853ccbd89439962a6078a674b867543b6b7d10552ec1758c5283042bd6b4cea88c9520db04746f089cf3a260fb0f33858efd6f680de5b72d9876324ba590299138f85a76f5be0e05e8859c02b23512559c8beafc9cfe901b283e15d16c792eb03b92880f6ff97aa38eeead3f4fd6c0a9214323aa39a1c16515e30dbd08b833ee40a814a28809c870e1d0a62c37932d5408fc6afc63e79a655c5fe3d4026ef09e0299fbde5ab34fceab14130dc4be007e8e6444d7aaaec62c873df77e8010743c31e8757f1eae9edb5597a1b5d84bd77ae7642e1aca99873a152ffde068a8e4ad9240b903332795e40bb32865e5ce034307a6c9fe339a1c93770df5ca46329f6b09419785cbf2847b0c6832837123853ad952653265c5b5740d194e00f23f9e966791f005f8bf55c388c2be9e21538925f8555e0dbd83be073df765af4940e59a3790b9836bab7909e5676fbf1c2126fe226d781a44330cc01d32830ff8ae00b9792e398c2cbb4fb83a1005c245549a89063fbe06c62a48dac43c5101249994e95e37f24c1d8b3bc673538c46055f800db1c0f956869b6b297d990f44f05b50c7ad6b856f46212858471dd0d39372b0db751573ddb6b5b56ba01e371c78fe58dcd1be53112a6a73da9a6bac75d3c39a1a705a36f640fcfad8cd04077594d59685f6e30de71dfd4a44c4e7c04d6ec7c2e8be12785bb05b29b39151d329f587fdc381c2df0cef73fe0e3fd9208d7ccb6e08d02f42d1feed27561d5e323aa148624e552abe87532de15b7f42c22c98e40525b1747cbd758bfb26fd3eed3b
SIG: a4245aa3395e7bada2bcdf1603147cc5f3f0ba91f40fdad8f6d371c3ebefb4c1501d07875b576f40797806a484c7a3f70569e232b0c99d29ca23a233b68edb0c
TST: 587
SK: 7f05baacf167583cf2fe9562a506991ed987f68ffb71567c7ccce3fcc59b78b0
PK: 0dec3952852b96fd75587e97743f9e41c09fbe6ba981bfceb4ebb8892d986a16
MSG: a27d1eab05150920ded1b1c2578af582b294f7837fe4fb1a3169c25efb70634ba66c7e2991b3e75cc5124826a03e057259b5cb706228780cbc8275c339f8340e402a665032a4ab657827b1c3481f7566d369735b82db7628c022b212730db1e47c9b2d9bc4d81b2342d89c6eafc3e0b6de50d484ccef11238c8e2d240dd595dcef8b2fc57b54ff9a8a74111f61f8a652f20ea012c1ade3e280ecde294c0e35717190162ec6a2265e7e6f3f0704cf8ab1a03e5cc953e2926291ccd4b0590d5c20568f94f9ff0fe2ab78cf9ae2c38bcd491e518f23e9b636f880615fc56078e512d7577e09497c1183453d5081fd4737f280ec5e267c4586b78b70fffdfd730d809df560f2e3772191847bbc3f604fb7f8ca49eed318b5e7d1f2b83a10da0c8594b339b6871a5772dd64168ecc27e240a45c76725e7d55bef37e135e3d9e0e34e36c16e34d77459a552f4074d067a31a3ed2a48cdea4895b10bdf1656f4b7a413c6a088c649fc9d7bc56abf64435491214192a6670cb8b9c917f8e1bc7b2cfce78d28fbc3afc2a50e98213e7e026378e4ea711d151adaaa719beb8974656c10ebc7de46b19ec82951ef46a8c68e7f436e1b3ebedb2d09b0575c9914ead2796b53e0061e212994ac5026aea81ec37c81378f4ccfc467700087968597da38fed52fa48093ae4ba1066c31e3c7d8508095bb45c280120f4aa69a24f3efef1f767985aa1a30e140856f76d1520732878487be53f712dbd7d779e315101588fd7dbdb132f92c27575ac1486f176c790661b0148394e92ffa3ae6f8afb2faa2b7f4fbd0ad91e759a702b3c702b4d
SIG: 0deed2df82acf4529c408a02931f676bec5cb7ade84ebdcd578f70f971382cf311bb83097300456a558bc4c09d8983ff13493fd611eb66c043bf019bad6f3302
TST: 588
SK: d00c216426710d194a3d11cfc90a17a86212e7a0e54baa49b0169e57fff83d61
PK: cfe6ae8903c6c701aa304695c651bfd850331f9ad481633ae370c86d7bd13fb9
MSG: 82f97841b3ba22dd9a4450837ea7bf8d27a9731470cabb0c2078034bf24e4c1a6290c03f4002b86fa09f07b5209f1f53d0ecf4d9e9223bec125a954551fe8bff718f5e264868e207f701194e41de39971fd385f49a4b4adda911eba55259fc6836653273f656f4af60b20664956d4f2135d90d09e9037d5366a0253444e022c7212af5fd4fccd74237d2885338e2fd721522de6763c2549028c623b9cf387d234ab5e7fcbe5a47c685b79e75a57b09574082a02221df64a2e841618087e722a21bac1ba4f0d7d87bdc510aaa8fbd10757f6c029ca820371fc74c3bc50bd898c55d8167f73ada377aecc91629d64c360c2c241c5cb42e3a518c5dabf0f418b2a7f3d82eefd92026d31e8b8160358eae821f730ecafe7ace647bff8741de2f6a131d11c969e9787cfe6a2fab37bf8d1c7f4a2f364d2f1a76ef046c1843e63ec00cf7920ffaae561e7370b719fc16fcebca3cfdfaba43f4f090c46f477303a660ee88dd4e89bf14b9f804b6fd495cb1412753474a056a0d8931cd9ccbd64f8fcc7a3123467c5d47f690679e8871288093734fd6a1326038658156413696594c134d73887f34ee67609ae8ffb3266c16d87f15345a476f72950c158796a88bbb444f1aa809cad875b85fb9151a0e2eef2e00e80d6b7a9ba406c0519effdd94126232fdf6f1e7b9bbc0362aa77516fdf939e7906aab01307128cf824c102c09b929c9b2d7af8f85b7d7f9a838b2aed0c697e8bdfee66ee016bb1bf35eff6b2f7ef4b91b1fc04fac9f116e2edff40f95c15b77c31ee522f3937c7fa0047d6225e0c8e55e278c8103911feab2b7f4
SIG: 15c45c194297e887029f49d8bdf9d610dd8c34799e1e9230269e7a58928938cf396a02cd42205490391e1c64353fb06b9f8e9b818a9a361c204a386995bf3b03
TST: 589
SK: dd123972e628584acc46293b8e4ce2b2dd469cc4ede14ef39521cf08373585b3
PK: 3522f7ae596eedb217035d95395e448dbd6ffbf42585eaeb307026541c78a651
MSG: 2b2857f45280173e2e0ef9d594e6083f1dc7a65492975b837def6cadd8c8545031ee9d68369a9393cc7b792feb98040b21f1eb84665f878537ce412e9db680d29fbd8ffc7731eae91a20b47548996204fb06ad740e78f0fc590b6791dc7a0f2659286cc16d02c5117b565836b4b8738cf40e285c69c50e412911292367352dfdaed9982d0f899a23c0ab51812b3ec678f6882ea427cdc93ab4b24824377054aa25d82246653340078cf11d14a51f0e686d7e018b36741668fce7458d169293361dd16b3debbed19e1bef7c36934e20f33a09ad3e82b53ab4e94c255d041898b97737df99584af14e404058d0c93bcae7bbbc06395a2aefbdefa7b2ed17cebd1513fa390fe9a9b0ce68cecc2b9e129b7a29f49b6d18c28bacd3af39dc39ca972f0e0d06855d57c2b5fcac2f79cb8c05799e4f65734668dad6aa7a43a11856e23b1e732d00e5fe3885b7dad42ec18ac8e096a080f7d55070fdcff607bc0b852d8a080d2a7405d59414695f2eb7fb0aca23c8635742f8ae57f13780316e280872374e6929598d028a33c05d831cdabd029493c3cc859fff1a67d56216f02a2295665365887a350a80afaa0c367a74d3701ae88f59d8a9d3a1dce0cfd2eabe2af5065a1c7fca4aadcf8e51e75612a1371b4dc8ffc0c0b9c4fadb2f081e2e032d96818e55737adde3e1ac121f56cc86fb58a0a582692f62ce58acce17aafec7bcb7e44f839258cd4a851fc01344ee9f1bd03eb94344f4778693c171dd2892b2426a8829ab0cfe33a7d4a36eb4017f7fcfd24134ab8a45f23717cd138aa6000172e37b4064dc9b6d1e1ef3af84971d
SIG: 8965a889d54cd8076d35bc2e12b009d56b0704c894f912a0d1d30720c232fe4404bf3009541e8f3283e89ea86f678afbdf1c21c924b23a52b4ca6d63f48fc203
TST: 590
SK: 3335ea928117cfeefbeeae146003881bdc8889d6580eed1352370820ad1f584f
PK: cb20d4fd7561848013111c3e97617f34181d2e7fbcf1bb2a2cd2e8c1775b8b03
MSG: 0fa7f6a6fca981429b572a6704871bed140dab93ee1992006e9a3bb2e6cc9a09d4c9cf17066b32ff7ef5b6b2e7911178ed7462c4c175603171ca613668b3be193d94c3521e588913b5948b550be99d82d966197d710acfd95914cf3e197536e83e68230dc3d67e67dcdbdee04f0d9c480237ecd28f74338db5f3f697d3d07ff33613bbce542acc9a7fed5d12490b9bfe1d109540f863800dd356da841a45a3cd8a08a945bfa3aa98e1712312c4c0f0d9dd64f6efcf736bd97deafca9dcaa3f06d87f2ed72aeb6a94f3280000c4bf728a01c1862dafd9fc5c7d5a46ec7d3a87af59a11d87f7ff84407d37010e1d946cf225d6b3b1edee2e8bbf1e079e47fb1f66669394fbf2fa68fc56fc89820a6809c251dd62f5b865c547b14fbd3a19504244ffbc7e5240f88d4360f9cacaaf5f82433d3344fcaee0acdeb7beb9c0b3c769eac920ef4f09abc2a2095512045943eccc53b1c03ed24e567f3d7a71977cab9840ce898ee58ed5c73f6adea823394c5c8e3658a6bf5acbbf0055992c312c26c79c5cfbea3860b8764a6d8ffe4491f8a5b8a215e0117a9a68164aee25f8c0bb381195b2400bcb4644ebce1cde5a9a26582cab9dc7f43c33eae350db65aa7dd22a079bdddcf56d848deb0cfa50b3bd732d9da9e8d8ab79e93469de5802b6dff5ac2aa8482bb0b036d8f9d595b8ead94bb8d7418e2ea43192efcbfc05c467bde0a868a516a7c14a889b72c5b73e7d85c2bae902e4e68d1f3ceab2b2773af5bbaee6a00d08063e7833cd4e295347e58f5d1b3397f640c159cc60a674a227b4cd8c10f1dbaed516ccacdd295f11b08147
SIG: f7c39f9247d22f018999247f0e0005cd63076ccf2fee4163421f86407a41698c405816647351c04e93b54415b62fc03fc8c25e20f7541dab03197dc900b29c0c
TST: 591
SK: 32a1883eff57a3a7ecdb310221ee83c4de92b722159613ecf816e382437b60b9
PK: 82dd1a03e5852062ba4a8b6b3b93c5e9c43ff6995bd2aac72606fac85802c682
MSG: ed2b123b5dd7f5e718e026c79cfa6111924902d189a406ef2b2e56a9ee5573a76ddd1d0629ebcdecf2aaa74e84fcd0208f14eea2e171e7c8608b818feff4dbea52db354227d023250b1f01cb4cc8c52132a98d4acf55a54fee81e094aed66fa0d6b6a200b6b87414402278538b90529a8c603d927eddda97bc4b8cb95d04b5337fa22ceafc8b340c46fef67198d1fd98d89c65cd089e23f53dbdca967798b5cd923205ad511edf706f1225f4648c985e009ef8a2f6a0117cdbe14e75312d8ac1f03d046b37cdee7d69c0f25ccf18145a688a8b3ca8875fe8d90baf86d43969e4d610214f1ac5dbba87a1ef10377e40d7806fd9d23457fc9df29899239fd1d278849681a943ad9c91fd1bbd92b73cb177a878f9059ee07af7a8731613e33d59df3d97796079d5631ed85eb2245106a5ff6a2bca40df5c6e87473b2c08c2212f56fc2933a969a3c958d37c5343ba2760c813a7a5165d231c5feaae62b755df49feca80041a6535f7e03bc48e5f27f9be26ef53673eb7c37a2b64744a6cf17e887734ae010bf40eea03cda212f512fba0585947179640bcc4544b8deb4ead129bc3322800adf98818f99574befd9b0016d4eec81a8e78dc3a2af13cab01649ae2e33d516b9d4208ad6613d8e278c393baa882340ef461ff4f94423d55cf3cedd2a6b56e88365531dd29d68273adbfe369402e6a7cee053da1f100540091a00929252983449024b1c3391110650082f0e7dfddb8edc2042f3c1713c6944ba514ee7407d32bf06c858efec42a78bee97746e5b4879141a13d9fc5cb123b783273b84d57ad3526b7da3c68b839efd23f5f
SIG: 8309cbe72f804bd9521def5dad4d8bc13886b1d4f662c9bb5b97ba4790f44b801f3195ead0d4ddb660818ecbf9a683cacf85f1dcc9e82c09116d733658091a00
TST: 592
SK: 22ecef6dabe58c0669b804664973e457c05e4777f781c52522af76b95481a914
PK: d4784010ef0403eddc5a62d5d45bb243b80b4b9d69c39ca387c6f5cba028640f
MSG: c535c13d779fc0985973d6bcd552d81734e92bdf10994b00cd4d53ce365fad8c7cfa96206adb62d4567be5e46631323853e38ce4bdc16d7b8f632a3ad9e02619eff37174eac3f0bf2f7a7517d4b82de6aa1af0063819d5e1f9278fb4f24c8cc002afb15f334c04fadb00303013c01667f4932a6c4b97d39cd4a4598506c0bd740ea9f11696357d7d17fe4d75f9d74241a7af71f9d869ef6cd695687c03fc34ad65a68a4888a1a74126cb55cf7da9cb4a6717f6eb88484089d2c5189ae381f25e7b3bc3b23d0c9d9f9cdbbeecfd1e72a05e67bb483a9764d9fc75ad69e4ab1270fb40f3958fea4da559b43980b24681313e8591e68546a3bf76ee34b339709295a8d46fb2432dda2f221812df692895e67cb29cbf6ff4502b439a4e9e43639ec067bc90ae814a293a7bd46968e656787642300a0ff2697e3313f6a418d3d12a5f7c51a4c57b63385f2d2a21d5d1d763fc8d1b93c13435f9e47ee7a425980a6ae6f1a9d007607476783c6d0c7887380f868c65b382d4cc8c04478bbd79a1d9a964b78171d6bcf0b8eec50a06a4ea234d1c23465d3e75b88bc540dade74ed42675b07f7cf078211e907f86d0dc4b978623d9f08738af928695e542ec2980e55a1de49e25247fa0a09678118e3930bc4d24b3214d6dcfb6ebdf4906c928deb37bb9ba29c8de1bb9418db718b2853ba57ad8cae4677addfd18b6c7e8c242621b35c7f0efe8dd5eb26ff75fd5748b1d783f6d68a7d9d56da2c1a978ac25f84fbb2be5568d91e70938221c102aee60409bcbec0c82e12ddb425eeb6ecd11551ecd1d33ddae871ae0c8f24d0d18018732b5e0e
SIG: 5d0d2af678b3d1b677516d08a79aafd36ec67c14caf5bcdaaeaacc51a14fb805cf2904e8721db271b20df709bee1a4fbfe62565073b2a7e942724461f927930d
TST: 593
SK: 8de86330b256095e1114b6529bedce182c166f67a91539cebc4bec25add7a4a9
PK: 33cb054b55bb790ac0f3afdd9a6e7c050efe9006c24f60b8044fd08a5c106c11
MSG: 39e61e0eccec929c87b8b22d4fd18aeabf42e9ce7b015f2a8cac92a52448a42fed4cbadc085bbb4c03712ae72cfcb800b978350669b0990084f2dab76eca606d1a49fc55c529e1e7dadf39122dd5bd733893858b0523ef62df4f134cf6c26eed02fdbcb30ce474b1ada3f060769f934bbe686ccebd60883ecec9ce3ffb8ac4a0678cdc5b005ae3dba7e4fe8bc045739957d849f69c1474057b428c5425f3cc2516e8bbe3be81afd4e7b575abe88c87f2f03b56f69f9e3b61b3788120daa495ef0e50eb970a645c13d213c7cfb7d0ad555c920a1e5dbcb46797d939fe0401f547bfd17543221a53010de01f25b64519c8f03963e4b9ca58b0113627c05b9608eeaa7b9ae6305c96188160000ee3a7ade96e0b4bde9d0ed6a0ced765d786840a48175a6e090a38af6adeaa1486a9cb5c8c8c9223ee0ae4c6c02691a3547e32582a5b7059d2ee66fa9cd965615c315b476fd861279cd1dd7607743fc5561296312f11e465ca40bce3cf0b1f1d5a30af6087de4de96ce43965a46c4fcca15f281149b5c1a0c88fdbf27409a134ed4f1fb730fa191816ea784d986cc9ec4b694402de1dcca9ccc64fbd07b07e54e931de827a842460ca0bf6b04ebb571fa77787e3884be22f1e402cf2b8a96a5d39770ec4a843036142a0be970bb1ab165a6374dcf43deb8b9830b2c49db9cdfe4b5242e36f95e0c3e077e8d238fa6a8ac0d586bf61b8248fb3a79a270ab22be8a9da055ff3d5bb2d1ca9bc25f7014b96407719de344c3e73b8c114f792075a5c22fdd416154d3494ec3f02fb112ee5737f70704c1b6b07eacbf94562ca7b90dd84d98c3edf
SIG: 6d01d237dd2bb4188d29bfdec387976a71be7adfbf9e23639b216d0aa0c11932235edccb3b42adcdb6291a0d299aed648de8b1957949b9d1cf2e50493030a40f
TST: 594
SK: bab5fa49187da1cab1d291900019e6cbafeccd27bf7ecbf1262a700516e7c29f
PK: f6fb1985ec591f69e3bac807b2eabf263990cdfa09b17809e48e385da065ec21
MSG: 5cf8ff587e52cccd2984f34791ee6843e77017c3b55ad45c44450965b75d836e78fbd7a1d1729eff6d6d340a903f3cf17d9e2aecaaff2a321fcdde0abcfbbcbcc09f4086f812c46efb01b78343afbe48309f917478455f32000c6a69f79fe211b99f037f5956d72275a7fe7b45296b5f739aa451ff0575bc705885aa5631b0d0850bc2b12c4192435ae5d2f52bc54386497c4a24b8b6db516be09d8ccf1eca785bde97e9be1ac064f094e2afcc307c0e06b4c564cd9a9a95305b37b81f434611dca55caaa031e88495d5dc5a04ff5fafdf0a82a0c03aff1bfbf4ffebae71824e35e751b09270007669860b580035659e23ace76b3b369fa306f2bed95799fafabc2e69c141beb0bacac7eaa347e77be5af3fcdbe7b364a7f9a66d5e17a07df6202fd98c14bfee2ca6f0745651f0c8550f9ffffcafb96ffb3f103e652e78f53916cd6f1dd05b3fe99b34201b07eac2652f5253571fd3822c695d265c7dfdd6c6b14a80b6e87183e6e032e5f2401cd238cdd3769bb6e390823438f5673ea9a479e5c63fe07a07f4e14f57757c4d7d22b35d71c44eaad4873c8eca6f6b21dcfa95520ff9614abf7a0e1885309f2ced3bcdfc319363a2da46ded79a5cc7b6f69383f94ab35c250629cb915d667b6281186754895803e4b95e7418289a6ac3bcdb6e1e7f6f1dc38e77d281914cc404f97cff14fb2c4fd81412d101c1bfb368ce59311e892a8b9cdca86936f3bca7ec79163eddf1cee68f49f1ebaa27ec50f490d61601ca35f8d6ed266054aeb9b199f933bffd6e0050f261b4e13d5ebfe2caa6557c32ddeaeebc2a11f0aa233240da1c7e40f76
SIG: e316038d6aa15b1c1b61c1a16b36904fe8a289c8d602becc514d99220086b267859f5bf6e9c0863559ac623a56d7532344e8d2f28b3f9df92089708b1b059008
TST: 595
SK: 74ca122ab60de50cdc04a8e2eda45d9631061bf187d316be5b7cc06f020c483e
PK: 787defd4fb24a399bd2a4e76dff7d603ed0acb3269813e4df690bbf5b2bc696e
MSG: a80b46079fa775f8c1a19fa0829be666bdfdca079cad43d70e0842183bc0db95468a539f0db2aea3ab9c7073b45d228a9bde232897a6eb6fc9edf7365e7101ba97c446a519a3649cf527c8a6de7251b92806815ac2fa0082eff75e2582cbca7e1e4da2a446ea233e7cf7cedfb0e2398eb6e11bbaefe3f7ec89f5d73dd34bd47fbcb4d7b22f2aaee373785651841135cd8661a701b21084a316deac3074e24a2e35a0330f7d1479b932f285277c18a441787224fbbe46c62e834a1851ed237998d48dce20ba114d11e941be29d56d02f7370c8f6d6d7e50248dcd8ec89d3b22f4f58778129fafd4bb92ede17714bf022a5bf92be479f18e63852ecdcf8c4211f530dd30f79cbf4bfa5737f0bad3b0106067f41327c3189e6f206f0d4f3c704bf2bd0b161f018fd21cddfb418bac4d52ef02c41c8792e413b04f0836cea1f86c92e5d5703bee2b5c5899e285992024f64e0d16c60ad0fd92547932d0c5cb98d8da22feebdbba8d1de1e7e9bb219a92eb6c1c698d3b33a37f9b8197d26b550febd2601e7a643ea7e1d9e448ae037f629a306ce417aeb79f2e3ca44d8db3848a811f1846811cbcb874f8af09e0fd0173cf175f304115476bf2c6c2d2f332eba534f46aae801c2692c2d2faddfeacc0f1dace440abc2ae5e5a49d578fd7f9de2a841ad6b6769c32b144ceea16d0f3c0cb3a8ee694c38c28073595096c813762cc2c5ec4b0d8d723dd660853278fc72fd6bd9d1272933dd2a38ed9d04b1390ffe4b294a6fffa721ee3bba33a03a149c4a0345265c01ce015e94db419cff7049852ee000048a85758f6d7b1c59c5089ee018ed09b52
SIG: bcb4b850696011997eb5dfe143f1a3d5628ef1a5407691ee48c79d69abe4d533f817ad7313b5795e46e595f3ae3a9165b1b6fddae86164ffcba376249837f609
TST: 596
SK: 65eea9ffb75612bde1d9ba3ea4fb5eda0aa6f2556ab15bf1817cee3b95bbba12
PK: 5b3936dc749b6b9239f15798accafd884c3659ee01b2d17d74fc7da78274e7e6
MSG: c06936323ce3253cac5ab4f6b83270cd4cfe85d0bf8bac1e1b8d5f0b153f541c8e8ed95f28d5c85a2315cd931b7cf3edae50f92830599162804b1363d3ac0da0abd09751023bddc16288944e616d21d91271978bb782d3ebed7fa61284c7490d27593ca8a3d5b475623307010abc1fbf793a816aaab5e0924dec79d60498965cf7f80ab59fc029f782166755b72b869075434ab606cc870a7c0bc8bf29aee033fa9cc122ed7c8e069b547dbae25901b9e249b41fea0bf8daf3826866bcaed2753b5e91ae937e717b508a0acf4c3b061ff0cb9cfd380e2494500951a662fd4928fc5fcaf6c18e84b1d378e49bd9d59686d087ebd552d07fa9ba816fa5402ca9e7252a648d106cfe6c431cc2a053e2294637cdb99d96abe689edabc5ca070f77c1ecd1d52d5385289f17ced768c3971671b9c0b2f855b8461c1e746c7b38f77896b85afbbedd08375fe922984614dd849fe2cb89ae7149dcd1d37f4936e67b1440be72e009398be6f083bf9611480b592fe2f0118e253db5d2e9e4b4541c11da00f7161a736e5f0bb934208e3ef4e0b9a52258203f060d18a195159e5e268aa28053c834f7bd5db9bd71f507d91370b3ffcabbd4acb3071d3f6d52c349acf35095348cebf5a86f8c59ddc965eff610ac425804c0e2f6be42853f5b46434a2c31d9ac99539bfdc04ecf2fefd04598fa63c139ff6c6d88410e73bd328cc4349ab4bb86f2e2ed7c73de96520ef7730ef38345e0f972a84c5388103687e68c50f9d8c9af903bc632d43204062a4f502e214c07059c2cbef72a54110dbf73e425402d17e978ec199b518cec0310bfbf7d9ad300434a4a
SIG: baa7113155358c924fed57488a6567f8723850a9f5c03a0d7de85fccd8fb4d17d7753523b00c0d8adb884dc0c8a7a44dc2a60083aa5b3c5b94a8d880f2a94d09
TST: 597
SK: 08dabd4e5c119ea907ce45f0a7af9e62c0c3f1c9ec61ad10567d79362854c557
PK: 945406b85d7b32e0b1ab1200b94222de1aaa68624c60bb4716b0bce9df005771
MSG: 6c4719a5a2a6894835c4ac1ed69159e5ebb5692ad8eaada439f79e96684b36cecfb44b89015631663e0644f6c7ab713989d742da27427253318a52432dfab2121d1e9233ead719e2c86a6be07363d002173f205446ca95fc17b24635827fe315f222408e45e833f29ff08ff31dac583a4bec7076d5cc78cfc94451cbf4f7e2fc5b5ed8070f4ef808be1d8a680ecdff59010f39b1de80bef1719f1e218e0ce0a1e393a566c51764d2370d95a61191d8f7af740dc208fa7831b210670512cd73766e609e9b780021ebb20cc8790d8da5f10f5b6a114a1db88f66766501802d9c366ea3fa6f1b1e1e8b0420943413cc6feab28c6b683cd2b333069c8951bc45e8a13bd522578351c882f7c342fe4331b921f533c92ec04a49b292bc569ddcefcab5727f9b5625b167a902dc896d8bc7d8e99920f5db8dd767839c43e3cdf947080dec954214a6fbbe0487a2f32cd17a6b000370bd414484fb73c510ea0124c6cf0fe56c0846a79bfc59779d3b07a1bd2c7fb7e2d0039f0bd21c8a308fb0f58fdbf94efa0857ac3bdddd86d5763e205ee1b221f060cedb8bc05f031b606cc74dadc5db04232748865a73d6ccddb4d5e930d528348c5be9088bfe34458487a67b19a18eca25c0d3fbe2195eb91707b65d9161ea93eddd64a634b23280195fdb0d1388f6998e1858a45b886999b844e6795d83d31837e4411f71699226de1ba0245608000dcf223dd18359b7c6d459a65dbe66c90f5cb8c09122187a3046a16dd179c3f4373e57cf5ee0eab6a212cc9ed8b54bf37f1d27fbd79848e4ec1f567243ab8740a05149d9602eada920a46d610d3cc823b56498
SIG: 33adbfcd4ed4fa67c58b5cb59e16987148697812660b3531ff6a21c749b9601660baeee2489b82b4cde132b6e62f2f90d8f9927860aaad25281d03eb17a9520f
TST: 598
SK: e0f7d00824c5f3701e5517a4abc13e2f2c0b138c836977843bbd1eeffabd968a
PK: 52fddae3e018a68473b3168d0764cfe274dcc834c90a91fb4fe74b939dd238b1
MSG: b39e3ac75a221adcced09a8591ac5e2fe15dfed5b919cbaf14c65eb7cd93086ddee3f7472547e66ddc70062b976297d1a3c170ee525c9c53ba93a4c4fdb23572b7ca6ed13853e70db1d72edeb9944bbc354a520e77ae591f318092efd5e66d9c0981c4a4bda98aa4e59045ff9c4b4ca3acb2ffd893201c70b34a77f24eda54549dc84ad134a35532553815888ae3dd9e241ec4ebbff86f8c1e8adbaac4b91afd18228cbbd5dd805acabf0a1e290ce5dda0251adfb37cb714c139b5a3242d88c64484a37655cc8fcbecffa97fbd14d64d512bf8f6305f89c50922de541692158fb547fd539f1e5877cc649495166332ea2b685cfa3f602019df2ab2c25ed96b68745e9ae89c948da11ad8a830df8b00f2e668192dadf2c5620d35c6e81a2853f841e375a0d9fca2d296efce2ac38d40b030b57560ae6e8341339b3d3c2d061164124319598688fca618fc64c9e8f5f831097a053af19d7dbd61218d926742c2e9a42a79cc1b148912722d8cd5ca793a1ad73b5f141b41809c2fc0530b7630e80390c6b338c71868dacc59bf463ffc489016bf67f9c9d5553c1ede17152813fe0b264b65dca1b2b38e4b809f8c9725ac5b1d8d2e56bec9649fe55c7583ff23b043d6f3768628f1f0516337824a5a56b409520a6a6cb77e4f5fc20b9f6899e00ab22db10d182f09b81e94f3ad568a0b81244df3f1855c6ef222a41a51b62a4649bb82690ab65facac0d81d6fe02601170a8db62cbc5ec9955d7711a1c39656a9f6e1fb6bc183d9bea1503531f17362768bb841f9d21f13a2c991e55dff7f2b336e29eb29507638bdcad7bb31c69e909207ebabcc653ff
SIG: ccdfe18ad6d0b65d086d632f83cc46ff3b3f2c07bb8e769d0fb4e82df8a3873f9aee35fdd18a5783603180a95c9f74ced9db5146afcfbbdd40df29e04201200c
TST: 599
SK: 6acd939e422226cc5443d4aabf58c11af650cb40b9648b4da38b927bff9a58db
PK: 4c0b91756b9e206f7863b155ffc5509bb52477ceacd01ca011435153678646cc
MSG: 8250d531cf2b66aac2b378d54bc57fd329ad5a414a599255898b3c3b45bf9c0d2c77547566b660eecc76a695a2d608abf11a5f6db3e607fd5a21714b0fad5d814c015ebf48bb73ad75da9c03c4af5489e782b6bf7908a1bd528d7ce788a18ba3528e3537aa7bbf75f6524bbd19a5304ba2a4a3ee58c41fec3132ee6501641215eff746d7800c4d33f52be8357e0ee758041d91cfe43c60c3cedc09b0d46d4cfb9ae2a0239b6f33c6941cff35372670eef5c8859ab65b6e9f7ebce32fa15a9a477aecdc9683a1e33a1edcdc90d420a31e78c153d26020871daa4fff28acc3f11a7206788806b6fa023468ea5a3d186d10f0dd567796663ba37c832fe75aae7dccebf319f93600c46a22f57223812ddd0a68d76baf5e27a9fc8bd68cc10b5b5151d62b41f9348e21b715352f2630b617f813b0c28996285904cf294e9c2856b17ba35f9a82198b8214a035e2896d6568be42392ccef32cd4ebfeebf12be0125206bbe89336d3e762991dfab68fc99dc1649b891383db31fab649e628823f4598cb636a38fe1df73e68d7425fc5d2eb55a0fd1bc9f5ceaabd6dd41f23e4f086c692633dc3c4619a97ab0eada171f84adf20ecc8ecd47c51cca3e59dd809b0aeaa730df94be3bacfd8ee888bba9d570850652cd4d5e6c552a57e9f48a2b06aacdc708d84a376fbc6c94ba6bf64a5f018800a7cc851245aedb20378b329acebb2977c1398082b3a0e5e2a9c2484fa301d3037a8224ddcc095b1dbd8a2315b55bf3318c27810efc3d8e25fa7a8789b73a4f55059080b08abb3699b7b8626cb2a780d97cc1ca8032851baf4ed8b64fc4330865f84ccb12a3dae
SIG: 79995877ed24c791684f2984bdf9609c3f7b576c57d162ee622d4ce8f36d9c5573169d8801216f1c46ffe2f6e2c09048e47d4beb997e9abc4abb129f9b79690a
TST: 600
SK: 4deff647cbc45ecaedc3f7ddf22c167af24e3d63da22b0e6a5b8439c0f3b1934
PK: 0c27c9d77ac8c725bb0663933ab30d1aad09cbcf2cd7116c6085a8499f701402
MSG: d6201ebc21cec1e9bc28f957c9d029cc38f9e85e06dfc90bf297e61f2b73b407d982a66b91e94a24e91d06ab8a5c079d0f69be5788ea8feacebd917291192233862e6acda1e8cf9a48bffb5491dd65af541b6c72af681a81823d98a0abeeb6ba9f95465b8411f99e119cd28479da984259bdf86c9fef3cca34e224691f183cf095037727da9cad29f242f83eb4f736e27fdf67018d711b74c45b2955a6a76ec15330df5bad8030c6b3a88d72f28447652ac8902b5b76cbf6b945ceabfec04a9b8cb30f43d9eb773e6705594f0de1b70f1a20c99fc4b1221f8c81b0bc30da12cd5dea8f4d90f13a811a2cc11a96846aafb4c42a00e9ae7da256a0d22b198afc25cc1041d24e056cf387601d7bf7eb3182d605fe5e63b18d531a5f84e5dbd0184a76c6c467a8263a98b5c005fcb2aaf989f5cbd0a9d903fcfc609d6e57d9c439021cea93e4c4e991f193caf3243770b32578748076b7f4cb97f17c17a79b82253c2423db698cd0a33ab33bb09b0b08cb8ceadca1e29c5de2fc12b2407b6cc5af5ae976dd3ec630d8339b7dd11fa34caac150c7c4791d8c427b0ad92e0529067a88d52011e1e0a18299b969896f8b8360f75c45c496da47b09b450f9822bcbcd43f4293c516802bf747c4abeedfaa3e79cb9103d3770f5607b77516e5b1ce0f64b6eec7bec3c647c006956dc55b6c79f6afb39d1fc3ecf11b974b44aedb72aed1316635083c2124502e5c72d86ecab6ac90243eb39a6aa9cb9480da38e1edb8d28ff90924c05d5d21af5af95957b8020781378711a29d0920acad8ccb39a311693278c9900b470da2bd4c12a01d73962644017b6034713b2a
SIG: dd5489fde4ba87d1173d4cee0682afdd4bad80dd770ea7d0dcebaf21acc61dd6324aca295ed0e23a915ecfdad50f175ebc516f1be5b6d87d90bbe38622495302
TST: 601
SK: 5a19bf6c941f394e93bd3625fb81cd9da81c9020b1c531257a7b5957bb079211
PK: 20e8699d087ce5e8151d28053dce66c23f28081f35bd26819bbe85d38a09d702
MSG: f721ca3a32c1e81c9c6f46d5e1fb50e7ce2f4e709333ca2b550d5213b6773d670ca59a2b5086a443843ac50813b244c9c9fac6d119698927813512c84fe30a89553010138f91e8176f5cf25789d7281ddb83a246705dccb999c4cd0ae219c645f6d71d451ae1f8d2f9891af8ccce03f438559fb83667b8077fbe435a744af019d6d1399fd2137f5afb8ef3f47bcf735e7c9ed8a54ba0c1c656b6650bb30adb1d57ecd2074639494231a2e9e2f985ed8422ee03cb3fd738c735a1b82806047460ed84f7468c3c64b35db06bc58de4bba463e638a94133df106ac4f470361ccde44157299d225b17798891baf5921986a2bae326dda0b89617c677bd1408ba2748baa67c8a2c5a969bc00cb40dbf490e07e22c913afdde6304a07fc9e60846992456bfb0663a09def68def67a16d29e98c7b55351848a8cf92310c7463c475f249c6f7557fd0d755ca88f877847fe0765756ac34a23f7840d95c3d294e663bb1518b75927c410757e0f5c07c5a7fb215dc7207433ebf791edfcec90e930f8e3ba9dbbb985413c223be87873bd323997581804d8896da386a6e9120050a0eaed31240aa17c7b6694c30cbcc3c6956a6820fc9ab21875533963dc3b0d88358271276c6056528910dd989ae0c330d1798f7d8e7d1184b84a81434325b8c302edf601dc5e6f847fbacbdeeff78c6621d1dafdc239b18b8c1afdcb4b9dabd5d3a92a932ea1599546e625f96d6ec6fb1cccb76b476b330ac59259c634fac9b3fa7de7ae7053773b5befa001b04929f74b71241e1b257696d65a26c1b4ac86b7b1fbd6957fb9b95084ce7d70090f55d44534694305e91769a82941304
SIG: 2a2fd6054ef4e79b72191a0ccbd2b18aebabe8b9a71861ded98b7cdcb6a6255328bc1aecb0c9335721a9a96ee4b5b43f90d322ecf835f78b264dae6e387bfb04
TST: 602
SK: b506c01d69746eb4bc6358720e438ad330c88b605aad652f4799573ab0a1aaf9
PK: 7ac8b68863bd69151583789d864a7357e3a045fa86522a9daa6e26fb79ed6d23
MSG: f7fc18066ed04b30e633d9865da3214beca60bd796019cd7ecc91866f9ef2446c1fab06d8651be7f101aec7bb84ee21e71ad020215fcfb36f2d11e4579ac39f8e2b1290e3896d522bcf513aaa06771f86ee228cff3a20a1f10c564339589bba9605344c0a6e682ad5ba40d1041941bc46f98b9d09ca17f8f044e983b8a4908933df2263cf78811c24c8f4814354f6f4c68b7ee7b78308293bf78fd0ff122f095c14a73a59797172ae05cfcec19563eb18d2bc5300ed4bf6bdc443ea9b8bc1cbede94cab905eda5a6a931597de402146fac9cf8cd6a8d104669f913fa834001ca4d090fb7949d3109a63c0549b03f151b7117c4f46974ba59c68296edfdde7692ee432acef7610647e0957865e62c1a0cf05659823a55452dd5e471b31c5a49ab05b5aafd5a0e530e896b58cc522ecf19e52ec82fa147f9e385174c7ec33d1d9b86934aeb4f6c5700f7d5eb33ff73c9fc6aa47df51e09229e6ae894e86c818bef065f825971a4cb90adfefb31ebd9d1b79422dc9868f9f74e7a32cd4071efb69b27233e6e5c60dedcd5321c030a46cd26f5602cac747ee4b522d857a3321a03f403a6006250406361e48815afba77ce08903441845ba87225d8b24046745d4065645a1b98410cac48d137cbbb8ab1eba50da9c231e9acf322a6dbec0ef416a446c3b610d93569fdf45aa6cdc1b640d8f301d78693b2826cc6ed468568ad9a0f94aa9b9fb92f7e78d484fdf5d8d45c991e28074dcdd680d3b1f189ef6bdc320ee6e64dd1f80d9264d83042d2c43d83581ef0394b1b5d1f69f3bbbf04b7c808ba34c1580f16f76537b6a7ebd0a1908be9494d3fcaa9871db15750
SIG: 17a19d2691b7b046d7b19669ad73140db92f0c978c7f61bc3867d92ca9d47580a0380b5901bad82af45f676f74287301980f71871a42261dbe0802950336e60b
TST: 603
SK: e1ccb80a262ff8af1eda075c972c8e941e77cef57bdb0a82572c28200b493ca3
PK: 3d37e2a5027effdee07fa511e423b2bc56edcea075b41649766725c6b30a10f4
MSG: cfdc5497b023afa62a7fe592caa92b875c7705747834002f7784ff166189398815d4e8a7a0038e1fdadddeba51057327ad1960e859cee56526bbb4127b6a5f90d04d08b15eee66c9ccf88b4b7d1ee9d3b8b8c6f42db3c34e59048a15c6041f142c4079368b7b11e29970118b99e5670ae31fccfdff1399142ee06b2e3e2b3c9707dd64119786e2fab47e0bad2cc8b558d963bb48a49ad2c637dd35b25db54bc5a2630222fa2acece9ce12ab0813077f7659f5074429ca6b494331032ae792a599c425ee297451dcf5ee195290312742e647a7795b84dcc664ddae2a1fbf8c4548a37fd82d810e2145f01df1a6d3bcc42a91a10768e091f3d69329a7bad6c072cac6d89afa31c029056d6b62212165cebcd49ac672e3830267af9f28ea319bd042f6c59de4701e58248736c8d976acf93b99d2f4647a547d392447a48dac11181e16b1501a94c9316e5a67c990b35810b4cda0473a6a4e57614215868e2e002c6058b42e4eeec84139dc19edf5f80aeeffa4f5b07e8fd23139edda31899ebe6fee78643ce686b2963a32072bd3b3bba68485a05c2cc0456c3da50c7c8c651a3066d13a3660bd47ab6dfec49e01557a6742896aa4bc6363a797dbad1a409cd4a50911e70ea007af8e9b1bb7e3ab56215a575c90f739c2d48b3b34694b5acdf07980ae528de0621edfac8b8fa84954d56dbb4d03082b984f13e5dbe9c7112ff9716f55053064662ce0fb81ea35f98fd2cd51137a46f64e0c1caf44e5407dc961760b2597f7f9200617d471340cf15176c3da880fe4e0e93a72fb94926faed865dfdc772e185292c1e36b1211781c3e938e3d4f24e29af517a379683
SIG: fda34b652b79746f897e222d37b77aa250d02c527c4833df80ea41d52189d50700e128b78ee8149c9b19f3abf755acef5348f5fbaf1ceb41c038906ac5946001
TST: 604
SK: 4fc512efd86e3a63b395eaff1ba011e1590fb9326ad3ffede7876dcc3e9fabdc
PK: 26c2a22f9bfad90606dc613ff107021fcddbec7237066660b488964349e0c828
MSG: 07cd1e9bfa38a7d8853465a93c77ab4f30faf914e48bc4763ba07bf96ba808c1f59ad4ce9b7d921fbbc779659d7ca36edb7dd3acf7a29452a845b49fb6543a3b6c5c1c293aff618485a10eea60ee9649ac9d481e6949967d3938b52fe09c36b9ade07581db4eb542a97f5ac8ac73d3eea184722556760cf483090564553061b90a0b6d2dff4707be763937a10594a82b766bb2cf6daa52fa8d7b48f32127c431ad9aaed3bfdeb99ad42118a1b4de7b992134ed9cdad0b5296d197a485e493ecfeca3653ad2ce0f9241aabc096d7c4ba603ba7ddd07a8b257fe523276417073a65fa4434256fd1f239ec1de5da1a0a8c5e686ee14d9dfa438c53b99c954afab2f79e60b7126f2cb58a26e290da1dccfc301f239748ede7bcf1bb7ccb4720e692f57e53e6f59075399e1080ac8aa9a61a568c4c569d36e76a2d7271f2c44de4e363a8c916a4e446b027b64392e90ceabf6b6071bc47a1379b6aa6344763b2a0e7ff7c4a27bff3106721c253e4c1d67c37fa3d7c1ecd055b8e929d52a8e45ed89fb180f74b552fe06f066c7e4318ca2f915946e8320d5806561472fb8ff7fa8072d8e6fd1ce63cf87382f7b9404540c1d406c70b226853677092645ce996922e7345dc07fb7339f9a54ff07352dd2b993063c2c83d1281a4fd178e5a5f80a5b33c229d0578367d44192e9a4d21e9734d3bda083b70f47103fd125177021df3e53d79986efea2dc04f02c0ac278788319ef3a9132e6232ea6db39ca5870855f9592fff6c209ad2f1c29dd168552898979ecff8c81127248f8310515300656129d9b7acbb7ed1e46bc98c04d1a35b18913738e9dde4d2b065f4184242d8
SIG: 82c824a7d1139ec73ae1d023adf62811441e968287f1a580b859cd66cb33b58e409bdeb2a874bf4c23610bd44f693147f2f7c29d443a905084f3eaafd9330e04
TST: 605
SK: 0b7dfad05ba665111e1681bdc0bc8ba973767cb85877020a2dbf918325571d9f
PK: 9505d9e86dcef56c9db76f2862b90e1f2773202f1750405e7ee5aed0fc54f8b9
MSG: c43fd34bb1424cca4e4dfba75c28be801844446ca089020885c748382547164a9d4a7f9570d3d171ad6981ab50eeee08a4a6c66d7699d23edbe1faaf44660c72f4552d87d265ace8792823474b90a5d7f7401deb9377627f60b036b36e044eb76bf132fddfcc0ef5704a633d845e962b47517f0baa34d3d6e9a8b9f8168bcdc84c6d2b30c6f343e75357f7f2c0039bd254b244d36cd61675581fb834570ed4113a78e606f145a111992c2c6b61c4267628ec87cd88c36a3c84706e44ae96a96e0c8480318546d6ea6a6df18a2b4f19f8360cfbce4e9d1cf1011ffea5633a66619aa4a65cf69be4459617945e4359a9d43260ca1a20f4ed7c1ae5ffff3bd92294ea70abbae0385b0935cd1c0eb5183029c585a0294b7999e32ef7a290fcb095675dc4f601e8f2c96f35b7349a37057509f4ec70c9f50f6011f1f5e6b061c091d11c0ed5dec8ece881aa340508f696d9e9cc7298e6bccd7c210e2ce0ded83592a3cfa13e8078fdb3258b39f1d11cdfe09670c1e60a3910a4fff51c6c7f7d6624f4c93df8888c526f484f9b13e0a7f62964783978684e292679800ed5eb280e287c7e639e85faa53fba2fa2045ce27d8fb308360726550df9752db305f8f06647970d014691999afa97b6193ffcc6d532f4fa69e133a1d10f3047fc00381f4997bb84e5b6cd6028c62132cfc024bfeb980301f29512bbd109d089ace182cf9c2ffab1b17eb00b6eb46ae198da993f5efe7c1dc22d25047c1ee5246517e7f5758f996abd83f13da22c13dd205ee191b55afd4831ef078bb6ea073a625bc97c81296160bbf2559b275cc37ccf01b91fd87d4d99a367aa9978dadd0689f8a6
SIG: 415adbb2f2b9840577fd1841f9aae252afe8f5a72236017d50db22d228cdee9f5b3e8fe9a17a4d4e98b7341381e8d8625cdcea956d253b74e02dacb84920a009
TST: 606
SK: 78188df8c754785621e27ae58e100d5080e16e0a15e277051f95f080900ec0d3
PK: a1bdeee98b0757ba9c2d8409b87424e64e42f9932acfa9bc71fb3f8ca0e11d52
MSG: cf70cca57feb1beefe985ad5af9d4348d3a46a63de1075381fb3639a044fd6e6091f5db9c94d39be0f13ade6d9a074e67ba706b3a8806295f6b654865728c58ca6e9419d5d043f2110814bbf36fc4070e4d9454965c251202ca395efe3fdbd544feb187e34ca3c80795179552fce9aa804430e5b6c8685341e91d5889fbf3f981904620ffe7013f53b939e17443d614e7e6bb57ad674f3b4b001630526cf7302a7d0afe7dc24d6dadef6feba3f96973aa5b8d6275262e430a82f678696971a8b60e38d3b2bcc170d5bc20302a39c596d27fee39e5da5b10ea9f382299e19819717a718d37d155f13923182b5b7a1c54ca109b22ca8e8b26ca5ca3f3b9062219461bace97e890c94e41ca3d84587fbdf6e240c35ccab71d58477d28168e93372686d42aad324a3f16afe0e9b89ee20e485fe6c864b5013ba88399eeaa159835a8b2bb2f25f579ca3bae675c63da1b50d99d4ed978692e5600233f38ab7e7a5ae0fbf8c0b69cc38bd30eabd977efa05ee2c83514302bd40c4bdce7a4110afbb6579c620e97f8cf2e9bab2dcc7c33f196e57fe761a050122894b7a75a929531996ddaad78de1d4d924cd93a61df227776bc1c39fbb8de1c4438868b6a3a2cd94c07b29e3f6b23cc7e0b63689009d9d0bae1606bafc7a808f2d2fa2562b8dc093842c01fdb840da4860aced3fc525ca334edcf65948bc416f98c450f0012a6107dd7f8ede40e1c48c9e8a565a810b9cfd20356db19f1dbde598921332e0d813f0cb87684370388772ff3cbfcbfa299c198c97bfb9617768a05161f4169ff5de5d9f40062090fb882984d9d5c7aa78eddcb9634e466b8853d512b4a546d7423
SIG: b94114eda46ccfc22a4471a64d790892e59c5d505618eb0e701392c709613e2d503a5c2b66601e636a3c1c7d49b1ac798d9089b0f9ccd0579bb90634d0bd750e
TST: 607
SK: 73cb02b0bf26a015da1dc301fc125d7e6c30b63c9e6eee9e065d4e847132c325
PK: ac9e3dd2ceb9b23e748c04ba7577fedf7ceab9ed87dc430b5fe22eac50950e0d
MSG: 0a2b61ba35e96e5819b88bfdb28b7ce02e64ae9cf572b21f13552c0db10f3960d44ba3472f43abc4e6295bdf790bd933ba3975fd4465fa3e2fe2db02b6377752223dec98fcb2404f3aba43265a6fa7976b6c6cb6868b881bd6f3d25cd9d6f70e512f8089c8ef26fd58245053779e59c4725aefa26467c9f500e17f3e1573f1a855e9b8b21925ea0527f3ce8d88fb54a47abeed14f399cc2d9f1fe54665fae0a8f0c68872a600046d1dc36397d310ce393fceafe87c17ebe122fdb543aea71085baec98273f41ac96698c150cf911d0e5de2392d84841d01276aefbfe9995e10a6d46efdc2678d456c9f36b2e10114d1187e7aca739037ea51f85fd62a29429ba529cdd8ad91347497487ed7e8709d4776ef68670792d0615bc96da5178d606db63e4e5cb172acfbc1cbe20269350f1b605f35dcd479135bd30fb4b5a39176cff744ddbb306c9e7b4167de0379a6166be5aaa74d7157fac957d88dc57597cfef23eb5108b3ce53fc632dad1b972a29da5de32d20d8ecede67ff00da4a08a0cc1a98bee7a94e3cb32fee94ae25a413544702c37b3e1778a070cdd4840bd39f5f45795192a867863876ed0d130d46e2913935082809f7e15a496710f255d783da3d016a654c15ff5df907a3ccaf37cfe11c8c3d496507d6760c053820f0f594c3d01ca269178aca525ab2821ef55f92d85fe685ea34472ed1398171064d74a422ec91d1a670618fc9f32424bcb11a77f6fb4e2fefd2c4e8a73c452886e931664d1a83bd927329c04d250b83521d7dc13c91cee1ec050e11d42a4b0c8c069b61c4422d3a49c07eff2905b7bc7f4a5b43e6b0d61dfb50e4eea2e90d298a781d05
SIG: 1a5dd4c891c8e132570187c23b9a1e4b26f05460e875673819396df561c8af0e48333b62c77729d49fc40e174a7f3c21f85ef4d339ceb80bd2e037d803af560e
TST: 608
SK: db05606356bacf23aff6cddd42b2c694352b5a0fec560aff54d9bd9710efe06a
PK: 32a5c7cc4909786b48a53f31093f549a9f1730ca6690383fdb5f14c2666e3132
MSG: 1bc9c2833f37cdf1356fad166768642717701b38a0ab0c2f581a26d222d65ccee4bf0f6dfe64d33bc0239f71d4b82644b01625a1a35fe798676239e0ca779ef23138eebe3bd19de2d8f7c15b4d96f13e51bc633bea5d61225bca1d6339ba53e81f7d8d24c5d60f04ce8c726761d264584f1c7e5b5b6992456c1c76892d6352111e3b926fe025c0009db67ce0ddc7f764e0c9adb0481bc2795484d96373a962a7b74a5596f527a73476498c7823dffa6c8543b07971b5aa271c12255e0918dd73f50c30c9a85ac7c2993dd655da59431263f5914be706374be9c07585c2871328b4dbc39401c95707387e6e069d44b9d8fb058f22e315aa0d5b4f1168fc107962b064f7d845af8e2131951d1cd66dc84dba46d200af4f4c5f51221bc9b2196942f8b40e7ddbc9aeb3d9afc071259513135a016f2866099fa10f4c3b73500bd55c477b2415e10a279ba110d294f3dd1842177d0b4bfb1734dd0ccb7e394b43d16f0b7548362280f434764da57f19ed3e302e5370fba49664c230057433cc647eb27cd2c7c18c7d66906f088246c22f7f790399deb4c5fbb906181769bef5afbe8ad1f5de55be588f52f69c54d4ef5a969a0d995c27407b23edd9243d2499fdf29473b1955c84b3f7cbdcd81b7656ec0be9e0fdb3381356960fd0ca70e7ea74b646fcd313948e6ddb47609476fb6fa4842fa788a0d57be3b0a6ca1819f71614760043ec4904881939968a43b5d1928f84a5919093bc3841588171a9cd390f8fcd61538b54e6ef99770573e1986d150fa96b7a07e1d194af1c0b405500acb3d10e3be647c89862006fa78583e76166842920160eb57f0b2a6edf193c44c5eeacf4
SIG: 53099b766adf2944b6821374842c25d6e67b0ccde9c637fecb11b8b8b07203e3075732805f4f14aeae73bd62e308b5887d689e29cd89b23a476943110717b100
TST: 609
SK: 1d139b1ad0c3af1d5b8be31a4ecb878ec667736f7d4fa8363a9809b6d1dabfe3
PK: 2428cf1deb20fbad1fdc665d825b614122df101fbe1473a79996baf6967434b8
MSG: 8df2d2df9b984da84433486a813c98c5973a696c11624610b23aa438083464f65a76796615b728c2ed4e60715855afc239450d5bc0911ff2a85230205c6f1349ba5bd87ea6f720db6ba70b77421788e0c654aebc23074c5f41d2290772140d981a6bc4fe709a268e64172a026b270118b4db51ab6a13c99b063186d8d5b338e977eddc6bb5fd7dd57d9845a3c3fe76177d5738dca16a8f9102857500174f23ff4c3bf3c8536f11580ef8514a409f5bbc9c0296f12e3478d4087f95efaa6c636071d21157bf11774bbfe7693306ca7213da4713ebaaab3554edf08011a5ff73da120375aed19628670f28ab24b6f5d5a1d570480f65d3c152bff1b47bf0666929cb7c99d9033faae8534fc35da730b811ebcc25ae10a195aab12c326aa45bf805c62dd4cd5f868623c04a8e1c6aa72f1ea4400c60867dff622f316434f1ec89503c6f9f65c137b4944cbcb35f086c74cceafa2242acca6ffe611c4b5587f5b75ffad349f00bf96e4a580a875b92654069b62eeac0bf78e5aedd71869ee05b9a94e1c98e35a97800a4a21220b039cd5ebbb756d40b4042e2c84a2ae98182511dae8ed3b89f4fa00fb8ed946316459710052ad4c02f63df05d3bb1ace33672151bdf5dab46c7b583db373899d4f035b6c111258b4e5a9e707a11d215e44e68ef1a6f053809aa51bd902e13ca99c1b1cecc83b9c235c710e797d2b1a249b2ea079b5c1674ed7169f1b6e67f1ac77f86b743298969335a772440f7fbfa72513500d84166114a8fd54139464d42b995530d32370b69bffc7589d6dcc97e0bf17856cc3bf4164dbeccc8a881d414d6a62029276c5f8137c0b3c68bc8f4bd4e7cff65ef2
SIG: dd645e51edab04db31e33172cf27aceeedcc0463a963914a0eac8efd5a34341f6bbc52e042baaf3b40c89a57efb64574e69677fce955246c1fc0f269ef819000
TST: 610
SK: 4d22e331e0cf6f6a272db4d20687ffb059f1225d81e41123b8c89b074de76a3b
PK: b1e4cfaeadd67b12d7b9dbfc0f88edd0373f9a88c7fa33fb7f2b1e475eccb61b
MSG: 9c8e3f5b4d704030e1ba71f02efc4b87d6fffb55bc3d8d03818f915624fcf701c54adfafa2b694b87751cb9f69918c0f050f4c105d5ccb40100b28dfd4f411d591c12019176ac2016bfbfdf0ddf11db8a7e39aa7b9e216f667c0a15fb977eaa9ba3bc455cc58945f3e944b8ac2fbf4d24fe7e1e619cdbeee3e5e12a9a527d28f5fd7cfd9220f1308d897b6d4314a5a0187864a2d621cf1b2844261247bf520bafa9bf226e115681ecd77427980cd12b08c359cecd1de3f5545f807f81ed76302ffd6477f89b958cdf12954cf70c142532993831647eacab0b4807bfdadb4389d7dff2c4ef0ef5a5c61d0df762e2e9080a7181cecd06a53199f0dfef702627adecf5fcd9b3e68c72333161727f871c7d1c43051ff1c921fd53b642238b97880d64e25fac512ab954bedbca540f5b20091ec72e67f88770afc32f2125ca0da4fe87b56aac9177f1f4f67c851725c5e8afe64f664799833fd79100b77ead25838879fff4747aa0d5672ec0a94348134bdbd4bb39b0c67a0cd30602edf4fec6f7af0cc2bdae126cea842dfaa4391dc5ddea938e1792168240c2d8b25352f9f3a644235ce36fefeb6992ad88e287ad2d85bd850396fc2e517a15209f5920ac98c532b1f4d869beb08bb03cf7c91af3ffced68d5fbfef86ff94ece6e2ead3484ce080db17bbe40f1db432ec1650ed24fdd250f3345745c9b7b9198c9109a37261fc5ecbbb12f83a0e1220a1867d45fddfea81dcf75f4ec7fdb5250e57754d6dea270b628a79530ec28b619bca9493e6305cfc4414c1c1de3389e890197c85f28404f3fa96a1e2fd9206b472e8a0a0d32af55606bb083f76a19b8eae3479ae51d98a99a62
SIG: c366b802f682fcd70525264fb1a3cbcd0ee35ecff5977c2a554da939229f17819a961ea74c3d7a7881ac5c1fa16bf984d9456a1388d3463c4494429b1dc45402
TST: 611
SK: a5228ff9bbb6f232327eb8d879d7f8b277ca72bae1f9a9d0e260dd90571db4f9
PK: d82f6a6974f51c8808d9d617f4cec2d8a37eb11a14237c9ab9cf11ebc80ff6c0
MSG: 1df7a6835e3310983ee7ec731125f5b5cf117af0e36b3685bf54ace1c48c46300560a45e9f9bdd96a0bc4d14e89d4b5721a2caff6618b182edb1202f3d0c5d118d09b61812c010e8b196344541cdeefe5fd1f961c5dd75459555ab72ef2aa7a759a4f3ad3caed44f4c9a8ef95b76ed9a99b55dd8a260ba08010d29ff819f2af3513c1a640d6ccdde4999205f9fca8857115d8b5db9f70a62e5eea0d5af065de153f2ededeec63e15c8e09a92582182ac07d81ca63ca4aa597a2220e70481957d415264e258bc263e1cc36e53478aac5ca01694ccb09b4ffd84739972c7dccf3defeafdede162ab6c58a1df27371e3f5493067fc9e2067e579623c009fc825eef0e010fd1ccf2a8d3fbbb3156f9dfde0c7cbbaf8433098517491b78db9698614ea40e0b1e6a1e36b900453a16ea276f3442bbd27a7ecb981511f5c9209eb096e28588b65b96b50188c0381ff712bc06b2c655cca0751c095d8016251585851e677434dc3efd087a12680fc22e5b8310a10e32caac9b71c876eed31ef09f7fa012ba08dfd2ad68c1e147f50598e550467ef99f295a318faa507ebe776ce55c4da164323c30a5e72dbe027c3ccf96c70197a6fb1b74af133a8be2b03c1b99fd25b3ced51fe3882021a3afd9229f641bc6cad4e1d3cb6ed9b6b68a25f1e1397289981f78924bff24c8dee6a18a0421fa32ae3ab60a0d933a6af4ff704874b09b0739e2f29d8f252d79055f89d3bff10a22c54ac3d8afeece818353a6abe2b7fb8e8e0da5b7ac1cfc985df97580b18211a4e3edff95afdda061547d3ae0406d3286cd305bdfd2c3abf8f74af9a03420e5b03f825e9c53907e13a5812174be42898645149d
SIG: 97650fae3f59ca76477f2547167749c5830248883225e354ff46c7e381965220d9bef2c2057c7d1990f08bca4cfde877fff2b4aa813d9c4b84fb79eced81ef05
TST: 612
SK: c04dc09f119d670fb1eae0136fcc06085f290f4ad1aa1ffc9c160ea5cf47f09d
PK: ff498ce8c9db7867f6d0276452a466724887e6172f6681671b8ae035f5865ea3
MSG: 1e42297f8aeef29a842e0e21f5dbae068e2c9ddaa6fd348e48881f0d42c50bf0ecf1706b94a5d19817ca02d83e9ab2f99d8bfaaa5c85ad39a150b225ad3eafa067815b74672fe026c3ccc677255440b684a76e128ca2ccc429f152577d25b69f40db582d49479afae680712dc0fd1fe1418839687ca60cdde974140462f96148295df1ce43a977351c77f2f0b09a6b26d6fe965fceae17d7b8620371402428544fdf91690b44e9afc2e9088c83ca48dc8576f628724798dc90323174c44996596502a35df8b982c570a6cb51b9a197d431af33f02b80011567fe50cf45ac111b3d556f8c8ce5ae8c9972f2a9936b1a012b9c339e30c97312b65ea59c100f79d795b8a24b31a0a97dc25cced6b8ff5ae145339a048ca12a579017fae8d5cbcb61d52e314dd7c2e72010c47217b1d06878bf2818ca188e8e307960c1689d7dfc0202973cd29f2f7ba743469e685e0e704b04baca4fab5488448a922eabf40be581c1994d74d13a366ce857fb40a6e05da8553694172cc3fd28062f538250aa8c11f68139e79cd1191ba3314b5cea0864437ed2e4b6fbd75b9ded0987b41c202a58ec0254d9d371a795f1dbecddac112be8d09e2d7b9ca5752f406cffb911ca36450bc05f1ec1ca3ca8d35124d1286c55f10f61334e46ece4183b92219a9dcd0e5e78ef2a76cfe9a9ab3795dfdcb44f63d45f5f48ffb4156133ad2e9950884c5bbd2c1cb8729e40a8787f784969fa880c07ffcc97d5c0d2d488085e9116d7107cd5db16ceccdead55025eea2edee93c1b106427618ee09dc3dad1e05676a2368069c8045c3ebc6c67afa52d59398248efcf15e904c7142304ff61971f4d9bf6460c1d6417
SIG: 4bd19f3d9c5116ec6ae0024d0f246d2ce250d9e0634a232ba06fd3566aed55cbe59f12332cbad65d4349a9d22e7d6e46d2fbdc71d5c8f9da15dfbf17ba225107
TST: 613
SK: 6791bd74d3b4620ef5f1ff56406432c26ab646f6d5e9dda6842ed69052275392
PK: da9915a7552f110faea12d47920a09601443d4000a9c7e218d5ba72b74989fa6
MSG: 36a20e66bb29155161ad85eefe893b53ac5ade165f089a77190b0c239dec8a201685b076b4ded4a10aa459b980a8cca47d5f8de4d2a662e446d5f7fb70ed9be05db1cceadd130b3346d9409f9d6ef52824c764ac6fb1cd156dbd6a473ae722d0ebb25638c51265a22febbb14967d6dd8253c1d038895c6737f067c8f73c3c1cbe6cda4369632d7f4c9acebe87d0571c81a58cfd72cce4a5cf53a1e75259f4c993e67efc8d9c3576c43af04a5caf33d856f7f2755d3a975ab2b685c6f65680cba9ac879f3a8c9a4765b879c0ade1e4bd0d4a70bb6f92b24d429dc746cc78f84811f076f32c61e3585cc8aade9b0ca15224bfbfe18be10a33643600f6612bf013f0efcca837246a0ee5b03c02f1573624c4a44a90f9e423d4e56061a71d0144f5a887a8cd4a9d6f247904e26795951959da121c83c6c941e2b6b9ab76209ffe9178591ead68230b94ae97df58f9f172428c95067598ac582ffb950840d826630c4625f5deaddec1305203b4db6b945f991ed7cd3d6fabca51e2166adad0aad5117336d52d59422f0135c8fa8cdd0884be73586bf284e5ddddbcb95b411f98568526fbe71a5592b56ad5a7345f2874db1d57beab43e8cc69547520629f0ee76dbf432a376fad28bfc77e14d840f0c02d478f1e2337c23b89e73e5279108b5609b18e80db0de11cfa94ecf7239bcff59c54118e4ede4fbfc0823ae546016f774c52198a963b5545a3489b89df7626fd11ed4658d715a4657994035d403b3370d14eed9718d598db675f042592fea89056544b32e5b9c8062828aaa3cf59cb476ad36db1daa2482227a9b7afbc153ce93253d1b39da95eb96f83128ff2554a547e34eea4a0000
SIG: b1e8d481065bd5121bb3bf569600bcc26df40c499fbaa954b39a619dc40b9590c31756b8b63f860151694b95765d697b2e1ade0806e92a06c4a559e90fcfa506
TST: 614
SK: 234ce4d39b5ebabe9a2c1e71970d718138dcb530cfd296023427d892bf88f8a4
PK: cb73930db421f6d24536837bd0bff6fa75bbd141c98a405d4244a3c424550779
MSG: 77730cf8c8f96b9187902acff9ff0b21746ccaf0a382a7b343d1c72027ae3c3168a73a6b8f49bc8798141e15c2732b6a6b3f757f8a8e86c7a4bacb39551c54874d6bf716897ee4af13253aa5bb79a192104f44dcb3de960745a8e6aa9880524a629fb510a4ce4cbda7e2957dff1d62e705606a2cc84f91850beaac5e5846e1420bc91dcdd2427b69cfa46ae38a4fef4146eae35f9c22e967cb14a1af9cabf83b180465bed6ef2cda382a84d9994aad655d8952e0fbb0f96fc8089f2e7489497facdcd656a8a451b928c11e7a4075072aafbf17d8f1054c9196288ded3ae21f9afd5810a100d8e4d84c4a35a98b30d3e18524438dd4402dfd8e7675f09d080cd915f14af4372f7ce58384972d5d111079651b2acf39d2a167c6a00b2b17ce0b268791bd2be5178fe0f82d64dacdde377a1e8be9e7d8dfc82b08644537bdc870c5819286fd51f6792dc5f67b54be336d44d54febf81b8df8dec5d8686db12f164d0e8ff1aa2c16bacc9806010ec8e91196597ef06a4cf1707def5067a04889d8e48a9bc2c0bef664f5acd1b4f5bc2da7da43dcb5f963245ba552fd493001d870a9517a179c2f0de85be0c682d057488e35c7816ff4ba529aefd7c66091f206f5f4d75cac8bd209ec2fa55be74af231e2f389dcc2d668bf695ed267c3594bad9efc00217c7a0e9e7b6a56a33079a30e73c3733f2d24efecdde87f72f948d277d6b6d5b035b4c53180d23d66cc0ff17c15dd468585e389d91a4c97fd80110b218a0bf7a5e0353f4609d2cf018a065571001c7888555eedbd3622c3b1769cd13f33374772aa6c8a8f588102017d4ee4e50dcbbdb1d610c32670934a6d9e6d9b784bbfe71862bb38
SIG: f6d060ed7d18273f18f7a69cd1d8126e478e88a1d7294ff6040846d46107c3e41a423babb2417139fe587d2910271a357fe5bf57c92ee3a7b77533729d0ac20d
TST: 615
SK: 103d118c7dd65d07e8d5582e45042a75792417c692001ee6bd9a927b2b3d9016
PK: b45cc94514a6ad672496cd4eb9fdafc1d4a167072c6874dc8ff16d761fb66986
MSG: 5a8ee079186b51cf4629834de0c6bd7334855039a7631d6887652a7728995972e362c1c409f084f5aaf2986ae3f536be0070c4baf459ef60a015ef9d70dfa3ea96711cbb18e92af50c527d7ed457877a07ab83721518c89f7a864191b1e97433b7c6cd634a832e19891e76c62122a49dbffd83498aa416acccb7737fe75f4fb2c35328e6f6ececaaa42e43dba5bc9689673dab96f0befa3c83eb41d4d887b3a117d055e30bb87fbe7c719472f6c7a4cc45f628f5faddc48ca344f77b733c0e3b9f5079dbd07af3a3847af141719cca2f6a766552b45d0fdcdb9868f2c762b6d4933ba10836f95bff71cb88040024c90534c4d7a95a2303b04c2961012af58bc784a96327bbfed039d0802a05262d8e663b78508e92508bc1f2ea2b9be7580bde10a4d663d0d25b0e973b8c5ded59debf19bb044aff1c60c70ea1aefe85f6d15c2c1b84753b59576a49473d65af3ed941a3d514b5c4522c141bdbeed9cb339695b2e02dc07000867f1bf8ed8cfd3b1afe688fbca80e2f9ba5c0b188a19adaff6686ca0ff0edd444661291fa27ca1fc529429a5d8ff79ed2027c60ffe3b2c03fb8a66a3985417ba4ace7d14fd0e2371edf5d71bc02b9052767c7f72c4e6f3f30e0638276b9c420aa4333095d31313033090582e3ac4d9fd3203120ba2514973ab9d1c7fc42290116b51dae9fd579410ae078ed320a5a1b49aa7b5fefcd756395213af8641e29b0ebb5b83e3780e5d10e9d3d11998148f6c6f86c4d4eb252e28c70fa3a55c43d4d7faafcbcdd45ad2637f215e81549eb8a4cde4715b7107207503a79595060b83ace8feb673b997968469dd9b4ad6a7ea81c6e61810033f3edfc137d974209575c
SIG: 2fafc13c43afe5054372b923d24f292b283afca3aca3b3e432380684961713c8d23e86b3580495dfbae424b767e4795a0f922f71b50f5d7a369ab8c6e880420c
TST: 616
SK: 47eee2024dbe09953e981f6986520f666082aa9ef4892dfdfbdbd250d2a1df28
PK: 9f13cd8ebf5080347975159f360296a7164014d8d069e831dab0332607997cde
MSG: c133f033cf3bec6cd19212ea47dbecb13f2c6018f9e0878ac884bfb575c0f5d3fc5b4999580eb8acbcaac83ae9ac9b443e6d1cff449c3689b433d50900b2e8b71d00e119c8b875094bdab916adaab75bcc852959d8d759795bbd6b360ee484afe47b1ad28391f25afb8d4e3afe0c5b600498a12833fe2a1a5483df940b173ba0d9d8c4d1321fa4b733334b0f6d878a0e5a76f4f180ac119a82082acb1488e49bbca7a0369c191bd6d0c5d445656821a99ccbc945949eca8136cc6e127d9de92ef64f174a6c04c8b5e52495f0dd674bb5ca128a9209968fd450dce319913fd6a30c3382798163e6585f58ef208be4d0c6a2513a752388397a4ae444838c8466dbc36fbc36ae08bec88eeda131c14d06366b673151454100dea1118150fbe441b1e7826e545d9868242e899f5ea53e434c37936ce6fd06146283e8fbd536480de55a16102c44754bc554d5bc2de2f25e19e567a023df4640e74ff3a49e4dd30e0e2558b3dbc2aab92fdd5e79425ecbc4c699fe1f161965f1d0b45d8bdab52ec9bf7a69d8aa0bd171e755ce7b8d0718f7267afb733efca54b213e6f5adab4c9d76c867fcb69ae05c74bd21516cf342c6161f6fc9eccacf970ebce540cd892bc106c6bd563610298b70968f091bcc6e1f7ab4a5b2c6374a1903f4d3ad5e1bd8643a9c2f878c3d7a4dc49ef3197edbcda7bb91e7e06606087d4e981bfab93a6024977962e45262517f338b6857eec2158a297b2aa91524b677a21aac57be0b63a8074fe54e7a9dc70c5a5c3de728b9c17ec1212ab1130eb17622cd7b22ab6eba9185e8d67be6c47a2e5adc663d4642cc120222e299fe134fd7fcd00adabcfaa642fe2e08dd52e2c3f32
SIG: 5defae0e173ecc18d5f01ec9291be160d5eabff63fd5423f2bc66e3f6408c196353502dcef21effa4b9c14bf27b687d1b6e86b2a205a89eb35c376a3a325690d
TST: 617
SK: b6c88b4c90fd19a149d381671953b9b16d428f6361cf503a110477e297f8d2f8
PK: 8ebfb084f997b2ea7932a2353b2c8b16bd825e1af587a8ebc51a6c45aea343ae
MSG: 7f4bf4f52173eff072f818d0aa97e6935d8baccf4839663253b2414fe6b1f34cf43ab120155a1a3aea7b4819ddd1031673b8a7a6bd0b9dda4adefe692a56162c646180794264c5122115eb90a6d3054f084302dce3d836ac3de820638bd89a86bf0a4c01547cfdc543d676fe1639ef72c5b845c494e07814cec8a47d03df73be4e33c05afe9a190dda043360496be4cf3a6319da9ab06481677f1a4374d60d3d3b6394f8843c869b0f41a1e81c2b1a54bf5aacbd98207c8dbacb36422a3aa013d5e849e044af928545c046097caf149d970215115dea0b5a85401ff672e02ed40bd0f5a440cd56494053c896c3bd32606349f7cbe7ece2a2230cf236dac59f7817965f3fa80fb48aa30b0b19efa9a96591646bd25e67c185f77e21d6630b288d4e55146b2abc15e95088d936080775618154bbdda115702a2afd6fd5f56b923e188833ec448944d30283e337254242c5812d7245a4e92670bce3546efaed22d274e1e6048b5a0f01efbf895dc42494baf1747185cb1a4b88fdf1e6099baabc6a5ab5a2727b1e248789d170caa2449671a8f6e094c11332ea0ac2afe88132c644ff883d0c499ad76a93df472fa013eaa27ab4dad679d2511b5049c4e98baa2e7b00a534891e290265edb076f7dca8e6fef3f433034a16575f0e53da4577e6b13f0cb0d785870d0d098d5d80f413a268ba84e0431a786923771378cd57b8192258e2633cdbe03cc316a0950970526fd3e09376bcef0d03b7074e59a5a84fc64e795a812156d960567650bb1e1424b3cc9a4d99d57ba858dd1a0cad3532e998146e79264045e28ebbfd75a426b0bb851a244ad6be7bd5765af493dfc44ee378cd04daf3917eef2a6206
SIG: 7447a20181b02cf1b6ad529569ce437c2a0508116f50205c41e6378b74fe2fc53630aa0dc4b80c31cb26c8f09bf8fab27e3abc8f1f604a5ec06631a84f6f2e06
TST: 618
SK: 7949a9472f725ce7c68d7ea8fc16e13d9e0e0a58f58c24f9228c88e80264090d
PK: a370f82833f88b4f5f5310b918e6af93bb724bfbdf3c02c503780b2c83ab6cc6
MSG: 955386b92dd6bf92601bf81e84d25144b5fc0bcd7d23c76e7deb5f5ba6316bb61a5d8e74185b012967f0a4438b531696deb4b8101089e0c0482adf13c0613191b977f77b0419814147f5da64a1d3beb1275b9849d1297ba8532ae0a647a8ace395ae0ed00f67348c5ee5ea19b5f1c5bd2e622818e8adcba3c17c27987e4e3d6d910a56c7e5149d3f5574fc06009bf4dd3e37cfe3ebda2c2116d366dd88ce5ea72ab387490585443b086e8aa38d11d3820b72c658e463cdb59c5393011d4a8f4cb6a195229304e76239fa5e8c2cbe0f39dcad138a0ecb3c51579ec9a120a51607eefebfa59a44620ea5b1916087ea338533fc132ff2e4a43d052fd08b6b1b24fb672f73c9b9ba20b7c1c41ea24d912de9b555b6e5682b970608ff229ad3086f431f9be190ec39224ba2ed8acb4c8eac8582e23aaa79827c44e248c5ba092ddac0f2f79684aa93fc061073e1821a56afb9bfec952df2719a9c7a403e6a93f7a656d74b61c1d19083f8d3f19e659fa2b718e0bd04b693d63dafb86adbee5d87c75b7d129122f178a0e669eb035ca4d8eb45397f1851264e2cf0a0cdd30720c5e139cd6a573f1fa241cae9425805ac79603e8de350efdb0b9bc95ba7b085c1ed92c12acf53f5d4a1137598008f2a3672c84e5f769a25c7a4a16579d86288774972606e4e7d85263ad217e0dbcf343fe554c109c5d9409b7939073ac55a03420fec289b114a5c54c20b45ea69938533ade7b3ae85e1a783dd97897c3ae8254183cc54045c2a18ecbe521691f2619d9b8f1fb347ca055a7b0b4c24f64d1773e01416441efe159923217a84874b9c4ec265cdaab643908068497812c1af15c188071e78f597fedfce91c5d4c6
SIG: e02898cc7c30ee01648247497be8a9c6378593dc8820bf7c17ffcd18118af09879a769f539dd9237e96821166634998f946da65e6dbad8271511669e2d6cad02
TST: 619
SK: d68a5e3c47eedb3099dffc804cf19c5e74bf7bf5f01f54d4d91d7574f3d3dc7c
PK: 46467fe9ce3acfd0d74346be21c46216db81aece6ce0308fb8dc6386fc3446cf
MSG: 596c03d0873f572f45c3b16f0ef4b52ad2bf59ec76d3c0e534d62c1f84164ddaa425fb85c9548485b7064677e99d04c39b6eba04c966397ba6a5f4ebaa69a241df95a6e44502509d6350557ebfea60264b62ad7f74d16e5d25d45970cfebeb33e7b1bac3348dd03a8e99133b26bbfd7aa722c2587f72d5526e980da9eebdf108211dae50bbe8c65f9abee69a1bbf84c03e40448babad03d3cf3b7de4887d2b47737702796482d2265c566b0f623b53c8671bd3719edec0ffd5f49b49b072c1564a57f9bab6b92d1f068d756639a4331452e61aa7b218a88b9db77a19fb82f13e9868edb798d5beeca55d1ab095b316225f3f6390f89578f0160428747bcd21be6ae1d86991b48ef80d569250858febf3276bd5de3db65a245c8bdcf1488c4825968945786bed63f3d13f1409363b948560476858b396bce588e40b311ddfc22ad622ca7d1e69561464dda5009e638aa5ec9f4c039293aaec75001ffc68a7cb3ae01874dc7f39d75027f59a28965fc19530c0752fe99b153da7c0e542bda76ca1e10b7ea158efb4d821fbc65e7271ad9941095315447abcad0880a0075dd04b1325c72633acbcb261fcb407c264a34d70bf1f044feead069af5a87dd352f4bd8110fa178adbd8dbf23c6b575cdd5df22cc9a5cdd37d9c8faab81a4cb3fb5c4fe7ff629dbaa9fc06b80c1fb691c28655955cfe5ca44149b150b3cf140d9acacb14313a72c84098de72bacc0272d79ed6617f72dec88e19b84425492a429ec6d2ec08b86346dfbf20ea2a3619e77b6ac64230ebe25fa0067abb5f33ee49adc7c44bda7046d7f224f2e7a4895683fca8684ed6a031844f5786bcda48b5042394487b52402a09907788a1e140
SIG: 896fc3caba7fd3fc285d5eddddc0120cd46da7c6efabe66b150b002760b8414a89ac9e7f1f7b7c7b33598f61f45718e4ff4ac368ff129614b4fe9219f237b009
TST: 620
SK: 31e82bc1cc5ced21cdc8bfc2dbbb976b08780afc6944af7e88e50e67874d84f1
PK: 8df977e2b040acebd3dafd67b87f9216e8c371beced618fef3a496d651a5d7b5
MSG: 69d461b6b7a866e94cd59a5a23bba4a1276602f042baa850d5b29249d6743ada04d3d938219abbc22ada66a1778197f70bf80b597a8b4ae00bdb876812d3ab4ec011df73341c85053eebcc2df0acfc21548283b553ecde0154828ed5af47571985f89767b005b622c9e7c079dde694e49dc0550c7918cc515c274dbd9c5469d2f18ecd90de664e03ca41e53be20b96e25af40c54ab0f7cbe9e05ca3fa5a37c1aa8ebfb6444a32c496efc68157c69f358c15f6ac09d46efef9a685df7e8dd63b304bd3c638ccf532fe901f11cf97c5b1cbed33c70637c721b0289adf6bb6d87c30479fa926e043074302b76f1157d0a81dec493e87a3c643e7a20b7a41525a38db04e78dae5e7797066bfae2cf448a447e9004cce8e41f0987991fad30311ddaa459a2644f4b941c068c0d6c0771afcf42bf9139a684da298486ecf67523bf8509a45ba5cb8b3864ad22c0c6a828c6db72e371de410b47dac49ae9d3b5702b1739b8d760ce98611c07d88df5f04683808a21afc2e61713fc2c025cb25fcc4ee941841083b22f61e2656fb3b8dad41c262c89d2f17610309f2d5c29589a2df61e55149895032ca981e4557e130a237fc0826fc872529861bbb8328d673f39b58b73d060ec596bf22e7ee081f44e92c02a5677679520e2a2b4d22c77f2b212d5aaf050bf2c141e3e28b8571d4321937426235c7a646d647e3efe183c27b7492565ecacd7f43c67a74453f4780e88711ba2dd4a3941b12ddd3909270fb3debd422436ab6166f08c99c886cc0e8e3cecd0642e44285b8864aa416943c5a186974f464535a870a012861bc2e587149cae971624e61c31d8a507e3ad82773e723bcb75df54bef847a407bcb7b1d57
SIG: 240702ac6c68d597d222da949d0c47d16b390a477d1fb579e9d8948adf9b3b6a7fd4458ae6385b7e2b684a05b55c63fa6cd087bb90113cbab8e4af142fcf810e
TST: 621
SK: cc56bc7cdfa611924e72b07f68abc6ca5b85ff8bbacdff406e51ba720d09a866
PK: 5ffee221ab4d0fe6f4c9346c5e5a4b8a636a6a0badce9667be739f4c9e6733c1
MSG: 088304f22e1a286062defbebb1827a64b76a14e87015e7f646178777aba79704688d7bf32e1efac97a9fc339810ebd3df93e4ea024686953ed91fa6d2ab6e07ec7811a6d91ca91b098db4725df65846a95b808635a8d0c5fe5ace25f0780e896177bc1bba1cdb4449251c01b482f023862f88e072e79cde5dbd6c1d9ad9c07c606f5df85a6eca2966cbfe0a1673968112f26a317053f167f611af297efa802e0a94b3e1f33a27b73e5597abb224115ebe75e294a1bcdcd979255b0a80265c089aaa7d6bed2e3d0c918f56f4a55f448d863365c6c5846fb9b2b9bb55f6b7c6dff5847b71bfdd4bb5b9bb2e4249bc0243a02ab4d22ba78a43d182195aed78fece84cb1ddaeb9eff68156045b2932e638d7731d0e8b4c9c8c383b0d6d392d21fc640762c87d3692b1810bcc4a42392ff13d45169ecbf0135055093105098c869b68887e934e2b9da5232ac6c9373800f70b64ec64a4aa0ca044c0777ca3a3acaa138c14249672a55b24ddfe4dc357573241e14ad0ac16475a8e3867886d41eea35fe7932ba9aeaa0c86c9eb6db7808049ade7b5cc1a40822c66dea93ad22d44b9e42904b5b83684ae2931fe36c608ff7096f1b09f811b02672804406e08ed9e7745676ce047f0f7f64708e49bb78754720b8aa226f5556abf05b56584645292dad08e2473639a8ce5475e0ce9192f8ba2dd32ce14c91975ab602f7c13538c52952d0396158c7cc6b942be7d923eeb523a73b5b411966d14ac96e5b096a52932a416292eccddb91071c88560e70ecd4fe2fe24d523fafcb98e4021502f4190a0515edcb24019eaca09ec2615a9bfdeb60eb354c84a1f3cec7ffd7e65a5515d47959a4c4ec48d8021b1754ae2bf84
SIG: 9b86a192b64f4f044ffbf87b41c7ee52f7a721aa320e7bad6425995990315cdd502be4e1116019d131a9218d19614ad95543b1889af0a97ed4d256dc33d76e08
TST: 622
SK: 7a57f2dda0ad0338ab9a13c9a3497e9c75238c1531589789227cd2749bc6e950
PK: 6f738dc5e7d9e240c9f4d0c06a5e021747568b69a75d507a2e0be7ea613526c5
MSG: 8c8575a11d2ff2c238e419ccb00633d04e8b8bd7742901d588dd6a2f00aa12f08ae41dcaa9338f8c47e95312192cf6b245a00ce688a029da56dd1b1deb0d34b5414fe1c21d6b63d06b8534ace8e866c933fd7c5a65eda95a1737a9ecdb17859149ac696951b82c230e8275e96dd02fd455ea675379e67ba63484b6283831fe3ffe52d6ec49b709106705c9d19b859de9fd200887cb44d8fdfe6961fa4ca2340944c764c704491208257e735482af8cb69041dde685241d3fbf46fda057248b8987be1f80b54eb54009f324dc450e886e79f912585b91c9dfafe9012262c471403b1e8b5c31fc5375a1ddf99b68edf9ed70af8594f7d84b2cc4911fe90500c6eebfbac085553550e35bd2e52514e979e7241e9f8e34cdf8513abe72510dff3cfec7e2bc6488641cfd0a65ae0e09ebe99b15b29d45ea67a57aad554d4f8bfce1386ace228839e3a8a534140eec3d37d51be361f5ea1883739f56615f75b055a06a91471be98bc9453783c358382bd0555ae9eb0bdcd66629a611fc1a11c653c82214587dec12ba120e2513070fe69e982f7a80ad159f6a325d977d01d050d116a62a4f8acab6c3d69ff6c878213c60a94845cae106de6c5d6fe2508d94565b7ba75d58d1ad47d76a20defa7568cb7fd66f57cf3774a21d3ffa7d8aa6d86dc284b70e0f17e7630bfc10cd1fc9a8d9c592d39f24a7b5c8e8aff353577e6ac9008690c7a159a7e83be5a6ae8fca9644bddfa37a92b07055f9fac9fa97fb3e8f5f4d917dda5c6dc6ea34b64d302405bc38062e07ce93a1a88aed5fbaf995a09b45b28ad4a6b273dec1413c5404529d825b5edc2e27a390eb7e8c2b43905e116d887ab5fb993dfe150ebdcf817ae62e03
SIG: 989123761d93563278fd0a78aed64e2de6f4a700fc9a70d2187748ac06d9c2c377d1995f89c7727fe2f120784e4171c42d6353ac3d4e3f620c639c75786c460a
TST: 623
SK: 32ef6d789a1ea393f1bf9f11de34f57d653c4e77d51e6050fef4e8d7bf183db5
PK: c1aa181e620f60525c2b17da8d290bae5d339e17eabceab58cd76ae066f41179
MSG: 11a9c3c1ba7cfb61ad103305c25886de9f8815c6c21f17a8733a024f9497da0540db3603a671aae837dbbba19e19f82ddfc8af855980a70125fc61cd7ffd10777e366e5e9569927af0f245d4f39b3fd0f45879c253401412855e5761905ed6ef318b6a06ea6e9f906f9bd016bcb694a0df65a016bdfe845a09f23e5086c5aaf375efeb86da51239ddc350bac0cdb03b874db1507e6ad4e2c9f46028ca2388363541493b6cb92c1dfcaa3efd68c6b4e91efb46751d23f4c48a973f0a5c7c6fe2a1269d2a69e9fc4ab8ba3b92f796449ba3dc70245ed505cc0eeee1636647a68c7679d0b6d651bba35c29b81478d17ca3685707ad616e6e5604381f84ee52b25ad02fc0dfb85432efb1fecd090c02ad002c1857fced88fdfb2ff26dd0f5018fb47d813581f6508ca637c7365177c513d1ee05879a65c5b676b3aa873a1935c5437eadcb66dfb052a5e7c3e81d44b3daf698f42244ee2ee4b6ed2b7e6e56e61ff9cb45e719fd746198bf2a7de6d25af3bc6c7b0ed8abe3cb389afd84ffa2a230d93bc0c29d5a9419cbff11b7883329921480b5844655d996c7cab29dfb2a3927b82ba7c306c4577b6f8b5dbe2afaf9bf14a8f9554cd01a69a991bf212828de1e63172e833de06698cdb3b28716380314572bf5bcfd34ef52a6fadda87babe6bacdb20ce63c725cb0ff61fe30c1b51dbda2c2625f99dfeb029a3e58cba7d01905111caf42f27025e720e18eeb07dae9155c55aa300e22eb5e94dc7a0a84ee67d91a960ae08ca632dbb1737fc9a43dbcfb3a879eb9fbffd7299338e264bc1237ab6a5bc2a263cfa99e8544439d96331639fe9408e54a350610ff01de3f85799adeb73d82be938074dea858ea636b63abd
SIG: 88f3a6e0bbaa3e060bc9d91fe2968c61126b20317f59842e4ae48711cdbaf62c6c0207405d1c4849950271f0aaa7593091109e478d13f356964f7dbab729af00
TST: 624
SK: 0a5525a4598f60992f86ba1ab9eee6e2675622f943284fc0553e4446ac5a4c53
PK: db60d7ea29f8d60dad33d02ec5f42232057bd1c4bd6180a242cb7ab6f4426781
MSG: f787321b42c08d4052449a488593d885b4e0c34a5d64149fa8b9c85ee54bcbecb50909b2a86b88258a10e07e8f8c2d068a89fb165a6ace7e64998ba57d89d9bf2b8b38a1f6d8364aee05ce3348bed48b88c2473bf5f2665f51ca073a5305358eaad4365d58b83bc9814e25f54c37cd9b68a808a57d6c2d7d7b6deb5fe20f4f96fe725f8de65c29a4f1ccefd7c2c6f2fc0116d58676acbc58691c79c2b006785a0975a31d8d3c949161596a068aaf2226ab842550e9c0b2610a29531d1f3f7f00826bb6c7dbe04e28ae1b9ff6f888a49d82812f452e1b32740b234ddd9642e18f32ad9a9af7f8952528674a2cda25b4f7ba867007ffa7f78f163db8f36914956bfaecd50f6d1af4ee133275a8eaab94bbc0ae52b6d9b2832634232ec0e8b5f8022d3ef1ead9b79ef9a16564277194f2380d9021e1f17b184b8d3a7a34d15139a39c7728c22e1a3a67a27a6ca4b8a8a0636c6054d0f741f046673619fc6b070e62ff4862f59d269007f3431339637a89f564c0db3d9bcfcd19fc25138ac66d474d80f4ad79f6d1e7844408e88034eeaff4a790338d546bfcd7424c119e211f363cb89c888749346a89d32f023bb6b0366a1ede4325032aa35f52e9df938a5027ebee9688ae480dde1a9c9b42d1a9c08f719223dfae1cfcd49dd1053aaa381c24cc9c7abfcf8f6d86d6af72eef05304412f3db2585aa9e0f3a4f1b6d710d02ab11db1fc90ad4de25d04299f3129c212e9cb73c0047953455bf98ec8fd2674e47b949957deeda018badc9f2f68a1b18ef5c583b095e08dd906da5f220da029b9c400e3ca91c7cbd87f3430c742337f61cf54745b0622bcb90762c6bafef87e1ec888c364fad646c33acc22af5438b84cd5
SIG: 8fa6b0aeac71132ad882975868f1bdb8c11f1a6c1b9c54594e0e46286ea6c9a5d6d5b0eaeaca9ae3af74e72326b3b6f2eaa893c0ec42a49c56ef514f75c77f01
TST: 625
SK: 2d5ddffa2e58c90451ea05de47b8c49234e26ced54854e3acef11d8ee6852da7
PK: 7bfd1c8a4a0bbb4606d2e5bc090f56b20d58f2204b6aed831d3df4d406b47605
MSG: 4f1c5b4e6fac3baa3e9010f3bf293c779e61fd7bbe05a586f5aaf08026371627a209acd188afb2dbe0311547940559711640f78aea9a62818962f445a8e7ed6fe6c5f49162e7435d1b625b88ba39dab0ad56fd2c0ad6512661362bf78afe5a1416b647f3b88a056c9e7289c9b0cc3afb43402198563493e737b1da052506b6c9306d75ad6693db6d1571f96f6f52990c4df19665a6bb63073fdd9f55596896a2e9c2622f2b0c2cc99ddd1b649fb0318058d74794e38ec657ebc82abd5bedf8b3f4bba3bb6c9935fdf6826502b769046b36d96dc695d7c85404284d2a2ab7fcf3b02f68a1493dd383ca6339fac1cde47f53c5e026d0869faffe40abdb98195230f17d0cfaa533315afdbfe7d1afc3a615b4f75090233a503f8861e32374e1ea9557674231d9d737d477b33ff82ac0b2c0ba93c11fb523e613618ed370524a60f4d4c83694c033606d1d069d544dccd3900c37a3b3363efbcf6697f9f762b33b1294583953fc53773ef56726eeb470ebe92149b73648a16161d494120a318bfb080cc38e4996f4b263ffe78c7877fe13c2fc55219f44260e8f253bdd379d870e6c91048b1d8d4e88b88218b2b049fef53b2ae1f8c921ed2bcb434669e3975dcc3fe4520ca8024842f7ff2ba1e22cfeb5d4c9e435eada601ff183b26364eee1faa59d19e6aa4f0975238496a709e46bf68336b068bd80b346f11faa3817a07d1cbd84382b2102986f295a1398077ba291d6b5f5bd860ec6177273468f0ee0f2591b575c4366e189b224e9ffa35bc78a4aa8c06954fe33d080ffc0b23e209fd0e79421f1bde818a86890cf172236db211657d1003119fe91d4e27c524ccc11fade0a25f57a7a1d677e1da0b9c043d02fca38
SIG: ced9d61010339c471ddf9fefcaa82d1eab3a2e0e60278553b4dd9f395be58149c91594e5618b0b10bf3aab94f159b530f64463eed66fa2ace54fd92572a06a0e
TST: 626
SK: 4df5e11dec80ecd882837554fa3135b9d5029df42027aa3b3c929246329fee96
PK: efd928898fa144c2d1c8334fa2e6b5b6a325a7102a2c344a145541ee9a6c046d
MSG: fbd6f371b4c8b152c9ce0c6396a77c0fe480bc02007f336ac58fd4addda9d69855ac9e93a45d3e350f41ff502aa1d8fe159ce89b064802a0a1890f6a40a7ef57c6e5e5ed040280df07e7f48fe819be63176710757cb6e440b4f78b5759dce028bf585b3c3feca1cf5981dadadfd27ea124af45ef638542a8617ff49f9470ac2285943c7c3b1163b903955ab99b6eab17f4d49ffa87207abbfc111c4b91f5413dfc9bea31843d115ddeb1da40b45f58f47c417b5e77d5818934e730eba9c4557bbf48cb7fd4e664558af4fb44ee3d94c16e883631f38476f4837db94d54122fa134ca51a525aad5e24b76018fee9a2e8f60e2bb48d24ab8b146f84ffa9820120e7c50d45c0cfbe35c8c31419b078e90712cfe934c3be3a94ff2158873aefe34dc6e36902b1675e1a47cb608dfe960fb4da8d2a8490cc38ebadc73a1003c4941fda8fae944a1de8e3b10ef6d9e67ceec745977d333ac9e71214121ede8892295e27799f206675a9d54ac12159d3a1f954fd0eeffbd30a31904fb2eee77a8aa9dc4ccbbe2851096146a4ce0e81fb9c62498dbd83bf83b55029a5e900086b9531ce3247a98f8654efd8fe7a836431f75daf0868f0108326e23026d2db4a72124ec4e39d4bbf3d846c9f51ca3cc31eb1d02c2ba321e4619f2b659c0bf0fe5c19b213f3c79124f3643f74dd0ff9ce5d27727be6c6958159c164404f43301fe1742e279de9efd441e73e4ea7a842587a79d115d36eca9c03c90ff0d147474109fc20a91d7b3cc22ebcbb8c7f71bd61e8cae47c5050cec1d4849a1d4a8e7a6f845548437706c25331c9e57c2cc6da117f2e5a0f4b368c4cb206265c4178e0655ff675ffc1d4c58eceb9edb4da3ad2c5f62cd13ab48
SIG: 62545e6c07801fde95b461e2e753c4b6c84c25124eb330a2725989d5e340dcef0c7456d4c7c6a178a221b6328348253db787a9e5510ab9cc278515ae3e58fb01
TST: 627
SK: 85d32330e2e073a46030ca0ee2df2f8eb874a9fddf5624c8031775111f11eea2
PK: 6ea7de2ed5ea5cdf50bfffee77f7bd2fcc21d48666bb1f4890c76a69cc7ba4e8
MSG: ae6107f38ff94ed0327903cbaf6c3e3a3498c47abb2989a8b37b3a19df88c6de790accb4b7258177b9151d1fe04063577d3c3acdb4c929968afdad6f252a67ed4ca89d060f1a4653983f7ab58ddb93e2878fbab0637dbbeb95d25c5986839de2748d9f34027aeebf1d9eb936cb6770e08d45b8095bac9cbb71db14e8a34222b1f2237b9f0bc9766a231a6d102799f7c081d500fbeade603cdcdd7d5b965fbace4be5c2cd932dcf5f6ed31722f41d5a363b34babf3f636fb303824aa701dfe1d3e41263078c1ebbdcb1f73f1245b83e3fa70ab8e3f1413e6b06bdae022b714d60a401d57480dc64e7aac6d3de85fc94d853ca13b7e67415579d5c672123a5af194bee14ae35dc2724ff209f1166638661f881b1194aa4e31b42a527964781591504ba76103f97b7f5520315473ec94bb017a16667b22a8576a7cc2ac0b7756303c756f0ddaae9d0189e6c8de349f91957c72a529e9f7e9b9456524840ba02344f55ad3c11a0b259901439f2655ab9f8c6c8e8e960c057d9c7dafe425c75d4a33b801d4547cd0551a6802a8005dd72424764dcf57e4aa22290ea4f5baac51d7939c05342882ee14380ef2d4704b41949b2282a1e1a3fa7ddea9fe83b9fc51d4eefa2ebac722e4c0a7c599b6925f01b8a2066dc0c26f92196f4f503e887c1e6efb093f1531387bd88c691997b9b89e3cdf7da12d3734183a4b6126be9e0774704b529659b5548f1b87512cc1878ca4ef55990b483c9af6aa97635f4f07949727065abf21e21e32990b1a7d07d74e02d9b07ec639931bf9e2ca3941f2ba6b5ef14dcc2a247d2117e9cb41efa3fcca24716641452beed2f92657c2fb731f0b94e8c892a81bba91f639df43796acd3013ac044f608
SIG: 414363fead6e59a3438ce5a3a277d62bdd00fa2efac6463dd13fcdded93a7f108ae1f528ffc8ff4eca331dab91ae5b1416e2ddb73b6daf853b03c81e9936560a
TST: 628
SK: 66590d369984c6f5ad3a89c78ddfca10a0a7657995dc0188b6b57ac3164731a4
PK: 98873ab13346ee48677c4f8612db31ebd13db58b2b034fd155afa8720f4e93e8
MSG: 2ec1c6b0829737832c9c798a92eb490b23d334c3bbe627cb582d17a9e42960efcdc7d34750e0b4aa864c204fb8d62b47992e91dbfcfd69f51d937dc06c48c0ad43e8598371cd0e3bbce416bfd44b0944b993aa2993fdea487134cde42277723e0683ec98e69595e9b7b14c8cf9617a1e30ddb8060eacba48d88253b165336108de0cb02ff20f5424b567830869c9b4329c9945f0bf2f3c7acd1e774358930cd890fd9cb864d950935ad8a4a3beccae8f833f6356191371c32633dcf882709b0d98bd807b383aed8d7bb097b6e262ef700c9d768f4b5690e3a1a8f21755d658db2d1bfd2f7071e0caec7c2c5381c5ef5c2c2281c6bcedc867390b90f3b27b0f0f64a33658578a5c0d66e211e6fff6e86488acf82bc0f5e2664b83699046037c0d33d340ff98ed6263354c24273136ff0e4f0f233a6c8254fc0c90764330e3b1057b1e666d5ecd5a2efeaa6a105bfc858431b88ed7fe551eb32ac0af27c66a9803a3bcf87634c66c7066dd0197a3cbd2d6f4e65cfdb8f3daf9f3ca5c4f4e0add45f5541aa18d041f706e4fa87c34e9a223d88572eb50083ee8c7c475df568bc73bd08c0f0deaa374afb1c178d0dddb236e15a8bc2385ed3f52b8761e637887407a20aec3e99ec830dae3167ef0cdb3f3ffd200d83b75b749690b9e25e2171d072ca56f71baecd21f7d45a12c91b2c0fb3fea3b158e54648284bb0095b36244b0b121f9f1384ce9004365e7772fa30828250f51985f1b17b2d2f80a33e8fc6d8565ea15cdaacd42a87bd7c9408b1fe1c770665bdded754bc2ff2ef91b973a86b99f1059c6f227246a698b38541509dd5449fce60d386224183b7dce1b3884f7bae1c2e4eb594510b5ca585279d9041df8817b0619
SIG: f0db63a1bc7624161ca0063853b2dee45fccd22471e012366f868a4a9c74654e13f1a315ad83916ebfb8dc31a420f83cf645c4c9d16bb4d5d99d23c7b43e2300
TST: 629
SK: 41cf071f4842ecd494191b8cf28cc0923185ef1b07458a79a59a296d3549822e
PK: 6dc8e446db1da353b58d0c45d8b4d816ba59e25bb680712d62d6d3dbf78d0698
MSG: daeb5f0e84f1590bca2b9d9719ef5d1cfa79e0583446332f18e9e4feb0b1f15340297ac9ad6724c85bb16558ea54eb5d702a47248badc6252a804371b74cfe1062d1dba1ec68fd1d4dd029cb55034bbf61068251eff3983636f6debd5727be91993b3e4d0abc96ec196421a47b7893f83986d6c0323f0d19aaf2cde9d3565c104c9d3176ecb5ed5e173fee52b5a0c42b6ab2fcb1ccba9649c2c67c520e9b96cea693df3e58609ad6a0bd522efaaf03858d245dd0a38f84a2fb1020f4dd97c3aeef0e24477d30d256701e900bef26a8a6269ab660d74293a2bf1d20c2cfaebb7c2820f5f5b07453bb69ee769b52391539f0c606d22eb3923ee6f5a1d46050af90f011f851ace76327d3d18c48170a9a25b04b770fd938ef8a30b7bd03391dd36c516b62f0cb78670740e00e69595c418d967253820b754c4fd666e3cce16ee0c94183bbea706fe298e1c99ddb821217ed9008cc8e8b83bc8b819915b07b146fe745024ac3c46116cb4cce5e32ec5d7524a2388d9fe297eb02811af4546fcd5860e14c0d13f03dd75a4249615900078a3c358c5342962bc1beacf68c246821a459ab5321ec9f574f49d10389f40f14ddfc8513ffe3deaa7336035a675fa5858b490c5d247780064adbaf75a76335eec9ab918771b0b1df5147642aef4a166ab172ed601fed210f6c0cffd91869f7490b57e7c65241863e7e8c0a26eba63b5342d0fd8214ac731e1c438d0177115f6a19e0935c7af6bc7dbeb75511d9bd8e63e3e2f47ab0dd1cedd7b180d74a4b44d461197aefdd3620465166a39b45395043ce8874cdd72c602bd3d2eecbad3466b5cb1aa41ae92a8afef2d764cec0c449d27efac437938f280bea9c50a582e57c27f9b3de872f0c
SIG: 41052bc417b24dc48383966af0143f9c0ba85bbefbdaf791b16a4dad1f570eb80703c0a2cdeb2f7ad6dcd3fa7bdb5c225e869cd8fb278dff0667d38accf3db08
TST: 630
SK: a2c8e161a8d9d6e888c3d09b0b972737307a2cbd2acd7ccd804d2431ac6c58d2
PK: 3a325775886732deca406857a8056010aaea2875545ba6f3df30754571386992
MSG: 83a3bebcac5f28c5433e3c4f1e7bf5d2e4dcd2f5e59dbee0a83b07025715350746f85675f1dfea374aa7d794287b892ef9097ff6d2e122f0a656fba0798cdcfcb3645dfcfd788c740c0fd04520e7a06a02a05829630a2bf0cdfe2ecca009ec44049946bb1d2326ddd61d7ec640bf69eb44fb23cc1ff478c570c75db7e766e35b7c43db73680d1407a94399fb621baf3845745c1c4ed0b9f0b485be2d53c568545ddf18775a837a05d9c9157b084e8cd01fc324f07f116877e4075dba2432c8a7752e9e939586ad93f0c0aa5edac94b8d82e5449997b15b8c8961589c442821aa83b60239ec5f158c3f5e9ec5bea5115d5fed61918e8fcd5bce61c777f20b6bfe803a69c6fc794ab8c57df271da863872a61335b1fa29f4608ff037f712069809ca642a0307c79aa92e10cb893a29d17201a0b6d1b46a7212b3baec9703c0b0392ba6b76e5c9c10f83599b81ea22283f9547aacdaa7f30896d1ff731e11fb9e56ad06030417119805bab63521496c3bb92a12f5e55afcf60ed4217737f3046b16ca506657a6d696d75a6d8e18e9efe2b08c8b1fa0728238e27cfb322166eee4ee76968b777b50ee6a2b804e1e9b46016620132b6588718d978ca2c0026979c400d3c5336751210f0b00d269ec8f4e2f9559e180332dd270e50cc9465c5558936355521bc3c9560fc19ec14242121e6bb2fff8f50337fc264acf1ac1704328334b3b52cba96d9303b1b5db859dae31d80f1711fba251e10b4d122128f9faff6872d0c0b81eef59541f832b0a9df3a4cdd591c87736b1aecf242c275a10c3fd67839dad4ef399b9494ecd77f7ba5b5d4f2ca304e5b22921307cb18fa64aa3d01c4411c8369ccede465ee369ee637d43d28826bf60ddde
SIG: 560d01b94df11d83347752ff51b3545ef55c5632ae7c8efb11aadd8312def72562e8f5d75ece10ad46bc96c860deece39e634a5f50654d4cdba84a8e6f70240a
TST: 631
SK: d3d188b390baccd95024526146b82b9184e197e46a9340a0e6ec18bf75be7fc5
PK: d8f794948aa6986100214e9b7b9024420806b4c67846d5bd506113b353a2ea3d
MSG: 5e65658e420375433fd7c1f6be678841e58104f10b4c676359d84fce7992f5c57557d738f830b505fa0c2b9eabf8d1a9f81fe8f315d662e2b84ce95299ebf4e503b5e1f7f8cdb668ae733f3d0cdd4c742ab5f272bea4f18d183e8923847662f9a39cd4b14ec76d11032fe573c26201aef66601cec683e34b89afd964e987801c706a85e27bab33701cd109bcf07b27ca67f022c494a04cbe5a9c6d63aad936cdf1a180fd05865198b96f06a78da95799d3aa4df3b170033c69e8fb04288c3546553b579c0ae3938062d3d8421cfa66268529bec0271e53b4ee7d099e7148a802df80fe5eedee1c903ae8ed4d640ead761262dd4014f25f9397ba3f1c08d83a3c485cfb55f89919aa972d6b7e7711be9e30c1eb96a0c3845309fb23dbc75b6991dd6e48cdde90e04f228e8ccf3ba23f2747cfb9d3381a9305f816f26cdde41c0220fad228ff6a8b095c77b6bae8fa3368142724bf1f5e0f6fbca5320c215b6ba86b91e3a8acf750e93fa7eaa65c4f785ef8421a19c1e27bc24b428e08a90242abac9bd4aa03c656f8f46dc40b36152c1bd0def1acfc0da10a2fa1dc3da7ace5a8fd76227bb1a602390fe57afd32efe281f2ea6b2e4d2545cb88d2308d72691c9a52b4ca25231a0107f25d117cc935397621c683bdc8f22e810340f2cbac4ceaa3468665261879f0074200743e0de5f3e58308b98b04b8c7148a4e004e667e832b0084b5f2bdc6fdc959f2fc28a8d31d9a9e78e5d5f9c0b119e5ff1f68f7c0daf0c0f16947cca5b7ced09601e2ebed282ef2bf8fe9a27ed27fc5bcda8aed6c71bee3e7751004472689bbf6d9d07952a242ff870d7c3f5e1ffc2c1f40fc9ab7579b392b554f3dc588c03ab957431fe5d02cbc711ad489fe
SIG: 16976b267de96e38dddc8478075f6bdd7159e56334b2d2d1920946294f33cd6b7f9c50f8057f496cab5d94bb4dca262f9f0fdf9b1b64741f4b722d32efa82203
TST: 632
SK: 61917a975cb7ec564c708a565388c57236a66b697dcd5a7f10bae671572ac7f0
PK: ecc0f0b99276e528f82b42f2efce8579f83e638c6acefd072828c04e434f55af
MSG: 6e970e0b1c92a7f496a82d8ae80cfd0ccef1d2c799d41728f35ddcd603b421c2a5ab3b489e78f4b62297de437c5ad1a9683ff87fa28eb3cc38ce242af59419f9fd43fcaa54fc398992f8c8e31f2b33dcccd0ee11ba7b388e8d2a36ead067c6beced5890ab7d4a94f55dab92128a0f814c0e68971df57bd5078a7403175c7c2fdd4a52447153ab37456729aee33e5fc93db8e7f480309875ecf6db07ce7f3cac5de49e361275ca50b6b719f4b715b3e30863cbb3b7164ba9eb96ef3304b19ad4d74dce4bd25e77bbbbeff1ee7d1fb55b9c4f7fc4cd9bd55108afcf99c1a41cd6f6b1adb297b106c8ba24e3134f87dd8efe5cf85492291b94d6600958c28b9122fe6e01bd3e329e42d1926b89f7a8c40a49867e5aa3ad749bd98dae7d006b453609e7dae26364d9172be7283330121ed2b4027e0885118743a6ea0cb7dc27409a9b2820bcc242ea10a00937bf849201e0fb6199421f163e9794f2dd4b332014a09d3ee8071da787747f990f5179919027ddff7cab0f55e9afa8eccb16cc2dd3cbbead7ff7ec818c253393f748741f55407f7408ee33a42ae2d6ecb3fb600a71f30ab630606e553b43678e59854f3a2947bcf4ea0fcfedc314d8370d1266395fda3c9105e975952f60e3086bb82481513d6fe8adb4f95efb9a95b66d480d2bb171078cf40684ac69a789c7fb7fa425333d705db00066755df728de02df25bae34f1d7d49caffc51e9ba2b10b98fe4cd9d22b7764ed931edb5f0b554496e995391e0af0b8d1c7a8295a8d15a7c6556d29cb19e0855ca505ad01d2aa30928a84bc48959576d812d9b27b8e88879faa2806c0841360ecd0fe83f5b848fc12f658f1e7f40e561c2e78d3b0125210a92061c2db21ba660e8608ff5
SIG: 6abb3e377b5c80b74f77219c1a9e096fba0eb68990817acff12dba7f61c77ccf595fb6608552003cead06ca1317c9cd51ac4724b29f40921fb92843376876401
TST: 633
SK: 7ba25f2797a2836f379d6bbcbe9abf4f2def5e52f72bd9e0b006571022fac2f3
PK: 6c2ed4e8c0124d5d0540796d3945d1de71aa6969e6abea0f1b0e6fc429c7046f
MSG: 171a3409878097b3b22b2c00660b46e542c2164c00bbee54554837940e70f03da9916a40f9bde8288f45e47bef7ffe4e557cd4474045e740fd959d984f4ec81da88d44a373c1eda0cfc6b08e351373d3b82ab0902df8063fd908e703e0cbec410ab5cdfeaae00188ce2ad42b8bf04f7daa5f0ee333a6f9311b4ad9810952d5d5a64b20f37e845415fc3cdd616febec50db296fb3f3bb7f6b366bbe52e4897a05617bf7c981a62edcbbbe5da4c39cafa869aa2b2734e6cfed90ed8be75949390ee44566892455b890cf568b945aabb758d3854be6539f3b86bf01d188e48cf2626a0d7d381703be6ed1290dfb947bc2e0f83dbc58703080d7f5b9ef19aef930908f68f0c80010a9401b303a9f6da805bb8a0ed0f39413eefedf919ffd8ea6391bf95d4229604e49457b8e23bec611484cc7f9832dd95bdc3ad177c050f4ab633dcdb3e691f5902873b38cb0720b9113357fe0cfb98a68cccb5d5f0809d59a375cf7b5a275d43c4c34ff68e448526e8e1aad44e20008a232afbcf532a42b50a025a1b2ee4e077eb0125a593d51a200ec20d872c05838ad36aaaeeccc3ed9ef41f6d122670217d5c08f6e13c172194589acc3c59f7ef790c7c85aa6d5eb69d4c89a72f5e7c9246985c1ac0c5d197f76a73e3774839d4aa2096aca190a30f4aac54057b64f358e0e06400c0df2f876412d34484c4344f4d7c866517d3efba4a90fa7144c9ba5db3361db5769403ec81626a511f93e30f8586eadfcafd9a36ecff8d24b42079ada8e579ac30851177bce9038b0e1300072d68efdd723f6355064843275815a66b9d73a1299aa59a1812f6452fb4115ea2b1f9ff4a99690596e3f2022d81ed874dd67e6189ca0e68b9304e993a95b66665e0d074c
SIG: f1f590a907ba980eb0d648ab4ded5f92faf7cb851d81d858a78fa6b77cbbe12f64d20df52771a7d5e539a152d731e1903d4211fdcfef9a48b46c8fd5394ca009
TST: 634
SK: d1e1b22de5e04c9be4651dd73995a3666cb5352c65ac7b7051b366fe1ac0c310
PK: 12fe56f1012d5c12f135ed5982f382ae5f1143bc90e8cb8c93051754551ee90a
MSG: c7f218b5aa7aae1799625a56c4d7d7b02637e572f1411a6122f113791aa3c628e819602fb4f0335a6123013fa64e9fdc4e4ae497bd169c2fa77bc236129717f462886b410893fa7809cbfdc892223b40ee041ebd4ec7ddab55be6081a1646643a9120baa46289acba15b3b48af3b7adecd69f43eede79d9b1957e1d8c3129e0fa0579d3d395370461b0e1255c9caa94e4725601cb9d0e2d60244d15b64e1f7bc9015590ad0991f12f8267311206e9eb5d16add0ba5218fce5fffe1c9ce5ffe1f731132f4b12cacb02f97451710846b7f824f4fa9e08919266469789c00ce0d94d38fa8fec3f51f2f886e9db09b804470b19ec9e80663f155b4984d2bbd0b2ce99302e06c64444b696e3129fcef34c3dd00f7ab5beda747a3fc6339192b740f3569b67dbd6ffa39e271faa400d9616bff86ec49a659def2e7f5d451f2a2b35e662a6e7cc22f1e5cdcde8a59988135b7e76562743c1e6a099901b3ef97cbff23f209bd7088c2f03245279a1dc78dddc1bb0c1d35100357882126b328d3d94e0871b60be253fd1b6ecf03c1db731d9eed0edf2b2643230780a4d66e99179aad1b82402e55f6d785ebc80f8dd2fd2beb09f31035df62c17f428ed0b2d56508db31e6d2dd5fb69ebeeea3257070cf2fe67d42d28816a55dbae0b185db4421bbfdaefc79c08cdc1accf71642562ec70036da2bbafa4a891954c4ee4049b55c640e91930e39e3ef1018dc1647f26942c6dbdf4d56e41eb2c898c821fac17cc273e8e4aa5608a812cf4b82f96019c252d56e7805298ccbe8ce40b0bd0f933b884c0faf97a958b20408b8a5297cce5527b2ca212806e72a3264457a7fac8662b82ca233e1c7758dc6e4f1b9995863f25f747bcee43b639b1f8f2026d2d2
SIG: abaab4fa6aeb0a0b34ee0d613a0af049edb4cedbfe9d3bebe9c00618b115b9d1fa524ec3495e1330b0936181eabb14299faccc40eaa8cca57ed324b7a6420c0e
TST: 635
SK: df294e477b1b91c5ac5b98c330d222d7cd2d53e7d0bc0ca403df4ec75327a274
PK: 5f0bd22f2f1896d1563b4f6940c7df89efc258c0ff6c2fcd674daf4f59fcdb60
MSG: 3e42d668409630cbb84812ac7ff1154f70fca8bdff3f1a040fa3af868aa1c4e91508b1aefdf5c3a8b4b077a4d162d2c05bd364fbbe8c5a08314c2e07dffbd6e8dd2e08a0dcc96ea92ddd4c97f79db9425a6c6b34c46043d09a68b7687236a918d21a561610a13ac5e446e0881bb26cc8e28aad1654f867ad82ae33f8f7a78a65be57699475516a1a8746843e93a1a294354624fac04d452ccfbe4fdd92a951aaa07d26676d5cb077a5000d439c124276c0dbcf86e7aa153cc24b5aff677c6badc261c289f4a4ae519b2e2fff312fbf0f5b4c4698f6aedd8fcb1d2348942de3fb73ba27f6db14c2f09180356e5fcae1adf65e22425f8c27f19e989483506e5df57a1b613a22e345038b3ea91c0f78ffff46383f38c72225358a34570d6f664a17454a151613f01cba777f62ec831875ec5e27d257f180b6366cb183107c40f50b01b2b9bf91b3b5549ed931a3537aa41689f72b257a6aa39cdc6fcedf143983be5bffe3ae2b29f82f882122d66a7925f5a710826c0dadb7e4fa4ec079ba2e76dada433f3077cb1ef74613fc5dbf8258b6da7c73c866372457ed500f97f9907e1fc26353c70ba3bd9c36151d46865d2c65986562485cf8421febbe777c73e6cd0026d66d35128b9f8f33264aeb56bd3e4b8d1f5266411ef3b23b76b36d4c9df3c512fd560c2be52ac523c19377ad2adc0e8c309cf5bbf72d9eb85d65a94847d497d8d102424fb84381666ecb1c35a3725d7d9e9284fdebb6b362aa6a9c6fb37aba87357f574c0e63b4497d498ffbb7d0692d784b4b18ce9f9150c146d3d18c382eda04938c69d0778f2902d5235a5652b97cef6d5f60da6bd7ed4ff97cd94d4939caca3b6baa3cfdac04cda95596f467cbc6cbcd9264167743eac1
SIG: 9945ab73b58562b355dabc4e2b6be7e05f37f89571440ccc32c1a94737095b7866747d21007000a0f0e351114b88e0138b55df44fe72ebe9591410e707fa9d02
TST: 636
SK: 70c6859f08cf42b4bda9eb62979dffb7cb08eb3dabe93fe94b01384617cf6730
PK: 401c9e2033e2259fb6383b3e8b9e17b3f2062746bbe648cf484516db0f2f1b06
MSG: dd0609ea159921395d11fb2da8ea4f747d7f74b58052e01cad40a271fa0bbeed91020f4f0c0846c4f07778a6aa768eb51712294e9e1f32a602b152514f5e6d39f9e08f7a7812bd900c10a91469e47e8a78e54cd4bd7cfededec171ef373f1c4f9bbc2c81402fb14ed0bfac8d043f117d6124521afae0916a510d568acfa3aa3301bc979ac28d551dbbea6ceac4c212aa8c8492b3613ae7395dd4125fc4c25d5b4d99230821d4b17ec2ee6be7d604195a2154333b973526580ca7ef9e30c6c1dd42ef2afe42b11b1aa49b9ccabaca17091eeb380ec5e34ad1e3827cc60dacf144286c7892590bd2671a8dc5f3a702c1de7cd3b42c1b150b09c3e58ef6943b45d89d41df361f1d5c25565591b6ac8deaa73676531f6e5abe5804b0097f8d45ea2939177333cacef12e4b71fe4936bafe00747a8930bcea55b8fd84a01f6df84e7acb931fc7c01ddfd63deec3ad3e69dfa2b73550583d5747eee96c5536368797e247f23f537d79079ab6da314102c7443d41960e3a3d8c359c4a4ec626fcc44e110ea744d417aa850db8ecdbfe340a962db0d8c57dc517be8b40d14de97b1e9e0426447fde0a04e50679c53ba1aa3cdc38c7ede6db6c054b1e9ce7deadaf93ebdd470791535f3ecfabf3416355f7a18a38afe6bfe507ef08c4373a4a69dee1fcb65b1631a0de1488649d0bb2679a9a45f67820b2a4a1e5a548072da7032d172555e788cc9860ebb3c0c359493751b0c2c950a7fcf4803c147f9340fc93d85f1efa57b39081b92d93473fd23516c4950ed4b29a2ed3a042ae3d92a1e52cb709636fc7272fd747208bee2b16d191e4c6deb27672aa34e43914cff2055ca4ee8ba3e1dc58a679c7f7dee2c1d53e28750970f57d85eab1c26b89bb73e0b1
SIG: 0f03a4f15c339b4f7b88b4e21ad9e3d6bbf3effb7b678ffa500d47383b71a7454f62907b56f59f9b9af6d5b2a0fc1c737a64105195089899f57a2c9dba509e0a
TST: 637
SK: c5962961815b57cd162403ce08e4105ddb8aae2d3f533fb49cc236b5ff504d6e
PK: dbade72236ba12d4977ba46c364bb69a887ff402de91d47afa9b93c95be71e7e
MSG: 4ae4148d79ca9425592aa240bd153424a3bf4ae27395872ce5728ac7613596a77d5ce8565d8d6e1b5935b3906cafe1ff888ebc9815e04a624dfc4c6907b85f6f1a0dbddff62e9151220d474462cb9f13d89d3a93a00ba2b60f7e7ca63da17a6379d673551e790b5911727c906dc94f86d8277546c1564a45573a7743bb8a138cde87b3b2f28e5e245940a51e7c458cf8c5f0a70275962553e0d2390d171db44c2f7a5c9e9f93b90f7a5f54f191b0d875bad7e0beb980c2a3365cd7b9208724f4654418117e16ef7134e3e2794b6f9e80ecabeca3254e704c21b7ad30c5dee017ea2533fcd94251e55ae75a8cc6db6674b39c88ca42006043d6bd9b00ecf64ceafeeb402b1f22fd891f2d11c515c1aba6a2d4c0bd2181a48e43fd1c0af91f9b7b7d37f3dcd9e4c0a759748467d348a8b116df6a4eacf178aecccd3066e92dca45da7a3e319f3771eb3490022193c5b652f045687e1705f2e5691c134be4006353d7ecd0e918d5de0f3b87809fca4acfab94e1148ff7cf07f7cfd0c745dd2be01a24a5e069280698bc3f5400a6dcd08e44595c0388e44833768fc49104ee115bdcb02bfbda179d164ce969936629f2335601b56fe8f785cca3805f0403872c62f73c3ce80563d070e976d8ecc51124e2cace7ee18699047cb0f8fb8d9c59b8a60d12c08a09fce58fd92cd36db6a8e89d118cf88a92dc8a2600bd95f5a8e85db5cdbb249ca812ca209c7618051c4564a3a0e192b7e45992456c87d17412c11adead526ab8db21452f7471d17f2ebc90015450edf4f0a44fb2f4905f74d70275ccd89b93a650473c02a7da0cbc67915ceb7a1ea59fa8884472dc917ee9d246339c5926843ecf53fafdc56a695601a276c23a843e4d30f89c97c9eee6dfc7
SIG: 8101baef004eb6f5ad4de0979ff36d3439b8212bdc928942e431915b3fd18bc2ad67b26f18941dcb16d2c29191421e779fed622fd9f582644eaadb3fe5c09803
TST: 638
SK: dee6866c7874c127029e96e025bffd35fcfdf4dc36966c15ee6293368013d379
PK: 08c94da351bb2bee72e6e196be748807583762c5296e05b1e529c47c6bbacec6
MSG: f1aa1977f5311b538b940ae442a3abc89aaccdcd0a79380a24258d4a9f1ce638fc2f5ba2e53f8e1fa6176f178d9024a77894c28cad42d629c793d68a02be9411b527acadae7e5c3851babb45b5fece329e29034cd42571083727f35aecad7c9be5954ec64e8f6ecab7cc0590e54156a4e1a45303849f7897e72cf2fbcd84f56c72f941dbb0b09a32e6386fbe18a43bb9bd8b793e4b9edd532103eab54d627117d28139b64e60fb0b81d09001bb2404d925e265babdc69f96b135e9e6ab7febb1ed3075d6aa2abd2bbf9b65fa9b3b7191ef37b633605910ee88f66eada79f00f536d380b82f2f4b5985112de004a56603f4436d8ff300f42bf5acdc7a4bf1ea9d4196c480495bacb0067630fcc000b4f279dd3f30f353276092d152c3f43efdc041deaa0bc5aaaba7f8bbd85e69c13742d678dbb65360aaf7b548a044c0ec60a57af650bc31973f832f961265bc2318f80775afd51f55194c42423f7bf4e0052f98cb206913ffea4886ecd27a4179b13773f947502e181bf1a1f2c62c6f08c20359f06df2b18127043b1070d0194ef5e5bfd37d227984cfb10989f21c71ad0fe3b81227d3a71789455eda383c22f4d2fcc72579f465e066f3d38befc024efef6c2e329649ce434d627367a900d07fe6234235c84656eac5dd0d788cf4cb31871824d66ae4bc89edeba1b36701298453e8da1e69cfb868095c3be6ed2182da1cff4905afd20731ac1ed984164737903c7d8bb0ad16aecf2fae337404fe35664515d93b701e2f878664454c0decd1c6558adace3cdb227507a51606f0a54df8dfaa420205dd57c65242ff24a405ef85c92d602886932b35fabe9c3bcebfc6235639e873fc2dd084c52cd6a7413b831d1cc99931373aabd847620eb69bb0fa
SIG: b78ebd6d65b175d4bbd3d9a2082a0efe6e991cb2e403521eece00f418f2e956b66907880658b9e8e47699653d159132380d9ce1109af9c2757daf4cdf18c9c0a
TST: 639
SK: 523623555995baaf2a27adcb1ebafaa802d23ef7abfa9775f2c9bfa07d64e0ac
PK: d34deae6523e619dd1bfc8f3c4ca4b78b368c0f720035e144c3f2fc105d4ce21
MSG: 0553e69ef211652d62bf281bfbdd37be22769d819746361c7d65ddd0fad677cc0438b301d1514578e0da58e55f729fa8e66ddeb7f973a818d24ed8fe027b8491179d07773fb5d2bb96aa85d6b3750454e50de91f9b88aee8aa68e6bb53edc66677b41e601a46ab4bb1e656e7fa5f0179933680a6ec9504275e7adf7a3248e63a0fc9c1ea5ae96cd0c65a89a77cec2b1fd8f4537e82c1c488a69a0ef64f58734d9e73478e1d1f123114ef66085e0ba319cb810b66af96d1308b1a2bd92ba2c265aa309ecd5557d402c3802cae8d7e95007fe610c2aa75fc66196c3fadfe997d6d5998e18d260e9da31da9218cbad103cbfc2c7547765d67e81f24ac83022ef51c6cc50864366a35f6b9b9af94e84caa9fd3d767c831f0967a61462fbcfcc803f12e3739039acd5dbe9366f05a33dbeaf360e2ddcbe5c443f80ef2ad62e03c1d5b70cdeab4a7dd41553064c8d152709deff82076b9071192376f51d4c2c71a84e89f2d9401320c2e459b3e243cca7c26fd098c264ac88ef638921d980b0ae9e512d372037d81adc48126d7c9e4b5afa57ec265d401b9653e928afb7dff9b48e295e470d6b52e88b39d0a40cb8eba249f8b13d81113db1d3e01ef75c722f269488e963cc8182704f8ca018e73dc0714e9a9fc79bc4363c28cb3984374f73b2aa8786e74e0159507a29883fe0ed1c600f525885f2f10ea006c39e59b925b765b1ede534257a1f40f2846584f069746b52f5600430a2863d7936095fbc22a6ada674d41b374e2b8b9a19fa712b5944533bb6d6ec43b89d4971b70205a6acd72a899da12618204db0c3e8267b845791693e0ae6a35f14da1f8f4dd174bce0318fb5a00f672ede42304cf04a62760577590f27e2dfa6e5e2795d66053b30af7f1bf
SIG: b1871729fec83aea0aaa472b700acd094813fb7d57b909e0eaaf21ee931847addedd2be8533d0c305cb9cfe5080e76c2808b6e51c9826290ddb7b94b6f7d580b
TST: 640
SK: 575f8fb6c7465e92c250caeec1786224bc3eed729e463953a394c9849cba908f
PK: 71bfa98f5bea790ff183d924e6655cea08d0aafb617f46d23a17a657f0a9b8b2
MSG: 2cc372e25e53a138793064610e7ef25d9d7422e18e249675a72e79167f43baf452cbacb50182faf80798cc38597a44b307a536360b0bc1030f8397b94cbf147353dd2d671cb8cab219a2d7b9eb828e9635d2eab6eb08182cb03557783fd282aaf7b471747c84acf72debe4514524f8447bafccccec0a840feca9755ff9adb60301c2f25d4e3ba621df5ad72100c45d7a4b91559c725ab56bb29830e35f5a6faf87db23001f11ffba9c0c15440302065827a7d7aaaeab7b446abce333c0d30c3eae9c9da63eb1c0391d4269b12c45b660290611ac29c91dbd80dc6ed302a4d191f2923922f032ab1ac10ca7323b5241c5751c3c004ac39eb1267aa10017ed2dac6c934a250dda8cb06d5be9f563b827bf3c8d95fd7d2a7e7cc3acbee92538bd7ddfba3ab2dc9f791fac76cdf9cd6a6923534cf3e067108f6aa03e320d954085c218038a70cc768b972e49952b9fe171ee1be2a52cd469b8d36b84ee902cd9410db2777192e90070d2e7c56cb6a45f0a839c78c219203b6f1b33cb4504c6a7996427741e6874cf45c5fa5a38765a1ebf1796ce16e63ee509612c40f088cbceffa3affbc13b75a1b9c02c61a180a7e83b17884fe0ec0f2fe57c47e73a22f753eaf50fca655ebb19896b827a3474911c67853c58b4a78fd085a23239b9737ef8a7baff11ddce5f2cae0543f8b45d144ae6918b9a75293ec78ea618cd2cd08c971301cdfa0a9275c1bf441d4c1f878a2e733ce0a33b6ecdacbbf0bdb5c3643fa45a013979cd01396962897421129a88757c0d88b5ac7e44fdbd938ba4bc37de4929d53751fbb43d4e09a80e735244acada8e6749f77787f33763c7472df52934591591fb226c503c8be61a920a7d37eb1686b62216957844c43c484e58745775553
SIG: 903b484cb24bc503cdced844614073256c6d5aa45f1f9f62c7f22e5649212bc1d6ef9eaa617b6b835a6de2beff2faac83d37a4a5fc5cc3b556f56edde2651f02
TST: 641
SK: 03749ca20458a35a37a8d7a26f959f0d59f6dc9973fa363c1ff8ca4e638c2cd3
PK: eaeb94f406bde6a7cf8bde2adf3081f8375b87d9335d496c71d042cd2eaa166c
MSG: eef5ceebd0445e9c9181aff9c6f2660128fcfb63691a42cfa443d6a649efc5fad8c20803763ee97d1dba08e63e08a2616da05077489f2fa2c56b7534f9402619251fdf9c320de7af109e2fd8b2565ce8a7524c9405ec0f8fcaa7149a6d210efde83b111cf82dc0835cf94f20cdb021b73bd262666555e6d62707b46ee42fa900b4f4f705de33d3dbdc68a88d1a4d0ae933566db6c6237ec8abe1024dac4b7f46d407be16594d9046c7312dda6614d9bcdb01fb8324fc62b8eeaf0abc23cd570e304fca08e88c735e5d31592409ceb583862e6b0a767729f7556fa2c053644d36c8337c0274e749202982fb4a171acac196c02b7f16a8da49071c8ab8076dd5d3abadfe3af82ca85da02dcc1c4a6f2e1930bee2009eee0d971e40dd12175c8d00694f0325a3b3133c0d0bd382a5194fb21422ce67c78a5a6e1537e3b97d5e204e5d195696390f77d19024c1bf6b5125a0cdbf7b9880036181c98e1ac2e5165bd496cf997451a1c12102e66946b1676abd4cbdd2c11673f4f2cd5f3c9a434d747fa05b40fbc72268b4eb2842e4741f51b7709b6accc47fcaf70d9c1c4c35867119d81cb3ff1f16081133f1659aed85f63bc901989e2617fcce153c2978d708fd02449ae4d538d122ddb8527c0a76a102eeff6edb65dba298d3c217f6551814eddeece1aef5f371a54f12bffd6b4961819a0f244ff0d7d8694c14422de9822c13179e4eeb81595079b9dd2ad1e7c39bd303cc44ae3f3634881577a266fd6bb7917812b999dc809dc09c3d7019dacd28e43013a2f9e4f94bb0bf7124ef091783f796397f6463bf1efb39cd46f3790a1d9b6a7c30f149b5e66c2937e39cb9744ddc66ab561bad4e6fa8534d69883822643d63d8bd7b181621a267e955e758d1792b44
SIG: 78a3877e02bdfd015e7f86a327a48cc3a5230bbdb1243f1a8cf227f78ab5e7680de301a915dc11b336fb5f6566848b42500adb5d673969122ba8f0053cd3060b
TST: 642
SK: 53cbd6f68cee27b9f7bc059b803b447949bbc9c5d5a38652d7789ca15420dea1
PK: 6116990b5331e2165f82743f01d8e7bd5d7088b30159833fa7b939cfb1cc04d7
MSG: 306f8e1df0a4ca78bd77e8e1191c94deaa82648355c2aecb7e82fc56d64c504619247e7cf8943328d11f3db4b1dc148e8ef6f6c3bc355969662a281a65576391242b7bd5a62f8fa7acb604e3a344ae1a9d732a254315f31a0464c1e6587462d29212c40e5ecf061e269aa0b90390ba41040721684bf2aa9582d83066221db60d0f7ae2f149a36e16952704fb1f3a982eac6b4583665c63e5a8996f24a566dd506a33d4ec8a02b2bd34b714c745000c0128a3c89d942506d12f4beb900e2903cdb34b35ca9b6d3ad9b350ac99f41db3acfe7fe55a28c0f006b844c9dc4853fd98535ada79416dca5fee5803a2d9f5d68e6b80539ff302e973f24e9bc88b7c4194117ddb9f932b32d5ec74868a13631ece68814b931421dc890249570341f4b423e86e8ee081b22702f649a6c7a0b7bdf5fb756202bd10b0bb2215c7d6597effd852f0b89abec15ea82257689df81e338254f93e81cbf061729d483eb5cf649805d78ed892dd0bd248ca1e252bea51847e1e82d39af58050dc4afbf9115a3a60493e8c0ba2e86e0898cd0d430891b9eb0a40f87431e25f41538a030f884fab36ad11165d267e8dd94dcb05b93a5ae77969430e1810134e157251b982df343dffae6123a99aa0562d5df72408f1a6e29c4059a5a8aaa4e621528fc63a9cbe1f4c0fef25fe3f8e18157774097a9d91020a9006b6c860ec1ee10d521d203a1f8bb82561296faad4b2203da53b207a459b29c18bc0649332b1807c13ca61acfaf90779febbc7f3242164797e6f572cb15a9be5887343455e26b910c8befee42aeb047f9abe6b3750dbd7de99202a0bb576ce1489e61c1f5d27c6792e63218edbfdb9b3dc515b4254d82c859e52ce6bd7ad296dd0e3709d4c466362f90265e99da7d0b701
SIG: d82504405ff16ba6443dc482367263a8e200360acaaa83fc4e4b72bd249f16103ec7e5a7e9ca17198f888eaca16b740cc3f5c3b7b617a34b9491c3ed76aab30d
TST: 643
SK: 8b6574f6d7396981e223a4837bc339c3fd659419845a2121bf85be2e695d860d
PK: e3811aca70634f5a9ce4b592a17bb5cfda53442422e203cda9504c9d65b263e8
MSG: a48aacc0495fa0f1259b27865d3d75dc52c2c828ea8c4c2ad78577072fef7270f6a4d582bb7b962f4c3fd149a60a06bc8efd2970ef03148ddf6198b9b695a69fadb5340951cb75398ac51a4fd55430378cd5da8885210bfd2146f95c627632fe8be06de01a7c27b89deefd67efc69c9b5c62b38108f776229143dae660c10cbea3cd4f7ee53dc3692ed01177e4a6f7e424b5666f7f495f2a65602c7d08c5d572234a567cb6c38afd79cab5c4036d62637aefab5588769a448ab4c65e24554bd4158050e09eb58f99ab40777b0356709b7c025ae5ae5422acf87444931ae4d9a8b3d94476881128ba1eb7328fafc75f6b9dacc96d3b6487ddef7c59262dcada426aacb13922935411566235e058372622d885bd0cc04958dcfb17e08fcd7f147e20156c8e26af85530f5511a68db43dafc4e6a23f667df3743eedd71a3f07f76f94d1688afc8463bfa5a439ae311469948e7447064f0b0506f36719c13466a1b98776d967ec58208ba674037303dfc6190da783ff27303b86b5fc3211f01c915e83a6ad0121447911cbe1cf696f618f60236643f2e94e155db657182944c1a43bdc7bd5eaf3481fe1284092cb3789a892bd79a111fd410143cf91ae332860b1d29aa041d177b50d6cc2b9660d328c0f230a3515e6a0d688709c0cd347ad2ff32d61d1e1e9ba76f81e873a6c420f1707f3841db5196cb53f506f0006352c7c44c080f3096801a57a49cfe84205bdd7a9801f843cf26b9558a2db788ef1b237915d587b9ba9779890f61fdc91e03e4f4cdbefe417cc22d522a86adddb53f3747450ab62b576565db32e0cd44276547d9a16653c279659dd4d17ec04827c533e33390fe94f793509256db67531736ab3fcee2a301ac3f0a24d3b108d7e75c32a5aba36d6
SIG: 2fd0905475a2cec3e76f9909b8afd83beb8daefa77afcda34cb4f11728ef15fc9c1d7f6f6afffc28f3874f913e17980f0e8e3d5ad23951df2b32efaf6219ce0d
TST: 644
SK: 29b2881b8caadb336e7880c510b80085f4b1221860b301eb4525650752a6d289
PK: 0c5c44ed29d21bcadee21cbde61a9cdb6d5936009ba2f5b2e777c924ddfb6751
MSG: 1974a2e2b47949f467a931d1d9dd5ce116e9f5030ad09a8cc728d1aeb148bbf9acf59874da80e708d53c668f2f14d7522071e909808427b2ab5a05f8b94f21505cd26abc53458978c784d479ea6dab105c4f7984a0fb9790e50624f4734b551905aa5ffa60184cd201cf2b26c9795da6e7e08d6a0bc7722400fef94fc21038be89d34bcd14c427b85b6866737196152d4eeb66d05b245ae84bdc7787c14a8bec2eea5360f042433d70794467d47393b93757f331cf2b53c660d71c29582aeea79b12527a28b0c5e110df6f854eead9a2b00d42542ca8276bb8bf988baab8565996fee50cf31b2459c4c50ab475265e83e2285d43fe1f752a55b2dbc49fca04a810f0413bf6bd81b79ac64ee1f89b97bd7d26d62512273e24a6bab2d5f7d2226baaab7b111209bb03733d8a60dfa31a516f4a8c7699d8285c1065159a6c7331c1defb47a30ef5858c50b7d045124a09813d1cfda5c9cc3bb5bfae73c984197f8f857f186c41ab87fb7962b631f4d007cfbee221fc6572784a551194c19777b08e6b596757e7cba7a0e27fe453f90dc59cc08c6472431c020e8dd0917590e79c1f207383afb39076ad24da8ee52486739453a2590e51bfc89b13c2033cfa5f8903cbe9961a8598ba556232869dfab4d56edf4f05e8b77d05871895e63b5351f76cb2d2c8385c109d7306192a25446e4d62dc7d624f0c6673986be0628b2c2d73eb941d35a3433090f59b28a5979d56dbc9fd6973f63647642cd903b0cf7a6acd330d87e2292710de99e0c179ca78929ccaecfaedbf2742414f176b6090c0d59a9db781c9967e28fa4e77d2a082e42f52169167e92d4fdd82e2cc05dd9184c7dfee490a237fdad4dfebc01868e0a4353a2954d090928461821a7a848d1b60817fc3bdefa1
SIG: 99e996e85a494f1980cb07de9ca6165e7de104d39fe3c3226735c5daa569516fcaf1b6e4dfad0d389b6db0ec8a8f20dd2c602656b5e761c8f3a6558382151909
TST: 645
SK: 42afe89dac83e7d38996c0dbce0c9874c00927babd77ca8ceac34e564474282b
PK: a4c5f5e3803f0a03d5c1c906caec9cc6d2851407f1ca29f72a45f233e6656244
MSG: e710a163ad2885aeb7658eb374f118b76842ec36ef3b010c3c6b9559e8b160c2628ded0b8511eb4907180da4b621e9aa4a322288888a1c09130f69f890597a9293e74f9289bdaa5c91b6fd24aa044ab9fcb3402f7abc48d2ab7b3880a048daa448645ad2ecb55b3caee2d68a8bedb5d1865d5e211de39b0eaf22e5daf10f7168203aa15b85aa47bbd3cc4169cbc1fe80b4700b625871edabcd4fe74a3e965569ce245cfcde4209cc8abcd6797d44185b4f96c0181bbd27008783e9358a5394fe3a34a06871d379da35b20bb57eef9e5524ee7912a6f41b4a1f684c3919cfcdc00f4580baf9e09d316cefa0f465dca5d8eec514e95e5a57bbcd27e41f8119b264ae14a319d8c3859babf1f4a6b6b77e442c861d6ee28ad12b82362e90db0c3672b0e0d9ff58146fd159aa8fa99dc755fc85b90cf9419279c0624b93e75eda0ef7c09695ae93bd7282419377b76ca8bdc0521cfee6f6d729c3adff894687b177ef19529a6bdace70b685c6d7a5d74a08e2a9e724035975c80d18cb369470de7299cbd6b0a27c9232c7eabac86d5093a65ffe0b40d40befe80b68cd9dce1ea1e657e45e9c499d0b690f74455fb47096ed8c18d1517f90442901a6c410b7f6415f20ae48c58ade8d675b6c058df16ae7698fceae95aa771b4cd88a0b3f22c51f98c71c1eb46b264bf97a300ecb1fd26226ad8e87a058cf3e708e260f566b685314045133f4a5e8fbc34561b9a0f1ff9339f55231076b736b6e11524319a272bd4453a0af1493daa09167e84643d207a02fee98fb223b01a99aa5cef2b7001e470f6f94a5dc208edfc0cb8cf3114a919600f061172f0efe039036bf4dddbfd0d45f91443bf26f8e15ed7db8e55f086a4a4583f4bda0f556284dcf71292fe70fcaa8259b9faff3
SIG: 4fba2d6cc1b7193d3562f8c8bfe6905c829db265a5427c5c265714785b83f69514c5e30e28b56684c82dae2637581bf3f4ef271420bc7e6010613a38fa101a0d
TST: 646
SK: 10f009aa887d91ced809afe192d78e4799d9037762f4a9d3a429fde0f39f7b7a
PK: cf5116b921212e9b78829a0263463691c6fbccdc0c118be141c96f8c88053dd3
MSG: 2edf14d6cd56896eeaa770211c4984bed80eca8d6534d5d510884f55f11f99ffa9f89b586ffe7b1ec7eaab6a9dc1a24a3ee3c7a6ab44ade9917883264ede2f1361be7d7a3817f29dec9581c319f18f95d5be26d9118be678340037a68abfc5efbb9a3f3f3878aae3721ffef5bb6a26c7b1a3a56d2bda6c6e860eb41fd8d8371174d91c74c5eb67c3855c630d641d2e571a9a51c6402cfe1842cef38980cb8d0a64bcc89be3189e6811f47e8f4d0063a5b1601f44fda20c1c4c2fc49cbe27a4137dc4638c2ad2d0a5474747229c568e3805431fa36eeba785f7b97844b5e319fa6a09cc5ae8403474bb91dd896c1ec2bac73d2e505efc62bd502b5ceb08d16e832ec5dc4f98b51b9d0738b9fb28f3abe8966bf22375a0b22c471a9e58e3fd700de15c5296373c1bc9d4640eb7816e1dc9c8ce8619a81183009ec974871e8f0a9772ede0a638b3574bf75d8f55987f3cfa6fec68970bfe00b23b59fb5bf4996ea5d7704fcf2effcc0fd7f3d8e6056008097f26caffd5415a282a276a9b2645e5cab12968872eb052f4d7c10cc7c21d5161818bb44cc856b0de769d559c55df64ad9adc16c0ac65838f660da81386b70b93525ec2f40f6f63f8ea5d4830b9646c46183bb4e6f27047bda2a546bd34bd4db5fb88fd8ab7c75f652e15d5aaa6b46a8acf6e448bf2dd64dee3c105647c7f83ad200d8097c444a158d85a54f0e5dbb12b43de943af1a81856ac969f52a0bd454381bd265041a2691d1a4a0d819fa79092c8803521fa53689ab852f1fbabe00c94b7f682d121cff54391322529c8d5ad7bbb98eafe300ab922f1c89240a1e633cf56a7b02f74a29214e569a057bd585e404d7cd5352041456e6cf90c15342e025670f4fccdf98783b6853214cac3fa808a66c27b653c
SIG: c37bb7b73b1105be086ff3076972077262df4d7332f608c7b2b9d978d474cbbc271046080035f396ee36479b7a6711c68e2561c741c0ec5fc9eca1734e811f04
TST: 647
SK: 4578c65a7ca48f2774050a7b0ce7a4fd5ad4e696b2b8af2396164a1c7e1b7bd7
PK: 15bf9dbd3b8173e6f03dcfd575d909845f038eaa09c5d908fef908a97458b3ef
MSG: 506f32b96814243e4dd8870a8fd60ddef09bb8c563151070d9bcb2b160a3eabd71a044d71ec93fba95288ed6fe1a7b921651604307d65a45ec5d3f2631ace40e58d53c72e526886e16972f6e0db94d57b55634fd39d55e9bb7f212afab00f7746409267e8d565ff5c2257333c3d04152174fe12de6a57bea057dc219e2fba5f191ed8141c018969de19472d6aaf763f19ec554702bb3dcbe13ca9b23b2418c99e71838a88cf454728cf9208a16c84ea39829b4ba9b4c77e176112bfe1bf35f95c4028c7db80b36faa29d2b89e9e862f31000065f139b3da77d9d868530574b7e391ed97b34f878164f6b8d87b406c7dc7860a5175f920e5a62dc1fc82ed8452543b107360d35d2b4c4239eab466d32bfda34f51037a6fae76f6d8b83e8f7f489dd4c1b49c38f53576e62172c17dee3665fde8cbf015af9665b0f1da2fb77b134f04be271e402f31537c2fc05c2f9b6fc3ffe47de3369133867c69d10e7f537bae4567d468e0f2ed806fe335f939c75994f363ce3b70daa7d5bd2317c833851fd8cc97251ec419023d9d0174d84d5609a6918a1740eb1e309bd127366deb9c5ab12992e9902e015fe58d6adbf52d22a760acd63e1edd8f138e9fb0137188601e1978e7d04fb2ada2b2aee12f49f2836c6842d88cf48c866e3d33fcd269c275c89c25e3669ca90de7b67a7e7a382cb7efa47e9c2bf76571c79a25085ef020487152f06bfa133015a1b8f1c0f6a9f0eae1ba62bf104f1c16ac14e1e96c4ebdf061e0cc7101d38da7e9e0994daf0f322aa3cfef91b616c2d000689ab18ed45268dcd275094f656ba3cf515261024741f7444ab7fc4decce16756032a1be270ff0b0317542ba02662260a376fc912cbb029cac54515f5a551364f6a99ffad0b9cbcd0e693b7a521cb
SIG: a1c242b45e94fd180f054c7101e55b396568f483db6f0dfc4168b69b59d385814c19eb3075237d1fbb1feebbfea50c56813c8c39c22752e02db7e57f3e3fbf0d
TST: 648
SK: c21e70c46ede66e68a8873bbc64ba51209303a0ac4fc49b1d83e8193ad46c037
PK: 9fbf80a42505d2c952f89f4558c3e6d187a7bc1ef446b2e3732343c13b33d200
MSG: f55aa570ce4fc95f73f51720d254e4695fcdc81aaa040130c7687f039b8ba59ed857ceb29c121025a857feacb4a01f38e01178310ae6e35c998ebf89dd79057b4afc6db340601c81703c87a8c40e5cebb0441df78a6de13a447cb016c65e741bb7df304d83056b72c682c731fac0a0c70b7811ca14a50154613099c2c437521c404b6361de3621f8ea56b08ebfdb07b4f2bb8ba2ecc164336da8efc942766ef0c74dfd3b49e087e9a27ae54a7a2b98281b9af93dc11aa2f09224ab5a730f0218f4a6e1ea4885a77fbd93a1c58277d9e01be73a25cda918fc27dddb453a5da6902ad02ba05775c67e07bea4df86913466744365c1326e0ab5e1254c17967447d591ba5ed1b63a42543b87fed41459a089bceaff219802a87a872a763e692333ce1cc7397825084b2b831e93d80d6737f32980f2f3ae82c62190fe3fa700c5b7329d6d50042bdf831f37548fcc80b11f57cf20f67a3bb651a7beffcc48b70d17eb60f7259cc53bf7ff6080eb2bd0923b0483aa3065a8955f01d23ba80951e0aefd2a9372191572bc52916aa22a2aec393767fafd086839e236fe0460ce6d639c7ce69fe7f9d3aad2130573443570443be6bab93a06a54b8ac29bf33ff9949bc92158e6924b6b68ecda5f6f3aaf42b3d22df6d5e67d5cb3ab71eb8ee0b0e66732e1daca6cd60d9aa74305fcd570076d228d446d5ee542b10488bf8aa988f451faebe74ab669d604d9ddb15106620ea02e8db38ce639b5747812bb9048ee8bf72b1a951a05dffac95417cb43b06dce61ee3da6f2832ee83b2e7288ddd62eeb5893f7f2f6c8090d99e336c9f9069e1815985841bdd505b5f83d895e879593dadee72ceb9765699bf80bd06a5c55331b2545527d0c7caece96584ce3ec7fe02260f20b8a1c0635763ff4
SIG: 0ae343bb84e3a299078e2434ba220022f3160f968ac04482bf8cad13b423f2670f01fb5f7b32c597520f84607e0f79c075fa7078e6e69d3cec319265d466080b
TST: 649
SK: f2c10577f7df77f0c1157a8c331a7bd2ae6386670eb65f0fae122331690f828a
PK: 0d4c340fc231aafb3b6f74b89bcef7eeaa0b04f293ec8544247bfc3f2d57c1e0
MSG: 38ea1e028a493d1c60ec70749f14d436eb3a2b2de54f213d01a645b580430ecd8ece6b5569cc017a4943e5595c5ed6e48c9443f2fa5eb2227ffe56d211f269bc8f6fa9ee8cd56f6b8470539208afe29ab0a195044d957b31f93e184a9cbef1a14e14f808bbf589ac7770084f998e1b254da59ca6d3e62e7be1790716d2560f015f399cbbce48cfd0391ead1993446f6b2493977d93d7b09a07a79a59ce15dce7a1da9c646f45af2ccad55ba158e638c4a30c5d30e9ac6e3a3339c243426d86491b2d92dac1478e8d74ff0bf149bdb5e09e3fb6b8262eb0687981554ae2cb47196339079da0a1a57239c19bf781f62fdaf4e31560a84317ef030492cf1bb1305ba8518ebaf2b434d3641672c8f6ea2defa696dc7e4f39efc08d288d1c966a6c7148c012eec439f7e12dbab5b87cfa44c9ae1900f8386f24444e1092b23a274c138e95c661e9377e8ad2d1fcaf1939ec9a632a873f7eadbe687b4a033b92a477f2e02e9ed92ce4f95cf170b3901518a062143e56db054df4e4431544785a6dfa24eec0f0de7a699ccf286dadfad85903612250764f25cdea8127d0078d554825ea6e7371c438bc46f29fb8937f8d9a39cf8849052d43ecbff6c4a3762a5f400c1514e85e91384fef9b40f4314e223a9d68c526acc70227d62b8b637a342df113d318202c51edd3c1efd1ff20b1ff078b32068e794d928133037f1e3a34689e629e43fd2b8e88eab50d7e7ab0647014ab5e4ad582006567eff72b5af2dac536892ccc871f8a80b5cb79d90bcc6b77d4cd08f876184ef58c064ae430bb79a6b9e96b0ad87368aa838a8dccffac0cd8ce9ea0d0ec4c4b0f42673416659c984992cf53b1e445431007640d47ece26dee4a2943aa7097dd356cff4754f21ac07f6b3f73c469055512f37aba
SIG: 60b703115a322ab892c276bfd18f70a9eb0c7323e2c0a6eb5fc7e330b0bc3b07a578a082846264f032c6191d040bd98e5d5a4d4f076fb9062acd36bea40c9102
TST: 650
SK: 041a97906b5956b9d340f2e0d7a1dcbfefe663e9bb4026f8cc1ae7e2a14de27e
PK: f382d32e88c3a72c7caddafcf8aa699e21db7a6bf4edd6e49a005aad702e6a79
MSG: 71a75957411544975a48cf103aa1f8e2ad15244459cdc0e336966eb8b26c97f2169e5d78537037efc077e86f06e05e9c1dc3418288c0a2be6ba34b3a04ab20bae7f3621094b87d78a7eacb864d4078cb4efcbac5add937a2c6012ee1a8b256cc276b65d5e92b4d00b9b11fad884991dec4c1cb9dce1863c8b0a210161ae6b3f8bf9cc4dce4adfdc8ed57d83e95ab9dd2d92658dfbd3afa99e3f8951e2ad74a148f6f597eb2c945c1f1b94461ae0745481fd0edf838c6286035e36f011238875dbba2289d3d6a3942a7f9554c644305244ddb77c117cb4b56237729dde428b8bb42df9ce29e144dfc96cf6c6767b1ee6d053ce4f8bb2056ab7810aa1368a8910f2f69e061c19d8847184fed534f98758d703a76885f91eb752a21954a10c6f6b4da10464ded36b00089f662915421bfdad496753689ccd03b624021080761e68176b10697dac878e4c3db2fd0b28c655335d98016f19f265bb0b2434cb4637844d91ed0ce05ed2591fd998965f83f3197d10eef448850e792032724701da305cb6d794669483fc3dc6f686b183e2999130c8fc0058dcabbc9188f26b2d63ebd6cb1e18a097c7704a59b5e187e0142593b7083f7400afa9b1bf0c1cc6c356bc4334af772e67153b45b331b990920c24eede2c6e323703f52ecd60735b23bf22b81ee775927c37e53dad7596ea65a73bb96775f3b87c8b3c088ec695bc3a7502c0c510f020bf9aca3cbb7a2c011c67ff27d634caf1dcfc58e5e397e6658252272011c8ffdd64230a93241fff68372c4ba85382bbb229309652922db68836631e55be69ab6adb8e4335357fc923efe154afcc222d60d07f56990a3e5a214b227aecff2cd1bb6f0c79ff545f70a616141a9d53f922a02443f7d2a4689c35b095dd394d50bf49f9680a5f7d9
SIG: a23f032e6692a0e8bfee5b2d30b414cb16c35ad08da31f696d461a02857822c4ef357f0ccf31025a4dc95ced30a994f41edd1d087afcaaf3e8e875708320f80c
TST: 651
SK: 4bc5e05aa003a4492f4bad102a5390f7cebab3d3eca9152142ad5ef7d84030ae
PK: 6751d3ad8bb6c64d6a17d7e447a27da22f5f0403f437bac9449f13cc853dd840
MSG: a8f794db1795667d28d24b70ac2200a6239a34e2438ced1d03f97ed48beb4d6bea67c14338f7736419dcd2a2a7973726572e6afe7edfef22c99be8b069f04f6dc61a13b343c6e585abad2214d85c36f02996fabb46bb91b5176ac708e49a0b053017048fbb55453f2b8208d6678d1a8cf6a1ee9ad7a91e380325635d1e236a6ca1d6cc7f6b59f2a2bf184f5ee451d6799f69ba11a0cd6bc04be8a351a80e725b5fc4563e45bd4749ecbc45205229105b9de73261498527f3d4ecfbb583ff532753d07c38526bb482d171a261b9cf89906a7dea8cbd7e726ba31ea68803a6b004f6dcd19e671950463738cca78bb0dffa3d6457e4aeca657ec649b97ee30e97c8cbe6ce43c2aa9a69958e9dc881e4aa7b3278074e787ace5fb601d7faf7ca5103ecbbd3bd554eb1b066f8296d2cc57e8c8a32e9c0e6a926964d6df2d8645864b322c322f1ca8073cedf2b556711a7a20b77c0a1ed277a9a6ca2c07154e863fef5a404e3e89f0d7f30f218ec4de7a53aeb9c41eeaaf6ce749649c9998fd62bcba2872338e19c94e59dd5e2dd776f53719d21746976932ef11abf7a32ae6b0744665d0e0ce513955a9e68531d8ee4de9a8d35ddfb88eb5a486ad63137e8892fd7c689d4f9e7021b1173bb3752a5eecf2992e3fd4642263c7b3d815c29b466ab69285ffe4b8dafcbf3d01d635553ab7575a7a3471edc7be412d3d01e6fe8e3cdc3fa04d2a7599381e22bba49c5539d79c62b52bb0eca33f74255e41a9526a89289b15f1850d9afa87e6b6fa127101c1a6d88d433e0c86aa60bba8fe7100ed61d5a9d00a00764513eb1c7f5f5c3b3efc4532a36b407fe2d17cfb4e6fcd6049cff3a355623a3a41390ea48f42120d897949111be3d169b2d2ef45bdb894fe20b1a95ef66149427a9d8f80a9b2e
SIG: a24fee11f7ec6da3e9dfaf6c858ac004b4531abd1c9d3bb64f40dd247f00359350e43b2d4b8fbec5f6b241ecf9f1101485cf418735b05f712018335b20068308
TST: 652
SK: a3bed9fe2354bd2860149a3db75a85b129cf83e9d73e6317ba7054521933f896
PK: 5ac03b4f13d91d066b2ce359e9bb1dfb6bfa5afa382fd1ccd72aef1176079f89
MSG: db853808686d6d21f4c57b541e5ad63394d465e60078643cab1e065c9f306c500078f0cc41ef0f9542b5fe356aec4777ef8a95554c97b6a44099e9bd6404fb0b2e41f91914b074d12237cd442ebd40b51b8bc8bbe437a2c53332d2beb2281bf7324a0cf5b741bbf98d1eb9858be926e915a78e8d314b4144f3d20dfc6cb7f48c23af90f871c6cda90845a41aff1707a87b4e5516f18e8bd7683cfd74070803e888338c9a18f792c8d3a704170ff982bffc9e8ec9ea5d1a62592f1688d4f2b01e11f9f88774c47ac1d58f690bcf288cf8a473d350a8239df9d3a62881dadd338531fdce7615807ce965496d6f35d6c042f0ce7f21efe5ce6425185941ed5636b8ae913a75d21ab9dbdb3c3b6687a45e044938a9f1c13a330ea9761e283e61d4a320e1f559882f34b607fefe32c343174abcdc77b065a92904b42d961db8ed916c01464ffd43f93c1077f1df7ee65031cfe05d780d01d08ee036f22a2b0512193b0c0f3801e0a0208eef245c9e519352d2b0096382f2cba06eb2a01dacf619eabbc883c5d4f2fd7c3423179c0f5ffdaf8cafff5c46b34a09c3c50e2949c06000207d70d37d65a743075fdc2be62d412aa63e363706ca90e6ef44e152ea4dc5c2893ecd08d796d41f172254c3d1d14bb067b53a0897bbd73c9954d9648b2af10d9c2703e38b6c62469f6f958a1ca0a320c12339e90cf768c87b4738c219f8093bff4c2cfd29459f6d3281349378e915a3b0e724c74d2bd7a851ac7c6b48e8afc7124fdcbcab5ff80d1dee30a6c024cb4331972366ebab26bbb9f608caac7e51914df058b9b3745d98c5d27e97105475ec017377e6316198ece4ec5909f04fc27e7b382e66adb62ac8a977f376fd5dae434fb55175249ca1ab6bb02dec0696f089be3454887a0c32361d172bd2
SIG: 33bc1e0bf1b493e0cfb7ea40480a1423e091f7145745013173787df47a10db24c165d00596fab70e68c94c104e8a7407cf695cd3fbe585b5b176b85ccca4fd08
TST: 653
SK: 88a24f0df3ae2914df79da50ecf8ecb42f68c7baad3b6c3a2e0cc9c25d09d142
PK: 12e6603f713b2305358568710018685e141553c47591396fb4259e42dc53b9c9
MSG: 654e9edc69fe634c2308ba8c46a955e882456286eae3593cae739c44866c0de9edcbbf0db1c44149668467709dc9706298dd2eac3301dabad5bd8e93c5e8a93f194e0fc1d9f376c144c293aefda086b2218f2e9dfd7c2dc52ba33eb229dcf7bb68ce0f876c5fd4e81afd80169f73cf264e5dc0ce16e1b876cd11c7ad89058ee0820c40005d01f119f8be6f1afbe24ca4aedc18e97896827c3ed67fc45630e7903b7fee9c990e361937bf4ea0a4d8d16cf6d9cf0381e9065e3625148f8ae0491a0341d0ff9f727be1f310ca1ec3f0104aa054321784dd24d53c985b28d44082f8e1c108a44109638ff5116edd85aeb86b6ea512a19b602edd9d211070d044af5bedb6c8527ba3491e345bacc130b36960282ae737b85c769274f0f7c588f40e6625b236bdc1a3b87320460eeeada278124b5668874f39f59c2e6aa208c3b6a9b845c4d0a27a0546786fa13e51cc98b73fd7ee327b6215ec6b629f4cc7e4bd3c0a3db78a21fffe24c70438716bc37b8da7c5ff7c3688a90339c22eb50b7c2cd36b68831fd5939175689bd3e22c3881af337ee14435709e351040ef3da955724e51c24a5e2c09f891808393fbf8ef7f1f5f0298deebdcd8d666cbcf3e866c718999ab6b1feec9c47e02e7d63540f89963d542c5d01fb6fc30768968ae81b20c354b4000c132774764d6d443add64f6dd748f5fb5b7f6eba401db4318be993989fcc2577961fa5ad31f6a2a9d6a755285865cd5dc3a88cfb5aba7d923baf78b5d131b4c214df55b6171f45209e21ca6645490d3a3644dda6dc929c7c409576d37164755ef8aaf3dcd4d22775ee7dea0e565bd54727921c649bc51f20c1f68c1fdeac455c67d71a1cb8837f4691448bf0bf044a46f1685fbe22b1e01877f7477d3499408c4c316510ce2e55b98005
SIG: 1707cc009186bf3f03f7bb9e3cd4cf6b737b7a6baade7fc6c3ff5c1225dbb2baf54f47c85eafa132c31eaca03e6aec1447733facd37149b7c6cf0cd41f611404
TST: 654
SK: 184d0ce2e9db7f257a8bf4646d16d2c5efc2702ced026b6906d3c8c0118f2261
PK: e9dab8fd9d94dc9b24cc79c635cc57ce66518982ba3e2447240741bac0730ec5
MSG: 6a9b876b0bf4189b3cc15f9eb4fbe7932b5577892a22200ce107156853d6d3ca363f025ad7a2d862aadc742d9415bd8d1fca13c9dca3586044e55a8cf5dee1ce564576e3e8e365540546501b34ca675cf200e0771a818c73d37fcda8cb15e48d5a0b9ea3beec0ff6610b2a8a214ca4f7efac0e71381052d9bf3c00c329593474ebd0a687a0b41d144b5e7ab1412b970a74baba4d274bb0dbfdb02b11f7f63964ba6f3ba0ad23341d083b91a4308239e33d50824396126588de72a2390c1c0fc06747c28772f630bf4d143f7a1159f028c093404894e6d16f634635d4fc330f3d7a7313ef756f5d49d8f6205eb1c792a9495da131b43345a0090c12ca56e6adac5be0cbcac3609d69f72415f6c37f3cfb2cf76b3e65f3c93ac92b63f2baa466249075bca69d4c1d1f3ade24ab31effcb90469c24bb410ab4723e1b7e1c88b3a36433563f71a99aad58fe80568f9c102da89bad97963e77d6622483166f3ae261f32a52a86101ebd645f6142c982e2cd3625cf8b46b9b2891246920f697fcaed397cb922c274945167a0e619b0b506377606db045783b0b88ea04e932d21ffc064a12a40ebe9b480f1a2c7ddd395a9b15efdc495c9714f36fa996f79f8eb8efa52d99a24abfef43b32a237c5bc0018da3b162f59b8d3d474e2ce08fa8024c58acc0a99ff614e6cd7fdd9ca4e8f41a1449aa618d03337e8a374d56055b207a9dbe69f5948f901ca7db0410f01aa373d9e0227623599bc212845b006e942fabc582cd726db5c443eb2dffbc9e3e7f0e5cb6744f7ad716050fdf2c60c7c77c253ab745db9c8552655683ea7ea680aa4af34df1325c29b8874b61be23de4ffba25424f4619ec682c26b3a67bda9bc4c94b79a9fc4d82d340495b437a1cbd6b60307cfcb10026f964a017623e33dbf233
SIG: b1e3bf5fa74d7e442ced9a98d927d8c45e0e64d874f8ea5920a360a4bf42d83ce18a924ac796e1a77d1b0208294b50f822177fdbdd458c74356fcf6bd7945106
TST: 655
SK: d02bbf70d51351e3b47ad8e5ed263dbf556d1498fa9bd5dbd99fb4269009dced
PK: 8ce4b59f94ced6ec9614d67d3066d9d3a0df7a46b37b4c1725ef1e57bc68a0d1
MSG: 554560f7a7fd1ae7758a2fce7d780f6b3f043d3af89d4f19ef573c34997554df243faf2aaab65b2afdd28610d4a51e9a4b464db6db09ebf73b7d24054cc9b12814bb29ee99e1a73bd603898360f9dcf01e670836286f8236ed8cef075f3d563312c16c73fc37eedf252f8f42d30a13e7fba3b165238c7f81eaaeb53190f3ec3b5d63f0ee03e3987e390d1d81e8277e9f6c1ee6ec4ec3fa0d720e9f53f9c26f04aa2ed2b5ef3160895999eace29cf5dc254ad71106bb7e8bc29a5b1d2412593d08194e88e1659a73159a2a22033ab066e8d3d8c3bc86b7b01de81a8c66047b07fe24ed240318ba37ba3efb6cf632604ca4f446a75fd8e70c453f0c60ee16ecaf524e703f47df5c282ca3289b3af61dee4709ee085323b1e5c8a6bc0766201c635031446891f3494e9db20dd4e9e0838249a67e138d13ee2c96f61e771061542aa16ef20d81e3a0f4e4521a6cd6c92fc26feef03b66c70e035cafcc19c96fb9d82918fe197780eff0eda6e2512c56e2a73d77032b768919bea9772f5989c8b6c65c3d1e97a2180cc3a37579da70ce9806ac1285a3eab415c0607d88cb86542eab90b9d2d67fafffcad23a714000ee59ed68c956e81c445428882f97af74db362e45c0d1bd8856eed166e4aec4bfdf95eadb251e2a1ef804852a9ea77d34577fe70831a928b101b60ac613e7ba2e6ba0a94013a64c2f8219fd30bff409099667a786f99327bb03e2f2187f445b46beedab6d325afd904e39543e93f4b6c5443249d744b2d1a43e141e4768bd40aabe4057244e1eadd9daec175719e51a093ace32fe82b2eacb5ecb0da6c1ffe98c8cee7886e301670dff87113efed4282471afb6b8a0fdb505e2e8e7dbc1a08a22e9680bd098bf1275802bdb459413a3b237d7713a1bbf597e6adf2b60eaf823791b3
SIG: 6e7c66acc954ffd9dd4c1c6335ab4fe79dbbed782c4a47ec30d848d8bb2b4f1069dc62e522a1e8017f54a6345e1728c073af6447856d8c1ed35878b571e5230d
TST: 656
SK: aa0fdae2a5a4c9c04521913004cd89efbc88b2dadf5abb246f3ca7f6923544af
PK: bffcb17c35c1304cdd9d624ff69bee60ec7c9ec327d12350d70fac12b47cc25c
MSG: b14184cfdc4a5f0c7f83f94a832f588507e2d72a89329870078571d208a0c4960c2fdc4c236cf88229981d12b10a1b6884c8650ddaf1d4b2eb981575b1e019fe3f60423676f8856a992cce36d6d0a3d026631c8c1e1ffe34134b296f40842b6df4f86f833e0175bae50e86bf856d1ee79925f434b8bf2c84519f1f5d25386049ce3ca61777e30b700a602d395250b60fc64ac6f8db027e8da8b9550f24ed11a11d9f9f9c5e0af145b8659751ac6b55861f6388a64336b31efe45c0802d76a53486a81eba07314b4d961c141ab34e2f76edac0e6de31422df792af081e769c7ed05da9a5af2fdf36f141769908b700937f0e1068c131f176eb96c67afdbe78f40d86007fbcd47e49e2e4c4ce049936adff1ce3eac42b96b3429b5626b1aa62acde07f45a13ce1bd211f32bd7efe4790c8371ebf87c164477a5c9fa3e78c2f88077b097344cffa031c4429c7f42dca07737850ee7a769b36d0f0625adf120ea23ff4e393a4fdcb6558dbf9b266a032e3b0599b9d6692fcebd815a3897607856325fcd0115dc310db3a8792fbebd399494c8371e585727b3d632414496893d03813ba1f99661bceb9dc18ec5dc27f52670318687769fc678ddc7e40227c200522013f5c0eec0e4781e6fc153a0c2f4f3f95e517c8419924ab39992af8c19465057f134486696ba7fd4651768b4e749ef36f02444617cf97f0a423e4c13b7b66ba2b6c456878b0b50ce2ee5ec564ed8854f782aa1d1c6aa760f2522c7d97b9b1abe0ba810959d7aa403a99375aa3e39a115d1fc6fedd002f3830a50a837dc720329ec0c73d5bfd500385c736838287e19201525d189c3a084cd5a3f359875e3b8325289ced18b63b00ff9cd070c3e67444bd3d8346174085cc45135caa0c67b3226e4a52e9a1c55aed7ec5fade6bf16c19
SIG: f937298969ca34d97584448907358b0f47841f3023afc7ef7681521c5be0f5e5628a8f607e2f31636ef63646b0e9898a72ad355706d2c8060fbc640efb3d6605
TST: 657
SK: 7162fef0aca4974b094a6a08054395f877ff9433f1e33e20e88eaa90f938997d
PK: a280640f139f45c35a4871537eefe6ef9db02de785ee9fd54f805fb57d3746ef
MSG: c90f450bda1c6efd8d1278debd7ae03e2eac2740a5a963fcf96c504e31d4d6fcc5e2b52a2518d2741c55e9591867b2423228f9c19f33c6f38705c62036d480ff53df12077e38fdb073c673105da1e11619ba5321a71b5f4993234a11948ea110cfa242bc23fac9aae462606e39641ca7147eebba1eec553fce94e53e4e01b073dd780a2ff678b31572ca11ee0877e756bcdb6653e5e1b4cbfb569a9d60e3ee336182dcb9b25d1be6dbf9b5c7146d775585834cabde0278aee5d57c85e983f84d8833a9e15bcc11198e1c1da6ba59282129f1db966f5460c8fb6530fbc3a98a31fc0f4e9b337366eec1dce108c826d49045abfa12ee88797f08f0683fef77edaa3543b91cb118e424d9c408da547431125107d9b0744c2443ce9917e1e328d81850babbc94d920a1d06e524dbb6c23dd82e1787822d71c4cdc409ae85ba4deb581f934748f75e7a769b9d68c4589e594e65cb6c8f4903ffbabd5a326e89441a542f8ac264ccc64e95a8982a710b6c56ff7d10916afc409ea8a41b74679dd6a766f59c52b9305ba733b13c9e811ee13083925f4200682bd05dea339532522970aa149d004a2ea20ff461e9ec0f3b62565c1a106259c836605cc27cadc9515cb9979e89af287c027d75edbf87d5cff63a7fec9bd10e7877ab9bf868d734bd3a2374cef7025cc4dab710e254806685a136ecd03e36770346513a15145b890eeef47b80ea08e46c81d202e533e9a06a38a6f76ef57a9c736ec78d00b808e3ffd9c79b9dc7a2e589907656c932ab8a8b57da1a495ba7452015e7924b5269ab1f67bdb43a35831487ab9002f52d78b134cd3751925aaab0b45c8e6b0f2bf0cc9a4659317108fba9136aabb0921a58fbb9b50e51243f9b531847dc9657e96fbaf7aa698fe6fe44f90590144c70337250c58bc5dd
SIG: ae161cce95403384b65c6bc9b393eb072564c35f3a6c04fa517ab068bcd23767cc0c8edd92b1a13ae9a9ce4864137fb89c1f37b748cfc9134b6741ba1b22280d
TST: 658
SK: dea180c91b533aaf736bc5d3c8e474d5e5d475b75b92cde6bd1d10f3b8f55ad4
PK: 30b20fb320b00e77c4e0a8eb3730af3c0b1c5f5ed9ee2b0562707e4f55c4938b
MSG: 606144b7d4f96bef7f112b6d41bcb500d2136c134ceda220e24d0f1524eca12c30f2b102c7f378d6bba259c5b4a5ef8ec9309d5c8da7e8d2ded3792aeeea2108f77d66b23045938ed64751f20d48326be2fb99628cfb1873d7dd27581c105ec13249a952a50784b8b34cb3b2c1a004fa8b628a0767fa9abf058d955df85d134a0fc7f4b7d7fb0c8d31bce345dd0a4282145afb2ff19751f2cc3a1caea242baaf538749bf388000e3dc1d739359dfebae64ae1e10fb6fc17cc9fb950535c2de129587a86859b7be36dfe9b6c1141b25e0915c8d4aa1cceae7046b3d7cfa940bc98d4d69fc5a30dde1dee42fb5272281bf8f8e7f3e1a04397fb4f3adefc57532ddbde36833a676e6f39c82aff6bf4832ec971e03be3829c02a203c82d9eb8c1630ee9693f45d26f5f51a3103ca64d468eceac1b29af4c42eb216d76ec8994836b4bec76489ca5070680c2c2eb457210a77c47fdcbf600172073a53f1453bb5c80439c882f0736de40637b4f5ab1f761ff355c6e9bd4abde7560d5fc113c830159a1b77c4e87bc2c69880a40c5805ecc8aaaf57575bccd8177fc6b83569233c0f5ca223ac4013ca106cac2854706aead714fa29f2860a5f9753268a3671d9f59cde6048cf0b8986050f7f549e4fd7557f2fc3fcdccddcefda586a64b3006e5825f27ca31687caf663bd90a05b1152d7c88d7f1051a9d791748651d888a6a12f22d6c8c3f78c2b86eaf5394b4ef7eefb89797b25e542dc93102d021a1d0bed6a7dcdd8102b8f0430a0bc21d904a3c9346c018343dd9937cb35250007a284825db08e9a11fee31cff7a314c48c42d8b314acc27822af03d1954c7cc8bf9ad4e9e98f4ad4efb355288daa8c90de9037e64a7861f5ee43ada9f0fccde34d0bcf50288550f700f215a7944a5380e2a8e3f04f2b4f5
SIG: d083333fb84e79c9b33e55e8192d571ffc8dc50745b6b5fdd8c44d92a63fd178c4e57c2ab3a1211c0ba2d39da30b06629d8d1cc1d9f2593263d524fa5a2ebc03
TST: 659
SK: 9daf6dbb7f762966e7a57c2ec1996e9f5b555b9866b8e31deaab4356eb13816e
PK: f021b55a36d9fbfbf2978bc0df736b289c8241d6435309841a134b07d47ce4ed
MSG: 544523900daa6778c0391ae4044a51c0c4a5e444133fbd7747d539a744fa60ab5dc54e1819dc8e56899c56efd7ef3da341790ecc49645ef325c6568ae971d30d21bb7f23464f46a24b80d49bb93c6e91de79b24331d0707f43d0665d0197743adff690d615a1c9258777fc47d0217142426a4734892eb622ab8e50bb128ec3a895266a3861a39768bc76096f581fd082df9b7223e85a8afbdb5caa4922af2a014bf8a5cd11e5c5ea93e91cd46d5a1b99b85a2670e321de2e32255afd67fe2c37fd932caca22d241faf4ccefeff58d6bd04cfaf11dedd29c8719ffcb02ef65c5d3eb78b4fc0d170a2e3432cc812f0d041d9760c13c12f7c7f2f84fe5e0f700c10b1a69ca466a70bdeff8dbec7d318fb09ddd827ef61caa6910bbc061cbda2b527ef2e59ed4c17229972f89567d705de9231924b41bb6e7c01fe854264474fa76b1f88cd57eac311171af103d23078424a12675f2fa36c2de0bf53c295feeb3157de958922986e32513dfa33b35e15c394a11c0fcc55b82d6dd0597cddd27ede7de12985a616e64026befb5d690482b3ff22c0dd21f27a086d37a0499ea36fe2c4b5a959d10e9a610cab1fe0d28cf1013dcae63d8fdee0ecbd8b4e19d5d040e2fad7d0413a38e8c4e73552ad46047b5bbdd15c09cc0d34e48b91fdbae2a9d162d4b21ee20a1ef535ea883595bc4951692a67163454c7367f134bf645d48f9969e3d4f0f9eaf4144ce980a0a2e3342c746c2bdc3ccdc2f8a7da57a0e8028782d30af5857d9efb37666df65d7cc384716661e61ff5c09752595e94112ca1a840d6e4f6ec0e55494c5b44f7c0f0d4a99cd70905bf8485561748f4dc0fd7a44a1b139113c38a1e8eb5c7a20f3e952eaea8ce38b207c28ed972718f031f477c6207ce433c515f5ac2840f4974f1f16989626c76bc98
SIG: 49b6bc46b7abb5694da94215efc4b30eea04ae2e73eb2da8e8c9ef9be2222498b17e13939646c29e32d645584640641590b1bbdbfe24f36c6f694bf87238ee04
TST: 660
SK: 7186f8d168d9ddf17edbaf0e7b1abcb26da3e4c0272d9879c7fdff6421c4ea50
PK: 96b4a656232029fc1b8364703cbea7a5d7387518a88ced1a915ec8d886848132
MSG: a3e6cb6b84cc5cf1fb1a848b4b8ea7cb7c87e0445750c61f9aa5d77deddf949463ecd39bfc71f2610c2a9424847fb76f84c5da1fa10ef718a34566cec1b3e899e7252e8d4d346016498ff119972750061660baed312827583181073d1dc74b76c430ca30d409e4e8439c0fc48c00680629d43ae2a77d69228f7f8a1253af15bd2cb6bb1c1696550c4c790f449869630ab92b9c11cde1f961aa2103ec23f7d9f0fe9c3c4132582efa79a66ae3426e5105b80bfe5e04dc8bb1e38a3110cd72984b3ef02a0ca62ab638cbcfbc8a6b593d2613dc06ec86fee34f6518d4a3fbdc157237174564daeb6674cdc34f4d6537cf81d8aa9bddbf3aeda312daaeee336f9ed8bff81e294bc7d44d25cd787072e6cb414b65fb7a846fc065367ba8e37beffdf0b7ba8f98cdf1eb870f4e8b7130fa3429d2e24bce5994daf1aa65e5f603b631053dc510b2f097e86e9b9b552302757968d0136ee6754c42a32c990add9cb529bc89751dfa4e5e3a0badaf4cc40b6a09507f9fcd24c3ca72259599c6ee58d857b3a189e048902e885a3607426093cb0fab437c0fb0ed2f1e96e9441a7e954fe3ef7646e26a39a07033d0a1555dfeed9a6f57794af3a2abf0057e9f853ae5c30138fd80e2f29c2f4a93ad3145da10a3e31ce9ff9786ac65d86037d98b7aa6d11de8800010e133869eb67a5039b9b8feb6ef903d0cc746412607da725ce2dc6a352109dbc6a5e40b170c23050bc4fb1efa0c34fec00eae3219c29040e8f5978c9384ee915d8c9398dd120d5c3cba38f8526b06197cb2c261dec7d726ae130f9bee17261700e99931fac4b4dca0f758701acbf3707d47df5321130ec10bb3b13078c4dc5de3470f158b57dbeb878b3a8524e0ed2c9547545f0fddf13125e45bb23d6a7b383a187f4c5d54a7b4c83d5957f2cd7e6fbc
SIG: a9c0499fc216a14532d736365c6355f938f8d8194fa1132848f83e490454d4bbf69269f12259fc6c074c1015e425e4f4f27c029c93334951361a35ad1176540e
TST: 661
SK: e86e8c62566e15753bd5577eaae7f24105b74055a25629580708bfc83aebf06c
PK: 8c8ce882d5f76586d8ddccc5579bcc1cdf4cfd7162304cb10e7696026e707f17
MSG: 12fa631b0e482e9b9d633e94b82d8ab436fe548e5b95da92624623d13f2c70da775ba136c5229c16a0c7a6fa914b2feda564e17219e47370f9515bb1d59de6e9586204d943dc560d73e2e757f7eb39bbc7111bb46bc643c13f602112739bec778d7d4f49d092563d68f5776e430e3b0bf2dc1b01beb3040196da6302908bfe91e0fc38e04c150ef907dc736c445ff21fdbd2dc1eac0a0f5d00a30af028afe2ff61162b758c7da9a776666a112359431c48856a87ca82d3dd1c8af376598635432bf891becbc33a8fda44ce883ea8af4ad8b91a9261ce76b9e939c461fac53ae0f076e82d879aace8f38f120bc9b04d8125ed24bcd779d9d24386b1dd2017ebee8197376e8c36fa3aef8c1e713e2b8bce4966d84888681ba78495fbd1d6cca58626e6854cda606b83d6293d01e8e3e13bbf4aac851d9a1e00d0024e26993b0b3091be7e8061bcbb3cbb2302ceab96897a8e1ff367ec8625693cf31534124a9d5d725bcae001d67bc2111d0ab8111fa1d24e4ed06d63583ce690f2a04626d791d29e3e315a415bf2e853a5f2974c833a3fe2e2909cf669c73c1f59392d30c37f3b9c5a3ddcfd75621fda36e4ba2f16147858f6f206b9a140f1ddc1466c9a53ed73f82490bc95322c955f61d11cb51d5e8a58c6b3cb0fdf0419763201beea93a8512b1405245bfc384155adc5ce778aa74d00a322726465119af79501f040dd0a7a84060001ca89d2fe5e9cf9779a547e3ebd3bf8642990a3690e2b2c3e54cb7eeeeabc242b4dd99274c425a867931c929ca70808601c3908cfd788867d687dc366e976350c9e70584bd390d67eeb7cfea26c42686d3d9620f62f64104ef41ed1d130d79e325938486296b7ab2d2adb78526743e400acb2b7af09628d68cf9475101625c20e1dc051d73c997c952e12812c805b68ff
SIG: 54d2fd44acf9e209bc7e433372bd73074d07806a77c6ce228e9be994418b00c7ecbcb7ac006c294aec9de668572add517c06b4eb4fe2ff3523bf043df44d3d0d
TST: 662
SK: a5cab2727e2f131a4d63facee799336663930aa07afda6bd5a8e985a02deb1ea
PK: ac355f95260fbfea778c55b5af8b3fd1f24d2693da35de4ee508a27ed350391f
MSG: 483439154dd5e5d109857c24d1c4e7fbbefd2f38651da81289f2ad3d6154306538b82ac7dba9210e740776ede4ccf51d4f63094b03e46ad3aa3c31947d8c36ce6f94e85296bdedcc1ead62eaa1441ecde0a225d0bf02edcacf865014899af66d9808040c2d02000a0f5ce4f1683c1a495276d9c4d728c9ecd6f078db8a0cfc267187238562ab1a1ea2813fb4f12e878e1ba143f4d06a3bc8100c3550118d69dae67b55ed692acf9444daa5c3e3c0a98ee28cf172de0c584c9f2ec9bb6e9b57f572a86ff8729f65f4c65b7feaccaa21720ed79e90618bcafbfd9533da85232b450883aa919f827f04c4a97bf51390d4f8569c191726f44f7e39fb3db73bfc415b6ffca8b91acaad69238572f14b49985ea03c98d7b1d44b3a6554765b19abf9b25274e97e4634e4b0f9e802eb6f743fff950757ee013a6988221881a7443f1f32bccb007e99379c7ca4f906d5fe11cb12f66b53a3d21ac947be0c8150bcd04f1c816b3f0c07c5fbc0905a7136956849da03836daec25c3e1a06ec3aeb205648176f89f4a291fac4f1d3899f56c9065eebb8768b84b31b7cc03108bd0888338d1774994970292d935031fea335d9e7908fe0254889c0b171cfe0af2e6fde7a5ea3de1fdcdae537b6313119c27f772024ef36e45c8b89f26c93d9eea13725e12d810cf9824aea04cb802da7e458e842ca375e3671346e0089dec571be169b0d90966bf368fe3698fd3e72bf16249dd900af6d29ffa48351360f12241714585f7a9b4c7bafc952226735de1462743d78abad0f6711f2495f3313ad4e0ba216b0dea5dc1516a9549f7dfcfeb93e591abeda5ea3c7045906523b40868ca5735d6a3371c3c294c11126d097f4c708e90464c1ad9142fa0bedf07dfc5f4cb67d6ed80f1bfe72683cfb2ad66530dc43d7023f3790ff42d95bd8
SIG: 138c7a8eca5b5c37158813843c9a904e5f530ad971ee432a44f344f8c64bbfaf102ff41daa5cf722a4bc6640588759b8f36f9c059eab936cc45ed4796394a002
TST: 663
SK: cb6319613779a4ef66be14144b2840ad0167c03f3b8d04ff592cd1d2d722e330
PK: 18eb03f0a334b080e1af4399d8376d83c533316dc687cf341f0afab450965299
MSG: 874a6c81d6db7133a79169760c84d36eea3d42ea0892b7c8dde844a3a6b60aa9f2660726c9c4dd26a01f4ed0dc1c53ba6005463f7ea64a1ec63953bc3d81052a2f1084389a7706df74ed4136082ab5c6e8c7f411df9d3a0f3c40f5a60e2d21a8548e7a25dee34030b3c3e75caa93ddaa9c190cb6deda2413d54e373d4353dba43d39491a2f56c8b36d45016f77d7471691634539e76c4fb41913472b0a23054f548f54b1e7109c8b6521b57ae981d050316a33c49c7116268dcc4b78c2bae53a3ae4dd178bb8b76bb3befe19e41a2cf12cebb71168f971f202461c63f7d6eef107f5b1030edd4e75009e9116c3cd0e8bddc299b41f1a45e784efa646dada64068e9248ec988f232634ad3d5aab19560e830a5bd665457c94295e1af0160fbce272ef4845ddf0c4f24d976f518690ea1f82ff4dfa4813641a67598ea98401e0ff10a0e582e2b90867b4e6232c34ea499c169909a44126f377d8cc1c11905866340efd1e7b077dc7456d59c9b96a124aac3b33bb227441bb7a52e6c3140d7a4f67ca05bbc93c93775b929119a224ed8f39005820f420cc6c530e61e20adca01e939cc031df49cdb1ec8ff493c9efbcad34c57108efd764558966fb1470b0745e6966191a9a9e44581b09faf469f951537203d926bc8a55d080a805181dd7296ed20a818268f755eaa66b082242f4d020f7cd6720890484c01c757fe35d87b5bc906deacc2e3071de4601bcf0dd6b837c433106047fd8ec9bd0e98c9ee806f7ec8c5a10ea2136f1f90f900b853f953f00b076bd1ebd929d08a38bec68d866435047bcb6721e06b64085dc0558c1fa85a2c83b0caf4c816084f10a4c5885295bca15ff7c18e596c62c92ee9921a27c29d195bd282213ff3660b6e7546b4eaa777ce39fc5d20484c71ed6ca06f9b77ab1d872393ab2d10255
SIG: c1b399cdc198e9a159e684fc26686de660da54cfe312ca7345df0c7d15a35743014410bd2f6cd11eef33a89b3d15cbc17c7a358937fd997205051f9257c25609
TST: 664
SK: b298adf38a6708f8d18ff1ed96bfbab421540d096c4e4351b92209b5e6aaab65
PK: 770edf42b8a039c6cab9ba65ebfb135abc2da314a4c309f46a8f325b52d06593
MSG: 9df4d5d7565d2c052262dd34d6007d86d9c0f07c7089af6119e304f4d8011d7eaad77b3ef70cc280847d59f297202b7e1861aef334bf38de14740e8073c955a851d2cf3dadc3edce15be490eaa845ba553fc6e8746e52915e655af4b86c629d4c522783635d464a2825777d89d7097677ef0e5eeae38537ecb656e3b28dd07358fd9fb2cd462517286659aefc79d374d1d13ed93967c530cdea4f314a0f91d6289b4c7a4279b6f4c4abca33357f69ed84b9119637adb7c18e694cb3c56e73637da910735d43c38aa8086675a06ad370e5726881da5e1a1dc6144d6a62aff7fb0c352d88dc971a3d72d3071e14b47425356af1b019233538261451a99a6cf4a07ce9ab1c3990de6ab8de2116c756105c512b7a3eeb3157b158b321e444e806d890b3890ed9ddc869f1711723bb99a72bdb923d131ba4edbfbb6dae99a5c7b328d310df9a6d1dcd85918962833e89e20f5c5e6333ac861094ae9e799c8641b9baea11a2e0ec234be5930e02880859cdec0d978237cbea5c7c32c111bafdd4bfbffe4fb3485effecd51bd195a71404ca5b59afa252d7b5ff9d030f48c6faadbdba918f21a0cd39af56966dccfa25fb5a5cf9a4b26a7f5441df6e320e34b27393de2ecfbd69a1594909a6c685ec645fcf3048d0148fa38d3e8a64dc3c21ae44da7e46a5ea7936c2ba083689a78ca3ac60b87be6d23ea40f5961583742842e37525a49c5fe8fd15d7b0c9e8fccd07936d19538212f7373dbbf3df7d46adf9d9f5db09524c65b883ae6f6cefa24b19ec48ce28cfa734d9bd6e77837d1a14d6a19d345bfbea559e7e6bfb71ddad83cd8deeab687fe73c057488f8f2b3e2e26d13009f4d23e6619a23c0692af76669217d5ebd46085b398890e5c91fdb4db5ba40e7773d518d3cf00c0a5b5a4b0f1b85d62916a59e5607b7b1eb80
SIG: e55f8d304122dc175cf0274674fc9dedfec2b5f8a2eeb1e3e7f8e0dfba0dac2d32f4e704ce91cd599184133c3bf1063d2fae63d73acc5772d718d81183318602
TST: 665
SK: e9cf16d696f63b59e5e25c9ee2d75bb05ed2baa591a7557f9fb129cf983de0ba
PK: 6d1ae385e80a3955e8d0c593a81f431cd432671e78cdbafe83fe58dbcdb98560
MSG: a10fea8fc93eccfe2a6b7826079563adf8aa9a666444932200cca9447dd027c5c7204ea62bf8f5e2e39145ac3948ab3f3186887b30bc60233024b483f3f519036a3e94c8d7510a853ac6e20c6e526ee3cdb76de663f67305ad80df2342c8501b4f4a8ee3665a798fc437dd814e4e47e7a466890e0ffa8f510f3e6e19c9c969f70a76e5cf3054d17de459ac8ee99550bd38319f36e433434a926ad68b961e0ca10add4ba992b3650660a2c3c26f5d740a31afb7763f542f723b8a3c92d8ae92a567764efc70530312baabdd3fbbd527fe0fcbca3f6a7064cdde1856e97ab786af7d7022a9d46a338e8e1754afd9adac856a38de2a4c9766dee8dbc709b0671a6a6e6e1e5d12074d22245cd73beeeb1bd8ecfc1e85a21bde253f7c465abc1feaa961c0ff5cff2d896472ae17ab8488e33ffefdb72c105e204f944ada51ee13981a136c0f38426e3e49b0e91841c32794d52f1335dfa637f151c7e40f9b830aed539ac5731b81cde3264d22bead31a6cc68d1a73143b5ba4816139232f3f7f97983f4ecba64c49553be9d6d943f91dfe03d1ee8618cd40d2fb7238a31d1bc38e76a551f9eee22e73a27d7a48b408772ea72c3ed637bb4b168f9d7aead94ea03bc11109901c889927d51cdacf962125962559979d3e4c8e3b5ae582f2dbad4998802856c4df69e8fb54917e2f36bb67a19a26e9a9a9485bce98dbfff0d2b02b9377a9137a734e57b5ce665053017e992677a1aa079240d2cf963cdf9bfea8d460091232daf89801fd75171a6195a5c046815914be1f62868783d6f2cf28af9378d6c6893e75de641111c684727effa31b8bc9b0a01db9c9e81ccd8f4d4e875d4bd90d253f58989a8a52a203a77a496d697986b031e9f699bc6a16cd5f9c36018ebdaa36bad0e014f4cf3b4b746171bf89314e8b72cbd47cc616a
SIG: 8112ac37eafb749d3f4a1ea1484379df3e383b019c12de8515e349e4f6f998632e30968347a1d15b09da2eb800b03d819d202bd10a6a463bb02b366d6855fe0e
TST: 666
SK: 238a6d4979321a14a997236f4585046cf7a05c0adc6ba1fdb19ec2a32f62beeb
PK: 0b4ba674e401665b6790cfda080704cd90e2f3d3efab253ed8dcfbd18e406789
MSG: 97cd619a2251eda916646431d4cd1598c2d44d06af3e48bd18e3de7fb4bd4f78e00a69eeabde3f82065cfee6cd711f07d22637161ff685f65a7ddf54553197fd31c5c6b71d9e365a941dce4c3e225d19cc633a7e12862cd23ebb7c74a704850f761ac0241be517ce7c360936ce07250d9f2eb2787115eec377e1134dc08f44eb0a2a2a2716f00144a49f012a57b3cd06efeb3fae920f285cffd9a401a0b986594e17b2c9c8fdab835d9f3f5d474be733c1925ee6f09386711066c3fcd645eeb0fbe7054169eb709d4a3f0d16f28a1ff5066c842bc63e359e92485b38757ff46c27f79d0cdcf0e16e97e3c7b7e2178dffd270282dd61205d5854d841f0e3fc0e482cc1ee48552cfe658935b5427c366230aef79aef4021d6fab5f1875cc849e321a75500e9e1ba5dd596b438cf88b235b01a67625c4bf84d0724ae6880a3785e33bd9235fd0f5981804d21cbd633cb180f34456460207a290a254d9fe61063d40634ca3872f0935fa28328795ca41b006a2111fc5932b1e779ce966cc47adb7c0dd987333ba7529a1a4996ce9f56e051981fe1f553e578f43c3ba94beacc93c3e739667c7a7c6fa27e1e081695d20ba705c3f10b20df530cbb0ecb87456501109687019318452785d38e766b3cd35b007d7e3cfe0b2cca8aa6ef7395599dcb9c4d28bcc35c76dfc35343cb1348ba3e962f10ee86f86f5b6d4cae2e8c2b185e3eaa1aeb87bcfcf2fb76cc7fcc6895071b168e8b7f6caa0fd6398e778cc07912ff5d6e61021a8a59ae0352160f56d5488fe2f2acc9403da9a9ffc661c1e9dc5be88c420db0fd77d845dc8dd9d8e58f9961b79afc68624baa86aa643a8a3c7edf71d553cc0d3224a6069ec674f52da29a1cb60c4192301a24347a8aa8326269e0a14780c9583cdff515927fd5bef528f9d23787aeb803d70eb916b
SIG: 2942f708c0ede4cb0ddef13b85d71d7213e0383dd294f534135fd69cafbcfc0e33090a2a0ca3fa572c72cdf5592de903b1584495ab63998150f2b393a3b3400c
TST: 667
SK: 59d501393dc5999723810706fad7d6efd163c44710c741c185c27e0425e3c05b
PK: 8265d43cfb0735b5d7250fcf0fcbd154bfc0eecb13b7ad93b6b02940588b843b
MSG: 564ed22c172f5c3afbb0b95ad2fc64e4be6d4db1ebb8d399c43a5e16048e7f8732181e5d0eed8e638ef2a55aa0d7b681fe02bb5423af94bd352d3c2ddec0f84760a4112b4fe017cfbc502f9543cfa41fb2aae75a3a081f8c499033d1fae5d9c50cb44dbc63605a54398fbf079852eba86f2fdfc272d0c4179d7c13cbc1c2a3da0b82845cf1a46ebbe31e79b6009733c7bfe7aa4f9ffd719c77dc7d748e492e14ee5e4179bfa9e649cf0d89534186385ee99410051d6656e623438cc7b2e707e48c84915549ae8d67a306c67b106b7a25f45f8e10dd7dd3eaac31f1052257eb6a7576b685cb9e6c1cd0d73c7a3ced5a8dd27308ae00f95eabdae9d1c4aa8934e2424c9328a5228f4f82dd4a66556d8217c5a22b2beb86a2a43413ee5e10f883f2cd6c2e8749b5508842ecae5ffccb796d9633e87ef4a96c0df7ef47b283d096723ba3135bad75b2e19ec04f70a478428ad5d0aac0dd2ab9905913e7e5ade408801d5d3c54d9cf7b8f0f0c5eb054c1475cc210a2c798d8bd89932ff9f360421858053a707b8bbd32055c44b20712a2678a9a6af9e36d04dcff44f431cf1930cd18fc935d2267775c69096725ed89a291dd60e21ac0b0128734072992823ef87b5efa6cc5b050177f55f4cec92a08a65bcadcab9a41c36086370b7b9dd6298ac7b0ae6a09c9710abb4676a8fc87a3651290144b6b30ef4f6fbe5b9ad25237fe0605e3b9f18a7718ac9fca6f325ea55f49a807fb80a2402ae13423080d327758649023798d5728e0dc64ac88a6e2945dbb3e3ffa9fdb4c7b58fba3f5fbd67c686b2971bbd8ba4d275d573eb796eb9146775d8cdcd5fd3eb5a88ea5a930ec3244e6a37c81f6a2554e5ba787f0e45319fe4b8a2ffbfed50770e7827b3e7bc2b44ce512ae6051b6f9f13931ea6acc096b8dcb0196be422484db5fcb299d
SIG: e646f164cfed8c2e060710dcfbc3e9fa5eb396376813190184e346f52bb0ba5746ccb6b59522b1aff9830f2f98b9e5dafcd832077883c44e8a35388f718bf40c
TST: 668
SK: 839fb132e69250ca1ad94510087f92ce068769213a19b2a6c89490f1f578807a
PK: eb586619b44a15379acc4621a2ac71ea58970026c28e2409fc1ba2bd8b236d1d
MSG: c57232fe32f11e894b437d40456207cc306db48169b20e0781103affe802f5aabe8582952ca8e95745e9940d535e00ff65ab3c64bed3d1173a0f3d70ce4ebe2b50d048bb47164d2a2cd9d95a10cf0d073ed1c41b3de333528ee32968223a0d847cadbb5b69f382164e9a28d23ec9bde9a828e8771c9eb49220af54185508aa073a839195f103bc2f32fe04f951ca45bfbf30d2fb8114056a736addf27ecd9af0f6e5e97e5773c4fa902268c32a151410955f3c76aae255549e0f033f89e1a78f265cbab6beb7516d4badc49cda4588316225b4c85ea9fa99c7d6766e9490c49de59da717f667653530071dd2f0c53e31d8768156feb08faf00db0a04533df97957a84aa46aeb7e36c0b0be69018946f1538a6aea71df536f1442c2444a43a043d046abde1a782b0f4f5c6aa720aa60afed947c0cee477dbec00557b37212d93357ca2b6b6f82715ba0e484f6daf2d0b7a98c033519ce38263586796d5d31cb2bc3d1125bc0ccd329a5c21fd27a218ded607a0e7515b571f192c33f5fba514afe4d458100f3ccba3f38eb430b4fc88faef999fa71eee488228903be29f24df81dc911044e924cdaa017cc7d87e56a6cba8760859bd63dd2d4f581b955ec924a49afb47ca0d63e7826fdc712b4943b739e1857755a33c6503675fddeae062706e34f744fd932648a5608ce608a61995783f3339ca3fe107e1972744bf6d4edafbf47ce021e05821fb124c7083930e68e6f5c32d2d9fc4a884c0bc88404e4cfe3c1a2420d41823a385fb3288db65c89545f6e73f0d8004b2ba12a4e07727523ef085670daffaf41c28a4c1157bdd245e68750dd200e023af90c67561e0fe4ba340c433f755eefabd4b039bfc323dc11adb75aecc448a869c7f2a58b9d8617c64b8f89fc583f8c948e2df0251a6c7d8c738c3b5a42b749ad5e8e986bd8
SIG: 66437b6bc05e75dd1626c3c4ff1f72e6db381ba1590948f8f16ad4d66e5991659aa84405568cfbc0a77c025e59e43fd53ab9ffabba7b258f78796239f90d4501
TST: 669
SK: adc1e56c3ac94e6cda0411cbc3ce2af128d185a2a273bdb2af8d7e50fb96b526
PK: 5dcfec1f9112751564ecb60715ebb2c517b5ec37b2534fd6329924429b7fd5c5
MSG: d4f959474e0b89e2dcd02066984f88d739dd1134a33309f0a8b7802eaf013303c13515dfeb461ea3d248e998b9a4e54dae5b00190a45e70dc67e98f3d4cf906c214d4f636d2952925e22b1a86a1aabb3a892a9f8ed454f39c63d35b71e87a2da55a8e167ac83a866ad167a17aed183c08518c15e6be34858b4cee2b8427314760fffddd5923854b1747f796e1a5249fb3044894ed646829f654316ee52f4010c8dd321fa1dec397e50145ed9e31686fd5203f7233b8da780acaa91ee0b5b47207866aad85f837e03b4e6f6de8c04acafd707bdc1dd45500ab564801bee9a58ece360d004828baaf523e2f5ab69326a03aabe010878fd43ffaa56872244d7681f1618e623e3d474c73af8b080a61821a574ef2fd752d23b605ec521c19c1550de980c094d05e0238f3e008e6b195abfdd4028ee1ee1d6c66a76f178f0b431e4af44ddccfc5290edff36ece63e8385567013f43a2aebb67e3ef406308c20488a76d58a214f3139d983b19afb12e3283607fd75107bd31feb6256174b7a18aecac9f8562582018b0e6de40535e35bef2b562553885129397562900d3417f98cdd1e29d731ff48933f2952958163ba67d59561811b83772bd05710b6e3cc0434609937507223abb71a6a8c838fecdb1d2d37c95dc806f65f3f9663d99f06e6c0f3c32e95af1dd708e81108636a26b968e98339c74128b6cf671335884ac72f75b637195ea9eca053608996c32ed445410f67fa104b39f0fdf3c9b5c6157b76803756b27f4c3ba1b47f328576248e9bc53e7b8ab0b2ed97c2f9998bcc7dfe39e264aad30c6cfef2b5553ffb5a699aa4bd0eabe438ce0522cc91fe4e72bf7eacba4771ccf63a37aafcadbfbf99dd76b85b80ee075d3a7d1a90a55b7729a5416e5be696bf9fb7f3158cfdb5cfdacdde8172ee1ab9486e24ccead29b457acf43
SIG: f02e5dbcb68704afad03aca81061dbdb998570049f10ce650ec7a2eff15c793ddf5a272cb683c22c87257c59bdef39efea79bd679556ea1505ed0036cb46040c
TST: 670
SK: db89df6a23d890b7f00260e81f4ad98fd09440365131e85e22c7951a187b0218
PK: c96763672ee4a2cc5a93b6a683df9b5de4d9386a790835681d1217d19296bdc8
MSG: 54c1c5111e08c98245ba4f1318ba1db1dcc74d14a5c98ab9689cba1c802c68bcfc81fd87ffc61caa942f66d7e5157f65538c7e7b33170484b4b6543f3620ff29638b64d4dae7b02221cf7783f187ec4231e6b6946d82762074f09c32781c2f3846de3e8217f6e1b6e0d2b5595d742e2c4e325a2841924044dfcf12b479eb69f1bbd40eabddd1ff54a9184d366dff9d8f2d863e378a41f10cd1dae922cd7fbb2a544e47eabf47ca0a38abba34454919bb9a4ef044bfb97b708c2f7428d68f9c57c0ee7e7925f7a2b5c6e7df82bb2680c862dc7cc68b0f54530e64afe2763d9c7baf45cc6fe612d1f7827739c4411398888f7367c3d4377907acc06a06f93f887226798f48aa5464f601c2c1edda77edfeb9b9b5d5f9cb6fed37900547477fca1d09ab52d63e491feb12fd6dc805a78cee3baade4352982061dea5a2653db8e7607772e834b3a505c16dd6e7c71b911e842eba925d77a33c5c57ce1184098078ca2e6a3f69aa6a14639dc97b4b30c99dc4fa3e2cf63c701c306c5e253c5113854c185ebc8b4798f68d1fd780054d3eed2f394c454304966bddbd12280834ec9b40c1e98bc2d98f4845f6eb44f25315eedb3b79ffca4180c1bddd97d0c9affbac58814937682680076fe5a3babb65d28f2517036c0cfb42f0293eb2acb13949fe91e0ad0678aa243d7734a89d997870bf9a6a584ed6e628163e39d8aa610d46b9285b9e1dd7e8f807fdf5ca2bbf6de5e5e68af7cb7ebd43ecce227cd70c7bf4ee1433edfcfe886614670cdd196343fb91e15416d2f6acbae3eadc030231ee9d2ecc52a88ce8dc7d098e7fac77685b4eb540e3019307143221b8ef77f3632c893d556e0bb743a1963ec15886c8545e87c95cc825f200d0f3cf4f55a3d660a536a23aefcc428a43203485ee84342f5c001ee8404e759017006282ab8ba8903e
SIG: 80b7fc8b6ae6eece8166b7ea534cb5b214c9ea9973921ed05de40c78e14f162b09e978ca6d86ee434d984b8b0070409dd2ad11b53178e239dab5bc39c7ba460d
TST: 671
SK: 00e6bb17af3c2df652b34f9abe19f99019074233686c7114e3a0edf08309934f
PK: 7b8232a66cec2f915aaa7951d29d2b9ee93d321d15b203c51e61e8ce83d187f8
MSG: 063281e41e8ba9703ed09ef3bf0ea46e4cabdd6ebd769d05dc045d4f990d69fc554130a4e61aa21e2de4c92db48a20a37b1747a7eac5ebb2735a8938197f139fad1497b351ad064c0f18f8faf1fe11f63979a69968e24cf91e58a3ab032669e4efee274f96b58be7d9e391f36fcf0709b2cb2d22694a6ceb17246945ebb3bc7f0f03bf0b08dc9626e3e715c991671d53ebb9ae83a7d08d44f63635c40f8d4817f58de9eb77cb25b2acd6def969ab569e974a8adac11a86b58fe6c10067499fc914dff56902cbc393a71cc25e8f05c03c94f13b84a2b01a58c10dbcbb60ebcee487f529177466299925da50e2da5b5557f0aeee3fd7f47b5c2e3f84cefab4679691394dd122303bb769afb3adfe8358b02b679273b35abdc6402576ccce5e10442a137ef9456939b289ef4e417b1cc6239f7ceedd68f1a8264180e068b4966fd67f2bad6edd8b4a1e8d2b542daf26db831f1fb51eb86ffadeccd9ac3d664f346e7d046c33a572841ea8334e7f2f417a05712a9e334e487fd3ae175455162fe8f49cc026a640c6cf93cf58875052f41cc9820615653ea2d084c896eafe5ad4725579653084994f956d5c94590a2409581b6fc86e40aa58bf6e6057a6f90af3b87aeaf32994a55a54f79bdf3dbbf5ce0ff812e486b0545d9e9c2b0bce0d4c3647b1827262498834e198a3ec70f3b03d6aad2c49eb80b5e2051439225fd9ce9468d69af70a262ee3b8b62a8e5b41346da3012ffb45816b7becb0e79a60bff71636a3e4bb1b35caf195f55117280f787217b3caa2e793726fc5a74d1160dcad868904c197381134ed8c3db3750b7556f69ccce18b77388b58c5b8113e590ad6eac5b91ece5a6705025c80353ceb1ed84aaa1cc48a416bc016aef173bb80b2ba28c57960c6b011b6b495a3f3311e79fe46bdb6a4c381fb9dc4628b0a83023558f1
SIG: 04b3b8501e396c4a788e14ac49f6174cdb5c855e651203cf68d1efa89aa58678d4d1f303a9877a3786d203c355b09d5286c1ca0df04a89aa06cc3f9d0fd30504
TST: 672
SK: fbddf6e61e20d806e55917756de60d0c9a99976f646716ff2ff1312c54dd971d
PK: ac538fabad4380e60e977126e7695eeda5417d85f7d23db21bd0ad111116f05d
MSG: 3e9953ca55d0cd233b98833eb1bc79d3b55f18c8fa1c42027bca25579153b55da0c5a178b8386956d9a54183b24c91dc4be994847237d3666a0a0130fe19924bc0ee50896c35a2e16a29e2e2acf180bdd9379354687f0ece6882d26e980e686698043bb1b01213aa644a4f8d61f9b613e62eaa3576cea0b0b83f05ce2558ff6356495c45ede4a8f65b814ab8a7309403dfd43cbea90893939b7800aa00232b5f6b7714ebdcd8bcf34a5a7e822ac7b1b099ac615f135f8c351dc41ae5f66d5f9c2600454ca01c009ba6de04162ae5f1f270893ca3907aff7f78e03396e32b622ff340537bf123e55995e9209609330b2eee51127484a40e250700823feb0bc97bb509ff732675dec32ecb635ed92c7d78fe3050200cf1d941d6b388800a8419d96a595eced5ec4efdcb6f987f5472a5c43058d3a3a7bb56d7980365ed43dbc2be48f1d18ce76a89185426fd5c69df7e9291ab7823c23a76941ed3836aac7b58c0d5fb6b636c42471a4d1703516f03e935f31f195450e537b2a07d545ba4b68afb0638c65bb0ffaa0cfd69d7104819796619d483a0245b4fd9017f62a7d3a5fc3b7289d75735f287ca0a951ad58344b2ab7d7df8dbd7922a5abb8d7c2e79147e6d36ee31f930473b0727dcfd58d644d7d70a0ed31ca6a13ed9dbd224492efda19e4f8eed46180fe750f07bbe8e99854d13f58ba968ce3859d61189cd2b667f3b2d0665b574c4bac19d9e37e5b7a80eb334e36810530aa5d1766393f8115a52090c91823428c897a5f35e12a8af2cd4fb13907ca6603a4f76f5c2e02374a8dc3a47c1be6f1d1c8ebc59b36d1cfa0ab23e9b0ae9b0e637eeedb9c66bea62dc630cdefa718239617e3118e5b6deb7c294475282e8abe24fd5a54b786fff9028c5a033384e4bc8014dec8da100a94b178ef88ec357b66d2b9098ab64791696b1a66b
SIG: 8c9b77aa0f1cf52e8f7a918b21b468e62335911bc59306b30ce77bf692c11059b0ee9c5daaf6839bb81373c61d28d072702b595e4dce28cb993822b24813040b
TST: 673
SK: 8a55e77bb0c8740b8c2e8ddfdfdb40f27e45fe81fe457111bf1c8730eab616b4
PK: 9ff1fd0c50eb24f99fe2f7711d52872dfc900380dddcdb86fe6f4a5f350a8743
MSG: 20fb414e264a954784f112bace7e0474b39cb3c9e53dee0a21f4cf6d4a99b9347ddffbe281a6c230a75d63a72fd05f6db53ea7014ef7709d18ff970f485fe83ba1d37147338aded6da4cfdacc1e69d2f3e0ef362f47b5bcfb78a1e179eb5c5b106c8d82a0a0b290df075ab27436929cde656f02309f95750eb676583262e5f2f69f0ff72a8e057266382269205318740bfe06bf5c2cb4533908ef9f9f2869a75b9533579820e3bc0caffd646171c8286c3a4aba1ff0915d93611205e230f39ff4c4caf3f333e753fce2b71213e53d608415ee17fd48212eedd8840f337101ef0d0b6f7be4bffc06eeefe8066dd27a0541a468831acddc4902e2fefefbed19c308e5621e0bf46bcd538aa13faf04d380759c0e107e912001839dfd0b635440e9638f5377ca8450f350c01129ee33764415c53cb2ffbf968df78b742fd0665e78a34abf4decd1fd386289a1364e64555eec58b0af9a4cd6b36d1d5c611a2846dfb5589344bbbb02560241b74b993a25bef50fb1e7319086e6a23986300834ed2dba98a168721c2f784dfb8d3800d06a054aef14d1772b6c574af2563d193ef2e51bdc62d2abce2eebeada79203498e6686c287f37bd88aeb166f7dffc3e6ad0294117ef6ee9da8479ed8a16fe9be246d266804f29658db75e7a0873be71dc7d407e39fabd66f988b457477427fad8130f09ab665f1597c9046e7373af9a8352a86830cb92a804488700fe6891924fe2a7201733d95e591ee0a1fef1c2636078d370e7ad3b6a944fed2cf2b30aba2d56f3495b2849c03bb614f48bc4e507c395a6c35d3eed4c7be8e680f2d45a310b187eb88cf0e8ed4de7d37246a50a6367b97ee3784322c0b71131a283198da4804de751dcf70c4bad00dd98d873a69dd1a09cf69ddfad7ae603500b6a462258098d8b66b85293594e208829b5228fae2fafc39
SIG: 8aaeba535c511c31d3f8e95cb077a9a7ec7d08441e5342a6abe0bf2a5d7fc930b43dac3d1e8ef2cb034552eb4d0839bc8bf294551dd2d80c53fd6279351ac20c
TST: 674
SK: 163b0cb6a12e8f07b0c29d6a63f6a652ce497270b5e46fcf833c99bd843f8c64
PK: 68a35de4ba6f0f82ecf4b1e0df8e24cb4f18f2103ff04dc1b5333991b6d314ba
MSG: 56a1603f725be07613058cdb3acdc52354e3bb1ff2bed13f895175b15c8c5a90ffbe46b11a06cfe362dadf7323c940417255aa7aa54312103e71463daa0b5cdaebd0be723c732273e3c3f5bf7aa3519d69df6f4770daa1df8280bb3cd2c714ac030200546579f56c60b91ae11f4cf874a35fc59b354bed80f56e11a6cd62a88ce6b4f6bf39d64ce3d80409825f90162c3d96d10e478607365f7a241e71af980042fec2d68891e0c8a37c58ec4e600fd581e790b0aae8e09f35d4cc1876df434b80eee05369f848fc4930577d1684275888f3259cb47376c5169c9937f855a96a9e748ad0a69ae4ab2f2f1744a392f9acc6209975b784984cb12f98292c36a53221994abc56f9a66dae4560b79356ff47e128c0796a7fb0e0bbc9600af48e49eaa9427cf6eb6620b10cd2c085b0b342004d5b0d3edc11d29242a4638780762c9dc6069b66bd84973b5011961ce56db58bdaf48e6be12ab9ad24416297004d02914b959f54e092f8cd4365fa6ab78ddbff4ce8dad4e2f53a05c0cc499bfb47814a2713551dcd19d447f627576ea4ea4bbda8bae18a6465ced747ea17180b009f01212160482b0433aac68e67644d00f41fdf9990b9e11117634deb139b1a40ad3fce4299a17fe1dd225301c7f8d8010a796dc79c13307d3ff992a88be664d4c886d68ca9e4470cfbe63ebffc424010e372b6922aa95c801d1e9406da4bc188ca82066405bcdb3eafc937629b3263dc7d50ee5278ccec6f11d5517f56bc269c873691e7eb53faeff07564ab46b403f15d9e0e692486ee098e7b51b42813469b8235042233ca3f9c4f8ff24a571f47e0adf9144aea488a2d2dd001e31fc961e05c3e85f0d981407c873158bb0d35bafe4b60422e67551e970165ce3fc599d0fcc92b16ac36a92b2c1dc6b3f033fe310cd196da04a4e639031177cd27d7c2fbec65a00b
SIG: 17738f5726550780651d60199fda39d9c4768db5917e32393631c54a419d59f18ef960ddd439380dabc314761bd0cdb57cce481e6109fed095dea6e865aa670b
TST: 675
SK: 8c839381b6a7ce2649c1ea464ae3c2d3fdb1ec666d7b4be4e2a941ab6d6557a7
PK: 5c724a30c6fb32815343a80ddee6eee544516418ea95e1bac80afc8040d63fc6
MSG: cbcf89c3548964c38d70fd8f68e8ece36cc39755c971d14d7e056f39b023ef166d17f2438522f010d6d835d886e71f474c6727a4221fd03a7574578289ed5493ac4c0947e3f428d8fe064006a256cef21811d72678f5dfc6ba66ac29ecd1b32ff5557cb08c5f130559217a0413b759c24d83388a2bb9b29b6b91d1f3101ed625211e4d73805193478cf995396c10b1c5affacb00899da04e3cce193b494e2a933c4eebe0a37bfb8f1b8371bde5fda09e804e940f344896a529467adee45a8febf85ab036cab880143be4f59b7741d8e450278b06365578d40b19dcecc6e1ee3da34ab29013fa3af7729272962110e385ab9a022fae4146f89716f7bab9d3dc682f4fac7736d3e08973c685bbb275bbf8f217419e5cae0219eba5166a5de1b11e3f9a908b8ac7e65bcd623f8c18bb024f605dcbacda790d8362957444a95c130a37ee9d563d0cbb4cb2b0ff71591d9390b6c8fc28753a0e402d6487cfac607135927d89267512b34f877057d9271bccc024dfedccc6c32edf75c8b7551cdf80154ee8e08a0cc43044e1036bae017eb48b6502c7a9d60c8b370cf3799c464f964a69ee659501223e789a6497b63496df1ada2e808d2434fc8bb9794e5e2a20bbf4d6925cb3c5bb14842f19200905ba9354e00dc33cff5b42d4e9d9668b34e661d44bef76fefe2ed51f94423a933ac94f1523bf37823a238d616c6b17973441e35f9405a04d99eaa8f504534c8b5fa5e8e335c743bcf21f5d492b7112e00fd8642cb12bfec849df62120dbb06bfc2946a5601e25be75011c6f00c65d35f44a46af9e4f7809e5789a3a61ba0a3b213890497296c81e42e88f0ec0f5defc1f5d39ff2a48b7e3026c9e547202edc7eb738c34ad3a15d373ef82a4c1d181f285a98bd3314c2c1947c9e2c60aca51750ee7f943caf0c4e1e5c7df7291e973b1f936b73707619
SIG: 5d2110d1d2f3edd683bdfdbea3ffa7cf5528a40b8b3d8d8c9bfd22aeac28bad471666e062f7d38ceda8bb37397a1c5c3f733b537967045706478437d4d187a0a
TST: 676
SK: aabbb2efedb599424a5f3e08f90fa8826c5c92170be501a1181fe8e8df974e0e
PK: ce7319ef88b242420666ca697ba8501d274ec4a5dcf844596608b9dd5a8a3acd
MSG: fcc15cc57970569e9ccfa5a778fc7aed71978a3f5624577b6f57fa3f167ea223ef31764c488d059d06531d016bcb17d544d46977aa241f8e07af4787a0810f98d766460c0841ad81b88f4d5d8164485a1258a94622c5492428d6d575943715766c2b0a865bedba167d5d340edb579c47aa32459b8fc98a79bb0bed1c960b4ccb7f2d4b5681a2a70d505b85b81e3d99672714e4eab41f3ab0ca874f417186feb69ed13fb911f49d1584758b2d18b4673edfae495e68dad513a7ac0d47b2753cb4eda78fb431f04dda8fe8030d7bb4e8dbccb969d7f580d9c1ef935d074d7a41d1f8b9dc45c9a2e4106a5529a98b95529ab0edea0b5722dd686f5a7f3cd8fb2624ab26c42df11f510a103d8a929830ad85f52124e3d5827ba60bfbcd736cb6c590ee777ead7aa2224d7ae46d257a90407247960c9cb03860aeaa7f54c1a8e11160d11bb473065e19b70721c8f072e1909d539e9ac94185904bbbfe54873754ae1ca7bced6f40561af4b505f03ac972a6f0bfa73b5f832fe23b898b2bbb0574a6662ee93b3b360da1ec7e838eb2c77c7cb7fc164f7c4627010489c858900752c92d9d75ad547167e4bdd11a07d28b651aa30f16a850e060dd2882fb820919a398e805eb63699f4ff595f991524731641ece25fb3f8e89ada501192b1eddaecbacc8b898528f2d5b3312694f5ec2dc9142e1513f777a5c833409c171633ff9fa2609d0497f5df4fbf48ef2b77d55e25519d2ee79b5fe9d8fa46000decdb4f25dfb3f2bafb19fbe2cbdac002a359a954bc69bdfe2fb36adfd9a1509f3e3a4c6b1f3f36e7cf80d583d440ff2a144643098974d71493ecb6417c0b8065bd2c21c1e34af09243fb49e9d35297eb0a52d56dd270fea6dc5c080a05599f78581e90fd8cc4cd11a505edde84b892d8953bdbb2379d33aad64658ae20607dd35b0bf3a2637d20c3f86
SIG: a0b19cfa6c80de77bfcd321030bf8c03893e2b21ace6c6ba1ff7408e6ff07d847e6b2b688d4fd51aa932701db6402ef22322e6e9fc7e320abb4d24e1acc6cf06
TST: 677
SK: c2e074faa234e99ab20adbbeae11b8109723b708c54586df652b402c35cdd127
PK: 5e524ece1c696e705a3514dd0082b840795a59c36a96cbc482bff5ab4ef515d1
MSG: 31290338e46d1cc25ce99cbacc40160341b785823c823c4ab9baee3b612579f1c011716796e56e2693f6ddad43922aa7847cbb4148101651bbe62d50be90825e8eab777aa4b8026dc5385a97d3df76160191f922cdd2f07ba5f85e95f45db22928f90734ff520c44dc8fe3903b4c51cd23e064f01c829ec74fbffe25fd0d369d2765740f43856bd7398a1911ad749836160fd98d04b28ee87e111d40718b5a166f05c9a471a41566557069f7a14de988bbbf6777521fcba6dd65de4c06674a11853af83accb70fb328dd8fd6105a7df5269c9faec8d900147e928d970c36cd834bd6054f70650dface94b7629d16e3703d766ce7638d0ad1e17b77469b958d2ba2a1e631a1635efdcb006ebc6e5d8b9faf7e5fb989dc0896c561a26f3c25f055716b367138ea5da1f81dc72cff7a55afaee5839ef5aa822b2970aa18a8982163bf5eed1b677ccaac1224ff6c6cf256374780ae65803bf5c6e23c80bacd76ec3e2ddd3ab71997506448e19db198efadc9f757491f1b0972c82db29410e1e8bb67bbb23d53563b8807e5e0c2e32ee596b5b4402328f9e179e9ce856d3bd199d58de6c5c252e7a6124d81fc9eeaf23d347d2ab88917aa684450dd58303516c1a4d2bdcdde220c9ae3790f298d7d384b70c2fe258807848fc35320b578b33503b75f38a1df630bd33e6a85a4dd4df9f6e55a6e6867c73801e593e1d591db89ba9a9af0fc292e06fb515ac8a5e8e343a821335575ba48fbaae3fb12deeaaee60f4b3d317ec0a554ddd425c84932c27a7a12f29d6371510783bd75e60e2f6da20052069ed71e695a943182193cb6851a7d2fa3c666c193028015ac8b7e7daa6c5204f77a6232b88b4abffc5362fde7dec36b9d454880849283b1156339ea2e8c3b10e51bfabdf72578c726419a38542cf8649df9a0909f582debad5fd89d8c81f83d9e423e7503
SIG: 657c3826b3483fd42ab6df869d1b77a8c4df67a6a590c7c6772969e3df3312ae0654fb83847af221935a0512291636ec0595700879ebdba8a1467c53d40c2306
TST: 678
SK: b9da4e6af07e398ab4d21752a32c8ffa9be0c310d35059fb661bd73afa97e2a8
PK: f862803c96cc42adc8252884547230b970047b7e5da996260ccc0240ab71a6ec
MSG: 6b95af0eebb6a08afadaa19621f76a839be80851c6dd315e8276f501995d4ce6d134df5e798ed517a2f0e62aa1d6c98c36ef14bb1e5ddfc98d5a7fcc81140a13c20d2ca0c4b40e6e6a03eed8c899f9d1f792468152199f4b95a432668947a51d7b8e104d8d1f12aacd967e08b08c41c3c8ca3feedaa5b8b63bcec0613864d953d81143ec81425bde29164a0876f23f37ac9ac9473672ce11a08bd5476f6f66d665e9ad617e34eb32ee56ffa459f20d1b9353d7821298545750c6eff3e7d4073dc3185ede0391cce0575f8ba637d800068d9d7e5403ba7038d2db77da144784f2e8ea76aedfe521e7dc6a674ede35579595993fb20d44b4052783f56c8c0bbd0440b69eabde84468dd13c671fb1bbd5cb022c2a4fcf3542d8b3bb518e5adebddc84e714b13be52c56b282b42ac0892a5459281be7160729f4112c7d99df9be5434f823a9ce0501789de1d550ad50bb18c8d89a33668270bff7b91ff118f5cd9909addde90c024a3ad713915174674f28aaa9f94a322baa543738edab4973312b5bfa12155debcee163cfe2b04ac9c122ac8a4e1bc418c14955d9610455bd945e9793b916267c9c5f9e53ac04518926ec98ecb84a4f0445dcb1236c76c3a678c69abe4e92c22971d62217201a1bdf05c04df8420a3de6a917a85e71e2b9725e77b522915d4c9946077637c2d8813f010b9491cf0eddc3d4668cc0f8bc8a683579be543934da2853a16f5715724f779819f44439e1debcaa4270d9b8594ba4c86e1063b3ce479d71a5409bef27ef4e5c1d1c96e8be13865af7bb43f09162ccbc83a2ca9e9b8a2324e6d996575eefed37ef49908185738b8eae43f8adca330c99bc66cc1fd52c530d7371c60869ce42c197dca0ad128b85f61c8758f0d542f3d3298b65e93c6e8a68fa0e9a1d5e8c5fec805b83aff4390e115eb64f3f078a0b9b66c273843fc6c
SIG: 625e1f42c87434a25d622d80d12532806afb2509332449e696b65e1e5888508f11c4ac25f59b8d94d0bf27e4c8d1867007c408da573082dcf19d15a9d5cccb0c
TST: 679
SK: 143f7b4247d549f6b7c0917266c50f962c28a2ea24762f537aa06ad15e40b35a
PK: c9959f90a2d5feacbae2c4c803ded5deab86987637064337aa2a0b0ddef2fd86
MSG: e274202347a0d057a48bf2a1f6e9f6cb4256079d800374093c020cbf520e5fa27fe996ff07f33ad3b21f74ab0cd93c86475ff37cf622d3f9fa4d13bc99f013e8502b24e46cc87c47e6b2c3662b50e979a0f345b784ff21a8a4d92adc65e86e33b4dbe17f528ccdf5b4864664ba94ffdb7c7d2412b438e6e43fa9668147ee3328224d1f52a3f5b54359b4f7fef69af8f867b478f130a147bea42ed39803bcbc2557bca8c3999f1d24f0a6b03c98846011f9ec74f666417b95020eb1fb2fb88b6312e5008cff03e2d77a26aa532d1780b5077f9e8b828674455d6bc957975f7b2a50e7fd7c1612ce02362efa4c555a1eef68ec34a5c006a6da008a31d4193dc2cc647685ad3cfa3bd7c560b7aed45f0f1a3d1b5b362268de532857055ab9d1d5d858d9ae9a759a51bb9478e8f0ee93c984b576b8b4ab460280be3de205a32f1dc3d572923fb213ac1512d80eb5ad5c18944be77fc17def13a61bbd31bc71acc23d250ec5894ebc214cfec0c1b906516d32d836adc838802e8de30dd76df6e61c1bc438b68d2b025a84f211facf3f1384d2612d0faef5d17131cfe0cfe833fe950e479bc29cbe7fd6da0cce307cf0b1bd92c80e878e432f636ea0cd42480c07e8b8e57e69b2f938b78120f6af4abebf7d4b05cacd6eed854491c029755c4e66338993ed2ac25d19a0c5b40f5e32c8a8b1bce369718186c91d60edff24a8377a9969757599067dd31263a06d6a61154781f29611ab812ff82e813739646263704cd6046357a23c045e2407b7a89508259391314f2fbee49aef0855c6e5e63d912a19df15b11ece34e276dcb88bf2f2e4756358f34a0ee3952b686fcd17578a884176d34ea2916c5d9fcd00eb9e0aa9f2cf0f16e2564bfd28b6ab5968b8448f068320e4187160f8665781b1e2ed9d049e1b54a7d72720ff9d4f073051996a9db6f0c6821c424fa51d
SIG: c1cfae58515713ea728cfa09090e8942f8df18621ba7090e3a3376c3802775a1ecaf436b184978041ebb75226f970df71d6ad353c0fb465023f9e298f64a7002
TST: 680
SK: 0d1fe9d8b9a2f04c22bbb0edea3833a0ce43339347531fdb67ed513a13d36b39
PK: 67c49f410f4853293d0c4d39f4c1b3d6c6103c5cfe20a9a59b53932043517369
MSG: 64217ac841fd4d6459bfc4a49b8801d6929bf19b408e8a53790ceb51ec341f9b46a351e8c2e59d887e1eaccb914231cdca1d3e5c47d166b4cdb9b58c013c59a3bd283ad10f6bd62c0f15f764ce14f3b265f537c63e73b6c4fa65e06ce1e1f4ae0d11489dd2602f95fc402b7712052abc84bdc778c19f10001b4e0d5fbe463090e83ef438fe068f3bb6fbc2c139af0678ed2a11faa1b9e49aaa4620abfc08439fbfe2c61840769e5fda2677f8e2f0a14564f9f504232a9fc0d9da471e67fbc574c3d56d2aeb937a586ed5583556308a998eb1dc476a014f5a08228dbed95a1208bc1d1f5d76b4e8d0b2434b995ad458e429ee6142a0c971768cc40c40bcb08e9603f09611474471b3859d7fd584219f02657b430e9e56955b3467ac56ff2eab22cc498489036a574120e2db769a3b21500389142c78a87d069f0e2576cafda8cddd7915a9228773d2ac9a075cb387f2a898617213b2cc5059d11941bc4fe58641e7c1750267e53e99c421cb4cf21d098ca2d1f41644f7908983eb174a23a781cf15ef38eb9116eda4123a1522f53b81fb7368e8075fb83859d2cf98d921535a709fafa9873c4a039aae682f7e6286b899257c0924016ca5bf6d3169099211a9a4a6745cdd3198f1337f60928227ce3c7d60960b53dedf011a8940f5c468207a3894bb0872b333ccdec9d5ecd911ecbbb96c9bc4bd4875320e4d3e9c02d9dc76109ec45e61d1cf5ac729f2e34a9647b95bce70b0c633171adaf0dfdb5afba4035b3cce8cb7141ad142bb7add4fc3f961d42d7203754a4e313221d487831e32947da91138ab648b5952ef6956e27aa5d2c175794bf81ef277faa6b905e14502866887d87880606e81b27af01bb263ecf2c5820585ea6ce8d8b391d86fcedadcd11fdbb566fdf147f402010fc35f5157e036146b3736c8a43359127c261f6bf0cad3bd8a34cb1509f7
SIG: b05725e7371ed0a91ebc89f3c30baa99183763edb4ce34fe901af3731e001cc54f287118915e90365d91aca8feb1708769f9f1d6eef5aa113bee00b5efab2704
TST: 681
SK: c10b5ac6055a1ddbca28552e5c72ebd05278c92239b2fcd0c1353651a8e559a0
PK: b2183e1b00816d29305f7468e7e45eed3fd8f23c15b305f9fda93e812d65bc27
MSG: 3594905f9ea464615f41b87abb9d167337f29d45d97f7a1464ec9f2ee50f90f2e67339874d3f2093be9226107701ec1aab941c4e059f1bb26ce86e148d1d9f0da2a2a0f9829a364fb4f13f58b960d0f8d72323283c4490efdf57878645890ff7bc5065dad6e51dd1e5b9a5075150978b3367f1ba84e45ff1f1276c576e4bc72be8aa8e405fc2b27f8146b999845faaa0595d3cb70e5d3712ed54a0fb3e322d45380b5de3609b967b959bca5a583cc520cdcb7bcbb829aa25d7932095ecb303923c2560afc3fd7324b7b7acd089a9f00c03a73d043dc0cf0ba0d8411e2b1b18d21d2a32a726a53059140f784f7cedf2f33cec66fe4ad5cc9eaccbe4ae10036ac3523bac700a113a98b598e6df0304c6fa3212acc04c4e3c7f6687362ef86d617c6dd483f8d80cea66d1951127428a61c1e155a6850bb2afb7f91c82d73eb2b0543ee8fc1f38e1dcdb3c503ddc9ba0812456a5ce2e11d556487a646974a7bbf86e806c58c68c4269a7c9bbcac0ffef9835b33dc449a75479ecd23f6d149c1e5ea8b69208ff36e5fbd68295550318bfa0d3b1d6c1ad4270bcab0904ae53491f9b1ca502e012eed77c427d49a0962f1055125dd7b53733d8528934b5580dd5fd5bbe854978bae3d25bb4ae944e9065e8e2e07946518a6f548e36e056be824d9e02a7a3eaadd37929f58101cb1853be3d7547f58f49e38b018a748d3f19c48582abbdbe953a8a25ba9d365dea835935899c19fb0b51906aa972c5ac45e99c40b3b76e35d327e321e8ae2306a6eb3d8cb6ec2fa5399add19ea0028a01792c08e27c16cf4f85aaaae72f986b099f9ebe4ad0b25d06d3de44a8bfa52844be4a93944833ce2add51bb554b356a7dc49748dd45ae7ec9e8db426c97a25da5edd3b621e4adbde48197a3314de1c50f4d6002027dd7519dde3e15729e486955ac40d9d66876f90668c689d8ab598
SIG: 8a9a3217fdf0643aaaa5c8fb2a88a556398859b8feefbcb48ccd88e585a167c94dbb5c0cad24d15bcabbc1edb21f02a8c457c56120a3234ac33577b9af2ddc01
TST: 682
SK: 061bddab280b0fdcb26bfd9a0fc721f68f88343b5d3983a16b6dfaa5e76969f3
PK: 815578bba6e7070ebdeca117568bd77ebff9e14cb8bc200c32bd87db1fb37d6c
MSG: ee76b40cd429eac7bc12839ca2f7cd31f1e0098a39c5fc19805be0331f44799e318d12571f06e2993753a3685cd2a96b2301e20024209adc5adf7479ff90c477c3695abb99bd28579dbc7831a192beed0ce17b038b20764800653af7af024e2a104ed0f3e52d4bbd3e109cf126291f49b0a21be433c1c5a2589ea572997f63d2bb3972d532be35a0471ef0573d795c072b6a8685b95e47b09ea9f475d93bf12bbd77b7d2bf5d5bddf0ae02375371d1d799ea9204be389e6a8e5deedcd49202e92df7c3e761f92ef8d79fa738d2c5bc280ed32879832ff2b026424589cdbd52d15b60f2aa3526b898849a34a85ff1c47dc6554b85ac76aa7935cbf3f7bc80ad009192a875ca209b40feb047cc446968f970da47b8cd67da7eb4e54a0e5ab20cb35bc6fb7f13307ce67eb6204a67ce9bb1d139c1b4bd5dbed58010c87bf831e6522ee182dad945804b767c4df2554f15b9e9afd2599ef258c67a22caeb92a57988006bbc72c104fac7e5413cd3d3b802c83e639eafe212a38bb7ef779af1a94ee137f6c60667bc48f27bf4a22241bc44bb6033836239bd6eaf3e2e223187841e4641b0f4e9ff8d5a41ddbeabb4138f6b585ace0fb6b53dc3c9edc0373b6047f27d835e8e246644fd832ccfe0df25c3d7da187c9fa05420d43455f2d08b571929386b59c6e0e10a35601da899b1b4dc3d95b67dd9a83818b0a318bfdda06464b4a42d3cb985f30ec97d6a2af13291155d60cec57cbd58d5cfcb35c18535e8d299b5b007590892ea949d1b137a62b39a436cd7e5b9f8d1b6938dbaa62c2268d459c6220a3e6fcbf80ba0118acd2342563fbdbc1f7c9dba7ea2c072afc8ae2128e3ebca0644ffd8163e80a1a557d9d39034ccd9dbd12c8855a6f9165b0801839cf6e07a9fba4c64d9c099e15410e290e677031b65cf7deb0079bdadc573cc056d7666d95d033a0b6bdba7ec
SIG: b83297ccdd6d0098ebf5d132d174de1958311a766bcc4da15f864d801f38e09d613e7aa8c336302735d75be4166d73b0184b0e0bc5ef39edbccb6e0e61afeb0c
TST: 683
SK: 2cab5bf55ffa914e9ad07622190d343ec55c13cd91b388cb7500ffe06df7c180
PK: b61e432bb97cbae388a2578a7484998e00e9ad3ddfd6cab8d3a5fc5ba04307c8
MSG: 2c2d04dc3ad1982359ecd5bc3ee035f3498eedff6104a93c602af2179aeb2cb1f41c5cdb0a77b124f946aa8a824aa3076c2e1acfd48f68070b26276a656b4a4758ab151a6a9c41bd74e09bbd9adcce1e87a0a80d17fd92e85e4bda472c988b6bb1183b7ee59a09d80570466db90dd3749579c4eb19ab75fc152ecdcd68cd1078ef06e593c73516fa8291481a667d3f95bfeb144bab59d6ddc73a2795c1017e09536b3162e4bc58f8ead38957018cfec72badbf22819ab0b406c64730fc73fd9ee61f74187eda91ed4e7993e66884af43ef4c6bf7f7c379e8f0f63dcb8041e26b8b8292b6b6d190e4adf430fa82dd74c57385b919c446db37b5e8767e4a0c95013be89b2bc4e9fd62754a844418400968aed2dd328d7b1dc91e1a2b3009dc7ad140a0686f673168a60e88d80c520fc2dcfc56ca9d4b0c88859099230714dec83d26b4630554dcb9c4901895f78f3834b09766b67a465de8c9490065bf568339243399fdc9d5100324667c5ab28f35c00f6125638e61dab70d1eec48951de0fb3f7b23d3cd982437c63473415bef374a663296f2986b1ae9579b9ffce71ec35eeca116d194f8fba9a45a91bae27ac455db71a6b01a729d0c135fcdcbc23e504a2943c00aa42070519d9cd77ae6754f31eb46a3e5be9eeb3fc8d31ff182da9b087be3462c8459126e862909232fd5f2d89c01815957611e6ae7caa98b6053776a7715c2f93ccf030887030c56c2b8226dae2977995a6d3f1e9d7911a9c9d2a303f0e01f32338efdaf8ee63fc41b25399cffd0b35f7ee5676bd8fd3da2cbee4ae2ea9808d7e73583d99433993146674a4040f42f63d1b3135cc797a8d8f0b88573a32890696cac9439d1e15d196d9090b62b6db7e63c96472d946e668cbda1f4db889300cdcc25e84c9f3857d1d9e53241cf625f3909af1c8aaff4309f68f654b7a15b67711c5b7f9de76775
SIG: 4cf08f4fabbd06dccbcce2a7a5941fe9afddc4d2d0bc80802e93b12cb135d3acf6511e0fe4113c5e3c5541b27d3a2150a757742ac65f95a9ce6673ff0cd21c0f
TST: 684
SK: dd7b59a33d970bef62e0e21a7b6e4c30960686f17f49afdb4a9f4e808e355c7f
PK: 53a0e57277d9bbeecf99c4d138fd66fafcaec7bc5f567f8320800c4e584ff82e
MSG: 75580367930518168b0a764d0958bec4fc46cf591999eb3737e42a02ea72d210daad53e54a7c2c134a6d478337d2633368548170edef0d85179f3023e1503868a6e5e2775e412ac05f0589d42a377e75aa6b8f5220a7699ae8aff01094ec469d6361d3e8f38615edcda4d2d5289acf73db6456985780c92e07f62c77a909fb6ef598822062bd572bf7058dcb835ef3443d3e47b5c603d92736dd1df26be4b9283b76e321d55ce2b638cde22577ca59c963c2479556c575ccb0d6d18c804e2eb01ff53581eb040ffd2cc46760737a74672ea6bf78058a6a0a1f5ebf56decbf94b54afb23c11d34179bf0976b4158017d407c95a401fa6f9624d77135eae8141ebea9f35d5f51b3ded995c7f70c025b094adef2b071f971155d7796d613a550d09e7f4dfc34517b3f8fa4393286a2b228017daf2e015387e13527f63661d3c13e78e90fb2955eee345739119b791f05b07c8f42a436efcad1ec5ea10f308f8e23ca98bc65a5fd9393efaafe5cdefba81058170cc5493c00cedf254097435d2e2fde55f866bb82dbdfb9154344974866359167b466caa909b91530c9c7ee8c53fa90164bbd0b1fadbdcd08127f19be5033071518d3cf10ae6bd6f9827e1206f5ec095c1986170e8d5d8e72e57d4228701df2a48c954873056cfdfbaafb10e46a0c1f144b1a0eacdd2cb66bb912ac471787dabe48353859120b03403567c415ddb88fc0d7fba4069bbfef406eed724a11abc041e8e7beb663d0dc99dcef3ac6a149007b42dd1f22a77dd52901814325172224a2778f366fb9eb02c812b842a42842561c68f2ac231c26ce9e8b19ae91ebfad3c0e9f66363a13ecd8b897a3d00a26d257648d56c6747441ca1c6ee99f08ddad25d116dfadab0383000d3d7225cf2eff7076b2adab9522292555f3193206786000d42ca34d708dc04284a94d174cc92f102efddf3148c2996916d4
SIG: 87294d22d4ad0d0814e2d6d5faf55749e9b39803b4d4b7879e60b777c1fc41584fe15135ba1123ff5f200db35a3468dd4d58dad77bd96ee2b888a5a8b18c3204
TST: 685
SK: d880d2fb06262f57ab8778e33d16b473060978a6549cdbcd5586ba8105f5aca8
PK: 0de486d2115faf2d547266772e430fd9727bdcace6ecbf2fe23ab60f7b5254b1
MSG: 114743e82a0993cec9705067abd77c168b53677ede5c159fad36f06fc1a14acd77f883799ed9883f9915aea638ec1741f3f4215855fb5b07df3793bbe5b568eb3594391a9ef5727fab93e57469b37de125b1e9f2e6fe2c3d1a10ecf87b6c0a665c6d460a170eefb9bf716cd8faea9764f579ff34ebfa9c4cfb34706d8dd7c9eb1d10b2df460a46bb5789430bf449158b5824f2a3a7b918b33acf2d9ebe90216d1b7cbf4af770c5db95fc62ff3a3c385c3a8217853b7346634aaf30607288db0c483bd4c222eb332cb89dc4a217e6334a268413a390bb371aec355fbe4c736f7da75f9c887541a2b7d0dac018b6138f021e77266ddece8468452ada39f5e63d0209b9d6dabf975413256dcaa15ac14b6068e177056c7bf0f0f7c884a3402032298cd559a6312039400632327f9c0e763e52798cb177da4475e4b2405c157ca427741108d33ed0b7a3f53438ce6b725c6dd5814af51cfa45dbced557f726db130d55cde7533bc2092d6b699c2c870af282731e18d651ae85b3db4ba02853f8c87fd5e3ab69bc57b08b81f83c239ccf22e817e2ada4d0ad14487ed14612c8b0973ec0650a55f6bf9af4ae9256ad3546a3f67dd35d987ef21909a94c50f0ef0640e755b1c4e1a012af0d31766eeb5df31cd104c64eb62eb4efb139cf305769401d213f96a488d5ee7e3ce32b0192ee8f0831bfbe8fe95de956886b524d3319b73fd56dc60e9f1c72d78155a97c6f43697b20466b3e7aebd357b91696e7348f4599b34f3591eddfce2a7bd849ab16f7b43ebb16e23d6f5210efa30ab3ba8d32c40662b8662fd911544bc2458c6569ef75a9b9df6a0f6d80d658ba86b241ca19ce9a6fcf01d3daa95afb59c3d89a18b948621394327fc5e920a75f98f5e2b3d6c95fd852adf567b6d37c54d2970856a599f749e2c55dac7c23e3fb1a63bb4cc47b8b94f3d589ac4beef0aad4e6292f
SIG: 4c00a71668d3213c29c7041c5a037edf13c6514bd0ebc880c909caff1506a45d27809fb74e6602ea2aad0f842831b74fb3d6900ccc520652da28368fd90ca30e
TST: 686
SK: 585871941cc282e333d57bbfc3d4aeda862cfa0a375030cd594b3692848c5f00
PK: 4f343816cd48050b678d3adf70008877c9fcf5cb662cc4ad2b93864c02090707
MSG: 651c101b3e2dfef0783ce9f61bd0a8bdc9307ac0488b9dd70cd90a7ed8f179a78935556295b91cc2b97211e3b981b8dafcb3d06b76d0b6eda7fc61945c0ee2652c5ac454256496cb82f98cc1cc92d81893b1082b31b47e6d22a2de609de4ce8d7cc4f4a152c47f410d7fc37d38ccd629a4b33e6221896081797d0753dd4faa8a8b44d6c4677166dfb4d5215446360a3c28d8f68e38ab54608b98821b83c187b5393ad874a76f4f5d729493a1fd74cc7719caea991d229c5d0c8c4c5f89d8e4345f4f52214313410b8c06b3315f45ed0c2f9138ab966aec0a645b6dba76380a539123e0f33b97f3d060394a3053581ffdef3e6d36531166b553a9dde03105c04af697d95e95217fd6dc968bf3b448d5f3a8e4f5ae7edc30ec78b1aea4f0db189a949a122138cdfb5f9693db004baed1a421dc44122f327287f727cf989fcae3cf3be3e3dd9b9f53502cf5d9fb186de791d310d122869c9fc3b695dec1607477f3e149e52b63cfdfb0d983e89af2f75a8f489843ec05c5ea5f0e721acab387c68025f20abe0d27b4ce29f4a64fb7f8e8a332873d3ed121fb493414b8cb0c00ad3ab616c5be5241471adee9f8f46974eae84a4a8ce6fabb7f5d9a6b75a7e670456fcdcd1d982e8f827a4bbb69dec7e3053dfe835b70301b7b763f0004bc906e145542f487b4dba2ed561bd1a20306236af4b36e4068e8c007b9454f8741a5f8f079ec1db8835eb6544290d6adb52a70d7675d85df4a9a1255bfd936c331fe51c0977d124b5a506d29c6eec33caa25d8eb28952d6ffb9d6e3da890382d888796d374607f6643b89e7326d9edc49a0f53bdcb8cc76ffd393a7706522d04170036ccb66330dbac9da7e6168caa88cb62181e55a7b6d521a2115e23e202ee2480b587be4501447979a8d736f9012ecf00e67b31e8104f6e7df08a9683cdc89c03a4e37ee22928d45fa19094e0d6e7b40b
SIG: 298856e570188aefcad81bb970f076965770c26762fe29e6554dc7afcdb801723bf6c763b4ccd65f4e15d7d8ea38fcf67ea9d28590c79255c1cfeba7b5e45a00
TST: 687
SK: 0588acd4e09ba90274c8f3d1575b2bf364a776884a9aeb4103415e163ba0bf81
PK: 3ecae697b425d87e34a1d944098e3d32e2c1ec56c3627df80ba2b8a43ddc1903
MSG: f828f8c9dad298c5b719daa852b17e762598a70f4ecd16a2fc596eb0263899e983d44edcc7bd240cb07610600ae96aac0dfc3be387b616850899b5cf44e1767ffaca3df38158598424f8071414c704e60b422ad77377fa7f6a8c5d0ebc0235e2d43a984f3adf759eb10447f3c2f6b80d5a11ef41d3a09852c0932a1b9ac23e6f40a167de21041bec8885f9433eb80b95c9785958046cdb7bf147a79947823b4149ae0521d7e5aabc1564fa4044106e2e392e9c344457e9929376ea9b4229c6e7738fe79008d554c429396914c36387f579b46bab146f6a9510eb6f8c85551cbd84c7dc0d0b1c010ccba5963a7f39f181e44dbc98e495aa63c01059cbe6a99b07b449e7759c9af9e0f8d9054a67a348fa19d7f91ec0a4d4f2c7026c3b849259a350417fd86cab2142e4cfe3c0afbf25182a2d52bd2e0bc920e85080832b91b927b62948a67c317eb09091461d493eea5ffc47bf085582968258a3c8dd81a858270bddafe7925684a15ffb51bcfaab931afa465e3090e86be41e3547cba234b85fe7db700496a505002df3ca4eaec7b96278c7d1a77db834a91797bbb826d092aa28b49545ed3b1eda23be11a3f528b955cb0c4fa66e16e957e5704cf319e5f79cc09f2d054e6daf19e2926b11e1e413ff822ca141f7c3d385ae95dd20b346e583cfb0c229ec39cf889a5419cd37bc184ef5fb144622080a302d9d7745c451f7d88242cc26b916a3569abc7d1f216d57797a472bc621761758e840eb8e29bc8efcb7aafc7cf8f4e59330d35ee107496dec6e714b1fa4309837bb47eb3a06b4604dd20733cc0eaac2649e18c07342ef55d19b8d039591ac2869acc34b6c3c1ca3cf263ff84ca43a5f6465ba34888c109013b32bfc0d0d15f5a76cec270ab3ac9a106331312f5a0a84282c3a3d4aea1e7cf53dbf8b240bdd111c34d2a93dfd1258fe9267133f7554dcc21a8f439c165d
SIG: a111b9706d242cd36d6e8741cbb097b9e2fffa40f43fd6f2d3d91693667332b5f2db5ee3ea20b83291b8405795b74d633d46f475ab7c47617118535b8051d907
TST: 688
SK: 7d14023eb48bbd437649a241877905a3c932f14640f29a0fb134114e8f33f582
PK: ea5c11b4b2c5ef4ab706cca3475043c95818eb565a797e33688afeacd68adcca
MSG: 9001db31f279be505319b8e72bde1199512980df65f0d8a9b4930467413a997b97a362b572a4b44bc940487f18b208ce6ac5c68716d3af1bcef170383b5c4b5c47e44737726f9383bc4f144768bf5cafb4e9dfe39761e6ed478971d1c70e6dab2fd0499dff9293b239d16c960261c68218b9f5b1bee690f0d240c1b3db711f9e821f0809bbeb9aaf249ccb168c67d965562d24f848516140bfd9fc050d4f20da5a1794468a9c0725ea5c669d5c630d9310e5745107dad37261b5d91e38e08512e6f373ec5dcad5ca09072907c8fb7bf3b926c3339490b3f51f7644e73ae2ec01d61be7c6526536b4ffd1ab6849fe0c2f40d3bda2a49e5550b8df979081da85168d0f71582b903677526d1f1b1511e138b684fc46aac8bd80c3def7ee8138190461807c5536125cb0e2c3d083a187c7269cb531ec3678787b32555cf04ab093c9002e7d792b4d933f2e3070f39ac8ccf8d5f5455f12109d8a8aeb4e212fad4a70b147c04a7b918460b1316376e64020859517eb7ee30c290be8b8d6f9673915256c3b04b9d9054b52338e0d360785e46a182844c5c3766aea8ed311b2d481c0b7b2114e418ed17f8debf01a83ff37517024ee9e28e0c90dce6d059ffee413d27cd62783a8b8b5016ad276e39dfd8f8f3ddfc428101818ce507f003eb58c9a5cc8b1aff05aab8f0d7f1d1f6d4b871dbced1f3d2866239752fb13f6e18034bb2b5a6635caa6ecc462e058ebe2fa651d3d0f36e20a31f765e4b958270bd825c6818aac1ad7563135aeedf14a2b6d398b6e34008401b218461820071c5af77846cb9c328190c061d5aa6e0ecde7ef5856b0e6814f833f704096df0825fa4b46dcdacfa27cd87bd7bfeff7f8cae166a3a04d437c7be716c49045c7bd3d1349627c9cbd04c15f00a696e3cffbb45af29122627e7ed33b4249913bec00f0e28aa11298cce8b649081fe3b169b4aaeaca485bda
SIG: 31339dce23336df5b2b193522aa3dd2d4114a66af1656289c952bc11c9b210f77a54d46161f4e0c52b3013e40b9e9e8427d851325bd71c4d99353eeed751080d
TST: 689
SK: e8306bada6d55eb188d9f75c815cc914e93c9c7222391c15bbaeaf9354437935
PK: bf2798b8e554f51e2286c3034a88e577ff23fa32a67244ea8245912e8bf46da4
MSG: d7043809c3e3dc00b17efd52c9130b11b786f1e257b5e22f81a7faae600bbcdfd518537fe852c642359762fb75e8ad859249e6ab49ce1bb04f2492f2aac35446ba6eb03e76de3abd2d5fc7e6146843add042860a4a16b59bdd7d038378a35e1a04b1217a55710d937e2c9032232ea2cdd1d25a0bff71ef5d3e0c056b29cb92f6df692bde14dfa50e132bebd89e9f1833880b657a781e94ecb603041756e5517d4423c56fadc13e2b318088feddf3b5c83c20b46fddbba92305e48606dab748ce3848b843f4711f370c3ec7d5e19ab4c0ac1ae15aaaf23d65fecedabc08049b9e29113e5761ed9d1c62eb075cabb2674cdbe1e3a889bae4b1dd31b6a5b2ea1b8dedcc3c515edc4467c30231176cd44bec8a057951ab5cd39a9623f8af8473cd27d93302bf8aa624c9c3c5799da1dc494494ef8ff1dbe0187ea5162670b8d098c3a94919398dadf79e6c2491c444392c29cd50d57435063290842bfa0e8530faebc006d6ea7801117e0a3f019ee28fb3792235402e2f69b87a43dc227f9de316029756c3167d64a3a3f6d73160331d5a18eee5b0e6e22a663efdcc8d67af3bced041ea843a5641603ec72efd644e173d199a8c830b2ea5fec0378027c37225afcb604c4cdcf409be1c509c9a377be0d0524107c6d92b5f09a29efb7109295670bb1a1dd3ea008bb79185f09b98f020c43f1439685b96f6199311a090870f0d9b10d495cd410aa95b7e53749be3a6c0fbc729f96cf8564397b09c13514016825f72f14eb93294d7010accfd11f17a6ac8f544263d6038d5c7db29486291b30ea49b6b54cf88826dd252cd9dbb57d841b5a4cf702a3264faa4dccc86ab14daf124ef3d5335a6878d065c6ba29991045765ee5542cc9f5d9f354dcd2c6e0cf7ff3a30f649b5912d971d633578f1e9f263874d0565c247301dcbd15d76211ae2d3d506fc64deb7e042565d438e2bfb249243b7
SIG: cc6627308e2f424383fa70594f575791600540027a2751619b283affeaebc9c9d29ac6db286dd2c1b596587b878d1df4781d436bb570c1c0f0d33368dc66520b
TST: 690
SK: 363c1ea7c32ea328a055af7bd8b3bfd204fb0bbd4bf42ffe262f3a5ebd54da55
PK: 7a83ecca51ef6e5aa043a5ce04d9288add49a277548bd3016b693ffa79a22edc
MSG: c41c1e1fb75954a0ae0ebc29090b9fc533e693e7c7105cfe40ef526e4e12a7405221f218c7ac019e1d4c92da2853f2d726aa62277924df0c343fc3d47cd5a99a3e279b26a1b13b1f2aa36f7ccb4b54fbef18bd87a55f1bc40ce7b2029145ee7aab391795ac68de6199f50594fc79611b85131c143021f26fa358da0c7c6a65dde076dab488675b722309e5ed9746d18a89309906a7a9df237dd27bd590ccc77c402ef6e19ca63cc86b85160330ee6e1f1f47a2ff807eefadc00963520a1c600a3e45aa7fb2554f47d897bd86d81c3b0877101222fa7850b80ce3bc06c9e58c0c96e32fec8530c9fa1e4163f0ef8456952bf6dd58045a363d61880e9ac976a3603ef77a4c395e6a07e342f6023b8af10225cff240efc0366a799fd86e9d062060d8724033bdf67588cd73ac284de4c6943cf45ee4f75f5937d97d78105f0bbece04d3dcb5e424eff89b773e5d6b4f37efa9a0654cb3ef345278a62d876cfef9a3dcdceb7081441877ebd5fa30c9d954e3684fa476a4f485d426fd3c8c32bea0f9cc20b15e8fdfc3ca4b302c074f508132d15de625c10ae0737811463dcc55fcc4014b20208fffcefa9dd452119b1652de41348f69f2c488f5cc1856d6e78a5cbe3e373dd4598e2d39f876eb94e0b01b21fa9129ef41b639f4e05e69deb1835ed44b9112a6862a5bcea072c6e1b8f0f058f46bac2a845a582d148f17760b9e0a2ba60bbbf3884af94dd4c7ec9db08e9a5bcc6dde1346442ee1f4707d1f79b69ba867f418dc279173f77adbc58ab85ea393b9dc68261900c1caa82d2f50474c42aec911314278c0affa2a6b6c36d1ff88f3b49fb2b7c339d2a7c2b3049f8c0a08d16a9e8df93d130da484bdba6dbec534cd51097a048221106bab48d67f951b7505a1484892b85779c5a3111702124d957acf2dc352ef9ba247bc80e2ce96269ce85e78b9ebda989076dd5ff73e1eb275e5d7
SIG: 5fd1e5f9922a12f636b72a7d6217091f948a55bcb1826b8fcaf99d26416c7ab1351c10f4093ffd8a2af86914a0a98184ec7e06d2dee87fdc0f4a47f8c63cf501
TST: 691
SK: db2228ffffa9d2534aef918fb85b821ad360e2d39dec5aeb2db0df02497f9416
PK: 6d0195777f8105ff523b79c59e3c3081fe89db6f87033f094fa5a940cef84bb4
MSG: fc07cd99040f13e5a84f94746d6bb868f752b448b62d99593ef29e43cc8245f0470f65552d643220f6719285e15c37a6d174aef76088ccda5f88685b52dae284c65b380da345a2e1af2ed76480d269cb934b4317620b792ebb39b2a678247d6d815f2a5cb9aa560e4bf6deba4c0a0ddc82d0e5a5a65acbc478e1ec6b064d7bb7388a73f6eda30b0b6b73dd8f879263ad1a0348671dcf211cb96ed08ed52f3317da68185d6bb2589dc11d755d47a3b6f6a0386a8594d9570b2e9b0d4b5e13dccd9bb7acbef0ab276a7aebe12931be67f10de267a029895301f5662530ad8ab3d230b3b6d7093acdfbf274757a9078e20c23bc822deffa61005486102c01ab82bdc8cdcf1bb37f9b56d39e50fd5a6895416e767f4e36c1a41778908125b5ca3f92a90da9addff155fb1fd7768808a80f203ed737ef007763bd2fea9ff28c84b43551c9fc438ffc47fcfcf64dc7700613aa8b3af8633ae8b6987437c0aa4781be1e821396c536cb3005d05549b1cba70135afb7fe3068961cad3a1463cc0b5560684e27bba77aef419d823868e0cebad1f1ce0ae902744a152dd29451a17e28a89a7158a1836efce4a3e5c7d1faa4c3875bc46c4d9be22d66d366ac6f59538a00b275b02fac6da755a854081997d5d1d0e6e568a5958cf334c518cd517ab9d73c48d6cbc4ae4eea4353113e7e4a7c05920e686bf07afbfb8dd2ec4f18fa7138e57d332cd7a4228fea73bc09252f24427294ebd3645ee0996c2e851a8aa51a7cd9fc2eab47c0ab213f4f51d216091ed089e4592e9bb0828b858f84f60b93ad84a0a22827cbd27414b781322a04d3960828f638df2834c7f7839d70db126bee5af2ee7559a8ac4c01a6c391396af93fa0608940297ddf8900c5ddb466340ae51c60c7ead762447e76d8bccb573997cf6614d188a0b9a2f56eed9b0f9d463a19787f4092581a65c6bf781b93c56087e54ee1343aab
SIG: 82189d340bc11ceaa400410e08bae9d901af059125e953786f8a043ddf11f7b2f8e3b617accd78e2939adfabf2d2471fafd6f5bc45b14075b328e34d8075b207
TST: 692
SK: 66b50f692e395eb83386e027c82ce3fdee3bd899b0d3179db086fbf524f57459
PK: 448536e982408437ce89674053e3c589c98c095c60021a118178c6261d8810fe
MSG: 7428a964212bcbe8df7d59e48e923480aa0ee09b910d04efb6903662efc3107ac8fdc0c5f39272740cd877e16cd71c549238c337220ce2f6b5a1fc6f7b0a1cd4ed21d93889081e34fb7fdecf4178bbd431e611e539d900c3d0ac3dc7107b36b41d6d0d5d32c19727f908b6eb367febb352a493581ff128b56c4caf6fb8e09981f0d37957d1282017fbb807614c20f465dc02b0cd969983bd5ae1ebf6578d7ff3ceff320e25562199dee934757cc1f58d5540c41aac1ce4f211f0b8ec4107174030e702bc6a8a9c85c505c9316aefea3e4372242de019b35e2bd3c5a956521971c106a3adbbc13cdc4f7f9d3c58b96a344b4ac3ef6bd8aca6ed9876b43e6497faf7fa4cf27fbcb665730c091e13aaf7e9efe7dd10e14eb19a9200424210ec8b8fba7e69444ce1a9e3a7b26c11f6b7145b6983a7805776484031bff52e81ae769b70a282b094ffb5fb5525dc1a872e207e827a2e11f4ecf7b5308c748a9278ea7bd66188194400430c8cd596ebb87221e536f6afe1f1505d6a59f41d16a2f014e1cfa513f7a69731d7bfdb2affcefe0537d42c796e3fd27e41b7ca72051bef28bb7bde7010dcfed8aa16ef676db6e520c3cef8d6f58a9a2813cff0f7041f87fbfb8431e020ede1d4eaf19e23b983445c5915b54adfb557fc20d0058f40f5e09825dba8d8f20c00f43b3aeebb6157be32ec54627d5d42ab813cf97f095d26db8036c12e82cb963e8001167e61ab393b4cca755ecea869954e323fa5262c5fda3e0be9a51e5af51fa6444824fb837cc67be537a87569c30cf0114d39a03942de4e1cd523355dab1af36080a9a9a548be1c2a7fbe5433772315d283e5156df648bee4b7dcda74f15905d542be54873c15c53ff42acabf8c56f257d764722db4e9c718e12098a3457486a6c947ac2de0af53e82cf950bb37ca29c8dadfa3646db4982af572d39b268c7f96b03ef6b653c87945f29bc5
SIG: bd13f6362c07078922f30c6330751bf6e7cf42a76916ee653eb17accff1fbbca35258c4cbc582a5e8cc94fd2c7edeb53762f1fc23123d7f4f145409b31cd3802
TST: 693
SK: 55328be4b370822733ff3989a6a3282d65fe8f207ab7270d7c2e727ca3cfaac4
PK: 518e02eef52f5aaebde3d108ea79ecadfc4d994ce1953621e54b7b3b121ff8ff
MSG: 6c24c9afbbf12dcaee6f10e4089252f2c60b2ab93a02c1602fb5de4ce3bd923eb02fe1039fdc15996a446915e767dee0176dddb78e9d6bbf069675775a829dd808d376b0cf7920bf1a66e1303ba52419785f25f28bb33899ebde840c0ab14b919a6580cbaac3a805627b9c4a77baa16f825a9eac2d6d3641651493370e50eee94c74049764365605ab4dac1a030227a330aa178f2f8da377af73f0bb040bac12366e65e0591055f9f23eaca35e9688d837a3c0d99c168fd886acc922cf37a7118ef8a44bb0a4fa4288049309a7dc1bed80621e1063e3e592c0fba42d7398eb15f74028ac15d7ed65a6368a13b7f956d19547eb506ce7ec90734eb949cff1d98ce414f10adcba8c007320018750a71bd36d3b6bfd6127054508e3ef65d99848514d33d68b58e3a4b224f79b6e34dd480340467fe7f025cc88213d808fbb5b91e2e43cf9d950640798659273d47a25f1f0132f6882faadbafba28fee5fa17272c1a9001172b3ab6ff2c315f26c07734405b5ee8b5e4f08e1e3b8aea019467fb071887f191901a21c5976c1ca8aaf0a1d4a2e698e7623e9bbe9ca2a67a153a16f895e6dd9ea924441b4bd0b674552e398b8d970343a9bc776a3a3fc1a8660c5625d6081b5d87f0f8ac9f07ab5abe77cdb8e30d2fd1f6f46525c75dd0dd1ca3281cc89346fb3e6d7388ebee154cb59bd9e95ed6a41d5df668b59ea137868eb120b8a2cfdf4674414fd279699f28b5a5ccc2e2fc802a4c9e0b85b76f20f6bce2a4954886fc402670a71efd261f5dd7bca16884a287c622fd445f68d44151cc0134b229da38daaab81b5c960d57700ca92b26d0b142134ce94b7be6c18610ea2136f8ba8329a2e8c000b8f02fe05bcf72cb71f8c72535ffcd818e38e7992a8f0c32ac62177d1522ae552c60c1ee616b75e4b3442e79657e4a333c0b3d744eaf260d0c336931686a6d668c64fef440052352c2b258cfb65
SIG: f58db19fd834e15194c3c0f8a6a50ebc4cf074e80ea2e70cdaf1e169bd51ebd0990bad77c4fa208b8dd1e2c8574c01b5f596c8dfa6bb8e6ae3a47ff412e7e209
TST: 694
SK: 7da05f04e5d38b989b83f72f7ab26c138776758f4f577e49dc73d6013ff43759
PK: b1de5167f4d330804eec9eb565ef4055f1b64dd95e1c9b27c67ffef91482cca8
MSG: a6a861d8947c5cd6ad0819602e32ea7681c8f73010eee553e5defbf7982098b5f7b39924bb7959ad64c30326bed560bf51e9983cda5dff4f311eea24cbe68c6106ceac9b843aa4e2ad1b6f8ae1e4f96871fc025be4a616385ff2d4b7f56829abefaf6aacbb780d6cbbc951b6e05a787f885e3325611665ecc924274aa531bc133f62c76cb3ad148f3c9579a815a14200b7648dae0b07b327d3bfccdb6fe3b6cbd70ea65e6c0cc2516a896696d07b2e77713b0bee3b92fb1b6f75b0820a5cb62c5fe6204003943e24857166fbdf571f115d45f42e75901df8b12c32618aacb0d24286c8d30396051fc272aa17f4d2d47461152aacd3faa2b7b208312278e809240592d1d1aa585c56280e66ffd92b5717d0cd1eb9fb7401def879487c374e5c530b6febf911122574d24fe104b4f45c7c601e6c917d3c1882c1ad3c555d8f2ce955b5a10db0d5a8b8ac7a6266b2e6b27ad0ee34f47ad857367d52f7096d4bacef0e46725488424b93b89acd429ffb5ef33a0b081dd09479679196023c3967f44ad41eb1a2395527fd3b79768f1b885f0429b495ab60525691be84650632a2f66cb63ad5bf2f6ae70b668c5a193f7499fc4fc42cf8cb308ce5029a5027babef55d1925ecfba9f27eb6081619ed0df8569fd80e9da104db39b5b8140bfebebd29085440065819deba8d469ae8b3ea6d3bac5891f9a4ddfb7f1f06d13c31a07ee53fb54bc97bd08696394c38e7f3680c0f02f975f469921147a409859097813b4c3fa43d174ac402f1a528cb5fc4b807518432eff33407a111ca3a3d7e9e84135abac8a8f52ea631c86d74a1c6e5749edd1491c0024e7de7fe52856829b72fd13da63a1a2343349df662ab3163536032346e5347f043fff528bf67150922fff2026bab742db9cae7cb2e3c74580719652c28447c5e2098231797ee6ef1231f5792054bc3359a32c86d2f94f85fa7d4a7419dd241ff662a
SIG: 05f117f9bc3ea55d455e9ef135e92e7665d18070d8f5e375df67be1817ce14357a55e70166f326b77d85243227cf67d8f2e0bf8440cabfb05275b373f1e1190e
TST: 695
SK: 1b8ec65880edbf039a13e970b15aa67e192aa02ca65cff9ada17d4558f40137d
PK: 12c1191e4de3bd44d039070153adb7b581f600e9a1dd69aa89f277c7069e76f8
MSG: 37f18b7f64c5133479d6dae3bef679cdc21ece3f5b579a6a9c3fa2e59e9be87d2009f74e1cfdaccb1ce37d00702369bd169d94fdcf85af9fa3217d27e6ed6d1d8e5df7615e8e37ea55de1fd0b06d77b4c83b929d80586fa0694be72ec8b365ad2cbcdd2b1ad8cf7f036dfa4daa1a9036cdb120432227b1f07b8866b122120309eb914ab84cddeba1dec48ab92636728588fedb3aaad7e7dbb2ac30e63c6f5f90fc6ce62d6d3bd88b0d5aacfa61de9f3267b300917b57a48036ab20c9a05446b8767494af249e7de7bc507a2207cc956f7184555a7d5d8883bb4b3e93f2dcfc57b0da8638658dcdce885d44d9cc68b1d8170a3677cc5e50cbf33d543ebae4477d9239cf83384ec59b4233e8ff3343f06f301877729a53d420bf01c62e66ab7fe55dd87ee823a58fcb87870e1f52e879177cd439c533f5a223e5a3436fe9d6426548dacfc86a0846d3ed23ac042563e887ff46aad005f4e1dee3ee0ee4c27a7251709ae40abc5e256864e4785a4edd8b2adf1bc5b4018e28d0b175867b02d052a6e17e411a3d8beb2a4208b76cc621fd18be148e235d55aa7127706557dec053a13f1a47dfda405b3fe5bd28ef5d348619f51e595ef5055f839efaf110e4901631ac31a02f4f7ee424a3a2c3e00d2602d2cc1e492906eea420a9268238ac6622a08974e5730292e6ed510256efde667e0d9a0ff2213f54120ccd81ffaa6b7cc48141a2b729852af583d26aa51fbde67be4df14e520c2257a73c5c2e3c3d87dfb25361175fd18abd7e99aa09b85f88f19c8d82d45858f3144c5dfb7a49ede45b4efd8710592a3720636e7e889c7e22ad13b2d44bb7e2b47b2963a5fa3f2557b85bc0c693de3d22ef9464f7b814a20a4676ad26fcaa03544c6aad41283095fcd1210aa8cc029ff5a26005a891226c298e94a52aa7133913ec9d22a5b2ac0bc6f15b251d0b93889213cd1b1e5c6fd08f1a8f5cbd4215329a3
SIG: bff269a35d6c8e552ce716d1638181ce8583b45c0ec593b4e58c40ac76e7f85ca1dafffd68541e623a1e35a7c0972688b25eed72f4da57eca16857a8263caa0b
TST: 696
SK: e75388026a6a6d6c6d199e362993a5b1044901e18a76c2fac7261a6d1c19a4f3
PK: b9ce14251c0cdf3bddb206dc6b8b2b7f5b7e4dd1be2ce1863ff18806ae00f1ee
MSG: b99cdc847211c06642dd111bc5e0beca53a74ffba2e3ac93afb4b0947518e8323527330a4efefbe4bafa00bafecb434ab1e5b7ce65656f7a4fd856aa6c385ed8d7bd6285580d7dd60882e69c19da076909d647de095a80e98ad89b814aadcbbf6f033c49202f656c0910503959cf97cd0fa82d5f6d22fba3389951294c4f7cdc21eb8244bd6560637a5eca62a8eba1f4a933d187a75f86711643af358831c8c16a9a0f09e253b2395e9cb371611eecdd66b4ab521aa94b3f20237eae41cd10c5e21a452d48e748187f354a67adf681b0fe61cdaec94a5eaf01269fceb570d514ff3c55ff1dba2fd2df17f86a8aeb747838113dee94a43b1384cbe133cdf6427e8d122e4e933704da6e26cfcee97fe3f629b60b91b2dd863867fa79801e2b916ec4c0fb62e07159421e657974307a1d02f7f2ed4724a8b521a861f55f35521e8b2e1a84904c428cfc5b6014bb0f8ba8434c2209bd40aca31130db97743333597d2351d5f6811741f62688973bd773d30266fd1efbd89d47a964f9d01997153d087d92696616dd103a934ccbac4c1d142f2075d4e22c3da4a0e973b23863196287b79174fa29755fc6d9b5e100ace0a45975e503b254d3f195c261710910fef106892c08bb296d230cdea9f5a11f91acaa6e7c05e92c281d2b3155fe4480b0aa5e0db41d10e05cfdefa4364051cb755dc72ffa978c00b94a5f212dc691f839b49de97e0139d65e8d73b2b289b26a12c6ccd8edc04adb452af7ff094aa901eaf57651eb1b87b833d0a09b4a4a6462f40664623769e95079f3c962850cc3b401bb0058b8475b10c862f32f300a2b143b3dea269ddcbea7be7dd2426d0d4204eb66a39f1318822dcb9c561398637f4ab8de196768ace74f348c012dd1babec17f5300ffe0d7aaaeafef7db650a8f2f309a9793f52c685c7e1d5133274915784899c481d485c9bd30e99fcdc97d96ef07487da663befe68299df
SIG: 6d0f83d9c55d84bcf9a86147d9b6ba9ad537832fd0f99dae7e72c8139afcb30c7b24f6b292e32f9847097551b7fbfd510c84e89be98254441457bd08e5f05302
TST: 697
SK: 5b323fc01a16c45d1064667d2ea4a7ea59d20342562d12fbc598d5aa7300688e
PK: d4141b455d301642bada2814afcb1620d5eb56d92b1185fe5dadef559625fa71
MSG: ad24669ef55c540a8ed162ce1d28f01760a60719a0377336eb00b1ecbe6f61601cd564f92c956804f9bed4e1476b94e5ea8cca80cb49a304ef851f7f675abe58e6681dc012ad55e51b021d9828569d0bcc9e0527a3fc03c891d17a90e6337a1ea67f2f08810587693837081e4c08a3d72c536c2140da200ba456c376f61d05651f0c5f395711f41c0d6eae98c906764d1ebef3f9046cb7c8622640fcafafbfb8f62e1cd32c66ee1c55509489a538ab612999e7997b779c6422eff109da4df82920930d8d363d7830908795a3888f25d667e14d155ed44581be430f7973b574e2bc0b134cf139fb4bb01dbda41b67b98147d8012f40677f4b80ce4a534c90adeabf484b21fa994b7a175f8a8b8a4075564478ddb05024580bab038cd9eaa1dfda552fb31229429b614fa1d80c52614e84faa2217f260ff7ccea8c7b06e3d77ff874eb81fc8597e5fcdcec951b5fe64a1af86e73193a882469eb3ba3c382734b2887b419316ea448afc282478c25f7bca18429cbbffd8871177c5ecc7d8aa9a1b9ec87192d29a52539c081c3593332444cbe66872cf3d0e197292b82b0be5fcd858cd6ca48b53ee5b61641bcaaf31d819c7e1cedaf9ee6b07e09caedfb30b9204a1d4ddb70560cbe1eb0c0ec43f1d178201b290819fcdc92c63e0db60fb87dff00e512648c8958a847efc36346073f1a4f1f2317060f1c543e6f01b42485beeb56cab3bab26e6a0ca6935802c762b799159e320f36b5e83d4aca8962aa2c3c2b7a3870e9e04731f3948cf941e21d50964e5d635a35a53e299811b8cadfcb4416c57598a3fd05410910dbc0ea2c78fdb92574997d58796279eaaa78b36dcef1c9a129eeff82399a26d008ffa3bf0418ff7d39b6427f341895024d16e22a0c62a82beba2e2bac23dee18cfcd5db2397f378c5367309082c44eb43cedc15220253a62320399665f71349cc1b944f58c73a10a0bbfd4caf12891e3
SIG: e2eff607f0227a29d582d69f3458acadd3226fceaac0abbdaed52675c51630073cd3a901707ecf05e893f2c36daaf0cc4901116946b5770dc038125f6d131b09
TST: 698
SK: be1c112f78cf13aefc5ce7e33764aca4481f9f88b018e122db9f8dac14624605
PK: ae389936bbf6d16e3c1eeb6474298970866e12ec9c1d6aea2fd9db6b56aa59c4
MSG: d77f9aeea0fe98ed7fb74d582a402bcb7931474b4a95d523f3fb769fb7097d2be4c6ec1052140163222553aa8f4f89e421730014ec73469720cea967f88b6a48d02a2ddc1a121fdffb8ae127738e293c4d6b1b74ad03844de6bfe821506b3a7a81d19c37a7f01ca481471219efe2a7b92c4bd2ac07743b4975696441714b84d63c549d7a6fb61f16fbcdb72b914d7882d091f9706da38c1a81a1c6a40fbec0d8e238b5d56d460e909f85479f7ad8b119f35455e34010caa7e5d01f38e301ad37e8005f6ed29e4a102db3f61d84093f78c49a9648c977bf4d5b689f71f406f8ad7b9aeb1ae22133a84ce1b278b2cdde465901b23a179d072a80879d0a24d2af197b322a07bf5d40eeab3af12117f13021dfc1681aba5c083f2596e37f1123422bbdca3b2c32cb594f56c325e0c564a1733288053459c62488925cd80e7c944db998c3c7be546bf89d7a511ccdba4b809eee0fc2873dad72b4cf3ba051289bb3f4e9925732e45ae7741058c8fd11599dd843927e3d14598bb83052d33569cfb02af0c88fa7aea4bb46841cd2ddbdf5988fcf325ff104a5dfc4a30d269d2a949730c3613bddd3673b42f6090e6a60e4a253062463a65d7e7fc0030bba769ca344bfa9ac823f58cb5cee8a5fc0ca37228de5a4d93e0ecf7f10821659a2261f7ef1596eda4e411cf3c9669d81de74547ce4bf833eb432f385ce9038fe848a8c96da7f01fd95bea06d1d747c8ae736495bba2285be5c32afea449520cfe8e1ce25f9077ed0ec0f6598a9b8f7386f15358170ccefc3d5ffb009288154de877c2409ae5fd8fef0093f1c36b3a8f547432cd0f62c4033242ad9921a8f11c00f366da9396930a80c997df429a4f5f4e45c7a6d7e02af033186757c73cbe64d2d4e78eaafe27539528035f2cfcf8eaf0a42bd25f88b2fc69e42668fae6677c9ac9091d9d15a41f3ace65d90a0229873dcf254256cca449ed4c17d5435bae4
SIG: f5fc5acb17e9957ea304f123b650e144c9e4377283509d431da6a2bbd527beb382c9f58745a3e56dcc655bd2ebb7aeefc93edc3f20d8d3c37923031eec0cb407
TST: 699
SK: bd8523eda899b984230e328875b9672edc9fcd24ea5cc12d7b572da4be01fb7b
PK: 02b734ebbe88c13bfa95a5d964fc7ef9d395bd6303f065dc4ee17b3ac1548b7b
MSG: 16c216c9be9f0d4b115410bdfd1593c8e262221ab97a2a395a12198f95c30205b08962d4893118ba9ff99ab1c7a6e1f2f175191070ac945327ad6c470babf7928b07dd788c85b64b712e0aae6c0ea20281e42fd561e83e3fbac67f14000ee56d981d2a2f0b9ca00a9ea47ca2f6fc8dca1035fceb142c3f26f20e3c732207ffff11b79695bdafa415214a4499302326605cf0b8c82f2b11392ecc90cd74a7b411b6d907a3d5c130c879b7cf880f22bbd7f0e95933718e96d7d16caea9f2c39e89b13cd52266273604a96b51d6e34f706735ddd9fca44d09cd86bb7217600e0d34d416ac249f2e41bd0f4abcbd2580adae21d7eba5fa44f39d780f17eb85ccbef58fef903a280d95f8f3210789fa12e120e21b6e8cad917835bbdcc3b07e84693954e23a94f99f937ddb0d4a18d42c3ea8fca7d1ea6ed53a00246f99ea520e6405bd2aa549b06e7da722c1ba74aa1c136e8ea58baaf8d37658693f3e0b44f631dd6d08ffdf4f09189d3035a3f03468e29696ef05e02cc1aabfecbda2301b540cb0eb0a75bcce73db9273a9161a98ad898fcd6579fb7e4b3279544f2e0bd774dd1a8157daa88a70321167703c60a608a4b54216590375e597fe21aea97b52185d0e37a53b6388a707a2bc24acf94425f84f3d56bc9f7ee7412a9e1833ad55b7eae6da581698166383a2eba8b6f53920f517a5c80bd3e03faad4087e3ee8fec9a79a01c779512133d7b6e5f1dec766300dc405cc21a8c583fb73bc90cf24385b086049d3bf20c300983c0b351538dccb227a14fafd23ac4b26be81a2b120cf216fc58354f9dcbf05f66339ad6ddc2cac14677b90e247ebb6c5c229007dc60f374a06d404eb23eb1ec49907c6e881629e1867268ca6fffa59aa3ca8f6c295162b9536c2be22bbe3b72380ef11b61b357a6253100e30a586818ba003fa3ffd1fc919881c05022f94848598f217fea222507220d108a28fc7bc39a8a11c
SIG: fcfcdb088dcbd0a51bd301e3e1561671935d8b6f719c5d92690640d3c91e775bf4054132efc05a2122fc209db3c3343233ff8aecebd52daa2b3b21eeb15fd102
TST: 700
SK: 33a85ae150bbf552f41663b21521c296d246dd6cf8195df851c695bd15f4a502
PK: c8c9c42521008d5efff576c7e4a56083ced9a928da6fd5cf93fda572a5a2d0c0
MSG: 937e05f2f1fdbd41731553e77cf181b5079758940aee8e92623fb1d5f07128b7d7f17e4842707a562c45ba69264c0f730a821c7db6bf82990dc651269b296c335179113053d6f85bb096b2911165fa3900cb102416487ba8078679c6b336dff38763c08dcd20fa66dda45c575df150d851165a4804973830f436df60b81319f9cfb564c0652896ed5f1849cb3354f50f0012f286e8a30c213528693474004e8504012b945560c074a6a163432cf4ac4ba7175cf26005db7199ee96d893cd1aad3fdf5d57460ef02dda6d3a140825196f3f8e2f37da36b6fdad184f2740f116de758a92917030c5fb80f0262496d2df93c7e276f25da7dbed8eb8dd4c563aba55b82af6ba3a70ca5f858b44a033cfb795604ddee746e7c8ae79d272fb9a2341a2a202df5eac08de75ad80c6580d92b169f2e1318857b1b1421c30f3dd461093de2d345ede7404b72a450de07b16eee68ce62887b6eaa436eee684be75ce0e1f96263e8d8736f9ba000d88e9e5860f328ae1e2dc73099d32fceb1bd2c0123698a49bead190a00ec9a6f87133eddd45316f65eb0d329b07b9a66bb9fe42588bf7b8d06efec1986b82a081ed3f6802e9be73464784559a4f2c097ba14b0bfd5d7e0aff65cb69abd03f8616cd7edf7ec368219edcf893e9ee71dad9f18d79e568265ddc6716223213235bb928e908dea827784cd1af396d590c81f4eacdfcf89c5cac96fa050064a22841ea715f8c89d6d5afbf597a4d005dbc6b13856d335b42a9a82edcb949835cca20b0a23de51cc3aec35566eff0c5ae1ab3751320d2c310495238eda383c38a4163152b8815690b8ff015035d1d00ea4a0d6caf324bb71a664a1bed31480784a68f438caa359e8d2673c857d4b8c0b6c695847b86800ea3d734b5ecc4d52b507ac69b3a6778916016ebc2315f44c90bf0c3e7dae01d49cbc303402bbc634ae1191f3f6fd63d303b0c0be033a47b90f8d3a77f0a44
SIG: bbe4cd63676e26d675a191151d30db72b5b84d461eec6564af867ab41bae9931147885519ec9d7e6c818743c8ef6d5167b35b421363c09b357367fe8de443a06
TST: 701
SK: ba9e686204975c3bded4c1e9f74c7e4c7a7e3c9981d01bfca0ad0115c3f0f5c3
PK: 4990fce6952e8b7d0afcf4bf9dba9bce1bc4815e37511da7c2ad4892581de03a
MSG: 46bb48952ae58f2bf58f5be8df4f316b50f363ec84eed8f82ff4c04b0692d03aef26e8e1e6c9549a2247d540a6e22feb11e57f4b808a2097e8a7b6b3b7af3769e6d81d64886e6962372f4f39e49cd46c1b5f735f380f7c277d099776ed1aeaa57a359c0aa8c72f40eb91a1bf07ea157f5ddb30409d6e3af98990ce7f30affdac5e22010646dca96a540060fc908a3125b000ad1ed3a0f255cd34f15d7dd1fd681c3c35a1cd652056ecc5264d39aaf72a9bb83a551cc934887ae107afdfef063217270d9596891418bd461bba63de65be067b1b7864fe46484c7c9e96349a7c03a80fa055050aa18ace2a44b4a03c947824172b30e21011159443ca3cefaf696a7aa8f98011260c9436bf48991f41d4d507b96ce7323e531adcf66347c55c8855673a9f2ec89b5c8024460617ec7271773b36d64fc14eb5d82652c53a3031457227093d118fd8eb9384e80229041a96a6493450f97e6736263abf1ecd9e9fb9a4f0f6d667fa824151485edc37b34acf3d8c35f9c1be48b5e96a12af8e2d35c23a03580f211da6316b34c56bee872d47641bca77da640fdbbad5a9ad8ab9dc7957913da734ad37492ba4de8cf136cccdeb6ba3f1bd3f003be7263c4f2a40c33f24ca3339596e6c3428338100ebcc0722d4f50d30b33b912d4e7c1a9fe65f6658a6f239140a62c3261e10392ed1930aa917652d3bd2be4e8a08ab97e145b920abb31ee4bcd5a0d71f638180f61c245823a399a734a4dcde0997880245ed71eb9bc65e3c6fc95ab920b8024c17d44ced0037d04a133c2641782f1d622df45269b491d3fa2a1227579eaa386de3e7de7bc455c6a154eee5727fff0437a20076c5c3b0577cac5b4b6934e269380222461a60f954e48979c0671217f16f7027983034121093186c78705fc27dc92e2eda4116a6bf7d23e0548d62b67b25c41ed06192bc26ef1397bf1601f3a6e2a0e7f661fb0505ee382f27aec2805a3e2117
SIG: c7d23a58e2fb2a8d4b8ed1e9eae91e1129c2af8bd05f0bd572abebbe0f30825925f0df71cfb7218c686e5548d9427710a690366ba85541c79101a58a10e8af0a
TST: 702
SK: 5907a8c084043875238edbdcb7832fbba4c05ea3c5f88a96f1fbf950401ec164
PK: e2f49509d1007f618efe4f1fd67eaa6e2ab18afb2decced5a0b2ba8363789260
MSG: 433b2478e18fad5cb81067061d225528229778307885475460fbe3137a5b44024894ddbe56fa6ed021496f0786e42bc6c2d2797ea0a6bf355e88115faa55cd92ed42133d9dcda6b9ebf63ce4a994d1a82d2a49267558be54182a6f85112bd12b247adacf1405fc7ec7a015d43ab40b82c677f7f85a0e48197c5b96576199f4c3343ff7654d523a30c43a054c3e464451278034b7f196c366768c628af94fc0ccfc9a2955f9d32338b944780f8e327085b103781868e4fb79d56122d7f3f5ab309e5d634add15da382c0d2358e647182be4de6e9a9e43e6a3a3b8215b204d9507610d461621000fb1893707af7d2595bfef8a8c5c5cd08f309a5fb55e45519aea9b84748ca5c672bfecd30d25651234a3cc319b43dfcefc1a07b55b4aca714c2e7ef9638fe7884a77b22253a01a2229500e9ce10fda73a843c19cc09626d2456c22a9c901881d521f4b15d2f613cb469d304d579223bc5ff73804df6371517ebaa5b677ea910ff1a02a26fafe48fef469ed799bed6d56ce961834a2edc2e23c0d9426eccdcc934f4c220e37815f7c334b7383607d430520946a881a08325b4164979d5e82cd8134d78cec4861c019f6de301c1b9aec52bb982033fb79b2e9731bab2968bc3f93fa5604b893c6028c204c36bb8c6b074be28c964d2849b5bb19d7e0ba24e22a204d4fda83b10131d383f10b136bd0dba39ec26af30e3ffb4dbc0c921f0cc9910715d51c81fe4c62950e855549a17cd73a09ac91e06d461518376d0fcfa123df0a837103458d9ce221808d1f9ef2edc5cd2e6823145b524894ea48526d985eefd3f60679399548e1edeadb5395b43d87044b2bfe7c6037029b346a402227eab81f333e10e77f1dbc06a211d43b82558676c2dcff9082b1dd53368df002de1329af3000b171a6914389bb80ec0c9f3e412a441b800afceb0486709adac66cafeef248839331f5d892197e25420f1e37d7c0247f669f5fcbf0
SIG: 8c4912c0f885d76c914059505373a64bddd67dd468369ab918f23ea28e04c19177a8d461144f0a8b51d215176cb08bd65301c3c46237b61bb1498ca79d4be70e
TST: 703
SK: 6020ae273e0e0537bac881d7549d923eb1cc200d49ca65d4be635e39173df9da
PK: daaf0e699a12a92c16e0ded3eb3450a36311824577e361f05696603300166297
MSG: 6a8011de09aac00db16ff7e55c2de67d8c9883fcb2040dedbc1e321caba7bb036971530176d1dbbaa927520bdfccbed8840126043edc44cbb7fa3528680e5f1b5664951dc90109aea4b9c336ca043d8221a4c8d2011656bf944efd36ba0a10a4b389196055750b0e388fb52870bbec8c55198131443945c09f3aace3e6915014374073266f34887442d74f468f8d7078bba0bd814cd6dd423c97b56905587b152d1fcfba0eb9fde2112691dafaf4f921562f241b62841001834f6ce36685f82a8faa3b7afad73a5e59bf5f9e713e59163f31dbe696118af33506d2ffea3d9c1556fb152fd2b321c31757d0c3c0f60ee113edac02d67efbb303dce6fa88f7b9746ca110e6a0cd099c0831f53c55c28b6c82af446456b842b2c950a553ee2c765e9729e6b0c546bfc26bd6d42d06b2ed5d4c8cbbc75f2a3ad8129395793d979c031fce7e20b38bd89c9b624748b2013423cebada02cde2052da5664c6c6426cbfc88f84ff602e2e20df9678fbba577a4c134517ee050681151580f7c5c9787b96e55c4075a26f4f8ccffbbb6ea18de1b2cc8c4496b16042770b7ec6eb5429e7ac1891232aa4e47467f4e9a985d80547ecc4c6fd9f59763ede91671f2aa5736a5d148e3a8ffc88e61253a85b0953654958eb2d69401cbeae775f8cb8c3ca42d21693ebe298838df94c1d77b126a1205cc47d50d5367b6f276ec8db6b95324a31e8fd2ed2e43420c4ad02ea277dd948a55193d0f0b4d1cf28386c725975ce5c12d2a6f35673cc22a0694cca4daf6afbfd326d88c1850f834c42ff0e292ba4f13e5ef0774a596d33904c0262d31df2c584a0a4f453f6ae4a88a275f7de79c13ae1a73115be02f425c6f177a1ec4639c42a792809a2b0919ebd321e316001d5b2f84894fcebd50a1dcf44d702b924532fc0e4d3f9ff8486c0ed180eecc3e09e2272a94dc7d24a4e87a931fe2495cbf992c0aae9201e0796298f9363dbac475e8ed
SIG: b1ba88fed7e5f4b757f3fa4d1ed9b19e498e5d2f5e6cd46e426fe8f039882f1be77ac9e5a9265cbf7e3cd2a9e9926c18199143798da5be47a4086440496ba00f
TST: 704
SK: 932a200ecee7223f24146283a4048c67a6a2d2fc4ba0f9248bdffd82c6cce3cb
PK: ec9bfb7a6d04e726fc1ea0c424610dcb7967bf15d6d6626858d411198d40e239
MSG: df953207048213afb8e2af452c889a21ca136a68c929bdc824f9a89ac596dcb90019a46fb682bcfd962fccb27d00baf8eccaf9d9a7d8183cabd7dfa506f7bafb4935ab045931ff8faeb71631f9ed6bb8f8473ad6290d7cf519db310a4442c461118f67d1a6d103bae6f2697c94b7426d9e02e3cb9522fd0b44aef600c962feff5873d98c2790887b8e88d160824f1bba22017639f8dce68f743480deea1f92aa1fd4135dd06457a60f36b7d7f517d40c94c0dddc2e465847d909b9f68245ff2b421d5919001aae5aef24e02c002da907e8605f160ea6096b580b75cea022d402f7f5fdc464f87f78c7906a01e8e48fb5b35174612b48ac8bc750e0f3aeb0a12f7dfc09b0842c1780a5fd9c54afb9399b9408baaccda20afbe3d682248d7bf1efdef4905a319b0ffb108b753b71cc97e9e21ec9b3dd28cee039d9418a1135f0add092aa66312ea2913300d1cc8916524302bd3d1b09e6b29c6857cbdc56ef4b3f35d8ee677208effa846fdb066b05eb717b4d45120cab72a7db7a7ca846e87b16b69047eb76d8f18da8e1399ec0a8c9c328cbe60e0bf42044d2ebf2818b3c047588452fcd2b3efc1e1009ae07688727db8fb6df2a2fe75d1cf22f32bac09c82a6a3d7eed7d00508cbe5b72460ecfcdd3ee911efe5898dbd8e4ce8591326dd1522f9d255da861bf9eb2a1d5725d7d5d427340341945e7bca8cf2ff8a997450953e77d203683e4b0dafc330e05672d2ecd13a3f442df137044e0f556ffbceffea26cbae26cba6f2568cf39f908489e1a92e76afbf297995da4b2cb1abc9ee1fe4dca5aa838b2fbdc109e89bef3ce5a36e5b2f712ac4c889438248fa5a2150cac6c977b5e0543f4010b7314732fd18e7fd5982e83276519e78725e5a5eeb86f4892084ae52da3849c228c809edbf69a2cc47c478d18719f111d737887c7a2eb3250898db34e5e5076fab9f4a9e6e1929a3480836dea07ba4d63fcefce5543430a8
SIG: cd1e4bdf4a3e4a31d65254333c8cc4087e4cc40b02e2a347d09a3dde698490c087d7109ad0209c53e987589cbf3ce26412a2b02cb8a3bc93fec75ab5d2c38703
TST: 705
SK: 5c483e837eb01ed5a4ad5db3792699824df13e576be967d12115c85e0286e628
PK: fe1aa8b069da56e676ef3a57d9bba88305ea032808ee635273b37c5c635def4e
MSG: 58d5e2cd899ba985378b3ec33e9a869822b23d5d896a28f424fcd6e4cc28b80d4aaf2de804367efdf5e423b1234d821d63ac05eaed12c73e8e3608af0ddccc8386b7d842b12e60d30cede32553945e7829e9b23f5ccc2e7103a08f2cdd9e75a7b36f5e63720ef0d49b2592bef3740268c89c86a6cbdfe201de0db9985ceb19399c9a1d5bb0586af3c8cdf2713299eb0443a541a47384607243c54a05915058367d3f2db380ed317a8c12c7a63e809c2e84d4acb9d9eef54c6f5af7ab59cb9168b1068f9d2ccd978fe721bad68a669ffedea3e92c76b32e3166658ee3bd0deb1b084194ce35d9a741c57fc2241e68efaa65320b23a1dd19ea8b7ec81e76f1e9163f9592eeee5af8eced0272f33512d0d4ca067f05551b265396e10014783cacac79437b19842de6ab91b9d923bbeb503325bc54869f663e6ea4ae6897701be7e11d16cdfae0eee861862000e7a4160781547e42526af51ba9698d234aaf510da81a0dbf264366153d7a6d5eb3fb08b9bb5ea065c2f5e5b6bb679d2e210b5b40e2bc82f78dc9ab5824b74aadadd89bf8a8b73a0a2f43ac748378921a73a252704a4adbf740cb99c1e1594c37ac9acc19f52315c6a846a57b36128c64d767af44e9c86305bf18ba7cd52680523a3b102fba6fe55567069d2047cbdd9605ea12c8877d399c1e66e33817731f50b84f817d1f0760a40f97468618934105eb00ec50c76db3c53fcf43fe1702907d9a756bcf439f8831d0bfac92e7058fb157be3e591d37eb34165e3c6fc60e72294c083e477626f9001c1d737c290377dfa58ea4ead3028fc762ce8a3afec2e6e132c662df6034ab554f93efac657ad34f6107d347fc5c5e53f3733e178b76014d2f9bbd06ef2dfe60e2083d8865f7f5b2acc025d912e5cf6cda6e798143e9dbbc70a0211d8e4003d78b383d66a6ad29717ca24eddef7df7cd3a7ef652aba5487afe5d026c9b102807294eb27d9824eeb6b40f083de7
SIG: c17c2fbf8c00bcea3035bf0a62d30229db742cab1199677c7eb4eb0ef5c7b51ad487a4971b631e794a58bb0823cc0fe62610fda6a9e03f8c4c3381cb154cef0b
TST: 706
SK: b0d0abdd8444e10f293754ac9f16e31bdcdd97b7067128aae8e4d7f11289e2cd
PK: 1c78cc01bea15352b63c5697f1cfe12ffdd16ddc1d59e77951b6e9408ee228ad
MSG: aa276cc543fcc62d70a704608d98ce51b645b5c24a640a5df10a5591417d108926df3f0ce1b921033309eb8d8659f489fd6f79aa1bf4882d72ac69cc58d3bce0fa89b16411e9753eb40c6c4d598dc8f4abb0bc48f1370371326c9a86bbc2ac6214478e78a38408bddafaa9592600c49a129c05392f8a7d642b49137a20f3fe9f11ee17cfa3afd2af71565e9c40080b60cd0dbc378eda062c7cbc7fe972bde4509a1de95f14df482f48aacc463cd594f66d648d3794738ad6ab496e2da50b0db2ba7b659185e4587f182e833de750faacddf21af5e0cf4c9af385b04f7be231498ad0b742d5a87c06115db230973a51427f202fa39afb9828b5f03fa327cbd52dfec66d71ea319865dcf6810f1858472d8bea3e447adfb4b60758e86b48133709732d2bcf51c76caa847b6537fcb05bb8c87dc5e9fb022b3260c1d71b149859c9663dbdae6a7bbfd6deb9d123809c241401af10719cf91a6bed16084c444607359ed8f018db111511892b46bdac6c9c613841ded886b9dec06c01e80487e48fbe778e9e97508ffda0577853aabdcaca8b0bab6ce41557aab9631c96d60977e35718b60595273fdba140f5500a8d3576f5a9fc8f3ca4c02c167af2e03d25750b42adb03b1417f2b6d219be5f8429331a26a449b5d4db2b1a09152eea2b25d2df7ef6fe0a32e25fae79360a9aee1511fda8064550937a7130971930c673bb358e5f55951f50b146d85d383f3e01c151ece6c06d836701253280fdcff4e139d3319ab2e2ca71bcc3fa0faf7c702c9c604e5651de4af5700e9ede7258b9bc148d5595cd34170e3e5cf292828390908fda961f2230ac0b8cac64739732706ce2d5e59abd6d5e207bdafea74d28d7a758f2200e4e00a0bcf0306a3cabda47024fabeae488ab5c323715cf3ca7720af9ebbf8582e1158a099d736b569b9d40295817ea2554068bef32442c111ec814c6ed415919ba73526334df30bac666084e5601c2281c
SIG: 64408bdd2d0fc892a5b62b5acf8e3b3c73c0b5c4fa2a72e39dd608d4937f9332f73e14d08badc6270114d1f1a556cc6ee8488abb907f79ae175c352e9f11ee05
TST: 707
SK: 498497fdcc6a105891e023ff32d75f7c3748d8c52d87dd3b2775aefd8160a143
PK: 2d79ae9cee4ac6275b05749c438ebe552b413d873cc07f14f5fa130177214c54
MSG: be38bc8cdf46190e304ab53dd29c2bc40954fd4c6d2bb990f93b2b5c691fdf0527c260f5066187f2d0f31f43a08b360ea1ed8200651764b8fa49595a1594109e496759ab6623fa33378d800e6117e079e13fe85c81b63ebe247b3df6c1584bc7cffbdfa45f2a2ce7c237aaafef8cbca70bcabce0b847d551f46a7d15ce2a0d3d545abacc5930010c53648887d476e0d13a34fc1c54df09d106ed758deedc761d557a73b2bcdddefba4ed005997b19279b9d2de37d041fe013eef05a2e11c9a234e87cc0e16c0c6da42aaa5bf996417bf64e5b785d67dc32547c1f052178d694cf20f1698589e7ed49be29dd59fd5c01ba1d9f5fb06a75895b7b1e15895097ebde84cad6303aa0a86dbc324747d97245d70c5203be01b06cbde06ae037204d23730cd696189f7ac267cf202179929ce5410e0e3ade513d2201bfd20fefa40b4476f27bf907c762eb7262a5be13cfc047a846d20a9f2311b6469b06ab545f0ec9fc446ea250cd3b73a7b6b960c10ca4c2d6c64a156a18c9fb810e49afd0c36daab8b8b856643a4ccafa9ad886e91e544535b8edda27c90c06ab6bcc53628be18d7d6369ca1801f91c2e0b95f36d702f77234b4100719c059951e45b1f916983934e32b4d4d8f29c0a373f8d8f0918b967865cd0e4beca01327c99d5fded4c1a69ac2d4d9b78ffb8305670021040250cc27737e75df75760fec8b8d30b245654f3c12f1f7cea0bce78ab3693578af3ea61ffccdf9baf7c3ea65b88fc854128126476796892c663bd14518c9918629a1095f614e0492446c3d84b16ec94f7ecadaeb6b659bbb4867b579061714fd5bb0faa4ad6be0ffb3888bea447e4e3438c8f0eae644fbd45a3802dc40ec451b212bd592dacd4da96686dc8b2024257f25e9c830bff795eee85d87a090c1a42321e710555764ed8257c9415c7f224b537558cefdc615129f28350267c01ba0403e07f5c6067f91c85a2c50c866dc4388af38d2160203
SIG: b0a36a2c934756348eb47c25a32c3f2a5ddbd58fcc72a08c3cead1a2d900335c3001e35bfe1f3fb5a555009ba8e96874494b97e8b09700edcb1f2584b9d0fe03
TST: 708
SK: d962a6719e5cc7724ca4a1d559536812b4e22aa7bcb13e4fb1722d28e045217c
PK: a944592dbc7d77039d720256c3fd340d34db892ab13e4812d662e2840c28b6d0
MSG: a6aa7a190d003ab175332b8f58e7caeb690854d9db56dbb6957b3fb654e2e0da991f3154214204135df1e1104317c9e3c58eedff1fc61aba57744c0c7ef486000a70b2c142ebaddc07ab065e2a855daf198a6803ac24ef3724487c1351ddeda0513913457d76860d78a9b6bc3dba66c40e5fc349a873ad6065ce7d7fdc2cc483b3aefbf2f03dd669bd9cb8f63cee47785cacb09d872c9aeb83e9868405254324037982e08613455d9521d88ea2fda020be730cfc8c07cb0b37614ccba2fa3ec498b815bb5adb996e848b38c015a6a5c752ebdac7b9eed8b69619d8c846b66f7816d1df1ebc21071cef0b251e2eab59827f6d6055084370fd27c203e86a189f1ee11e8403abdcbd1f45341a820525d8637dc484a5185d6551cb882a96b9981a5f1a821f27b656fff90e7f69bf286f752f970ffca5c53e0850b20b94f9431627094acea912a880b749a6f80bb206ccaa746fa70c833c9f323089ce0558c9dc200d5739d1e499634f2c16e54b7f6d7819c47071b60bd54dd0f273a319750fd3c510a49ab56f630c7ce6d8023d97862346859bc0b4d605224969708903760301409c60ab25175611f0be98b23a8cd8ac535e3513bc77e1452193dadf4435e63c3629b666a5ea4c4bad36eacad2601404eabd8d9a07956ec2b4b7bb6336ed75b8df8f16de42c0fcae93652e3c407cbd45e8d413ef51e8542df62512ee793e41358a1de19246c6586b3c1407410421f6e865c75a9f4a6a4788f84a9c781d8f8024bfdbe25bdc7d4b69cbaa7719628c0b07ec2c4a234fff4ac3d4935b9ce4c8a16947abe7951ff8d9ac9215e338fa0fe9124176d17bac1e05592c439868ae5a4f75fd1ea82aa454c20a939deda729a0e19646cebd822049c825c7e31c6efad45e306f2d9f0569e0717331f48004c26ebfe68f3843e90f8067032d21e786c8539e01be3ceac5954a0546c84b734d999456a7c45f8cebaa478e548007f9d3af836f754de4123f2f
SIG: dfb9b635ac0edf83b7b59d0b8409af475f66fc9946af0b7c63ab8cf5929d4701a1bf66959cde62fbcf59a48ab3bbaf0b9a61b6e00b2181eb934282070a5d5300
TST: 709
SK: e1d1416518921d07c8c39e2973d8ea1249caa8bf659cc36c7937f84ece7ad4fc
PK: 48bdcc3f1a5b8058ed9a32ef1cc48cf7a8ab76a6e4519e5a82855241ad6fff8a
MSG: 3d263de1ab91e8dd7b317f7a27fb60a6e1838c0c793b03abbe7082b6bda0c7c46062262192c88b65c026c174584d29649710429ae44a46140b4c82c8a0b74d56a004f8e2f5c18f84f0464153772f8312633fc6ad28a7d9fb55f7d78cd6488ca58117eaf923fa28875e2b3189893185aa3ccd044d3f110e2e7cabdf6f814b9fdd6733bd5f307a87bc73b6250d5883936deb1db0e0af1be7ab329b5c6bd935bd8f8dc888f0d1c464edbc023cbc080753ee8f799f1072bad1144dfaa615a59e2aedc662e83cb1f8e52096a7ee483bf873b25a0c04c1851a0e87375063aa1a94fa835c052640366b79f735d3286197ab32ebdb5123f6b47ad3f442c44c530a68f8512759e9cf386fba07b8064bc8fe83e245495ec45f8938f8259dc8016205f78d3954442ec1b445d83d95ad1805a5e0e8b3d56b870a20da18d74f26f550a9c7534a4144dcbc1c3cdbbe470cc153905043088facf1d303559de41e96c0ab409bb36dcf38cc9038a6a4908dea82a653195c16f290a7c3ac487636cc5bcb18d15a14ac624c70b6f6462bf249e000cee924018bdf7dde39114cb4f652e122e8744da28b0589e1284d70d9f106de16d073648080e6437ff384e68177d5cb718e2ce3f17ba1e990ae3ce940660130e93750b82e2fb41aa369774568d7cf286725e3c58f63e73f8697aeecc717c5cf1af7ad74f446292c905d84e22b23d4e0d2604bff48fefc40c6204b5e34c042292e53bec9360159a5cd97b2df5786b8f5a292c0b39d14a870a4588e67bd12b2c2f7a4408462851d2aa787971d9315190f42cc588af0d2dcd91f31bb715e9250f1192814f7b8a21fef4517b0cf8bb8a1a1a5f500ee219dfb46132efe8e90bc49093a5559f9681b4fb59e5ba9ef3f05d34eed034c14d77ee95ebd76ffa5af0befcba18fdf932af4854510b75db00a7257b234887d49607dfd16180db516c7a20ccfcaeda6aedfb6a2377fbf31e67b517655db73ca29e118624d6080
SIG: 4232d2a481084d1196db62f22dc74cf2eaf2db0df05ad7cdde67bfc29bff56cde019ac9f03d81f1827eb1e3b0abe0204ca7f77fa874ab5268354ff08bb7f4800
TST: 710
SK: 2bf74f004d7d0af73a83ea208cc206723d188f4cf607bcad4b6980268ff21fa7
PK: 8fdcd99352438beb52f0d1742bae71844512dd0685aaf1c909e38fc4b5aab6cc
MSG: 898e4303ea5bebd200a5f7562be5f5032640a3f5ccfa764292045a1a368d02aa591077d8f304f74dbdfc280734454ed8c2727aff392c108c526e527e672c5397b2d77c01f7741ef8dcc2510ee841b59dd10f4e1d3ac501af7cbdb85ba31129c262fde1a0c8bc83d6ff944b6bae3fa7fb62587c681d8e342965c5705fd1a6ab39e5a0770ee7798d9fb6c0018a514d53af848db6047cd02db352d5563b53662373b971935a1ac2b7b6361dac6748771813f7749316694961b940ff3805811a49fa27a9ba457ad28848c697050e0188d0773e17fb52194e190a7872a398f31c0f0ae06537a273ffb50c2c816445ab882811922c0621556c46a3a0ec40bfedb411e90b6db1ddd4bbebb57d10df566a63d726a33308514ce3b499d5e526c22b956d8b99913dcb13e437e947b666c41c54d8b3ae2356647e8017ab678386c927219ae7bddc0d821265f9dc4ff3f8ce5be60f8e9defc5ca335068ee29fe8304917b788784a2388a320192f9325d0e6cfffea21e6eaa29e7707f63a9ea4fbb2558e3d0835bab1f52361037ae59e503ee96b9d708a47a3ae4bad113e2a460a269ccf25a0003cb3e68a551864e59840914791126f954788b25b5af5aaf586ebb87fa5f377b4d7d7f84c000dd2cb440e214d38d5ecf70f20e9881828edaa1dbec37093db960686ca123f1ecba6336b37f46cf765be2814b9e6705bc9d6a49318118c7529b37c84ec88d58a8453dcb692c9a36016b948ebe6fb2c1d0adf5f198ee3097a6ff0b8eebbad8b0769330b18689516bc0fe668b0d05e3a584fcf89c49db501d61c2def7ed3722070193a5b683c5087ef274ce6a193dd4a303536c67934b4660a841ee1b446a6892b14d0b0aa3e98fdffd43c797add36583f74c94d0e2d68e2de818d9af200598f0b2beae169c8dfbc4d397e6d1ceb6daa6c9f6bbf4f8311ba26ffb194d44216c51305267074e856a1d6e922780f4798e2f220223fff1dc370c8e34514aba42df51
SIG: 3eb5b339e191a3b6168545da5fb0ca9be209043919b9c70a07b4a7a3bf64b102f6ffd6d2b02559dc681ed3b9c82297b201dc25c4973880e155e13a29426eb40d
TST: 711
SK: f5f7d5b73c5a65301b5b4c6710ed12c16e7903177db792ca715e23389d05d83e
PK: 7c4762e979f0c7e207be1843e2666aca27ea89bff5b61d573c985fc7025e1e28
MSG: 7c9318d56e63f16535436fa45afe278e74e61881bb468997d0418bc720b630dadb8128b4b65ca6e921e501813df9fe03b4ef0aae8035dd08c5f820ce5df12ee118d9c36d3b151a52c3f96ae1ca4c82fd19da669ddba94febf8eac8c42b447babc8a60b36e803624f7d2047bd8d8a153687f10dc1ca82100b7c87d32370ec8f2671ed7d067cc80587cab8db3a71ce5e406327f763ec1b3c166770a75536630c815fd8267582d1b5051f0f821c02150b2eef349b50590314aa2570793fa64a76ed2ed83d2ba1f9b9f1163154612b49a64ad8d5573c25b1cd37c41a44e3df78f1053d90b068f0d37ae00c4a32b1a3ff874c41da4a7043392f18efe5518d76e88b41ced69e6f4c014f06ebc5146e61e82fae1c49c37c394fea34199ab86c11a4467a374e40255a05d426971430d56cdba25a21ad779cc7f62d22cd87b60f0891bd856a517e14b72a9ac7672e4e8fb374a9758ab0c4e5964aae03228973f173a5d42aef9db33736c3e18d8eec204a1a17b9d04593dea4d804cbc81b9ac5458050495539999a9985487e7ca11c37582ef85c841e8f065ea98fdd6b1c60dea1ec2883521568856a6ebb2749f2072eb43448be0705ed477cf4b2004865217de5fadbe2a0f9d6b84b3fe7f7bf6c77537496246ec796b8ef2c04f68ab5b14fce0c6d287b836227d9f08fa0ee19722f6798a5d8280d107cfc1bd592d9ddc724ea86fc39dc94a394019e3a3de9e0d1c735e862de2bb9525b5fb4bd121212bfaff9ff586ac3c75c5ace746d9ca307f795ff2697f2b41a6346ed23397eb38898691e6f66841637d0ab0d968309e0194002309015416e74472fe32425d45f07c7711918b1e5790f572ce4441042d426033792297b5f81e0809bd9691f0a505e3259fc03c9ff107eb9b48795f49fb09c1bab5659d39ffecbdcc403e3803dc012438c2fb36f683015c5df0482cb7d7fc5757364a0a3c10d0e1259c01fcc4dd5494b5290a694aea3f6fae547ac576f
SIG: 58fb392f82d5e52ff072cc77efe048f2235250c71125ee821c5f3b393bcf2fa46be4c5d8caf13cb519efe0c2fad9ee231ae9b6fd1fd509c98c69c2d36c753e0e
TST: 712
SK: 43d4be6de9cb00898e99ddcc2e1530110fa2cbc4376c485e9ca57fd65586d8a3
PK: 3632ad389be2fab3fba0d804bf6345cd322eddd6a75d8c37fd4b5ba1c9c25e8f
MSG: d9d55dab0fa6da76b68e841c24d971bac1f79af513d834e426a5d08114ce8b54ce8b7afe016b0fad03ee7450c6c3097173681a4b2eb9f9c179a88e7cc36813f2f5d15f7998afa9fd4e546c73bb42e7f9522be6afabca8c7b64fed0e292e4375f3e1e5fd9fcb539f4e5e543fb6a11a0df321e70084aaabb70a9950ceee3d879c386efca1e59c3cb7c45b560095e7af00ff52f8a1aaa9ccf092f0bb806d97610742ac582a3abbeddf39f49d229d32a1186d021518d74728d13d962635d63baa6743b126bf458fa2ac756fbf88096c8d3340c622390534a743f1864d54deab5e5536372ce5ac93762287414eae158a76bf81df5417cf4c047be3ac1475c517ebd3ac1d1d1bdda11b3f99c18173e030acd51d2b5cf79516509415405077511bdd9cbe17d04f47805e98d0d145e60a5d0e0f453cd9b5c1a24f12b75e8cc34d5e00691ffacbff788fea834d9d779c1e610294dce19170d28160cff909bea5a0aa749401740ea3af51e48b27c2b09f025444276c188c0671a6da94b43d1e525e6a4a8a1a73dfedf12401846ba43068a04092b12912270d2b60df6099779756b8bbb49ece82d55f0f8db1b80fb4b59bba860bd18c75d6c834d69442ae0314cf2399f5392a3c6728c63e5c516c4222aac60f916dd63d1d0517e8eb10bd0e15eb90614deb296403ad15b8c12b9e971ef2f01e59fc35d90c55a8e20e9437dd434b26d5c2c6ec2d53acec17e81e47831dc2de82183d713b59a4d1f46969ddcddaf27f44e5a311aaac39c3d5a97bc90cad712f46f85e6c8fbf5d58d8bc3ec27d310a9eaf2c369cb00649770390a3f988f362efc155f56a146a62650547e9153250701eead1bd01c89462272dfaf0a431af4bd7c3db451ada603233fdad3aa8999aa21e2d3a43b0b56fc6a9124d33598b3737f4e5cb258beda756ad2e17d0691d15d416bb7cb07ec8d8c7af5de80e5b9394e320c4c6e43efaae684ad00f6dd20a8750e959c2f04206fc023aa190c
SIG: 86ae9325f80b9886c8381f96a18c2120e6db016a0d6ca282ed93ba9b61caec02de88efca8b8e916a4b16a58525a2f68d21e5fbe67db4c4d6209595c4abc32b09
TST: 713
SK: 7d010d760f24e5a2de34089c9fdb19c33b155b0a37ca455a5e5b1dae7a073176
PK: 4c877b3c4971fbb551166e214d1c7624c52277903c59a562a80b91a85483fb47
MSG: 86e2115572bf4c013e6b4b04d0b03e606ee70d929cb8ec36f4e2f355db3b5e1573d658d17bb1a310c16989a16b9558922ee493f359042103c4dc1b40dff7709901fd5830133f42c4651eca008b499ee4f84cd4ec1edaa78256edb62f24021a0076256919e4e2ce0a5a20f921c278cc299159644b5e3a3bbd089dcbbebad3766aea77e9f08ee5f7d4c19d8170bc3de1ba779a769914f965dbde2b61bad214c508186041f76c25be957656f5cfb7334eb838a3cfbc55cfbab67adf1552619941b835cd3e34103b18b49131e82096f05f570b899804bab8b6cbaddbbc02f9f3b559736d99ca7b02d3268fa273996fcf0571977d1cc3008c4ef848970ee350b158c47ec277add4742fa2bcbea9bd5549c7bca038020ece68f188c1ea3a62dd9a073d4c138ca8a9ac0408dcfd46e36bdff73988a58b9617caa08bd41bf3e812e7824f0f7e8146a444f36bf53a1cd892039ccd335f5a2e79745eac96148c2a299947f1b2e328a3789bf13c6d73506f3bdc68ea48abf002270fe4ee9ef9ed6b10c2fbb4ff1275b9d7dd35d8a52e371758574cb466c57b5abc242976befc8d98a0131b9bb846b219e4669186a83c056cd8080661de16b51ce5767b22e9a93242bf8d3205c66a673ce783d1c0d37b6300fbf0d6127940f88f1819c450dcc90543ed794f1fd44e6539febaf19a4cc98870014d7ccad74d1876a123ecd145516c743b4bba62d821ca9a7951e0dfb23f38d9e3a365fd8322f2ee4799e9ff11e1c5c30b55a355c8a5deea81a545e34705ab56d17b1fa06ed76415556702f364808246f863c319f75cdf6bd748438d1a2eaf4206c560bfafc235679ad6049c1a01526fcb9a3ce1b1d39be4df18b15fa0ea55272b17ebdedf6c30498a8a14f2042be1c2cdb09e9ef3846d6659a9f6d673df9afb7eded04b793d9731f0accc41468dc1f3236c99acadee6239c361b8bd7e2d0cfe8bb7c06687e08e76b71ad57a036179f291d096ae2fa0818ef4bf4866
SIG: 5570613879ae22778bd54f14fb6e8c0256a71f3d79c3e5cd8e41aea8cf773e24d29f1f1b24f8c80d2949e8201465dbde8940b1fab6483b085d418e251014200c
TST: 714
SK: aaaabb7ce4fffe4dc35747baea2bc5f050bef06ee0c1fd632a067fece1ef4fb5
PK: 820a2442d5f45f3c791478e098fb3b068da52ec4e8dadec85065c35659f437e0
MSG: f9d28597a3e2b64ba327ac5cd29f081e74bf461b2eb2d3cfd9d5e92158d21d1d2a47ab50981cb19fe3f8c6fe488249b1c49fb897a0fe21ab5404414fd914875c220f1cbc12f5c38cfba79f7ac303a5231a372b02fad6c8462f8cc49f0f64965b651dccef0bb9608215090849177be47b2d3072944d36e856da185c7b3a689f7edef988338e0963ed31a6b0a80d5cb0b1cccf6f394837aa6f8b2f3da5efbdf4d360d4bf4dd708ce6445587d942b79761ce951b1bb4d9050703618a6d930a80c69576fc4af306a2a56dbd884a05a1e4e9f3136cd0b55ae474bb5d3d0fbc9b0339cec344fdd085c1928101481c68794f5c890137108cea791d21f81683d3e1a9eec66ace5c014d89e69808e5fa83d3812ee680f5a9971681b8adcd4a16e9a4c165b5ef9932c5ed825237fd5037bcbefe4cb11564fa707c8a93290751414891b1edd3313c65f8b91c2e925a3c12a9d3aa45fd5a667b78393c3e39df88a8f0d1148b5311e3d87c4a92e0a3fb915bc90d5558d05b475a8834778aa943ea39b8eaa95ad1832e5916ea3102d7de0b836cde8f3759dbb3b9d56ea817b3e49c983210277c2c7c5b0db187422532fca98a28b3b659c6b815ac126fadbe2f400c73e9d2dedcbbd2d3a365ffad7e666c896e31e61b384ed3a9fcf1290538df11b9474c6281cc592c71c8808868b4292c17ece6b3edf5e3542a70b911593e93f35ecd9729bd8880a24eaf41fbc6574dfe167ec2d0e7ab3df5ec34b8b55d548ab93738a2eeaf21c884c5c8551db2edf2b049f1a2a84fa72ac8978a4c27809f209c1b2195aff504f699856cc4f22d44ebdd0fe50374468d0b1792e574b5110a1f4cd0e221e824a78ddc4845feb46d66d633d23cd23f4b6fbe4c8ce16cd1af61536da5fa67b10ac7555a68c0e0bdbf2f8d72309d995516b8118bf43835d0a01c08ffeba3ea3ed05cd2d54f0eabcda05d0037d52caed3b19374faf73999094f79055924bea9aec4470135f5e8bf183c9d1c9
SIG: 050ae8aeceec9627b80137357a22962ac8b45048661708d394d0a51aadc381fe8535023d6e1bda0e72b349b50b26da7c3a3085e81e9dd6cf127868fc5baeab01
TST: 715
SK: e95cc2a4d1193b7539fcbbeaaeed985b6fb902dd0efbd6387457550d0d6a2fea
PK: 72a1ff1e9bb11c8d88968a7b169637adee438e2263f006dca4fe02fe066cbad3
MSG: 84267439201b0591db60c0f17a9c15e45409295652d5f55b87fb351967c846a567f5cebaaed1762bff5485f04853ca9269f464094e512df1f02e13e517b1daa58d34caa2d5ff9f9e79bcafb4ce96e8a089258ad61343b446628ebc4f5b2a84d03b72ef3f738589fa13c42519a828299a3faec035037bc10b44e3bdfed9e0870717cbaf31bef8b22c4ea16e8157fcbc63eefa39ed822efd4215c247dda48786277ec030a86c0ef4851d673cfe752d0677883c2c452038970c09bd481714bc3fbecfa4ff2a3c245695d7ecc2f4dec7f5ede04ff6db43e2bb91c066b649ef73fd3be860cb83fa80b074149f431eebb917ec8478da870c11e317703859f9f2f4008a6c7c754b06e1f7d2479689da84e88922f38274985e11ce13cdbdb0f2ece68fb602ade03dd549a362491f4a203ff80744f663c523a026b431aad45c5829e029ad6256d1276fd7b7a12ddbf1727d9e233fb534457370a426e56fb39cf404a3ecbf0c4b50bb522dce981e0830fd8406e6d9725ceb1ddd3a1947937d90e04d768ae1d126e2aeac21b8c9efc54c40961b7f4e9e88025f7e0b9de901ebf0049e741b797997d8db78e9283bbb5f90f35a2c4dee273142ec258c02ad0ecc61cc5c9f12132db28af41c1fb78e524be5327b5ffc35962779fb11ff0c5d3ee0a31ff47e73b1729dfa46e8986b1b89abc88ad06abd5b6f766d23abf642257894ebdfa79e6309f1272374ee9433677ba13e451baa95330e660c8052ae872e0e32e2b2d1286d01a0ab5810424ed8b9405465bdeba03b698384676fe5ea464a03446c4f7cd7b43312ecf151360464571ad28610581fbadb945a1d68181deb403aa56eba0bb840328eee36103c7de073a6879c941c7554c6f6f2a080809eb0e5bd0e130f29a229e930db01fecac2e036bdf0e001e2a8ea3264f8649d5b60c29103f0b49c24c97facaf7e81069a2b26ab3f933f427d81272c6c8b7cd0dfb7c6bbe9c0eaab32bbda2218b9623a2119aab1f3eb
SIG: 1b8d7cc2adf36cae1631250c82431bd88437163a6349ad96e7a864447e9fee753ac3655c9835b4d1ecbb306c638ba5402ad02ba6d225d96882889fe8d204a604
TST: 716
SK: 77ad0f942c37f0313e6b0456dabaec81b2d61f6c118ddb29eaf3ac5bf19504d4
PK: 692d2da5a95f48611a6da89cfb3b3540f6aa0c850d6d98deea870e397fede328
MSG: 87e6dead2c85549e3d8d2588a0a3360603a624fb65aebbc101bf7f1fec18d0b28fbd5dbaeed38752cdf6355ce8dc84e18ac1a4393d2ab888882c4ff1c9c8137f83bee36336bcbfbb72d5049e0a400874514fdc3633046e89383dded93ca31fde0d898e11e9268d3d5c240666ed5527613da79fb7e49625b44cde78b41c67902eb0216b3a7a3e560e261d71d764aacf15959c17fcd6176fb25e249ee6bb1b3bd7bd90f60b0b0ffa0315a065a24bbae8f255bf298d7e4d44f0b430c415b4fb36cfa6626a83f49a2567f6244f40e923add1d49a72f57b1530f5b379de3a91c2e9a1ac79ab37bc3b9ba73d8828136bcc87d2c01190de5457facd90f369553f7ac521c5672b0867dfa8da3b952ad95b67dab99b4820572f2d4a298e9518637779289c031b793dee859cde7b24add649fff871248a6602d2516279da6058cbb696fa8b1d89a20d2099e646443210483e5d4134e928faeb38a3b508199e0d69bb55ee34774205c0a61205b50b08febeaa401e6e3a51a2bf98efac78b7ae2b852c5395a12c40e2c7dd1b202504b5a7d2f7e4fd4f8610930d2868cba8864339e041da21c0715f41b2b23d14d0b545480bc3bd7d7215cf2f816a3332081ecaa08c0f8b99525251f57231b6750c2dbd1109ac4160486b768324b6bac87ef5a226448c431240328f42cca586be7aff3cbe7605fa341514fccfb966af3d4530e8cd9037a11ce593c2d383e1035a0c2eda098de90d50c5184a9c01b57f26b94dedd1454c340637ecccee70625754a328c65f42645b5e1a5655eef97dfb1c6308edf49fa368d17d17e06adc512b3973ea652ac40a9978e1bb1b2f86c5a9ffbf60dcc4f6bbc98a64f4de65e7ec61721edeb0e5238456f761d2d1293af0de9f793b11d8cadf01a94319a02a4273ffc4d3ffa7b34d74fd2e0b100fca58b5325f907a749193e751d6c116687aee3747b59460d4ef156e72476eae1b8455d76e71b306b98129b72fe1cb5eb405a7c2f4327f3862d4
SIG: 696bd552dd01db80b3d67d61eeb7ecc56878404ab119442a1c7422992cfa35aea920825d2dafd892ad7eb6825ad999aee5c83b7b507906534f91ace759c5510c
TST: 717
SK: 29321469ee9f2bb165a069640332b489bf5c3fab682e93dae9d86317bf50c52c
PK: 96f730f8ef8970268dba0f7570410b6188a1a3c86397740913d53ada262ab87e
MSG: 9c712c83d54f2e993ca68a9632846004499c5195448ddc491c3a0d2e3a666d6b33098e4864fdf86e619d50f10b7cc6c39b3ff2801a9491f6fa97c5f1c4afa7aeff31d738f9a768a79c73b25577310fb0ad4faf8543a098f859571b6148e8b52926445757d5549fd25a26518531566379d1c274e6c6a9d64132e4ac25ac9af9381bcb885332113f43014a139a81f8d43c8a6ab54c11a5c92e06191c1e51b757ac9f11e3dc15db4486d167ff9f2d65e23e6c96223d9aff8d10d1502cf3dbce5e357e6b12dbe9b7e997c3d0a507d3bae3cfef1ffc8d056ef7dc72ddc1c81e310ad205be16e77f2738354b10b484d3076c27e6b4f166388581f350befe22fbb082b54121ee59ecc7ae5dece89882acf26cb747ffaa3e2d05a696f60fd9e829c709d8f02daf537b2369b891fe6ccbf8dfcdd7f4a364b19985be7edec67ddc1db713c0a90fafa48837772562deacc2d2a0e789e18a8b5b3bd9e083ea92fffc3183d5d414153259b33a4329cfc80824ebcbe044a7e33ab8a24fde54bd9520aea284b0c4c4fa9427d251c0ddd013ecdd8290ef5565f608508e363589e529d84ff0f26f9ecb03052d5897fabc917e56e601b64abfe5a17c3950289d0cdcaf1f6005a9f8106f43e17adcaa2d1e269166762f8054de05135d5d1393d7000a15b87bd68846a89d5bc22863325151aac843f72278ae6f4af72a4e449adb7eae6d436a1ec7e58e59b7b8bb9ef0ddaaa001826f8dcb446479deafd8b8d542041c19a05b1e0ee47b4640910c31930ca4e20b105758ec75f1950356947f6261d0037fe30773a3ece6a96c8d5433333d822c2777ef7ff8be6033345b5055d58f5eb3729af5ae8824f331ee0731c89b20ac118f550427cd958a55f6b1a2888a087bb7db55bfc73b29429b4448dbe9119c45a87339b4497a69a4cf833e8f3770cce5e01faf5e73bbaf627683c0a28c73052fbece203043389dfbfd45495e51dab86a252e5bc1b4b7fe2807e3d0e2363beab51c67fb31
SIG: 4e1aff8463bca1b7deb1d3773df2e7a06864111b6dc42a62ae98deb2313943b3153ee46696b15c24efc2a808aaba81c78e3dfa4dfb50ca9fe84445ea68bc8e0a
TST: 718
SK: 04657750497e68152c43ce34a58d2106e64c557cd7a84ef05d9eb82e6bcb05f5
PK: 3b3a1947b4cbf60b826d609f192dc230aa9b9baf4cd6a6092e495f1d2e47ad62
MSG: 2948227a890f6f845b775e62c53af3805064a1576446f085d90f8b9a5ed68df1ea393ce479c4414149a9ec5a171036424dff0344b4958f6132298d0e24c926d28ad9d79f98c6e6bcf1c5767606ecd291c6ad47b4f9fb2b0201155ada627b7a1fd5b07419874083059eb52b2f6ec22818b78246228f3fe6355dfda70ebb9bbe73229378736399557ce24b30bf645a14e2256f70019b3336b203fb77c6ec94a7a2634888feead4d72c2391e99e8c8d533fd8a42b08c11f887ab2deb6ebbfe3d251de63536c36cd53422398e544cff87b07a63349fc5085dde93a1bfd7171133a2043981f607522c8133c63428d1b92626c79b7358e7021cf1f412a78afa7cb3f59ffef9279885a5bdb2466acd34cd51580830b8351ebd440a96623907ad1f4b56203f5e159a429e3546ead0c011dbed09028717e3c3dfed39197764d4d245ef228b98044718ef4d8822f21b2c5685038473bf93dc0937451eb02d31a46c8dc7e94c3e8678c83b98a43818f125b528b476aad31d1584ffd48f149e5736e58f94205d3889e567e4dd1eac2fac1f8f4dc540e5322460fb940e12e93c4c98ded1941c1904f967fb4643684c19a4d5c441d60b0e9f40855e523fe7f99107657a68076275bf84b7c69a3f2b3855bc8026ba9b00bc6fe34b99da0631700a67f52b34e1796339887a48305121d53ab4440fc4b5c9bf72394d5ed372ff18ca3f007bd02df651dc3ac438275f1a3e52422b86c4586766a21cd89f805805dbb44fd89fe24fb2c0b40d1b754c335dbaffc3b3bb8bb46c74c36374504042d86789227599862312e99ca89eb504cc3d75d19495aa86b20b2736b121bb2075c88ed4a3fbdaa6b2c3f76d1ff5525d3a2863e4d83c72bfe01e10278809474e1822de2d96283489320029611aa9dffc4829d66869e63494f9aade70b77a7b80fbc93e3de4d935913752d045e13b312c5d082f6242d4985b053b3783eb02c6614963dc0d55d4cbe887bae29cc18979e5e2ea945bcd40d89
SIG: 7e2eae5a293f418391f6d85a7994b07c452280017ee653bf617a8d5be24cbb5d0efdfb7f7f001312260f344e6fb915ad8d7de9c0519827c05726f9ce2545dd0b
TST: 719
SK: 8bd99070c50a9fa418ef7f75c00129916a41c86070961ccb2b202be18c2d10d7
PK: ddd73308fce8ca6552d039428c7a1a94923320a31c0f580d3c235280f03c1830
MSG: 485f8d680f79ee2d828be7d018a65e0b64b0f0184819863e7110eea8f299a72c4dc87f8ee8a8aeaa81af91dc71adea79fc9797421ccc646e6cd5dd48b4dec1de968693fbce0d0021a3d98d38a8bbc58195e6dfc3b5e1461b2a594103e80a29441d5aaaf889e31cc865141f0c6b2c8c81f721679ea2394ec6e4081ec203c2ea397d9484757a7a0ecd53e652db9df17bea0e32fe8b2cbce0d1d97b961ed74e8e622bcdd3558b7c48695adf18aae6110ea9a339b9da407a9edaf2ab081a681e1832cc215b1f08a67d559a4744af7cd50318c206ee91157582f82eb6c0fc29027b4461c30733b8169d1481322c4860509ba096bacb71a579246751d567540e41431e14f1b46ef16eba276104bc01650d5c4926e47c9c6040784b043cd0aa4854efe8797fd0462d4539f38035aef08b4577c1a9118d004b6d01862f5276776dfef1371864f155ac0f078389c205cf0538d85fa348244d7a422911310ff6c10132b1598bb445c7e2077b763c473d1e7a61a38b64929a648b60b2e543543739224b40fbf6d87f1079c30bc873ac38991d51b89e9d261c4bccb375355c072c1ea20e4ff91d55d9f7544e90d1c6646c59af72424d8aaa8e0aed07b3889d4e450c1209684ce138d0c9da079525f5aa02050af570e4315c2fa8b099b7765bfbb894fad359b8e24804ece052ac22a191705335e98840a624e4cbf3a1a1a327812785b2c0f5d6381457b72fdb633e81938bbb54b8c37cccb5d59c5827c7683a5247544977e984442178d0852906ca6f945c4229eb08ad27e6c275d7b4ec8dc25fb2819337e53ead6c7aa787f91a7dc6ddafd536eefcbdec2c50167be34306a82e16d5d52b3b1be008a7a611274ce2cf8d62e3b900c09943be70ccc77b070637c25061d61be910eef50df18744c33e76f6701e0a8ff6297fa67e4b4108c13756727a9d74bc9e17983eec08f866b7c7ffb37f3ccb0141a80feff6322b2ac62b84ce2797fd98d6ff269a41a0c38482db679862a38cd2
SIG: b14a7b262012c5909e21d587fb4f29a9093c8e1c2999816a82118fefbf10e68ea898bf0da18ebfd0341ea8f82a1844c8e0dd5306e509b9d0c35b473a7d209507
TST: 720
SK: 1af4cf6d24ab3782867d96a1c275ceeb022c691a308e6245665d616bf67c2c32
PK: 19d317ea98d35ba5fa67c12ecfb32750df275d7a45b8e211a7ac47ede7712d9f
MSG: f445fdcfe28c17bd4427aea5676c0e1280841597e9d66de7d7a71723110939bed00f4ebaf9603d53c9cbf6271be547af29b2a045ec41288a7bb79d662dc210e215957fa84688c916543e5617f560e4d38f73baefc37e11914e47c515067851e8ed21393e13dd19ed9b73d98945fc826a258e957dc083dd8e535c30a54b4266dd71d113ce856b46282a18033627a98e6472ccb463ed3d96fa7b355d3b2c2a2b6010dd14f4ea3965dd87be1c429bdea8300b4b0b44458635b4979f5e3e8eb5c618d4e13e1d688bf88c7e4a3d938e84336d67be68df3435c5c99086321c02e13b4a12524b34e46a0b4d27f30d7ed4f5cecb36deadf09e7efcc755ca667568297914c6bc240627d9d09aacf85415412c0635623453278d9bf0e10eec65fc72affffa9392dc7881d1e5c760a40280f16b1475127b91b69ccb65dc4b35de10f94325c0cbe1c47019a2eaf2b4ba92d785229aacfad1826ebbdebefb7dad4b05f88243e15f279766e3321dd8dba650444d81fb0878767a9c63534bb4ba21285a2416cb8f856d11a96e0a8c8de1e1a75132f1564cd994995690bbed2ee154537fb6f279fb09c8dea6f6afabc62856e3d128fdfa79fc4976193bb9b336861e47b56dc2582393d2e544651ac85bc58e9e6a94dc4c39c4ef72538a14f856cd95c3e2790adee03ab2e52ca0ae471de502cb19e676af35f5f93d840fef9606cbe92d8bc25006105d92344588838842c3be505c7350e351b735e6cc6fb79275b27bd9ebd36ba4d060acee73b5a315ceffab86d06f2168a67065578196a0ed04a4dd71d6734837db083857ab1eb5e0eec4ffbac9544f4ec19bde194df84b1c848341574bf10daee85b8178196fb608123a808171d73ce4206ad65216ad1a5cbde40b19d6ae7f40df97ab8432e2c53a504ed122e25fb7a51c14354ab3928edeb39c29eb246b74a076f89d03504f401bd176b5cffee4b9db097c45764f51aa376704b5a7f210b3f1a905e25d67002f6557ebb749737cda31
SIG: 7eb46cd0de3155b43747d732f1045d8ef74492ad827a2245bd17102828442e43a0ce7e8b268ed7fd8d3e7b28f072795da3e070f12bc4e23eaef57b853cee880a
TST: 721
SK: 2aacc8197ff8fae1c1cf3862e3c04a21782951f8e48e40b588f8bc7460c30a03
PK: 9a1b01e2154f1c36a8e16b79ee7d2d05b8712e0d27a061a6d41d475778b0df8c
MSG: 5d82752ce5da3180faf4787aedfb19294b4348a1d9202c85398331323e0f42b0835227e68e1156f2d4ba2fe450e6d6ef2b92d89bbbe4096e12ca8397eb2f45e676f1673aa41c959fcd30d5578853b5dbd1c0d5b3a0f0d870eca71ea13390111b258f6548b32f37a05e9744a656fd778d65721965c6d9b328600b45704770e04b099790aa7884f00d7bb7659e337210bdc23eaa71d7b016030aca6223b5569bdfc290811aac409524dccbf9babcbe4bf20946b544317ca6f2f91831c79fb273b6404eb4e61e1f7b106ebd0db9f2b1974d2f031bce25803606552c3441655efcf2c7ea52adcb30993d85f2dda79603e9415a023245a66c07a956933146f53c993c08891808b8166b30721fbd1f8a1b937d14070d786e9eb451f2ab5142f83a60f35d76ad8b81d6a57cf368fc6fcacc0c4758440d9cd595b1b0942a3655e250da983b7241546dcfbe0ae81077650295409ff9e90977fb9960cbf40a2af5177402ba2faf50db6f1a7365cf99e992429e38db43ea83fddc95a648676c0b16bc952b15de99d52f6b5233da4eae1978e8ba25e6235afbc511c76c4c874c9237922b1cef0847d07a80200cbae3c7c81fcbd0d17252ed8c61ad1954fc862e1e04444c32086fee380d1c17541322b9a60da662352e210e9ae215e353296db922339aa17d2173ec31f1c530a24b1f348a31572e1469caac808f9c76ec2731873b803ead3e54ea24bc24499b9704b3bdce81389b9d14d49527c04b3bb9e3ba6d946cea58cf786d4d28b89b41c58274035a86905ad95758c3161366ab93da81e6b4c808364e087daeea4c4c5c2aa6871937c5feaba2149f01f738f45396e66ea8063221e1c81c05255ba564ad440cb5d07cbd4bab941ea593244930bc5c289b3165d3ec8847ebc4b674c0a49f9169adef786d7767bc8f213db7d95c06e99bc11e200055b65eb79adaa01bcd2c85da43ce6370e12e349bf6d475487affdf92e20a3acded1d76f9e83e919e98def195072a50d0c571dd25
SIG: 647cdd6c1a67290e57676a78113aaadca69ac57b997715c509895b8c5c94e82c0b6aceccf3ba8bd7cf61752b1b19d13b49f15f8bfa046eb442a55cd5bab14202
TST: 722
SK: ff862156c7eab681c95efff8003e00a14f1f0d505d5507e6e5b39179df9b1cda
PK: e1b89fb31114ea46107ffd0329f1066428de54708edbecf3ed9d4708cd143fe2
MSG: b3d1db72a6a985ecd70a2cff6c18c179e217d4f410fd3934969685901bd071bce6c2fb6763e10c6fa16e75a1176066b8ec81ae3a8039e71dc2cdc64a40fd62b7cee7be4ba0332fe45d0b60158652e33f8d3aff3cb4d6b021744d0dd178b1bf0a1cc1d3fe9321be28421eb88263a124f49792d079475a8c555ff5690873514b5d483e53217e0cbb12862b850fe390c8f83008086e649ac904b018350ab49157ee9bcae6c07a4b878b48e25e984fbb4d36b61d689b13468a28d1e387e0e88657f8c8ac9586a6e26cf94dff6f8264e3ff6258865c6dcf857b00147886e175df0432e32f04400e299f21188312b32dfc050e7b7e87eeaa0cbaac6be9937a5e0cc31113de7c8b233e1ce8e5d9c564fbe9f37bbd411df7a5e44e6c7ebb676d85894dccf4865e4dda0cadef2bbc55000b3a29f1f71ef4461ddc3b331d91566534c5d6d84c731376295320f80adc90288f9953554fcdf9213de6a905210d4c8064af91cd98325ef91898d33d70038202e32fb6709ca3d788fecbd1b841fa4e5e9062d64267c35cfd444fb69e2f6047f58b1c2af4cc7e4cac2f890888360592113e96ad3a857ed05eaaba6f9153ef89b93e00e8743733ec472d9b0eec1cd8fa52425c4a26bd7df73a2712bebe51ae3b25eb78db82149031fe7b281af6cb7714edf89de915f3470f153eed7f456243bb90342e190e647f39e046883ce28a892003315ea379429e9582a935eb78963396d136845f86c466e8faf2272f43ffefc2ada5601f8a6b2ac4cc6b92820917f2e0393c8faf982d6c5f4f230e27ce2278a7237747fa85a9c857bf1802c3eae0d235b5ad58497d66a0d3a9baebcc417f1833e9cc4460f975d72858cd118d7aafaf1c878297cacf71ac75676dc1b4fb51c1775810d03537f2d766278b9971bb97d3c49b51feb26d375e0cb9109574a816f84e76fc7ef072d5793c2f65ab2efd9052e6b8569f2805861c31a7344a3c44069a94320d274e271271eafa3bfe64de7537846a01e51fdae0
SIG: 4b8137042d6784757d4a9c06bc7432f4809b1c6a903542736d9a57668c20845c17d468557085c57fb63213dad3be0fa36a118f7c1aeff2562ff4b8888c26900e
TST: 723
SK: 582619ab3cf5a3ae776688bf6dbacb36330a35ad7524e49ef663687764cf6ec7
PK: 2002ea0a38a327e0384aeae468db0f6c8516a69609af9eee93e9ecb94b449c66
MSG: ca74284f11c56e2598d78a4ecd03b40e017a558176012b26fdf695c3de98a74f8f40a47d7978edc24ee8092bfe5e61596834deed1d9d34a0f5cdaebe3421aa19e012de865b9ee1b73479b2bd1ac982f97ed9c7cd20459c60fbb11e1e2b4eac5db6844c71d72949502bba503acec905adba25f6b119eaf9639fa8abb302dff9932d850cc44c57cf90b2e58a8b5251c126a9e28f5c761b6280e2cddd79cbd68e53ff4a6226d3bd4c961b9b9e4345a2545862c7973866f0420b898e7baea90ea4ee004042ef38a1fd956a72fdf6fd43257da9fdb96680ef4fdf9e943d265cdcf2e52e3201d5408bc6ce10e5700adf12b55ba14aa829d8691c31f24fc4a51ce6faa1f3ef2ead78e5e753446ad3fa4a84c193979aebc8309bad60814f4859b931d70414764491c6c9ed8db673c543d35185cd2888aa21c1a9203427e0ac0b1fe34c0e4a4001e0956c13cb59a3baf87c2109a888a4c9e7aa481767d8020ff35dd7c5ccec7c08e971a7e218138c90546a7ddf36ad114be58557432c2ddf34ced3379f70d4407e5879f9842f381717051b1685aa7ab0ad38541ec168f51cb688f3cd1a019a336c9f4f3f82de785c074867fdc8800fc76fba04c8ad8de10d2e9b430581be44c41ecc8fc8a616314399d18c6479f57e573b22a6ee5ce2dcc08948a0de1f0dd25b65715ab18c70c762fc3d7d600cad63226038509c19ab35b5493eee73a703731ec535c90c6f06d94d3e5f7e51a09f9f8f42c501b8504686365ceee9e0fe001329f303522146717c6a1258d0f157cbea4b5a5e3d13bc907e95fd6e8a71896a02c3106bd26a510051f1b30258ab27f875673b1337ee36b71a376e0f9e7809a67c67d9acc16c251dcb8c926c8e932516d38b7233eac6159c59cad0307c590e7131b62219145aaa355bfb4acb6af0a5500006cdd8b813fe1908602e0874c9622bb37673ba1acba414231667bcc4907ac871f87e6ce3f591c19171057a9f457f5362aeda105d18fb84f7d0f0a7da7ef8da9114
SIG: fe9701da1aa81c55bac33638f775542b804480f34b7bfc78da9916e5246a604d390bf920c872a77924246ee8d0393b202e7b25b2484f654ac367cb0925ece305
TST: 724
SK: 2bbd830ce7def3fecea1ecd6ea0ae9c9f4fa8ffc3b1f1938c505051bab40cf7a
PK: 0fdfed8de3c1eaf891ce37e34cb4a2441cbbae0883383d70de2464850b4a642a
MSG: 5f1edeaa3c0b2a63311d97f1c54e7e2f687170e6b46e2169cbf56c66f231bfc4a576bd2b8420bf357d3a90f8f32ea1ad9939b467254b66a1df1f5b4cbac63a5c2724260d24d8df8edb58ae247a2591e920b1a420cf8d8539ea57db0dadff1ad3e98c3172d033163cb434a766b0c118a56abdcce79c82af7bac74ed0ea024ac4ce0222d0aa914f432092b1b517804db5918a845e9cca55a87db7c2852f7dd2e48360185cc442c7930afe15dd622cc02bcd1ee778b59705f14333241588a522de24407e8e6e10d5ef3a88e3a3c4438c17f7504674fd7e418cb2f77ad0a56d2386703155e9a401c43ddb51ead5520aa7ba038e7de5331418ad552bdcd185f503a8548f55b6386e4687ca515f7c0eea570983bfb24be16f7b3003fb756e326562f2a32fe65ff844c3984c72e40dd49e4f3ae8c0f819a7939b2e736e381f5823cbc61b2ed01d9b05cf8b14648a48b0d7cbe882ac16cadd8c42aa2c70246347b4d849536a7ac22c720da3cf178725ee557a92c25b12b8b956d3bf4802e9e8a15b5ab754235cca0e5b7e55e4aece45a47e084ce1447440598ef5d4f5fdc2c98a5ad136cffbf87d3cf52f6738cca7948356092078fdf254577f55969a0c65246dac809a2fca1f60a1d929877b9a6540e88a9e6e9155938d22c687e63b387534d385e8961e5886743f95f4a7080d916624517b15336030a46714b168b83d6f9cce0606649c01f0a1d0a2a53f5e378f6aa98c384aafb3eefdb3421fa3ac98a0d3a9c029c2300ae0241067d1a4fc92e438688ea889fcb1a1a9e8634b916c60baa0c18bfcd139bfe3017bfbe16291343ce8605bb7872558c6b5fd56dfd221577edcffaa8bda34d7a11ab8cb278288e5834842676fccffaa9111bced2b3575fdd49621b76e8d129b61700eeab0314ef94d550506a4b8d1ee65508d89d0e99e9336b41d9f74aa4d722114de0f31ecf00b097f53c9aca9c7a285b58a35d70298c5c34f74b4a705308033100349f0c62f9c2ebf7dead0a77b298eb
SIG: 13ebc979a88710e3c5f345cfbb824813b308a9d5c6dee328bfd235a97de7b326de6c738f96f69831949209996852dd9c098d5808418709f2bf510d46b7f03606
TST: 725
SK: 1a7a3c2f5481131be5f868456aa2fa90e56d52cb721c7184ebff06fed2fe685d
PK: 7c2ad0f2a570550326fb50a850835821676de1de127f6de1670299d814f6e3ce
MSG: c62834d9d55d1a4403e925d0a5b552da174c02f4e945dec338c1bbb2aeb4ff40020ef70ff505205cf881b629960abd62764e5a54f2b5105667b11c7d5b7a4ccc3f488bdddb958a7be9546207e6c4671897c053508e1fd83222130a7933976d2bec614ed8f9b6a6b9f4efb2a58b9d005b943e42f171b709a7313070cb2e068da39cf99922b69e285c82ad97f2d6c77922cae2b5e320e83577c0d088761ec88152c297492978a9d7a3ff67ede44c2a707cf3e2352e232f53c8782ba48928a97f8a36b20a416816e94579b9d7250a29dc8470f63a7058e2d2a99d6f0ccb530df5969505ef5c7844eb167d20f412a508fab1f8cd9c20c5eb9a417a5412b5da6a57135759fab17f6314f68df35b1772421443676f312579af6b1411535ada8f76012b69bbeb60b2897ee6607cb369cdf52f4f6ddf88cdb2630d78896f1361fea22ae634217696ff114fb42dbe4f4346f1be5b57adb384ae7e49b41f74b31b9a62bc69dca16589c634eb9d7c6c94f8ece44b60628f98e1024cf32e3e3dd6dce55a1222532f490d63e6a275281c0f3a6c101891b8d57a45de11de35ebb151c0dcd75e6c050b3cd8babae845c39f66c36c77cde05b683e4fb0103d93e7659335c87fc0e3235b2e82488cdabeb5c5c875808745eea92de86b8efcb63e16d082919aee2e92899cb0bcf1c1421577a4a0d9db09ee1f9feb92a5382103cf7c32cfe463725ae4866daafeda0534c169f8f9be404f3baae123fa768ace46178d4b9bbc5bd7aeec7903b0a5bc57538986ee09e07e32077b3b9de50dd1967a372c385ac886287c18451a64efb37d056f9f4194c08b1e3ec97022267bf0043c13d26b9ce1f53905f6e41b3d99dc81b331909b722666ef2432e6af8a453107531230ce4a1af8eed626da223da76b46507e33d7cdbde02d411040c89a11d95156ed4ac2605b826939c6cf877b4ee736c5da77cf4650a9997a3b9cf46a82ba2bc01333c04478b5c92e2498bd002f013140aedb301b95993d1d750870d988
SIG: 976160fb5bbdabe5c8962f23babacf0b0ab41c2bb13e9c0d449067b7decc7db4e94e76a71b9c0ac4d6af387a72a8cd73e3bc63b7ed650beebf17424c490bd60d
TST: 726
SK: 191a1d90321c7f4e7494bb982909a9eb40c3341dd32ae4d96750b7d02966b40f
PK: 9562d9e213f145c456935b7031c680669f8bbd31a4c2ed3c91c4002a5629e97b
MSG: 85890db4e2fbce093dde5a80bf8fe09a984b83a49b7ccb5d4b06cdafddd382e4b8a8a50530e82c200612c9d7d8a089bc8aa845c3cfcc38a6195d21c2618c3dba2b570920eccfcd236f17f08d814268f882242ddf0702da8785f407aa8f86fecfa903c48da83f839777eb6b4a2bbf5df7a4da53475af1ffe44b5fe0072b8fbf3d26e6d89ea67d8ac8459492890ada657eb3dc2492b88de175b4bba1a508064d619674aaae2af09d31a5c27c8d5d5a29b03779f4286b8966ce407e6ff692fb942520a9938d69cc70acb06b014b6dfc19834206cf1ac6c448ae6f078025b55f3d827201268a92add9ad178ef76a2989fedc6e39f4ebb9f96c9b8352694fa54fa022019c0ec0012d0d769e2367803f925f175f9fb9cbec4a0c9c1e2c83ea57e6a92a17f555cab934271e72c8cc3215fcb87c20539bf14277b1bfbd6e5880ef953fc75f23c0dd4fcc1e0be340af947de02e877fd5c77dd1df7b414b5c0b40c74956a545a115b0c6993ab233b7e72c822b6b3381bb1fc10875bffe3e2ed1190fa33fc15da083794fcc2c5bf5a07909063cb289a08a2c8a33d343842c2d6a3cfa2a16ca2eafcab7ea100d1c714baabb7149f07e25dee323e780757dfa8016faa7c0626222c365f8f2f6687d1ded234f799cc50d1cd26b4cfa4045917056fc79c3b88b2b1908e372df66dac8734631648349bc37fa34b25fff3b0747b6bc16b94e3e5895e4bbd93d478a6c1f75e4fa30faa922049ed4c50f12f4b312a8974d0fed8d44255dcb2bf0febe47fb3fb8ed9903b5ba4ca18e3cc6762cfa1eaf04dfa944d496e0fe8bb7dc045451396bfaba5485d9d5f391a954c3714253ccd9b19964d4280680720783036b3abfaf2884583ea5bdbcf69d08897ab288314635abb4c2964b71ad9291feb5b61f80e9b0cc07f912a8e5598d5548defe0eea1c448573710aacddb152f93c7c6fd3f7e4ed9f7442a6b900f23c3c544ce5c9ba5f5e92aafd11c9ff5f79c08b9d045fef07970625f62e2f4334a4d664caf7
SIG: 74cb028dc6b75b37a1daea1cf88465db83a0093fecb22d99ba855e9ab59d05cb22c87d0b09df7c116213baa8f189b2703ff953cd202eb9dea3976ee88f5fa703
TST: 727
SK: 628563aa3ee2fc611bcff78bfb2a75e9fd8780e87a939499a61beaa6a4b71913
PK: da20616ee4a41c2ebfdc50ab54953b6d387b06c6def75796b08809565c6cf805
MSG: 056fb954fbe6a6014fadac1e1a9f56cc08af37348ebaf6920683384efa47626ccddfead2d5e9e8cfff45f7ac63de63f69d12848ce3c0ef1f530ade430f0afd5d8ecfd9ffd60a79746a2c5beedd3e67249982f8b6092ee2d34047af88a81feab5d52b47d5b3f76c2041725f6f813293050aaa834b01a3a58f69aa4a8ca61f5b746f600f3d452c6282ffdca4429b9338967ba3a7266690aec75ebfbf7be98d999b03eddc7292581b0d69e30a0351a151db70412b0bfd43d3baa9d456cb3e0b4fc19cb09e6cadcb6d3f3be5137cc7a8d3219ec2036ec670ed7ec523b1b1c687b5465307882fe38d7472d0ba87a471868309d2f773ff24c87d39c16b708a4ed9af43f74c8d85cfe8ab5406907e941a14970e209c29ff7ed8a2f935ae41709f270d0d08555ef7af2edfe40df399223c785a43e7f3691589e2ea4c036f11d03d7d1eea14f620035325cf2b33baf386393e8a972a7af6cd9b8543b32e2533d1fcc3177fd96d1e13bf8b68deb222f94497265d3ccb345751bd5b669078081998d608ca5fdc134839d4ed2bebb2952fea5a39c6f033c1558f698ce4946e4f6c08af874f27357f870ebeeb2199976ffaefac951f8e17fe7d0821e1b92a90aa4e9defd3fafda052a444476db1ce38a9e176e841189abd8fecde0fbc5cb55f511f5fde07ea97deb39b7aa8dc84a3946a6cf926d39b95c11af9d64d98b807f4704d0a2bda97dad9881ada1bf6636366e60a522b4821047861c7aae2146a02eef6b25d51371a0f17d24bc187dcdd05d541c2f72201427915a3928cd378689103ac50b33f87a47e8cdfa687a5f0af8a56731dabe662f4f2836de0ba8fafd86a3854bca012d7088a00b9854c2d3c708ddf58faa355a89afc2c80f3f5336da01d72a2771a055813fb35330f7d2e01b1d12daa95ed55d3bdc5df7739cbc3ca097a41b6b2bd7f0ff9dd1d8658983ba3ff7920c15f292a1ef9fcada1c607ecb45d3a73c9ffd42f3e16022fdfe12744926395f74fb3111793fa9281821a66a01d
SIG: c9a6aaa9b4e1cce1b58445725f61f552c8fb45831f03482798f01f663e9983db1a82fd33aba3eccb96226426d50ae17cc51274ce18a38860f40b2f82361b5c03
TST: 728
SK: 9141f79ed30bf600611a13f367b40396f2ec839c5612bbf1e6e497f83954bc88
PK: f14eda962640becb66c4d1f1a021110251917b8b1d34828298d32145baf6e5d9
MSG: 8fecaa7ae9a3d4a4851a66362b366e167b9f4300fdab205654751987f085de61bec9344aa86f5e5c6477514c2804ced7ac0cd0628529a3a1599236ed67bebe1f2e95aa151fe0f3b3011a1d4be9901cafab2f1891904d4bff0128c1d35ececb322b3cc01dacc5ae3dca6914a7d34da8c9657b950f89d1d6aec3299bb690111071fa87282774943d96a4ab7c3d6de7d1bf119363068cc82d45e4b76454c608bc3566b7f9b385cc7eb38ee429afc2da99669fc5c1be82161a1b0c33f7ba9ad4419d2062971901db003bfa23c44714995cb06bfa966e5023aa9346fd375ae2a1e84084314df3f08ce20800c2c2adfbb81366f6b104243d62d5041e7273433f17581bf93f4c6146fa966f638ab07ea16694a7ce305cc609a6e10623ff7f6c7916b6e4dbdebb7b52eca7f0d5187ff664d7c370ed22886aa2671329d928e0a3bea3b4711a128b9aab90266f8651d220b9cc1cbf5b1ce7265931803690d3291c01ead4dbc3329a97e85c4fe1d356608cc9e60b05bc14838a8608279a0061de28ff7b8e81f59c8a8c5523924c4c485e6ea80ac81750bb0e419efc7858cd4af50c8b8c80650facab4d8258f9cafa0310a007cccbc4185c82fd146df1d811879da3650d5716f1004b71d2c7f2bd6503c354589f8602c950a1f5139f811460752880a341116630e4ff84948e74a9eb350d64d8293002200233f209b17d78897c7ce6ce29e29f82d4ad6c61eb79f5739cb668b21a745555c96e19526845e82c6ed2b1c6bdd6364b8fc79ba9a32dbd3f8b975eb923623958ae0daa4ffa139217c00e021f937e9b791c37991a35e5231a1914c045a787432f97b8e2063db105e14da979c1c4cba785210eb02011334b230cfb6831998ccce25386f4f3ba0dce2006e9c3940b4d5a56aaccdcab02718689816360f18852fd1998a99fce9a04da3f5e23af94c6e8a5badfd39304b9e2a376a1f9bac09a85bd042476e26b58ec73f1236d41ab4b4e7a54def9d66a38f8e546de7b388e1e7d6681e5e2a096f160
SIG: cf202d7f2f9ed117f429502b2a5aff54a7f751d2171515a4d203753446df0ebac86984c88bd42bd1fb8dcb408776722a38f32cceb25f32a25d7393f138eedf0a
TST: 729
SK: 695c960bbb0dd57ffa36151c85de735154fe5ad5f5fc77d005a0a32011deb30c
PK: 34125e4e21f789ed0e1180c1f6369c721dcae9859b6f7b04f957e51001eede8a
MSG: 3706696c7a906690d0d3b71e7e211c7b067168f3a8f1ed984a0a5e6078597662e4e7889d52db0f78e0d5ef0e5f7a0a0f4263b6848b0725caa4b1cea6987409511c8e5e982d3f5b82bb56a4a7947121937f8e105c5a14b53e6c37cc716b1eba922421828b046f6856c44fabf13a7516c62a5ff98568450cee78b140335047bf1ca77e1549a894feeb078045e4641832253bf695485452ec369065a60029a6c9077a379db20485ea2edb6c969547bb2653289bc6e81ffcb84bdbf773ddea4b3750e9a72395d117f644b0e22061d4f3bb7c5b612e4b70395e0779516b46659116902fd0fbcd2340eea45e9c23db2564a5e11dc79e8f4b332a443ec35aad9604fe791252088295e84f65a307312550d9ebf61f367e4a0f2b5623e53ef6bc132825fc24ebee4ebf338cbfb5df69b32d030d447c44f313ba96fe07bbfe5b0166eaecbc619bb6b2e5924010ba3ec150ff6a69fec4ded9c442f98c15e77f319b4843b3b748b5d26089a76c2b834ff93c413e04ca9550cd211ce2d6a583d782575066db6dd33e8d5e8374355d068a5eb96f8b3da8dddfb5baf5c596daaf556a8f2cb5781e5042327f92ae0621eae088b5f013592e77873a81d7e068d7b8337db9f109a835b475e5caf7cea5af3b4ad6d90baaf1c73655ec676747fcdd41775b4fbe3924c3f41d8a737528d12d6156653a22358c6821426b2c0a33e1634c62c7c8385649bc233e7daf9439f09db9bd11ea01e28b77ecbbc4590e29fdcf0fdde152f6478132fe4c3a5b45a7305af6e381cadd72496e66bbb866cea47f7e7d7e63341600af3f49ce9c9e4e37394df5df71dc10cd391fdcb8a193dc98fc19059fa3ac230ec5476bf94d85556ace6e1ba32421bf59dcbe05c5e15d34c6644e27d0a02be97fa8387ee03706f22a8f4b3b4040ad7d3f8a86971a20a09ec81b7696d834c526b8e51cb97d27643f9abf5e29ffd0333f95de15d110c2064ca49467c14ef227f4babf1a55e7b1cda0429cff256be31cf116719a81b9c5fb75fdf64e
SIG: 4af41c554d990812686c329a875c41ee24b4a7fd7b3d4f8c8d5275f2e7cb242b258b5858a466de595ce2a2177e351c7f08c7fc4e0bf97ec5fb2dcb8252d2c90a
TST: 730
SK: 25cb17fc33d2bf8384ae4df20c1fad5c35fd765affde04b5256d4de01ca8de14
PK: b86ca312fe598520c64be5c72f5b23816507f69e070f828e02d2afcfe11bfa01
MSG: 4b4a71cbf8cbaf57a77d4ea188a6f964840f0d714a5f38a095a13b4e571297a88b792417d16184427f90e043dd8a55b7f1c13e00dfa60516445cbe77068c79c8c35ebeac330c33f1121d05731a8f5132d6480073274641195a75202116fff1c318817178fdd768bbdf105fa069c7a3d143fdf5d17bfad7c0624e5292068fd7bb6d303b4a27cb20a4e61875076787d19fa6f729c94dc0ba9b8c0bfd9866da5cb2e7a2cd2edbdc95ac349e5e5c2172e5a4cf7bd90cabe2c6e2245980bd72d0f6f5479881e8c4c354f68aa72841d0c73b986ba51021203161026ee3d729ddf1a049ffe9eb25439802f03011d144e50b02bd4aca5e5506d32fcf69e32f542544798f4e87f72bdf2433b1ff3259292e1d90812cffd79f6a543270baf24a3c39dd3598e1c661612922522f387d51597692f314c4d5ac4bf1883a614636336a5544d59ff41d1e0dbcf8e6627e7c8085646322dfc20c332cbdf35370d47dcabb802e17ca84780eec661c904d5bfbc240ad6a14a7533f71a27500c61dd3e473983887a86835187abb0df08fa62cda69dce86e21fa5ae954c22eddb60ee3131504a69b50486a17767091883760638a29c38030e1e05fdb28e158633010385a620613cc10d5a5f350955f4a347c65edddb7e25159da8dcc2655928ad6f6d8c4c1abb817d7fef3bae5de0402eddee7b51521ce280a66b796140f56af9bc20e465875ce2628a8a10477ce9b2eacc7d86f88272457bfd443e712526996254380f0135227e9fc151c8695e9cc64d272b256ab95c9a9f568e93716e0e53d29882e3ce74261257a02cd497c37d764d90f7fd478a17a890a8b2ea61ab81f6869b120a2f6484a88c151953391eca445015377b3a5dffe4cfbacfb5bab2c47f654f72a9d19cbc4d29537198405e3a04b4bfe11bcdb5c1f30d9ac02f54849c57aa96f7b56636116f2bb6f2583d9af94c86aff5c137f63ce54e8f0c21b6c25c1f0472a229c90817e6162eac71ccda309a1643bd6312a5263a2efe646dffe79ebd8157a28
SIG: 8ccb0dbcf7cc03e83e21c57474afd3ad8898097b972ede175acaae48e3ec17b2db06fc82776b0751c0f956fd7196f3d1c96321a6cf3d892415d8f8eeb4a14108
TST: 731
SK: 49e24d1699833726b18c78ea6568401a971e1ca39dd06d7563ac8b4250d4a9f5
PK: 71cf05e90d301a6d9fad7f0b38ec8bb044fcfd97c849b04c003625de29be86bb
MSG: 6d2605f61e1a04b6ae18c2c25ae100dd42a61e664e2db5c34d7ad1f84ac507552b741c2086c17c852babe07a91e129a506ee59edb9ce73be1b1d06d120ec36a1e94c6281054e78ceb1bdeffbcbf4f01051ed381bfc8ad1769f41e240bf6059d9704cacec666611f41e4dd438b7f50242ea86756bb1f81e5942c092129fbc6de4955d28dff35237db30e4a5036a9914c9f84dbd8ccf82ba2b1b3b5554a2b7a74cb0b2a1e1963345286e258dc8e7d56718035f95f313811cfbd852a0f8f49a29ef933e7cda7ed9c7e8b162cdba1a82262cd4df7cf8ea4b586db43dcc1e3764598e9ca46673822baa2ad87fb14b6fdb9e2032d0ca51c26c5ef3d9f79785fac2491cdbf7c399f3cd1774c1a6b1e4a67f5436d80db025f8fb6409e275bd0ed508b5e039ed2e4eec8b0f4d5be99dcafa6a1401252732a65b37c943c07ef3acbcfbb3dc06dad0a88f2f5eb551a3997ad6c6eed95edd9a0af4a288d5e43286b2ac072977c436b7c5ff7ab61c9484f257f58e010c9b6ad41581d742cd19752cde54d2b420d643654e9096a81eb9dcf804c7c2ed0e38d13a5ce39978cdd02b25350945de78feecc0c2c22ffd705c3ba8113265c7b9a7c8ddb59178bd21d7f6c31c6be2c36749ee0f9ab8bc1dcf5da5cb2d2d5962358f71f96ab3792a252a519e415351f43e7e12035b0328f28208cf4be529d299aa5c128c9d5ed575bf90c5350569eaa6f2d5521de1180309f686c97e9ad6fa1ec1dd8627ae8951581cf604b8b917c5ba434a637be1bc8b79f4acaf7795f4e51aabdb885077bc4f3c68fc3318de5823d7e0804ee995b70387950f799353682300d4e797f3cad611b4c562c8640ff2b3fe292916a970fb98c1475c1f4e27b9b33cfe0d3ad932a1ebe6a27fc3b446622954aee1683668c8bd4a3f903be5c77dfdb8e8914cedc51f65fed2d9c4d03e13a668d4c7ea5e31883e1b3db64363e2ac5cc54b54ce69c6ad52f874999b5dd2c5782f03c3d51505df536a1fe0d860d33eabed641a940089f1297dd0f57f
SIG: a0b6a2af15b6be9e951ef3f32cbd1c6702e8e017fbd315a3f2599c3f1a11865d46e78459a0d7f7be046aae293cad09137ec847e26928106d9aa35e0982b99202
TST: 732
SK: f8ff97032a34cf9999088058af56ff70b6acb2edf759e131faec8440fdecf6c4
PK: 5438b4e33f1c5ea112fb1bafef4059bf095a11409b64d46bfb4d25473c1c0874
MSG: dfb41fb9d53702cb2b9e3ffcad4ea602716f718a7ea33e21843e2a6c052c70c6c51485d72b53a5bb4e34e03e3e1d1a52518eb3e7f18f2a1e1caf78acb2116089bed4c617138e716a91431f2cf644a1210f6d1920d285994264d6466b0d8d2c62638044616f576edc7d0d93cb660131d4bb50875e153640123a96f15b75a5bcee46d5cc5eb1a431c59d2eaddfd5531502feb1551bf7791cd5989d17d10296d01ba3ae3e384c674526cab62a7c24c0ff677de71ca172621a28a85e01eefe07f6eef9c3ecfd7f9498ac42f46a43716f615318a3b28757c3a15f4f1c3822ae7a75c203a298258d753638cf425e15bbc46202b093b8e4f3e670fbb663db2b69c8fb0f625074d85a44d350e042bb1b74021d192997a2c27dd6c8634841d100a0344baed750a39ff5dcd9848dfcf09e5c8c47967b96556e2332ca17d8e42dd8f393a5445a372244600b3001b8fe86c45eafc6e738aa7e117b4a79fa2e6b00f464928d1856c83ecfe87dd34d158f5cb4e4f4d610f59717ec790bd3ff872040b67e8d3939e804e3b5db985a095621cbccd686c0934ece3e27ab2c6ce33fb52b111f48e4f274bdf320d0b02384c83c49e1a041bd2319109c85a06d8048a993357abfd811ac2f38059d077acbc36aa966c028903748625f92e8f79d51bda10f78522977f76ec4e885e49a46c68de09f3da8f86b71ae6423bd29deef1cc6a113eac115a6cde2ccd011fc1c0f0e3427f43c3e96fc4156edf62ddfb7b0836b888bab3c4345055a6c4178e9e22829fd8cfce39b0b8444eb26487cc9dc82606feaadaf4978694e6564f2729c1b13ab37c9072db4e9de940ee5f1d05884ae7fd9d9ec9cb7de56347600a88dea9208a63419fce29ee50055a374a8f22f9ae2be9805a9f47615aa59576b44042ff126a89824e36ad6bc58e06bb90fbeefbae5d6d7d62430f373b6296fbfcd4d6620168353583fbd3d5a292b9572517534e2fb0beef2fa98a464e59103e7a04287f15dad0fac54970e7715078d63ec26362f6fbabcddeaf7
SIG: 509e9eadfe8dde7914ac20cafc0b0af22b84dd8a210a4812cd8cae39b0a272e53e02246dc8939e9226920336e140b31532d068137a34161e599a8694a95ddf01
TST: 733
SK: 2e4c39219fc92a538e48e95fbfcfef30f5a21b78940b81053bdad4602b4c9690
PK: f8eed892176620434c7f0ec53dcff39863109e7ca4d0b3c6c4b56410be01e537
MSG: c87d1fba9d94a6a5408980fc8083980fd2d252fae540f6eec19ed6746c29e339a1c29f6f53bc23fd6bfa438507eff5daf903403cda707b4dc5e844805d6b1ceb4afff4b232e8e69d7d271f3c067c4854f3d94f27fe325581faca79d1f02a26290ad23af71100c12c09157647ca9da43d7690ddcd94db65e000989c878b75a0ff22d2c70962594c9b0808f27846ccac8567bce5d2e3b7602809f23b59cd718a0805d108f31a632a05b8dfa5035ab9461aeba416009d74fdf9e007202856890d2cff80fa240b978a48270fcb2f473697bcba8e730a55c28761919a23be41da27ffea09e3559caaabf9519ec08e1ffa86817aa3e8874fa816e7718c5b2f344967ba1bc2819c4f045a97b40544ea61d717083ccaf11e9ddc04a3598ef181e7bef4acef45b6551b478a0d7731c4f08ce5802f78258d419017661076d7d6d2ef39e57cf9cd9397dcc5debf64ab82b66159f578316e74cd49f5ad2c6fef83cf08683b9570a946ad4903df4e96ec008e14a501fa9386bdaf2a63993c6c9bdf231fd09ea6f96ef4d4e29a3a3327cbf74ea831054e66ca86680c6ce53b66f9465d06b3fa0798bb6905ae38455934f2fb7e0ba472328989f001308671cccb566d222c72165bb3a744fb98e2210f9620680df3e3cd14a8bd94b5745c0016dda77f059f26053b64cf4523c3d429112fb6b328398bc630a2e906b95a6c5780cfdc0641be4751bebddf7724dc9c27e78d60ed0fd736d5abd88929c1795d473abd2b0320c540475728821867a409a2ff13cc44ce35e5981e9f6b87a28d4fa8b8675e503faefca7c1d7984737871fe919ac414eea265ee31f9f78f521f3f4f8d00c3fb79171f3c6a5dbf5e1ac8bf63b4c3d8d8bc121036e9e55bb702ea6c86e925ec0b984ded2c71f3bfd4932e6c41b582fd02ca59f53ce297445785cc4cac247b0b84e7fa0bcdcf79b3e4a155f9878c1f643be9c42f7a4f27260444505c1845bd53b550a31d7953cc738861f46bdf4870f3a77ace191abd63c45adb153909fb59ab5db9b
SIG: 394520122bb0a564648a7a8bc8dc73636c517746a3c8a05b901e7252fef0e5023d90991e311b5382d49100e52633c70fe9c26c1450e0603e6d452299af4dae07
TST: 734
SK: f092e6be8d2d9ad069a3e2b976d244e34c15c28c48d32f5560a54185d1501502
PK: cfeb3e74e4b5c8356a81757b8f1be4b429fc18fcaf497cbf8d8bc0480ff978f9
MSG: 2c255fb25d45b086c071e03e525b4d728578fbb6b0c60da941e6bf2a4898b2d5b6988c53302785ab7a3bc4bb2c205acd27d6a4cbdd1a0c0889ded784264cb7c02889c5c7113fc90bbbcd31ff001432c053f971073cf6712f667fce4698776b98cc5444c692abd1288198be5ad5674609f7e139ad1b9ccb943f8dfd9d12c54ecee278341b2ee1277991ca62cd3bfe128d1392964e9588e2f97c321704a3de106188c5eb335aa5a19acc9067b4a94129b9d1a6167c4bbfb56fb97684cbbd720c86869e0020ab0776cdc9954feba862124b073fba8de9ea9a38eacfa003ae4f1cdcbf15c32fb6b970c73115ddffcd4fa3b71846110edec257fcaed6113604f7192572577264b9905ca6aed8daec138403ca41aa954278a5720b267b90ca163a9bdf447eade8deb769a3b49237a73516977c28734555dd234ca7de4999261bc7960f536ba8a35ad3d02c75f1c2bea0a0612e7d49c40397dd6af5ff58bae6a64b6a77e981f92d159e0b2bd205ab157052f47017a3e18aec944d0465ee0017e96148a6129f74d3ccb489fea13a15a9b9aced58c6ee0e6e84e05fdadfae07b334a98fc37f7e511cd5a44e9c74e478d349e30e29aeb46a4df01e4307fe65e1394a758f6ada2fb120225ccd50a49013e6c9f175af90f3fc8c57e7a6a969a916c3f1aacc22f3e01a070cc48e6fd878e2bd073df9ee6f059b98568404fc7eae7d4bf6fa16c0c803c6be84e8b79c67affc8c88cabdeebc1134bb2386e22ba4d2e9e0f3e1ab3a0dac7c80ddeed773cda0c41dc9defa67fea37769cb4a1e1522d7e0b3d7c4638bcd983153d478be5ecf2b6ab1b40124e4222b8caa4647bd50d74d203943ab20938d5f27d908a673674046ce2ef18e858b0a01a7e7530ded0f8cc89ef09b73ca597cf73afbc9a271a4d23c92fe591883c440109c4ef416670b7f2c5905b77f65f56d09d40250356f9b1dbcaf1ee2c0b63696f84d68ddbea160085151a9526274d7b846cceb6c4348098484de3bb723ae5e85276df49f5634130ff905754f
SIG: 63cd4c0ba3be9397cc0f3c1af348ec4b8a91e42fee675da1d05900b9a86c138f9174eb996bbdf31c4295e0c578ac0f9d537641a2afd5dff93a39c5cd9d3c480b
TST: 735
SK: 01a247943afe83f036b6b60f23d97774fd23208edc31cf3d8820e9dc63661103
PK: 8c97a58be0e847c48a6a3987cfe250a8d7b07d97f961f6b7b79e7d8042b8bd7b
MSG: 08d81495da77f407255cc41a818eefa727e2c47ae411f4b541f01f811d906d55fb1e3c9c484df30565364de9dcb9fea0af66112fe75fd11ae81d2641b547589f8b974a97e7976ed692aad640edd288bd863d11c4ca9836f9d7c115c3d98830d64247cb6f8fb603c6981133552a3204041961bdd83e2f9deba770c0394f9b602a453551074921a3de28321369d7f8ca640c45109e8f522c97ed9f35b9277a350e295931b42e0135e94a92fed363d6cae392f7c45199327e24b4cfa5898ab599ae7bd50bd3a00c0d007e95faf8f2ae103802ca7e53b279184d06905f5748ca8be1f72e668cb83283dd00406491f8b9b4e5a9d4a5438b2fa4371e0b05686f87575baa796e302f08ffc425662750a33a0c9cfaa4b4d7041f9264fed7be4f9fde2cac68a2158236f6ac43047e911f4c4e8bc663fdd50517dfaa8fbcd219dd7a0e9369f43d0dd25b4f0cf930f20b7b7c6db9d5be0c6e1960941a3e04d141c03e5961aa33e9024477d533c995378796bf2292ade922695b14569fc339b3d9085c63fc6e5bef4d990c80333a6b57af478f938e3ee738b1d129bd976afe686128bcac08ccbeb0349b9b537313bc7bf591c65d4a7123ad30bdbe1486b428084748b6507f6f5ef67c26ca862cf726aac140b861ae0dc74bb3c0b489789f17145e9a855a3e2b5daac418d8353733239ef69c7b565b5303eb87bd7f649abf40a2f135a29ed27e3be4c12cd6ddd2e5418a99974383663f5849bf3ce5532bf64a80aa521191d25390bc19a45eed1d3feca1d9fcc0db031bfb48e450be3d4593356d5ba0f31047b457745f21e32ebea3ca6c35f05d78d8c31640b0fecb9401165675c7f9cbb19bc4b5677c2ccedc4e7aafb84184c19199aca0db21cf5067dc3af769bcc629355ff7257a9efd71a6a92d130d35abee6e70605b5cab93c028fac3aa2344ba861ac1e8ce9a4b070c3df740d28c5ece0f1bc31c2d7d1e5ecc76104480939133a18660e4a3e4846b2517be3b8e7afafe078391d8aa8e5c30137e85d94d64a279fbee
SIG: ed2ced1a4fddb3442a637348179a6a5beedcb44c8e988ca26f78936d2c8db5c516d54b8c4f08d91dd7042ab6ab26d87f230eb2b2156f3ce2994fce7c2b0f100e
TST: 736
SK: 91fdefcdbc990d3e8eeb60170434da10831b03081f6afd0d7e12b10011e02aef
PK: c58d3e20b8d47ba455b912572dc840815e3d885fa5917d1da48408b9a9564098
MSG: 5b0c1a3a95e0ba7474766c9badfae34ab860e0a6c033a22fba721127f5bbeee8e2cbde1a1dfeb18d551c95994d21e3ebc68afae685444a3a4195bc755538903acfa6715592dde256e7a1b4c363eca71ef0f3a48ae3442d50d5661b394096b7ec27bbf52953f3040cd25b78ce475527e0cc59f1ef9ae2e0590431582b2df8141499829a2c5f7bbe3598e4c96cc01ede2f43b65605b488593709c094b5a042b28555fb5227a6d156376f3ff07bd5c8bc6804d39a3282ac5970ba08aebf7542b845f6b5c238c2ce20443f7f7755d75fe4fa16b9644ca3e21d91a9a87c686115748a16c0ae4ae4e16d1c71ae600b39cd25e5633b399fee7ff2e362bed25125c6fd5c7f5ffa2da2353fd35b784a1b1b0319774758b7390c44dcc92fca4201dfe1a37569de05f0664d08b90d6e2badc21b92f9ce872142357b9615080ab7659a246ff0852adb17dfda70cf1754157b13bc032b4c5deb8e1068b4692b93165da35efc9da86acbe6f80f01bbc26f575ec5af5b050e9828afde6c3b78e733eb5a912492f765bcad731b95e3ab8896b61758bf913b9a1568f9c5b46033cf45dcc1750da2066c608dc3d343738e848dc390cd474432e991d7aa2c5b2781421efe55e36b0b42c1f49ae277480b0fc5ff685bb5a31be3a0fa44823816077037548a5c9b0e1cc6c63504a407579a3632b3c96fcd0de5ea1e4d6e87c0caf7b6cae3120db8b1f4615ce6a75a81654f390428b64c213e727eec3ae7f9f42db906f4de1fdadd34a3da2aeb12b4d9a185f4a60cb0c26745f530b481fc976a093ce24a30916af605ee94b08785193a949d569c4b7ef59603bb624360e7b408d98ca509daf5a92a6d4015bdb6f97ad4ff0cf05c8f0cd5476a934426a059f2444446e5864f089e0f0675615910662d7c1e79a6c75fa314b7ba2c643b0d37653eefe593172d1d332c8dd64492eaf104fb1957baa52049442d10b56af8eae8ff82cd8f46a0494bec2fcb9fadf10cf71a6eecd0547dafdc7adbaa4503783f943a46b4ad0e6dd7f2cab55617
SIG: 510112223b33a5ab1564f7537191cd292a9dbd5a323d7add0584c1b0ad00d0ac7199c3fb758e913ff3d716c2e90dd90d4e8f59951e87ef8b78214a5175c4e608
TST: 737
SK: ef00b3c181f6327d02256751cb51c2c36c0c0a78076340548f5bc070d86d9e26
PK: db14cd32588fd741e8f42e5121cc811ad45063f28141e83c668f07d91228f049
MSG: 7d6abec7a11af67324ce17b1d20bb40c668a219bc95df05e325d86f88795e264d454fc5fa7d9c8aafe77e90a6af6b57453d85b970b552a856ba659ab31bd8a660eb7d3587b453e5c5fc6b79472b26e8ff7dd6db6be3572548b0d754ed4d985b8d9965f88b952fc4fa3b761ccffc35354db0eb9c5a171718a8a5592870213827d3691bae7fd9c63f20503e04319b5e953579de47e3ef8e1628549503cb4f6871ba25db87347080e531a517a8b7221e6ad84dff83256d9ab9a433de871b9cb9c5044589e67206b317a5206aeba96c92fd6094071c644fe52658ded9220cf6abd50e2305a1c90fd66aacfb38eb05eaff6ca5f85f429cd57716eb87739a02b64cffa08c4f685b00310b5b4844920df215a9f24a17613aef85fec94f511dc8a4294eddcea11c08c0b399a23d916383e29adeb98c65d41c705a57f840520fa808d7fd25fdce159f7a084d062974b30132a571242baff4196246d6d757b312e9d608553d2dc53b623b2e95c7538fbc5deb62ba73776d85e5118fa1a302d4d076d99e100f0df119c33fc66cdfe6fd44d71997b78c8f7890c707346056220d1e9de88bc173cf0b76cb302877ec16af46e4c31639f54eedc16da9d9eb0ad95bda545dfc4a732b6da9814136ab1b9392a071b022473b3490557698b77e7447ac8590dcaf4f242ad3dfbc0df716cc0ea753626973df08d935d178e3312fbe2a7ba9c5093c53b9255eaca29b72578e3ba1bdfaf0c9ece21a5dff6ea421524f70fc1904e9a2cf7c518bfcc7e3673ee87ff27e1ca2ac32bcb4091cb34a82a71563ff6a6a15da0ebd5bd10256ce960f4eaa7fe35e128886050d049fec3a4ab16d5b0c107267eae1ab801ea5b91983839da1c488c12f864d7c3a77f2b6ae27d540109f68d78364bb627183bd503917547aaf3b3a1809da02577b3f03a9a3f5af48c8802e297c8bb63db6a86d3ea727a6d7148b3aa444b8d168f38c6c8f24088a49af33177a344adab2cf6e08e0cb0371ed52bdead132f77e7ae3ee5d8fb17afc0a0bb7311b9560b67
SIG: 139f9cb99b995be6588cddb5051694838f9d82a60761fde304b0027ff86584bf65c73cc6d253e560f65525df04bfe146c83b42269cf3780f8bc392437894ae01
TST: 738
SK: d071d8c5578d025949932aa6bf6a80b1cc412f106f91574ee24654b445ee9a97
PK: 9bcbf7d2212fb62cccf8b6c76803a5ea24409da6287efbb8b1f0c7b30ebdd93e
MSG: 3e8ee70e51e56ef57f6e66b3a884aa04a7b4d4599fb9b43996b393a868093512ea741a0c6a94f40ce49862d2fd1f7551f4647abd8075bc1b742ad40e29a60461301224fe8f7692b14772782b4e896b63fe05abd5ff5314f9ec8075f28d908ccaaace5e905ea7f57a491b99b3591eea54a6b7819167749d38a047620676a1a7af11f485a55b7c879e6850380858c8f45c0c1ccbd7406ed099d84a7471b9350c4ddb28470bf5bf327d5b3c22d899b4c660839e104a0622ae85c84aa9fc7f0a2c7ceb6e691c49c064b5313499683e8e03b2115eda7ddad55a49f9fbe62544f914511cfbec6b84dbde7e80909b45fb10502e2caaa72124fd9456a3872f9592707e9a4c5012daa972eaf65fabe553debe825701efef5c756bb465e966ab68dd52f3dd00a45cf6dc3f19b86bb0db4a86e4669885a074696a67d8ea2118c766ef625f8a98026f9f4a3c5cccf9846fdc90ed93ec7c1f3c7086954fa2f0a4ca96d40184aa57545527a1f965c11d843c90c5a5e08d7c11f2d561004e90574852eb5046aa1ea7b61009fd5dd7d6242a8df58a9e8e555c7f4cdc130d6901bfe6797fdc6c39beecfbbab6625b2e4fb9d8000276d4a94fc6fc1051fefff5adeb724b87090db0a2c697d056664d991fad80dc80fab700b1f1f2ee27734ebc26b2a641c32a0c911b270ac76b0da5c08914971c9112463a70709c0ddac7910016f913f6210086d7255cef11955710f651889c83621dd8a4fcd5366302d6c9b56eefcfac85c14a9478b6d718075428800760515cab5f3d4455e2b970df9fe4be8383d70483bbdd756071f53b2f9c275c7c8512d163518fe555837514c86776c947f29a77570287446b69be40c8d4abbd65ef2507249b5aec33acb7b8bd3f35bc859ba4e37bdb49cf913d93989c4438d2abcfa388cc89d78ac06270656492e7528f29bdfe8cbb9bfa9e73c1da013fc3ce2105657613ff62bb0c3bf4dee3b0d2659c726e7bcd9e97ecce9247d4600dfeaf60444ed862b00ba11e70ea88d4f0b6b539fc9f36bb2a1a9ed2b3
SIG: 0c297abe0fd8ebcc6b771998755e2c6be07c812b5a80544957063170ca69432e72b60daae322958a2238cd6a462894a387eef65bf96f63f54c085687a502750e
TST: 739
SK: e9d486c29ae811b942e10d81f0a6716317b842c2c5bfdef55cc432b7fcaeb818
PK: 43a52d15b9f731d737b1c4dbc32227a480963091d2c6286f482ef1e8367054e5
MSG: 14fe1ed5bbbd76cc73dc5650bda92de86326e24d2f1f6224ba8568944d6fe3442675db96f1d8498f1634ff9b6e50cba9db4eb0b0b021b2becfce4bef33c4ce0e32c8a98389eca9e059a662d6f037c54aa40c76cdeee85650f089ea56e1383ab0f5c36f6d6645ff7e87667301f944fdc2ed35b0d2c35cb2e4b45636e7498e927f5846b3e1edfbd160a4aef3320c3428496bdaaf7d3ed56ef0b7254ac597be589a70584416300c1adcfba4f22cfd4cd661e1f50f155d172fa5748d296b29cdd7eb8121483ff1d9fe953f9451c7c7a542007285ee7246bc0fdea938814029abce057a0ecb974b12d360eab6afd30797d61445ad2bac7e52bce4346315f78eb87542d59528b2f6c56d66241cb442033f643d3d2a67cb637d8da95d4fd1234b031a3e51723a1d26e6f5ca07987321ad11a90fcc1d4e2b0b896650c3a7518d565529bea806a05d447e08d2a6a3dbf1a36915b2957ca5b40e58b97ad0369735c428bd6d69bd210044b651418d98b059d90c83e46011f41c032c5655a5ef21ac2c8c2bc94be07e45426a7ae5d47b45f27cf4289ca4ddabe08a12b910207dabb34a46ab75ce69b58e7e17664bf3359a8fb68eb032c9eaa6df873829f0e0848553f732e1c3c084b32b7af75074e7bbaa4eb5d7ead7aff97580109b60f4c792f9e2a65137b0aa48175b8115d91305f4c77e2d08e7e8d7e7785c966842c2e350fed4f9e33bf6e184c550b4b06e957414edf52fa079e81973458461fbb9b7d7d34bef150357f432caac3ae9f3dc96eb5a2d123e09eda1702e1d1070177bb220c423c096ec24424385c679be02ef84d09ed102f49cad3b1fd670679a39714ff1d6e4228d8d7d0e19ed0eba132f2128d47baa569a8ecb7bd48a826282f9cfcbf60ddeceaf1d02132c8affed3a03d2340deb787cd649c51c6ecb9ff75d7a7b4ef9b15139cfea2762ab18615197a6b51f6e75dbd04573a2448094d0cdeb0fe4585883ff9b68824a04b83ec91cf84acd6a7446cb1f5ee37d5df80f17cb2bdc3f3122a8faf76ebd06cfe817
SIG: 65191aa885ddab9f67271879952fc6affe41ca20eb3bcd86673161b03b532694d6dd88908eb1b1eec003cfcbe6146b4538e21df55969912a0d7d8818ad79590d
TST: 740
SK: e6fa10dbb478e1e36b35dfeb0250f63c08515070ae79b22f047e271708d64f5c
PK: e02e1f2bd8792ef483481c6d11f7c7c9dbdeecc9859432e7f279e9d173d31164
MSG: ad3160758d8c08a661525c95280a3718874969859f1cc918e34fec008acf23b8896e8d50c3c0512331dc89780f8b10fc349c675c4cd82a5df8586b43c864448fac00b847b9c98054ab793f63c71aa5e5248e22d069bd3f852a3b8c6e2ac8ef861d90bcd984bfca87583e59e9a7468f29b808dc2fe5302a989d6f2ecde7585cd9be4e4c761c4d4b3eeaf4699f6556ef039af2b80f9407605ac397351dd85595584495baa177b08c88d2ec1fc4e32d1c0b8d7e7ac5839dfb923f09b323e78eceb7e96c0604b01a19e49c9beaf4f25ec4a84c1a08f2380eddc3a7f012184959ccd19ecbbac65eaca155cee9ecfec11e7fee058e174fc4ed7c679f2c15631d4e1527bcdb0e3bb0815ffdffc0c856bef0dc0f5c8237f7098e26bdb69e8782d1ca5111ec3c7edb425dff8032026cba3d2e081b71310db9badad1ad02f1eccc537d874cd18c6bb01221f71ee66250d94cf8ecceaa96d3c57eea2b0a8ec72429d7606488bdf19ec3bb16e50867c7937def09fc783f20a2a5ec99253d6b240df4677dd2d5277b01c5b8e5bd6c7df0874205bc8c2fffdba1314674d31c9b2c9199228e19e0421834c1657d0698286916c7e392f0abd5545b963ac1ffa99721616c23796f85c34a5c664ae81d16b216a5b0cf5bc6b5a908297285d61644128f886f38af9edd25193d7ecc77a79994278da071f54495937feef5a51957527c3eec7cb0b4e8aa7a4e856defd57dd92334151b986aa69ca69260d1e2d7b53c05677ee0d216b28d036252dd3006debe1b6574a25e6b19dfb48fa64316af8fd68d7893b397e7db5780ab27bf8726fff605d3b46d800595b4624bee302c964326034b5234d175dfdcc2ce882e65b3d93a0438f692e9695de1f24c70a79beed25415ec5aaecf3391953b2ffd453a8f0467561a4a47ee144a43fdff83df2bea5f66a722b52abe8613f20c594af0982eb3f04505a52461dd034da86c36ca16217705c04823911d72a24769517633562886f250f2cf788b8f32864a9474f57e62e57de8fdaf959a6b72287440a8
SIG: c03c470359127e9de3af0e0ed7d3b19faee0ec140b79c299e2cb6dac0a3e7e314141cc854b4596ce4c51c7b0dec8a5c8cf0936205361d5365f4bcc07c4287c07
TST: 741
SK: 058e3680b8fcc0aa1490089c1124677f98d74b1bfb71ee8663f025f0d946cd20
PK: ec72ce0e82c6a3b21243d2f00e9e883adbc5cb63b3d936efa50c07cb929148e2
MSG: e63d14f5bea7a1abb8fee697746c2280dfd0622de7357226cc0742722a3229be126b083e868aeaf07d2fc97adc3342709674193ca281744e850ea15440050aec930e45d7a87b8ac8015c8967c20033a532d29591b135586ce0fdd2e668b5c864b3bde70c7e719ad241931251861933ffbfa96483ff82856748c56dc26e257d692e5134d82fc7191c110d9590d3fc751cd636b0c46f44f8803e59e2f93fa0cbe247a1a625b4bc2c7b1fdceb5a2b22591fa6137c5404dfec6a69639e3f632b5976ab9fe1c63aa3da9d52b044008f3ae44b7c364f085664323a88eb4583e87140f763782bff8819cf741a875d506c929d34bbd43007de4b18f687a758111128b1db86fc5ad2fb9fcad12c9dd28fee5ad10de0739f8efd9bff66f840b11b3f91c5e07c21452cab24242b6e32165cd1e69572bf216e860453dad2fd129c333758580bb7d0f19509745e851463d127a5f9be21fe549cae55d56b8bea80bfafdac10acd838ea8af31c007dc32bfd74082d9110a3e91e61e0357587e4ed32827ade9b6910a988c1d3b2dd22c0ee76ef35fe15e099404a45d4b2acab9123ecc45550a40faf8336b46c630a9080358ff8b8e58af0bccbd35010c1ecc12816655a5eceba95ad3f503a18ec5bece3a33f469dfe917e1c55ef1d81e5a75561e6bbd99c653a6d095b9f387911e40332f6216f956a35cf7d99a9fdd0c44c51e90a564f1c36bf3d40a7faf4ba28b1a120b3205fbac1a98569290be37c58bbd745ce0fb74835270aba2252adaec157dc42461221a2cff687b9e65ceb57c2d77700aea6320486c5b1bec9cc53e7ef9e48fcd1b7783acbe75a6be0267278812dbf3d2576cf7ad3911271acebe0f2c04602a080c8b96c120fd86fda282aa4e1c131fe97c907c15855f87755f511c037befad0f56b39f32a2133a22f3d5a9bec3443f29a694e97fe05e10fb8ef9991302b9e0d84d929a19eb03471f3a8613d39368e15883a7e4970b53cbaf2929d8de431b48b435d7533caa2e36ceab6cddb346e535e515c4b3db76de07d9855414
SIG: 5734ec50a7f82e48536bdc4370cfef2e150a631dabaf89edcf0fdabe4f5839f4f5fbd8df8ec4a3acd40a8bfb963d1855ff9274dbc33165b5e6d37a239dace903
TST: 742
SK: 51ba3a4f3d85d1548c2f2494a3511f3b9515663d7e85370fb6150237e9bc980b
PK: 7749de0210bce06d48f59b95aeb1528fd9b4e52cdde22fb8193bedd5df12817c
MSG: d18d0cbfc16d0f9b67f2539ad6207cd9217ad5ed0333cddb1041e0ac2bdd920276629652b49cbc9802593ec364ea795abcd1582085f55bc66c48fd3eede618d6369617100eaeccc15f249d6eee5bb2c43c01b0623fe603ceeee49b40fb7c53fc68473673c09b1ac77ea9beb7e8530379a86d69ecd1ff11813fbb88f692f05ef1320742b4fe7e06d5ba71656646cd7500de19bb93d844536603f40bd4aeeaf0c4dbc0acfd202b286b64afb83d4a378dd45ee3c1df6b3ef16b8b1accbc04063250ec47b86ae5a71d1dab38b5eb80d663faa788f8b59a754c0f9c9f6d906252af46ab1fffed276d2388dbe70d96ba6747d1fed4fc0b55293d5f787bda0c0df46a73f4aa7d29e1c9cc85cd043e3dffe057462ca5fe5c6470e739276f8b534c0172e460f340487a569468aa5890cc14f20d67d79c661e87febac6275971c3730807ebf175e0de1049bee67c895e57b71ab8a2f3cf3641fd548d09414f5fc3026a0a35f6ba951673944941cb236f3d1976dc69077d951450e7660316988f6f2a6fbbff3b37ceaa02fd6f0273bd803185a109039c63f2519b983daf6554253bed5497c0b0bdaa0bd4a1fac90026ade3e40c554cff2ccb36990e71556708c5c4039256ffc7337e5fea11f5e90d3e4d93359179116a85c24136ca34835cd34012e4d7ddc7b721c246c73700e276dc2ff9f2770b43c8e80a17f01d32680bae228e6423a880c3fb996ab8d221bc6274ac5fa770d205fc878fba9bbd776a3d79ed77048950f36dc0aa3ccd28e4756a991904ae051b8a4b7de3a1f2ad0fb45a33d0c68225841f8eb65b6a16e95f893591e1aa73a64f0d2ee938ab69adcc8c59518bec501c39f139174bbb00699e1a0f0e0d889aae543a55e6ac56d5204c1ade1f27d82a6a95e14b2d6909dda7bfaa7f487fb61959014b78795cb4639f09f0d329feb35ccf52edc2db721914e423306889a483fee876360ee326335319070c564f3a8b953f52f41513a2260883c38dd978a248604a41bd4bfc9e84184dc9e84d2589f4afff8417824ce5adba
SIG: 16fb290c913b20eb1c3d7b798249eb8459d4bee8125db2b3f1daab8af9d9a700ed798addd802dfcd297a412593cda7be9979a1f09350e86f698ac3380e341d07
TST: 743
SK: 7ddec526a4971d8912a6bd43c69f92ed86442b15f42fbabbf2d17eff98993161
PK: 0dfeffb2762309b4734e4ce2523cf1863149f7e19a7c147ec0899e110ca9d87d
MSG: e8774a45d4d8f86dda5c08802ba2472ef3c8d36c7f383ac04612a464382e9d6c07d8d35822c53f4388f5153614fefaf46374747b9d4fd446a864769a4cade843c1eab8574319112f0179d2ea9e3c195dc068f0697462b9e07c8794870f8fb8ffc081e4586afbcdba7a4f5925e9fd9ec942d8434733c2ddd5e29bbdfc7342b92868719b544088a48eba4c82f187ddca8f474625a71cf6b7aa5f081c74f7408f53b781636e7e9d29b07fdb6d9c35e5eb382db7a31a8ba516915df8dee9e1ad3f182843683e8d1dc5d8669dbfcf09541a43c0a04613381a5b5e4e71b23c5ad09b8eaa51cb938d0c752cc3d3a10f10b42be8ee7f6bdac8078568434946bbf56da70e7d54157a6efd4846eb155278c94c3888658a7a2f8ea3bac147aa891692ae8b23f1afe71ecfdecaa6c113b5caaaa19398c7dfe73facb4155fd6bac18d5df2129e8b2907ecee151bdd147a7c3e46ea72754de32ceb066d9db1c26e80df3631292b16174cfa6f1d9c0828b849c22d29651a73e910d9275877f464ce9326c6e4ed6b07dcb3a35363c1aa6472e02c5cd855e38aabe965ace9f3f5a4f5de03008694cb90afe416c9d48688de7f75cfe243ff7f41e059310934903db568844508262c899dfa750cd6a2829824ba027aea1b6d0177726a343add4ecdc5f7e6e909ab7de615ef2807f9e7d71ce2f78acff57eba79c3f5e07c8b661c1e3027f8176d28bfef767dd68d4e5d628fec0bfe88799341f306128734fad202aafc9f11123fb3e363d10aee0db5e27a1570dfaee47e24da473b07fee59a6c93f0981dbe325cd8cc2d2ed7dc17166b267c1b110536f2636bba34751a78f7f6298182442d83c123bbee4f50c5b0facff03e7c556ed9e64ca27c4bca5ab0de0d5f9c2cbb54cc2d9473a32df999390ac2ffeed3d4cba34973dcec3fbabafc4d54cae4e7e85d4a6e8afe45cacd71e0f2e6d04b4f9d3bcf43d3fa41e998ccbed0f150d5ca1d5272932d93eca10495c68334fa3268f31de522cb12a7449ffb5cb5e8f1462cd9b51770ccaf58b1e0d82ef929
SIG: 9e603b015f42871b78eb27523fbb7ce962fca32ae270e8e12dcadd25aa852b891f6fef77b59a546c9a7a7cacb55e1d32adc805ae5f61a69e6764c7c08292eb03
TST: 744
SK: 0b6590dd7c2f15f94a56e240169363c26732302b9d440b532723002e155d02d9
PK: cd18e032577c5576f223f3e3d8a1fa8e9a870fef09e9409faf40d7143e52fc44
MSG: 71fe0fd55d5ed1206f28ee16e419fab6fa66a251fa6b0601da261e429f55b8d5ae3f3c52a17fe1ec734b810ab63aade4447039ca0ae4687c2435f561e46c5b309717ab31e0f64076b2169211572b74e18a1f4525a64fa717a5edf149758129cb04035e7e20ba4005b74809dec644504c2454a77f99b20c5374f3cee7d8c6b68b243cafb30098dce90490fdc3b92f54948f424639e19f8f2020d15513daefadd9e9b12a84761e5ecea088ad561f06209fd4423fcd003fbcd1873ea54963a2fa07c7476b1388f9015d9eac305bea5a3de194f55a17b42d599e5ce62c8b7c19e7e7096137b9d0a65e63c1a3b84538ca65369a20e8822fff5ecb57fc09b4e6845b4f24d4886971ac1ac28c77580ea5672ad14ce4441719c214546d0736cb7ad0bd9fb5b26c6d9c536bf8c857ae42577b36341d392b43323bdae7dfaa491986872a23d827c6ef8b57e7d00feae3834c466400aad1d367823984aa02d2ef492914ae1127e7551b812559378305e4fd52d8bc7e4157ecca451f43ee9f54c82153c7dbfaf7ec35238773051b4e587db136957ec571382b90590b5d1026024580966b7252d2cd3f4f1625c485ba906bff175992188978f2d6274f3a031749ba7e702f56547edc96ec267b84892880d750d7310ebf6db241253cabe4b25a977458c6ffc9e353e62adf05e6efc0fc1ebe89f527705bcc26b701285610d98aa3bf23872b6996d3de480e8d09d783c4a08cd383c9012635aa68978b5006818bbde44f2987479bcb2b711c1beeed27cf09970a164e454f710822eef555c1c7bf9f76d5254ce220c9aaa716847a249488f9cdb44c48f452ab52c40f6d03adc8bf3f197b25e3d127830e74fd81eb14f754205b3a4844c596b6e3a9936ad6fd9e80a16320b381c3ffc7b69eab54536f55abe22c91d898408e880c6dbf0fa5648d517772caa5353b25db6050d753faf198ec1d375de0fa72180a93bab03ded7716cb87505b68ac6a35e73d0fcf34457eff82178952142c7bac9dfd872a9a82f85b24b88fa42d4be0a0ca0b2c70f4c622
SIG: 642d81acf38cf099a833a74f2d80b85448ec2b1a5ddc64470b213d54b7be6133689a7194f5d89792e16e5df755a4fd9ef4689ea952926e0e4ecb3bd481fd9102
TST: 745
SK: c6d9acc5175fa2b8965c158c56ba0a5a666ad2c740cd5bb679bba9b1dc509284
PK: f5cfca211b02fba7720347703bf1631cb308fabcdaa67429527c5b7b676dbaef
MSG: f245100cd2d31648f5f351bda564c9db4a35820cc30ef651337c4cd888070569d117a934b9c918e5df8b3744dd6620ccbc49f6b3e5782a30339dbb9cbed05dd2b3b8c5bf1546e70af636e6615c48b2c3c2d19fe35420df5314f63c4812b58e82a2a60b1802f38e505ce748017afa977d3f9b1b6bea2192acec73bdce12d65e684da4d8b41fa9a86f11086edc2d5296f67efc53ac84070fde13693eb2318f5a8c3b117c233422adcdd352f328f0ec699a4650c93f9b4a7d795d7fc2622a03d99b64f7b3dc3194f6c3b1b69d9907ce092401073f47a28f4799d229092a1b074129954be80ca4a3e6582ee05c302cacb7431d1ca6a451aaed7278abc7f78575241c2a2eea2e84cbf9a334df402109c028e345473a13af9b008e20bc8cf0bcefbb7aa727ec856e9925b4ddd99deba8f252911a590154b579a8aaa31f07dd5025df5cd8a09f742964cc8c365d8aff4eb1d79f6e5a07dac5f4ede92b4e2e61d34cc2d4f0aaaab037ad5fdb95de6cd5984ebaf7cce7f08d0ca0dbbe483ce3cb35cd790ca0427065a34df7f4c2af86efe9b765713aff257f5c1d54709527ad18ac33abcdeedb208064ebaea4835be4942b8fc666ad1b79b6651309e5ea1da302d7fba2e99f0e6319e82b9905a1ea482ba043b6800b330dc48b3313f59bb2f9e8a7f07eb1800a702745db14c6299a982dad897954445b7d98eb5837fd70bf190c649552c8e86feb7ff5b3ed8e0a06704d4553a3c2dd74f18ea8233ae0a50d914fe08fbcd3a1435fed56a9f3a7effa140fb552ddd21dffff7fa47332ddfc1e5317f4177d5e2f11a06ec84ccfb89b654ea81bd42d7e07a387301d0f40264abbf9f9107b30ede864cc7690c06d2e247a060bb2244ad78ed5c5515a1a2a612d61e3d931e28bc939b4d3435eee4f7331b1f0f85375d82ac9a77c43740032051746dc9269458c147d188d84401954a489cb4fbf9bf84ba7d8f100903ce67831b4054d0f58cd883d542c4933103ff070cdfc9dbb0fcc31efca466e77a33f1a813da6dc0c7c31585e8f4fef1ebf42fbd1
SIG: 4d2ce707090b0f3f41462fd75bd609a2724fadfe5ca390e313a42cab42868ed6e9a8914dc13909c0d6f61e63712957c76f3bd8b7f55349715a3a317515c07108
TST: 746
SK: 7dfae416419d7b0d4fc1f823840c3e4bd4adcd4dc2dc17b38637acedacbdbb45
PK: bc51d7745931317e1e346e2e7c92039181b6bf38ee2f5a44fbe2339c4f952ab9
MSG: ec843dc4dda6e902e9be31b70f11763b757ab6ce7334dc00764b2d084e9daf2484485984ee28a2830fcb94c541cb469440036731de80ff560f530c9d9e6e1f7d9c4c5bdf50b04f5403c29f76d7e36e00bbea35db1cc60da8d776526266c3324ce7efec6450859609266856d701a47a48dee8bf37409565c7fbfa99a204e5530c971c605b44305d5c7467894114253cf43cddf18b6296dd254a4d96ac7000918186dfd4bf454ed30974c553d0ae151ad4cf540cecaaa0b5948b0985a9c7b6e7815932bac11732fc7d10267f6bf8f1e7c08d650e567b4edd15ae7958410e42f1f537fa732f727a268388321d5344c4e78bb9a74eab9d6abf968965c66693d5f112dd4c14fdfdd96005eaa6757fa2cc1013fe4327ab0999d117f3dbf325b07cd454d4b141991ef7e23db5ee24beda35884aa3704808648aa43cd6256259f7d3db5e055311f253e8b57a4cda5afe0b0adfc364e160ca37e8dec6b95aa6152e5d5da6eb91be0e44ffe8e49533267b7eb795f5f8e0b2c35b29dfbc87585f22bd5b909dfd6a5edc0e3a9d97b0c4f3adc51e969937c08fd65f537aacda8f11275af02c3354542630f3920c393f5c42b9fc633de9d94c72e3f20002349ad0418035b3f25f02ca928e5b2d40a77a1c3e56221f4b9db0c25b096d6e5d0fe758da2c69053e8d086def4edc6e3453783ffc63a4960122d923671a906008bac10561ae6219d2b51d5367bf13ccabf5931b9f186eb109bacde40e1af2b56481e0c6dc6f5c5473f8001cf371919acb40cec5b962ebba80e32d6ebac4806d04d24768c2ad2e3f92a8cbe47754f9bf615953522b263dc24937fbd932c8c459eb8b109443af6c195a59fd2721b0125628f2b8143cf3c128bcec1392efd16b734c10716d96ba7d1f413917ccafa5bf5f83f524fe8406a152115ea770e1745e82e8b51d752b8bd785df48bfc12041bf874fc73afb42ca5d69c6416479ceb4aaa0492b6ff21ee12db2213a4286fd5605c93a7bb8a3b071b0b25fb01d77abbc8771489470a107aadae9f640c24dfd5328f60f4b7d
SIG: da34b1983e8c55e41fda8ec8abf23b367a0da606c8cdbb1e8b57e0343c0557a5f0e815e7f22f8605ae93b27d03776ac1f7de3d792ea2933ac22d2dc23b323d0c
TST: 747
SK: 709416074997b9c9af4d37a01139e8a3f9f2ce5d72a57d805e822a81186d017e
PK: aee110f1f4d46ea60649d786b150052e287a9da60122c47b0908fa8b2ca28a80
MSG: eddaa369c0e31a1fcc1da46f65362442a0cc21c7dcdd5cd90e0a2ee9f25110812ba114931c868a708607ac16084d79715d13b338c05c6aef7343e7dad282f96fe28193188f0cc893c7dce805fd3a7cd268b72894160b5245fed9fa9943b7c80adb3c2d1a353d8f12df25a31dde7fa385bbec351da66f153032e17756273f8d54e9a3b9ea25ae67d1e9c18cc68be601e3d68282818ce0e7cf88a4d1336453021732f08d9e76cd23637929b0911d5f8614f4842e670c142860afc265c50172b13bfd35ad8fc54b28657da32bac153ba9affc897afb3c721f48caa46240585710b0f2d24d5ff4965d1d10f1a07b06abea6a08e1d6f1500da12c434a6d778c941067108000475ce831bcfe2d0afe40b7419d07059bc0cd8dce4be9587ff29ad8bf0b268ae23ce0da5bb5bf74ff0b2b31b82112a9fd5abd9bfd0a90e6f4723548c6bb2f99dc061ba32eba2d53e6bc79bf441b23fb7460de04e8e8efbcd4d4cc7355de9e3b0861a681b983839d4488e551751f23e9a6e2e4d443273b9e0fe64d8acd1c748b5559438223dd21b5183189e0f3c0e8ed414c0356bab77a654de1a5771462ef14344970a491511a722914f4a89f4f1a827e18cd84479cc92592eadf8de2df824b976dcbd284a3ba64bcdb0df15e8f41c0b2471586b26a06353d905028235c1c6e5c4587222725af083e11e79c943aa444d4aa41218d3e974336e372813e99e2b0c5f0ae810ffed9a7a3d6cb74c5473d990a5911329b8e82ec6bf2bd4321bb487370f8739e7a2a4a53430833d45b9fe3deb93f79fc6a51d563695ecdb97858d213da584434b7c71546aae8d967e1c6d0082b10d4a72de1742e53c4b2f92eb8b5c8c35ab6535ea8100b37924a0a91d2a728d0f5642437aa66c82ab74b5d0745ec08f7705cb81fa079d89ecdc9aa1f8d7d82dc7746d34615343a6925dc318f352a2b45012438424f9098fddf6e61fd1f8fb49da40b3eece89a1af1996de70cd1696cbfd9e301ea5f4437c71ac2a032254c140a90e85fb8ffc4667fa139c1ee9bbf12eed906a967bc0921
SIG: 8e4b41f097d83614184ba7f52ba2fd9f0565f8a63721ef55f93162826b9f0ac070c0e2864b5ffd8eccc18efad18b2ce84be57c0b4a41c52e20ef37722377c60f
TST: 748
SK: 3dcb7ae7d9f0f141f1d9f07883635b913ed29fb61d0f741c9afd05a27b045b06
PK: ae62b7ee1b8db5764dafddd9724acc106d6c0a4d1e85d8906f7584b558f577df
MSG: 38116a572669070dd5863218c91a77a4ab47553688488c792838509e9aba25067adb7ea4249848009d914ae987a6032348c1c0681cf977a9552dd6bbf4e6ff32acc9fa61cbee25a39307650f8ba6a7ce421ef2f71bccc0958138f9324c86bf2e528fa3e4d1b19f9f2ca5268409b8cc19c62dd979b89697e457ed2d98bd2096f62d3d9e247388795927803e79ab71d4f72f568e945a8a162159d9b84836e4585644d4979f614aada73ad413a83391e9cf880c42ac2a98343b6a82cd2b61581456f6de5ceb24fe46b7625d52ab2c2c324ac74703d15e15f1aeff8055d2f739f7363e16ec1d78be2c6299436c8c8d336bd29271a897a6ec932ed08725be21b28f9aa14eaf4f71853154db14587c930ab3eb0227ad7ffb45b3baa6a999499cc8a6e45b1ab4d0b339782bcd9cfbcf88cf7eae891cc841e9c88a1f6a691f3948a6bc85ba7f4611642e84223c3b178946ddbeddcfcdef4ae4c4e1a814b9b1f02b1eaa824db93f44b27d14206b340465a1cefcf535c63e55c4287224262733d98aaaa154f3ad42cd8546a461ce0d46d886d3461a2150cb45dbe56473ff63d3dc7a2b957b823969f19b5968e8b424c879741926d82c6386753b0fa1f080284e5578942363aadeb21f8e1e8909fa6c380764149bc915b228604efc56d92e4beb720edc74c4d78f925d6cfdf7ba2f14b5623775810d2d07bd388c573e36523f215738e69114dcf8d80f170bfa676e31fb626a7d449ed96647363475970c8c47809709bcb5e7200f2a227c7c8e7b000f30c0bde61d67bd6895361629a36c8fdd5a56b81efbacf15c1b3530a08cded5b1fd457fbd2f03042f56f1b37ed15cdb912fa0298c276725087ee27d3cf2550fe6e8a0330af417f4f5baf03627ed67c5f8323363abac5a1fe34823180e3e0e2080f75bfd91c207cf6baa9a229cf443dd442c5902e0673f3252b8526346585872f6cd366025a56992b70ede39bc8d322f9c22a1dc599e9f0d524cb6d2ea5ae2878ef6bed4b702807f1e1e73ebf290eb6c0eeb85c13716f626aa90d364b4904837ce05
SIG: 09a1e6fedf971b3edbfaefbeb89aa539ca0b02b37e7ac4ea8920d6d4348ee0cf9a2d5e96fce517c665e7c38368baf24979249a95b70ea7436c00785f16a3ae09
TST: 749
SK: 297311ddeffec9d2be68ef7b2a20fe2d277e1d8e51648b03572ada27ec1f9f43
PK: 6a6c28e761640c4008333aae5a3366302e2f4677a953ba482ab6fb4a1d70b447
MSG: 2652acfc3bdf09a599ec6786bbd94fe577cf578e0263cc68d9f57a6c83458f80acd8a75ef03040a635672b968ff2afdb288d28b9996f6415b2f3175e9ea37aeb05df81812e38a4c976eb92856cedb91a269a46fca5df9bd730fd84452b4bd93577c61f42c14113979882a86a9fe632e4756afd89816fc4670a310503fdaad2db764c3721213c3e60f29c2668d4de8f42b087f25cd56c69a4e48f134f5598cf145be638a5c2318863329061729aac91da6a191fd774880cf9cb555eec15b0044f10e5433fb46a9b8892da8f6d24f142588b70ff0b49200c506b88bed449ad10d3f92c2baeda6bbf58676c5bbc67d31f64fb12e8d5e78876d5c849fc314b2cf8010c510204c8633d0cc31856ec6a114ea8a89c48927b07a31ab842c9b8352d9367345141a99b40049d5c48e7d27cab427adefd1f0fc1136b353cb01c3def91fffee8ad91e88f4bb7d2615c0dcc95344cd01950938ecb14b8446b56a06bf2f2f65fb8735e8a7bc96bb46ce9cac71a88eb8fda5e69d69eb29aa42a016b8583893e9d7277cb1359c5687eedcd599d8a46e6c14963637db04a929f4bc79304ac2dae733b3a839eb74fbe3de5042fd655eaecb15f39b2fe16dad8a6ff8dbc054fed51282a856e9da6316fac6db5d56f77f18da8412eb377e5b1b8f4cb1354ecfe8fe8fd54e62d767a80de04cb7620229a8831dbc9ecd4578ffa2ff06b5445e440d69aabc94c47bd17f22b69f52eeae5cfcd01a5cafe0580072ae9166b95743d68c3564c5a7e46f24bc48a898a1ab2ebe63f36851d2aacfa0c4f32d993771d314e725a43d9805d1371cf723ef161d42e63ffca688d7f0e21ef5b3f9a561a6210702b85fbd1f8ca75389cc7a22739bae4ded93757f1520dc38844a1a88be8e09645059148807b933770878cb8a9ad9211317131e69324532fd0279b83185b628fc2f9e21500384693fa29f26bd1b9c301601367665f05f372dab4e3107726cd3f639ca62bf63a75f77eaa75f7136157ada2374e65fb4fd349b45e25441fd21b13e6911366b97cfb4d6ad522b850adf40c
SIG: 4bf0b92c6ee4eace5e8eb10370ff9d9c68a5749d59899d04327aaa38f8f825e032e59742b37de23107a3ecdd3f7a0d08122614b78fdd37293c8d05e28f5f7108
TST: 750
SK: 4db2b58144a8d2d0ec03bb9bc29b4ca893854c80b64afa4af7a9c936935ecb04
PK: fc5cd750e174ed718bd938fa8ed99a1b9d556ba7670f2a77daf1c720113732a5
MSG: c8d1dbc936911e122cee18f92b16a39a2eef0823b227f898cdf5842b93d59fc002edb5498a20872e19554ef73999eb3a7b3e2fdd9070e1efa9228e9e93b29a868ae3799e4e572324836b1ad5aa812bf00f845bc217ebbc3fabdc4e1b6e51ef9efac2770aa0a4a11ee52ab956ac6448aa2629cb61dbb1f1edb3bde99b4876da392a6e0b9a0c31849a5890aea9522f56d015a1935015b91bf4c6a0011d2377d671c3d0d753c27f8c76e405d0230f1f4b9b88fcebba1eaf13777235e55324b7d3f81e686109d91ce689530b90d2c5c71dd18772b385d62ccbfd2e089a1b670983f60c21c4455cb9d1a0dcaa74c874e35211f8227ff7c234dff85ec0b07e368cfa50a343578395a14c68f1f89bd4ecbc172ef805e5831ec89475fcc8d685ca9255a77e3ba3c147508ec92d7bcce879af0abdd2416b67b5f50507337914f390bbe0b450b6a2f1159372c4bccea382ce3d6d9fb2515ecf7930059a0552b75f978862bf97e8325af24d1b8ce9512bfc7cef884232042341d82f9b5dad2e502ac6ac795f99dac7fc60e3b8639d0e1500dead4e78aca109957d577a13c1925d7403c1acf989a9de6711e23c67bf8722f551b774cada931b5fd973434e3b7172819883e70c52785e3b49d323d05636641158640dcf6a4c200eb2c13b1beeb2dc360352470d15386e59e6fa60367e5e7f172b21159d5ee7cab0d7f5868239858e2a93550480fe8fb4dcaf4f224c4b2ad5448791632df30e8e5fb998b35ea9aec8c934a4403aef82187ca1abf82a344d00ffb993d9ff3461d6fecdaf5d3b481e0d31153dbf6aed288c8add064e8331550141bd5f7a7e047b8607d846a6bfb72d683446a445114606250d8d2d3a8b9508bb07d4623cdf1788b5499e9cb9a1379849bfa19c9a9f4cd3d9253adffda25f47c811be833b02f3327ebba83730195d614bae6fe4e7a3830815d2af400d20a9417a095e7e8eea1044917cbe512c4018d656e2db67bb989c00e1e507623e8278d729925b84fb5c186a7bac189e6d6ab14fd7b62fdc632bebb5f77cb5cc2f707df4053099
SIG: 424517aadd853ce3985759a327e7760d9156d3b27345383f0e4ad6661ee4a3724d18d820f6c557f82797beb62d2f085433744f89a2d85293796481862ef8a40f
TST: 751
SK: c820413c2456747104662ef4dff3ac233ac4b91a76d3c4ea754490bc9b1e291f
PK: 8993cea2f7f2806c77b3981b54bfa9bf1762151b418e5e725371ca2c04d223ee
MSG: d2992f83924a594887e6ef13f2ae808fc8639c7b2c994faf0f795e36016dab7700a0ee530170f0b9fe98ab7588ce03bc50c2bae65e052647e756735b35d0b59c964e917d8c83e2f9fecc4cb05564287f0e34c9494005e25b1a8b1b942b54d89035f1b1c3c945fcc84e4a39efa2ca50959b459af74d21b6242e2f56518f70e8679257c089d26c3bb792687c923355b2c18ee2136d40cba45acb64240d9667f39dba3639b6516d4c4947573ef4ced876b5b2ea3489eaea539f557f58da204691a76e29c94b8b0538232c5f7d0bb0fdd016910431354b3e1e7ce62ad436917cd5c315a5be9b971c80f97bc9d5c156ffd64fd4e31da56083e02a0c8fce554db68674cb62700ba951752b829b03c542327412eec9ccc6a50adf47bbee15446682da2fea42048936d763060cd8f539652616dfa808d623ff777b4113652e789ec025b85e04efe8ad4c960b190bf4a5a6324d6f57c1ad22018c83cd7e7e097fc67b80269c13b4dd9701ca98f9876958ba7689c6f6f10a732a64bef22e8b98bd304d5dbf4fb1f9e4ca539a5c4aa619c44d6f58f824b2dbae77b7e83b56db5e5aa7b0ae9ce1cd10a69f04a80f1379eb0c474e4782df0e3ba6a148226bd1a662d95ee2d67c5207333cb1d54176d9e506459479029f31dcace269938f6bc562787841dcfe101f4db60bd66016e1eebb6bfbd9cd83042dd1379a464f405aaae3c11807848cc4f95c3cc6fa92ab4ea5305834eb86b873fa30ed1f7f470bf663f1a70cf9e60ab680cd1dbbd03ac0433b3d4bb482f8b344d46b3aa934b8633f57090bea5fccca6488799835f133f8bcf6e887ca59d19076d6ca19d4e28349051e016b03e9a920f4120fb523d1371d0e38467319543f127ed914b43ad062226a536582db728ccd76e983f11766a8863c2f424f65508dcb26fe0c5a800c35093960a121976e3051e2ef1a2a99c12fb7bd8bc037a439686806eb72017a071a91b3e39c90e86bc335f9bb543b127c9886738cb53806b9cb3c2594c7effc2a5920aa834be65c49f47964e89eec74728de771f3d675de9d1e
SIG: 7ef70e4a14954d509f117f4bd01b220bcc192d3b5fdfc3482fbbc3b69dc068a7c4761d1bebc2317d6db74f906a155642b0a3c6592bdc72e64eac6f203fb74e02
TST: 752
SK: 6769cc8e125617c22ce57237a4fca1507f941234661df74328d04ab62ef86c47
PK: 05112ca60baff79b4916c1bee2b9390c047af08c35ebb3c381b9748d1dd4c4fd
MSG: 685489739b98564749587ff1ac96ba682da30b40a4de24f54ec8b083dda45333162167cb3f97b2c7314ce7a3f3f3d319ccc35bb6a9f0077d563161e281469cf08968d9dcf7ae5fff830a5db00bc38010e6662d494f3c8647c4f70ce2d29a9da84610a080b5759a3b582052dfde66e4a7fa5fb27f065073fe723d83701d5bac06ca43b46d1e58097670c194a13af8b573a3791a9661557cbc042757ab8add0ef7cf4f35435a4212353fcb3c203c73dbc9d26852d0e91732e3621ce828929cdca4d9192048751922ed225eab2900cff971a2a2d342463648bbb1944319a8ef6d43db62480fbf1d7257d22694539793f25c927917caab25c1193a2d2b23bb5cb8569aefff4f0ca423d19bbd46fc5ef7524ff8cb706ffc47076509c05a8158af77f98df6a9b5cb3244aba4b5c5f9ce597e7d29ba07013dcac1911b6de7113c736a4005c459992979019a45b2dd802a07660909eb4ce205408170d82545dacba8686dbde927dbc9c7d962058e9a95ea66b8dfd3ea435357a93c73948cd355f6ac6552323f17c2a678662bc0e9726ad5a5251dd27647404cbfe61ceaafdcfc08a475ffd87cb7f597e56ac1670409dd9408ae4770420c6e5e6dd8e748fe03a72dc12803d02771d92f47e6e717ccc144fc037275b6f745dd30da1a45d29db6d9073eee5009cfd5462733414a495f349db0b6dbf2cea9ccd57238ed5ee91ad8bc86179ad5695a85a50484e617751de5ef7a7d8a8db950a98a6b7f7dee9d42a5df692fccf555c940dc39cf2eac48cb9d15cda14dd2a7ecc0b76ebec68ad4177d1117e07766c48590d43ca7662868eb9790ac29f4f2392b9a93f89759e7ba546b925bd86f807d8d16c7e637dcc666e90590bf430d986a67f1b0c7c2c94930845869ed8d8adde18fc1887456881b4b26b53dcba7a526f0eca14e8bb689d66f0aa1b253c3dcfcf59540d5d2f5ad617f52c30938a5a92ea385077d75aa4ac07afc2b35fb8c1d5e78eb295fc20fe37c41ac06959d3a1797843ad7056c1b412dd0b480aa3b39bcc20587d9a0fef92c6c950ebc5bb8e142
SIG: d39d853d2c2c5d21b5871ea5a75c041048d93a47dc599a5fddc0856285ce636fcdfd8564083d06ff284a524bc633cfdfc3b037163d674cb9bb5ba3bc25bed00e
TST: 753
SK: 1df7acfb963304e51ec471caf181102556783cb7d91ead30bdc2534d078a1488
PK: 05a31ffc70e4e3569fc2be110c643ad5f087913c7aa476dcd8d6e4bc7ec22d24
MSG: b0c3eeb57f14606ab7abeab2ee0573843ca22e6db2fdf2c9064cea5198dc5830eb158da8e2daa88857af8b8eefccf0c26c3ec0f330e92cff06bc05a29bfc99f940b61f3cfb2964b337097a6550a3e9a328c85be6f160d2c0a57ff6f1b3c5ffcca89089425ab6be0172e175baf40cf12b24a815f70f29a3a4cd0a6a132f120097752f4bc743ede08f5f21d42f282f7671f7783e27b2a8e2c14692f1e0e5de82855dabf98a1a63976006ffbfe5f5a579b460e26d06bd542842a5f9261bbf260451d2321c508932013cc6e904f79b5e4686d033e12c7bbd7eb1c92379c5ec341bf6457a3f17264a7c278b27501ecaedc361eba844442342b4b10fa94d265865116acf43fcbec965d2ab4bbbe614c4f90ab6b3e0d5383fa04988bfbb260307dde22d84098b6331d155141a927bb78d664b341d2f2a93e291cf79baaecd2612f6b104f3fc81373a7c6a045b5924bf950cd542f7b7accef3aa7d725de053055d951bd768111392596638ae097170f4492ba50a468f8e347763db612d3c7de7e56459b26ee029c630827a353aee73de68d6d72b27afd75d22164527945c7226844fab15b8dcc914349e3141c61316adc894dedcdc843984d9c7feae39db332dc393e9e8961bbde071c3d2858b3cb5f33b164a15616c6fe1bbc24a35f21336d261c5d8cf759e27e22c9101c4aebde3e126cf646ca7b2e03128095c5976bf3f6e491af0f0b640c7310966ac59c59fbc5bfe0548f88ee61ad9ec40c1c06dd29d794c44a3ea22c3d4762622ec1e8b333e45074db93741fda193c911f6db5879e55ee36ef602614ae64a5cde9d8306d22fbc4ae9c881a594bde6796125fcb628b9f3b6fb3ffd511b353f146a27272afd3e5d28b77f58a67f1fd27285c25ecc1ccf64e38d21f3b9ff22e00ee900629ef1a63e713f258883dd911f30c0d398b74bd797149be5e2696722da09d52d4ebf3c673929d298aac34ce05bea08ea9a424e93459c2eb8fc2222c31cc13d803b90a8a70bcd0a30c209211dc2ccc85b0bcd4582c695f58d80bf6ec471a2505f68847a75f6e911fd87
SIG: b181938de10142f32407b4e786cddde932eb11dbc0bf0e5ac509fae7a5bcc32961fe3448f912c8500fc6db4e1d3262a83c9dbe769bb8c3a761000fe36c0d7104
TST: 754
SK: 7ed87c36dfdbae60c940a3b325c19fded814d76a544820a32f286a5c0ad71d72
PK: 3c4ac510b36222c252a2dc1afcb40fb0eb85bca90391196a5883aa2cc912b2df
MSG: 62d313912abbb006b7774a6737714a349970ce0421112f400463d3db0e2f7f128d7b96939f43c1e7107b5118a77c119683d866b7e3d72ac21f6b4272b4be9289b6556fe31b6051a0b42ed5ea0cf347696d30fb8bff6b8b572719de19a231cc85459a990c37801f0837186cefbb5521569666967cd4243d7307f1b0b24c8e2b9b692317304fbe3dd0a263650191b35216f52916573af90524f91db1a92471d758c92dc6d14d1a4b26f41b40403ca87dcfabdca47b9fc2533578f161f3b0199b5c698e080704b21c9e615269fcd0d40439ed8bc3bdfbc9afb44c11fa89275f0eaaa5d08fa959d6378d0db89910d48f2d86a1ebfc5cbf10eb2d5aadf51bbd8344ff8bbb5b8afe05a45011b5e4b72eb864ad263e8a03a6c7f98aeeb354f730a318aa30fb56d33d80748c98ebec15878ccf3ce822f69d3456843c400dc56b481a95e688b8a4735bf3843f5833dda0efe09e7175b567c661387afd2ebc079a48e34967ec97b927dfa581888f231a98a7ed33103bfa8e8f9ba6513527900b39b86231da7911a2fc935888a75f1129584afff2025249c4188f09052f85687706d05e299144d40de8898b7c8b2dfef0c3708573d8b0563a6bd0a504c0b6745702b1b57121c6f040aff27198948ba69c21253a28d39eba726219beda1f8209fb83e9adb07ad409fbd6d25565889ab45123f9d945ecd7d9ca7028ece092e35fbb7cb3f328126efddac5d859f2b2c6eb090133690e20c17deaf3882685f07e9ed2653b803b9b383b70748a1fa92c86f86d6c47ea87b10b12e363ba508060f47ce2a2f3b6a3eefcd4dacfc71c41f436fe0c2bc34d4baad49574e7443c126a589f6ef7bca44954f0bb28ec7151b0511c23c6bc42d5e85983ec16bb5f50a382d688150a49609cbde5698e86dcbf0212c2292299dc4dcf87429f6cd2eec80948ce867e25c94584cdc64b099029eb854edc26ea21421eff48cf4e41f49e2d89478def06c42bea220a133e50f5c74464c7e73fb1c1a77c507cf6cda85be402b7e6d6d21e810d6d0b5972b9fe77e54e74aee1f3bbfd6e7de6b5c0
SIG: 579b38124bd0591a597cc9a389127ceaf55156077363edb811d0b65552acfcc677b272942199ca25ab790de6e084603ad1052ec210cf6fcb1417289067ce3c08
TST: 755
SK: 6a29f81b8d9aa48a1b23364eac8f6a4bdd607a84cfe8e88d90175d80643a58a8
PK: 4c3be3a2a8425ff31c3a0db4a52a0cb1416ceb48cc3e4c28a4f2284ab3460715
MSG: 7876a3f4eb69bb7e54e9ff954ebd3b10b93a4c1afeae92fa03c103cb6313a201c5b33a9a7223755cb510e25ec582b54e81b84956f6c53f1f08a63bf0c4a261af450e523fe8f61ddb3c0eeab8751072688801b2a473b71a2e38708da68c2f37925cb05a20c4283b3af97b6f0ba65a5403554375e215d9e3aa1b0f9fdb0f849923edbdaa0ab481c545a5df8f51d1f68b223507ea0eccfaebb5fccf5e3dfa65a44eea504568a88180a060bb06c51557b81e667b4b04e3210fa4c379876c49f3e56bf2be1cf519a7418393d240dc8a224c6c38ac2ab9d8fadfc5362030c7930c3ce7795b147c26c8a28c653429d90a173a86a8b18a009e62aef6eca95d39bdbe45647778a2532a415ae19bad231129127842fe1d0f11fab4a1cf0b17e498cd5952c939e090090287b144895dff00cec8d6aedaf62481a41783e021082ce352063e62811fd99990104d8a46cdcaee2bab458e5247fb023e923330a428c7bcfd20b08f520e8946dd658347352ae0c4be73c3d5eccd11149f3ab7b8052cfd95c35d4164546f5d8f377517a7f432c0d5563a7bcc7bd119d3421dfebaae844599b29b383bb8d5dbf140d9bd47a078b7ae7c6aa87b1e29236c9fcfd654b7f809794cccb261588e18dec6c4046a934067d0dfa03791d03d83b718ac4d24dce785a3028de0c9592dba7c5c5845184afc9c0dfcf94095860f0eb802ebea20178e78b5642e5dd61c33b39769052d9d854dce902f476e21f96c650b463b7bc3d0ff2996b65c57831f8b7c0fb915f4dd7226ac955cbc7dfb03f9b758dd3e0dfce2e0e580c91a30c783ff567b17f12dfd5d3137646e20011cdcaae11102dc716886cbf123c09488b173636abd54e962caeec97d5eb940682e703b730f61562cd14b9e6561b5e93f60cd0e1e86d1a1b4719c5b508242bd6b2d9a548f59bbb875075969ef2032f3196b8aeccc45a44d9dbdaf878ed16f1d855e8918ed65a45ee5c7fa32a1ec6932a159cfb50ffc87be06dfcf7228ae8870ccd357fc656e33fa4b6b8b7d1a7215553cabacc70a39c980b971e51a17ed6318b43b29bb
SIG: df09cb9b878d3dc9e542dbac28943e28e41dcecb92cb7ea44009885e46499743330561ba1d36aedd467675fdca2baaa4701b6fad979fd839c470d13c82daa905
TST: 756
SK: ef12df479d983ad96e8ba65330b36d49aadb983164e1c0b452b560ded1d08d60
PK: f761cf2826927a7cda8cb04faa2c59f8425a8f7d398f76e867021c951f073809
MSG: e58f34daea755ac4e41333d6f0ed0135f7dbce50309bb1956bc71acb12c77067a647ffd86aa5870c0c0007e8f995a22b88c467de225444544201c557495e253e3319cc5ca376d3e7cc1eb467346e52ad956a6fa733720b17117b5b7585e4d559409aaefa95580f91e502015f497c5cdcb7d4d561f544efa35c1e2a53b72bddeceec2d1050f177d480f687405664dfddec06eee4bd147a912fdbf74f2a95d1fd1e11268694ce4d4ec4fffd6ddb3254d360f236fab4d1a17f8d0d1a511f944692f239639ae03d64facec6538427ab71f7127f4a276f9bc45bba611dfcce6446cc13968976c8bb6d6fe2106d705922dcac956966a76d48f2aff4b86514e39a67e1643fcc321858024e693189833c8ad59b4b625298ebafe64626b480f326f1340723cb3d383f4fccbfc237a3f4c4f7ecf0ba436b32c2fe35179da93111b48cc9ea24202bdc1b2fb60a4319dfd9864470f73f54137206e0bf007f5ae88a88747008a60f4789ad167724f179c02b63aed002573d28a6bcf88e07ce8daea5d5f1acf487b4c5c16c2bfe11231ea5ea763e8f332cc73da1b2f8c198ea8173fd33d4b2ae69e5d4d1aadddf2fd821b85be45151962d1f99df81308618852ad7cf41d72da08a1b39df7d8b994b4ddff37f9dfe8f38ce30e91061d95d58f7ae826b02385272ec09f01a7b3e4b391d09bced665dad69505b419da8481bc3792bf8b8e7ad64b63f245666c8c32fd5c1b1b48c9951e1c21a1eb5f507cff137cfb862c2cc98766e878c930a083828c9d8db18bf16716685f39d6572a8ca8b2a514f77003d4e75bc154aebf14103778f365b1c3f03541ddbd07d6e23e56762d971eb02983e93c4e01ba4b8a2178928c4337d302f31c9ccb75b249a82dc96821e95a03ab6b770df2c3dfdbf1fe9773f8bc1bc5b3afa0440b102578f3d213c8d019cff124f75ce4accc8c667feb27c751a6120074813104e0cd070c9f5e451dccff4c80d71107c975abfac07d4d270c727d8a2fec349b533968e271892d2b62c125fb7974603c305ea3bfa30fb610fc5a23eb68a8406444391a521337
SIG: 4c8010866d9115f05293b934cac68104cc2c3437568cb9d5c570b1a8bee706603075537033bd708a9c9f3d1e2519a915b1c4ae4ccddfcf0ed0c049d342a02e02
TST: 757
SK: f731317cf5affe58704c4d9497ae860bbf739d0fd96b7c02efb6777b3c858a19
PK: d7d638aecce1461e314255aa29d9a6b488aea1396e9682695a470eff23f3ed84
MSG: 16f51c59e9aefc26b0da5e0085eb2e2f1f856def9725769e3af12f860905ae133f65074da76dbf25c67f6257d2dc66c05f9b31ae177b69929fc183b588c519bca14796a0896d2905fd942d7ab4a3fd9541a5529f729c5851419b5fbef7b134d6762eb97e8a951a8ff52aa0d7e67444d06b07aa55e4eb9ab892f47bfd111df5b62f6f3fd1a5ed84125feebb77da637c05d5265ced113dfe8782dbd1cecd2c6c032b8fa8855b3ae78de74faa5aa20a761463c2a30be66bd38cdec75f8957cb94c113a45d546daf475d89aa1482f8d2803a23c939202015a08e94b132728fbe8f6019d7168a08a5930170e5639d110e4739db85e61e64495944b5423a74ad5a8a0a510612ece655ce18864051525b908e0b19290abe8b1182c48c700d350515fd349956e8087327f30b6fc3f131c2144abb3f0e9ca331172b35064a82811a68e2cf36b43e3ad2e8dfa5b1cef50e2a60293fc5f635c9a9998d8c1ad296e7c78fc0582022d63067186b65e764828cc0f5f7632d5eef863e6c6d90e38ccc87d7b747fac8491d632cf7f54b9a9eed16eebec01b6cc33d2463f7f950d828b55ee3f77cbe974f48948eb757aed4e0dbb00ad95ee01323486eba3c8da886ed7f57bb400d63a1b2ebeaa2e70adf0379e3393001ba626c0dd54b7f0c9a25aae6c9875d4e7622f3ed428fb3124b29c5db9a7ef16ebddd6805f095f5e769823c43f262868ff43e3e0525746d9497af124a01dff61ec718af3b5bb746fcc08aebd16684d456ae7932ff5ed7d6b0f1b25c7adeef598b5d58877590ac1dc05975156796998774081e5b66822a94a6a802c3a2cd9f489e1628aaf4652be1184b0fc7c5ee7f97ce08b9233b4b83d9367be5f4aae9782593a35265154dea4c375c16f0caf6dc4594d2bdbfc3375bb2a0432c482f13941ce2aaab4d83e74d116f5de4ab28f8dc3d1cd19d271e56e10398bd1df5c870fcbf93a7d1df3939547c107bfd90643f6f5001ae7e06397ae1a271bb82a1f38e097bec667466b80ee3e50dd4fc9d5d54f18faf7a5b55a8834594ef0cb7e508bbd28f71fd34235bbfd3
SIG: 2a4fea98f9240171a1823f2f69352062672e6c6e6652d388a87714d647995df75b6e1ed1746af2adf4e806135d60754e60fea032128e35abc1f1615181125f0b
TST: 758
SK: 498e5a21a9b0c347ba83a47ac10069457f5783c2e1e6e4640045e594b1c69332
PK: fb3948c81199569105cc1b7d9ceb3b41a343bb00575538592e0984f4f4710abe
MSG: e4fbea864aa51190826645d2f772cb0f9eddd3034473fa3177c7af9a5d41e1a73ad5784c7096559fcddb7b7c85891cf24e82c588d74774ffcac0c6b4eebc2f3fa43e9d45f259d67564030cfeeab9236c665b650af0c92c875189f5f9383504b15360a0b9a5a00da31f635b96f6c73ef47b6b06f02811d1d19c2e8e53550ce22e42ec50a1eb2ea2f4cd03c442d4aa436894238ceb1835fe99b240358aa0562c249698a3f123c2c17e591010bd6fdfcbd7dbe70b04520502ece37a9a1dfa1ae3370417b004217a5b8fe9903c9a3b9f4b6d5c46c0ed0c538cec22f2dfcb2a280a42adc489cf2e062912be9928f0c060891e432091177526f1b3a968069d4a57ade828559810ae0360681ff99329fa0f59e7e59cdf87f9f33c40e97031b9f81d48fc12286efbb3d4e5a62ef57bc0d52d533b99c5106aa79cfe1793a908518596c383483ec49ff98ec557bfff7490a46daf6714f2c2c32f57932ca0d730f03f381d69decdbd9a7a6d4afc62406543c8ebe90ac76e6afabdb82492a206a369e04286d313e11107d8cd9b4bf68f815dba4e990b049d79216d3653138342cd118b130f66b006f3d89ac3cf89837048b0f8a62d94051d2eab891ac5f47888879d88e546676d1daeeb4d175d3f04a9d74ffcdd47746016f84ad0d112afb59ad12187e94f22535d77e9e0516fa42185c197ba774b393227f741fe68273f423fb0e0e0474bfdaf2da78aeb1cd5b98c1dc0832124742a4754125fc78b19c559a5b3f7711e068c440cc0469a1cfa5c1864be18735aa8bcd406c4371eb857754d908bf379b91fcb24e34396bf87c19a04a83d59dae71f3f3839829d06221301ef595696e719d56b79520a0e509929833b1d804a6a0ea40400bb45028ce5d36933883e17406e27a8109057b1a1a5e5da210a6921994f467ab41aa8f0d88775a8a8ebb4ec77d7c80e45a7bb422a4c00c90583911465e6b5f0fdcdeab72871ca542e1d1a2ca94df4ed2eabf90ded0045290324a9fffb30145470209f3826580989349199dc5ab8d4a25df7a0529cf91471e30842abfacd44ab781dfc1395
SIG: 2860830ccd1d41d95076816a398424f7b739c49fdacf5654529da85fe3565584f6aac2614c63f774b61db9081f1410fba8e50ab3b4c39dc06314243f3f0d8e0f
TST: 759
SK: c24cbf401ad03bd88dcc7b519ecf624db2223e990289309e1e9f1f8f6127c6c9
PK: a74666f357209f7189903788f107563e50c051c3d40c3f3dad10d3c3cff1e678
MSG: e7fa359e6a09b2c54aabed3bbabfb72853a805aabcf4d18ddad39f03f34601e55b6ce263c9a3ca6a3e5f1425c821928c61e7f750919bd3af32bcb7b94d459a7a9a35f61c941792e2cc2e4327beb344a841a07f32068af102b3de61eab64ef6d5e69062e393ab5edf6ac9ef7b38d49a01bef0003f421174c8885975c01832899c3135e7a86e5b55d9b1328bb4289b5c40200f49e5523b3c461dc7175e1465022297c3d380f2b1fef39cb82c00fd160f447eb51263fa25b4df0fca41ec0ca2ece7472201af86c3038c49df099a9aefa1f88d0edfd17c0b3c86046629c09454054aa0fb2c6949dd9c130185dfa5d903891e08742cd0429403f57f4052158b2f401da4756854e4aaf024221e37513cf677ee6a0b159f501d377ea32eb71e778004f27203cd6d553fda5d65e1879477046f3ea3d1d75c9d0d30311456709cc7f6ab68c7b0d52be40f04cf655655323285318329e84c6a5b07e0ceed5f78f7f1fa6229bef878793c584728abf4510b7f27794b5942916254c589a09c8e911f0b954211a63699a752147f2a4e1a18956644bea2ca2692ba182280e04a72dd89b0d1268500938f347bf43f2a242ee9b9a6baac9b350d656fb19ec834abe3164440f2d2071fe5e32c8e4cf905539b839ceeca2620fcb2a087f780e6c7f5e05c506888250ea7c856fb30983200aa8f78fc1771054ada0f3fac38ae2f33dc4a4f851b76ed740c0962a76a4de44080dc620a44ad8f23d3462b792ab3afb19cb8a9f4d9e59ad765a771899da8cbec89e5077e85c0c93126376c941bef1f8bb992d3a35f270725846fb252f8b5fbb7567e406a1b53b619769e632b2b4087cd4c276e5d58ff2b56e89edec48ce53a52e329ca1559538f10902c01a85fbb3cd72e6b8291e5fe639bee9d47d34c249a7a07d7a1427a01f63d60984c450bef819b19f65e2614fd9c2fae7b9231a0bca414ed94a5ee7e66327d2a99c84878b7bee087e891f253fa1fece313648c06c45db2d9f3bc8599937b752d38ce5063d0ed9a43ec9d4015893d43bf5b2d1c60478510468968b796f0153789595441722a
SIG: 581e6c85aec623b62b3d4c9bc9c77759d5492722e252d44c1f8ada9da2ecc67c17083273aa091bbac046ae63c78893152e14d926c41ae35f0e6e3959496b1306
TST: 760
SK: 8b3dcde4abbf4e6211c4a51c4b026800a8a2a061cb38a2ecc7c9cf113f9270bf
PK: 514535580f0de359bb0d41f2efddaa04c2ec950119f31634b2c1a32f195f6968
MSG: 481425027da672b6f26c91b80e55582caef47bb15a2de8fca852221785180b20a7fd6d4907b5881cc1d6e39ab9612cc74d6977e9141f7087bb27ab3084a26285586f8411db1f503adf52dcb25ab8fffd2ec1504c1777b9d6dd4a29e2019e5cbae1b7eb26f95bbe07d90c2f6fb0884a59a8d58dde5116edc3bc349d37c160b27befbe5a5c181ce7256392354d221b58c47eb0bb10929e7421795f4b7a7c275edd08c088568772e993218dd6f3c2cb4ac657a0a3f91f3126b991adf6cbe7d1b19b8cd83be3602ed18f039633fbd2387bda69e2cf0387d8644d97b303fb00639aeee7ae463f6fe1a2c4b89aeba3e9094c11fc29114b20283f287c6dd28cb098dae8dabc48e85bb59c0dc6e78c956605cb7cf06942353e7a22e96f80a37a66f718d9e4db8c52452aa0a35772e81ba2b303205b412dd2bfc15ce9b436f99fbb32126b63ce9cb43199f157d81751a7c4937d13af4c582952b5d606b555b046bf1de06cf39b63a80287371803609a387ee80f3a5d88b9d6219650ed17d3cc183b2c70d5eb94e3bc52aea7aa7f53be0e20b8972f143d8e20162e803edb4aa83d5553fdd553398b0fa176b959cba140d6e980c9251b0fa0b65e908417f82f451ff9f2de6b9ca5e3b5f41ba40d05a54f3dab4886aacca05c9c2798139a4cb33e96a91494749910a17ce8b392fc0fc7762974d79d33db924bfef8655a723776ff87f950fdc568b1e526534541f572723b840663c19188c424f7c489235a424b09fe25c30727ea1cb04953d706d68bfe12100ef6f64c35c6b8de67edf0e3ad014a400e821ea34024321999867b43c82c450184b78f7425cebd7319dc6f65d360665dfbe7c36674dac3a54e96da910c02d3640780b22d512ca0e3ca3587b94ea9fcd7a31b4af69fd6207c68fed25f89921c1cdcdefd1c090204492bff9bbb52e08885829d012bc2dfb4fe8c35e59cd13bcb8ead34193c40b03ee4d825ee1322ff4ef071279574cbaee7c07f14be606b9cd0e261111ef20d9681d76cf78c89a8c397d6b8dc778f4984166ad5df3a81aaf2e6de09f700195ae2c1d4609647
SIG: 4f3d4d228503017e74a6bb58aafae35c3f37bdee4ff6be2e6240b5082feddb222735e12f31e056fa685447e5384803007ea7910e605c1b78118cd5acc587a606
TST: 761
SK: d4a7a9524d30a6337c0a0be95ca90591de9888038e3e59e1b25a4181ef946629
PK: 9fc3ebd139cc5b7c0e05af47bff6619b812815bb01ceec392a3ff0aec3811d2c
MSG: 171980c03fdf7a727bd5bab3ba0945e6ad5faf0a7f506a56d1d0edd9a306b3158d843266d3091fc1e42281df97559a2201f5bdddfe683d0e1028d1d95b2f313b484c392ffdb1cdf88508afde3d6fd2a12888bacedeb79ff3db40c9ac0ec3fb901b228698adf8d845ff4fce10de55d42436dce930973a34be05d1401f334d4ce8e3a793799eafdb94d0f2ab0950b079e6653eeb499fc7447ccbeeed8dbd5456808cd7a38f9a15a2a9c738d61334cab8ceebbbf4a4814d94c61859178784604e0c2154597e72cf587cd1f5dafe5922051890e76d616d8cd5b05d6478d0626ea83ce808c46143e6fb06b4182d228da8f6d4139eca5b8f3b1b98af68c59b4b5a53c136ee90432aca2bb915529d26367949826233b43e55804b55fc9f215eb0b0b79291465bb34edaeadffabfe6cf41bc07b5dd4d0142f0361f058ee1b3b9fcc196eb9b35b134be3d1d232004489e8f6993f625a63015bcd3f1e87588324858ccfb770dddd894bf297bd763ef5828e21f5c89aa98cfbc1c082dd7fbaa4307bda40b4a758ca8f39f4e4aaed309041268dbcf0af32de0d7fa90a523963b780b6a932cf89499025f0e0d0474c74348947510e6c5ec7c9e05066eeb4a73520c3d927c39ac26ad7596325b2cc47c5e82a775455b7af03120b1cfbfd6ec3fc0c3be6078b00cfdf8342ae8bf147159f50e9d564e2f68306dae3caedd1019f323c478a1e1f67598dd834bd1d1a8733fd7fdd8a876526c531518936edb72d01656b344c7d65ac1cee37ce5997ba48d3f4d064d88057efe9a482d9e00ab5caeb5aca2d660e337bd15487365697956a5e47b02abdc30d8e353fed4e1ac41d2bc2120021143635935c620186a522bde54be0446fbd2dc88b56304b3a64227d0acd5f85a6b6787a3adcf2d7cfc86c634b4d7ab4315b97de9e666cff3ff1b88f3295e7bab9e9fd46fafddb4f5fac51cc0170129c651b4ef4d3950d6942ff020d1668a528bde1da936c0ec1ae09e84f8205861fff491502a872c8154a96e7ea25eda955a7fd2e4b4c7a8d273f60bc74fab7b4968ca6f75daea5040f839fd56c2a980
SIG: d15788bcd88d1d81b9e61d4fe26ea49e66819a59d2ae4832321b814d5062fadb87807db6852e1d8295e31a291b1e785d01d834895f88f400df8832c1607b5b0c
TST: 762
SK: d08f4babba3b5365faf738795c9da45db1862cb28b93eb6635d1320da0f4d937
PK: ef31b454f734e52b3438ee2f1cbc35631b1969de54ac98fe4633f2f500ac8712
MSG: a394d8854ceb5c43afee1a48926bbd6685aa8aecfdcf854133333974d624bf2f1f9c30f005bbf34cee3afe2b290600eeae6f1dd12a0c346fbb2ab9c916c5d5d80dcd87887875a0ac847678039fdcd3a9793541f5d675143a6abadc3b18f0fef5108c19c2dbfb59710eef9866a4f3f297a09ee48c6803007dd6ba8fd4be841cfb10ff0514c30fc4dd49a3cd43bbd16e460443a11afe649e901d63d89af598aa686b2f607ec11f35e17a798a4213b75a38788da4f27cf2b02caddfe61c3729a87ec6e6b098f68e7aed28a800c484dfa0130401208f986d792f54635add2848e151262a365eb21e2727191e1f700f3bf5c73b0fb4c546d0048a155c18717920fc0425c8c8fa8f167c43a277bb366e0ad702c89bc5aa06fd470943be05cb9e3259787229714c30a4e87b00a633aaf7be6b5875010d12e107c9a5261ca562d67025bea0fe223463edb92ea01cca92c44ff24da9d8a80a6421f3d4135d647d1bb0fd988c46c8a170ceb4f33fff9c0ffb6abad1092c84dfad8290898b249516a292e8da96fd51a81005eecfdebb05933099277d073a480c3f9eb8aa11968c4d8dc0787a9aec3e0527b7fe4c0635411335a1811689e88f6d5ced0d40d6b48b7f2d992952934894153076a8d37372fa00d9cefc5cf8c26adb5acf325a01cd005ab8d474a52d67114078c6516aef804bba19b887a28ed5e46ee9995e5ad3a82fb9cd93283433680921114b4d9af8fcb6b2b535839c36de8df12b17ea6ddcfcb3334ff40e6cf04ccd5ca6403ba0b62b4cb71bbde91d8babda69152c9c93ae769b5529c8d52fd9a6909a15e1a0601a714649c96ec996c1706d1021b97487980d7b2c2a39bbb0e470d8e46ac4aa609a0922c9bdc01612eadeaccd5fa523b2a8d0e62ffe56281647d61fffbbc840535745d144259cc81300fe99dfbffea6b0b9bcd28473982d32e93ed46634a9987906d6f48939d8dfbfb37d33b888db608cb2ffe39a8cf67b72644611c7d32a4a8df612468cd5e5d75fbba79e638aa1daa28c4e0eeb9a637ff8a08b65f7a7612414df76bc7b0b56b5537d666facfddaf65af1
SIG: acebe4c86fa9fe2c1a5c576ac0501e8ab0f640fa40380536fcf95059d53d4a3555d220ac363587175e4bde163c0d00650a12963d46766c99bb62bf7573e2870c
TST: 763
SK: 8f474f88cf863c485456a5a2155281ff27b28459f63bc4f1db00e0031064f649
PK: 43144a329d751d04e07169b779ee920dd029cb445bf376ba3a668572182344a3
MSG: 840891d948ec19c8c7f7c9d3c4775362a544a0ec97457ab5d14e125dc54b59c8dc9a635e7badb6be73c3a58dc0e9929f2b420d8356d617c3d41bfe69b4e158d4bf08fb17e688d3cf3c948b69b35f0b6db66272a8eb2bd410d6509f6c828b6a20d6586eaf857601ed9d6054799c25320eba8077fe1ae22671b33a1588ff2b235d3c71a27ce5c6c66e18889198d116933676bc4fb0710db7ff1ac2f20ce369bef56b43cd1d406cefdacf00f1f348b8ca7aa614db11a3a640fdb59389d1a6a394755c133f1b019c8308ca5a951e73b810a180f6ff25b29dbbccef4c13a97503393907a2dba096a8ce5c86c0ee6f97c1441b8d6331cba53b19606b421af52f65f9c663e63d3982718f948c6bae961b8e4bf8cd9e31cd09928e4e80616597ccfadcb8a614154933bc37589c85c776e34e5a90660f59a65b5e93ad438842f982d02b041e6dbddf171099f8db70995731a0db8c4625c9bca710805961fb176dae819768fcad7ff9bfce36403ca7f783e7613726d7dc59f24e247cf15068ff3b19c725fad65ea8e8a7f722d528c95fcef1c0cc79d18ef07cee8b011eeabd9921634d76a61a8a3c8931b827e8189881f81f7a175f21fb0378b8188e58bdb2017bef390f1800d9d74f263a81df8e67522d092e775d01e004e7f8d8281ae2c2fdf8c3a445f9eff7fdf13f261a773ddf2dd9cc6ba5585d990c995e6eb89dffd9ff0a9dbb76ce5e10dd0272d5001497881366f5d636a9cceaa283228d3ac614db217ab891d6689dbeb950e1200c3de53bc5da07f1d363dae9be6ec36eda6e687d26290f7abca268a7fa03d9318864eda9a11e3b26140605920ac13adec1b5548c9a7a3215a5876b7e941afa1cb5d7f7f0c11630cd429f3b2b37dc76c6cbea4f3b726aa8a5f8b9f705b05d7e9451956f8af13ce0a85955c7135d64ade5496ea542e70f8da5b573aaf137085dc96c6927099695672668b3c7c6f93c977a4e8e9e770295f20d52dff187f8dbb25ee7e774024eb9be08121ed74b6d5462f4bb7dc2003874caa31bb7595cd93a99ebe1eff928bb5fcb9e9c89dd31d487fc0e20bbe150
SIG: f61f7807c33e196d0fe182efa4d4516a9815ddd449538bbaa6b86b6901a05f5ddda0601ec90f39f1554779db7a09a60572effd4d128d0d3c2dd4e883574bc60b
TST: 764
SK: e42b30d49c43c4fad83dd51fdc2a4ac5901327add800b66972c8c70bde180adc
PK: f734aafaa4dbaf315c258cca8bbc1d4f34e83601109874222aa05589f3a6635f
MSG: 0d497051861e22d8a9c60e5f7de6c895cba335b2e82e602118ad8342b4d4edaa80f95efbb59cfda1fcc0291725700e8a81bb12a0b8623b1fe2891b8d98f7a84c59fd92f8a7adfc065042f7f4fd7e1a79f55a1d4d5e54e04e672f1c9e4c4cd8d0003f3cd54b76e2163dd737acb2de5c263ac102a48f696b60caf9be39c665cce1e0f3d498553f579061889a5ec5603e4d141cfdede8e7317572cfe76a0f48e4ae06062c9157b5eaac3468938192db4b16105c7364a94432b215a71797fee14c3c9ce2f746ed790302fc41dc492d37d9ef024ab51da3bdaf0f81d9a930aa0e025c04fd71026b6afeb7ed01a91a1efd6c39f5e447c66dd38a7656c613d02126f3585dfaa02df930253f83bd42196463ebc50f8cfc949ed350392e61ceec1309da15a432f80dfe948e261ce6d8421c5459cd21f3ffa2edb500982b2abfa52e82437ca230f609116320d9893eb82a14df72b7736667516fc012b28a03c9dd88ea4308d8ceea44cc604454cdfa2c797615bc0a6b3e0089af0a81be54d1b110a13ab911b452c342800cee2ad239a2b188a7fa875e941daaebcfc88b70ae4b1c575cdb6e6d89448136f60ee81c703c47822d2c0e50c7f1e8b7fc7ebd80789fcd7e06c7e50b5fc8b776e8b9a4cd5905a29069bc3a558d7cabce2af4f310767d5b117e3076b3a0d527175543b2ccea28d5f716fac32efed3d2e0276be44a8956fc8240f2db3397614f2f2da02166694ec6a7feec6ece39d72b64bbc6b476a4f84f8d879380a38488e4d6e58cac0390ae25a5fcb73d47414b4c26bbb9b4cc66e42594bd56d841a360923491d117be2c6eb2320f3c6175e44e27b6653c5dac6fae73600b67960dca50aa855a89e0ff511ea04f143e89f1da028476be4bf6d94c80ff726339e8bcfb7dd9f8cf202259c0acb6276c281e3847c2cc8d2fba84438d2d3c6031f2a7b95c1d8f9f3cc86a5eff65cc011de95ad896858e1f7f6d6b94bf49dfff5de2d7fd71ef108134285f61ae475483442dc90bf013faedf3771c47c5b96dc3cf8e48510060ad8d45fd5461622780d869d4617b57fe3cb5cc0203153aae
SIG: ff8e076e343c8b73aa453bfee9b2bab6d5c2f74c35e1bad1e52ae777d69f79764083f994368a1ac851a641cd247008a34f3b608962f4dd5109ac71cce978ec02
TST: 765
SK: 5cb514217482bf42f611fcec36a5286807c2bdbb56967691353f54310e1ad553
PK: 280699003d5d3e1c05ad10fb10959bbc595cfe213069965cd8cf39dd426a0568
MSG: 2f57258cca7932e58bed546cb0041115bbad23d18346ef7ab5e3110082b3a9712f6cbe1270e6dc0cea3364a06a5f2f283ec39b63058d34d59979072fcbbd7a5d0f442bbdf082d5bfe2998aeb51bd26127803e5c796c38843200ae2f6e605af312f54fdff17ed1dfaa89d28fa67dce462de4fe25268212b282e222a443e2f31e269054171aa73c719a896cdb7a539dfd1d42991978197d7c4f2d30a641be34bf1380a4f4dc6d9b101636636a496beb357e347c1666516df8eb560a0e0d1e1529ce36a60e00ed278da3802be192342989bb611b4e3cbd9c37e8cce07efc12d29befd7e2f3adb13d28f708d97b63e107482c862956d7ce8dfc2af5cac8d51659267b0bbeddd5efa414ddeabd17b23ca6e843ff49effc82a5d07e36a83b67c2ad7e48eb9990b421c5558009bd6934e86d54a8a6ac4078796e305c7cc810d3f66ea6b9504fe0ae6757c504c5552530a6f8bbb52409be079d8e4a28a6fd7dc8935f8eb9498adc0f23d0807ec86295f4898f5d05e150bdc43aa8b7bdc893a0a684c3063898b6c95e7d56a4c102690438e9df99758a90f47c608dacc4ca240266faba35fa1eb2eaabe288d2c2ad50b6cbf107c002575e91ff472a4417940667be8180173854c93df84464bcd312b7a7ae4dc2b9059fbe6f83f53806425bdff031c6aed6efafd9de8dcd0dfabea8e6fa681e99193fb3c647e442112c9a23f596e65411d8d6bfc3923004ece91ea6deb881111b1dc29943f578981ee8c3bce8525f78565f34b85ff20015feae846f95b18700bc5cdf14b2db6cac69814d63d74bf20329303e5ca9f04731f6881cec6d3abf87f5eac08734faa34cff4d3cd9a4a11d7b12f73253b4dd0a43178f0d3c19c0c40d9ed918dd17646f616af79fdf6194262f0fa4f71b3187dedca48d9cbcc19931a1519677456256ed38354567c3a67571cdf82170a2c85bd2c5e68e05a0f3b93903f191b894f84946f89000568054c1cea9fd0b8bb55019506c54341c24931984548ba458a4d813089896e86a2dc33d94604003f354a7cc941c754aaea24253cbe4cf2147ffec5e7b950cbf28e284481
SIG: d53ee2e0f0fd657b2052478fd15df1d38fe0e93a5483eb4a6e7de93d02a4cd544d8fdddcea822b71576ed02853d9a6b14e1a548aefe90d92f883792b7f1d8609
TST: 766
SK: 87d3ba95c40df80069b1797ddf68e866e66d46c51fde60e768a9dbc5c92f57a9
PK: 2b812b2c9b60ff31975c429a86736dcc17a58d3dc1daa34623a4bbcbe2cc0581
MSG: e11256f82ad76f3f4a49d7bad3ced8718d36d2f2bb3d31bb61edd1ecbcee6621fd2eeed3e3deb597b149ff71b851f61c8c6819e131f9a2af7673c3f20702acfdc8b8f9064b415c9a3e35568e371d740a38127c1f27b391b45d07045aeaf00a54e5b7fa548afb5f96feb5f5b44f60cd1707e8fa9567f7806e15f6a01aa02077733fe738b08f21efbcf98c19d5b970e6163e5fe8f4800ef9ed22a0f9b5126ff1eb1c7d65019c8b440391927029b813dab7c7e863d48229f8df85394345fcc88a300f60a8d516d877a5a3a7e3c49a9eb06cd9f2665ce2a89022962b1d49592b09c7543da835ce63bc9abb822145762b71cbe150292ce5c8704e5ad34fb4592f972044e43e69f0e1672d6c83cf25aac68efe3d27af2ad34274b9d2b77742d9c6dfbd57f92ff64d3e4c67c541d8502a7d031895af85319a4eae2d254335835eff11e7a3671a6a0d21b72ce1fc2acba1a920183834bc0a4b73f639ffcb0f6b81cd920f2e9420d612166d5682a06060ea0b6fa695fecc7704bbe4b052aa3ec8f720f7d4f32e8aff86b80b8c1cc12764a04874037c3103e9dfecb8f7abcb0e073b23e67ca0a9b1fc72993abf31dbc24a8fee095b3251c22626af5dd1b6d34be5ea06a02ae176c7b8cb9d063501be6f612082889fdbdcbfadc33a0d311b080b8d64e49f16b16dd8edd3b2ed1193a74e5be507609b042727ccf08afb05cc6c50524ef0e2664621dc8b05b15ffa81ab6f7e3c8a5bb3eab1f68e3656c119d969e4144cf3285af23c04dbecc038aefd9183c4e72447b2aaa8315f4696ce6d1ef429ba0e5c3d5ffa7f050be39c7f612f4e10f8ef070df72f8addbeaf3339c1ad8b5fc39a2ecf29a87f82e29a0117baac6625ad5c80cfe759fa1dbcfaa12b374477d80bfcf06796c30f2c39cf0303d00dc56a32d1d039592ddb06c22aa068841c0b46fd48df8fbb7492ccbc590c563c8fecce4263c8c7539218bb97b35711537e988195dbf5bcd5ccaf06faf508470977a5358e6f02608349fbb99a23fbe36b8c97155adc246ad7d93a8c203f75446c83c4342c35ba104ecc67e669db4a95466ee68f458a
SIG: fa0d12cd53236c41086bea8c0cc60b7764a3ed72bdeb9d1ae5eeacb48811fe529762a2c6f2bb06d9b318218d968f644435497a1bd0d0d8c1612ab8996d98d707
TST: 767
SK: 7c27ae47072b0c9b9c2c351f1327899895efa536c9c067d0e0ce8e82e6292793
PK: f9febd121e17db7229b56709021849c35d69fa08b50620e667f842ec7ac782dc
MSG: 1547876a988d1be714a42fb91cb03763f1913a892ecbd4de2ccf8344d20758b7b6d00259101fe97225b297f87bfe222004325db7f632ceaffbd134c96cbd57e985bec8434f81a4ee6af85c3fade50e4c4ef20cb0393545e4d4a86e1fa39aaf333fe4ded054bfc050a8983a03dd1ecf2b5e9517baf9e1152129a8a75935711edb20af5c8cf9c694a33cee451cd950b2fff08e3158c5cfb7b15cb3e90d46f494b6a108d8888d5ec29a33c066023b497709b2d9401feaf2e74ff26c16d36c39e6517ff954bd98bce7700671988f66e85107644ba2ea007a13018c1c144e3c5bb80db9511fcca4101bf49f8c80ff3ca7d298257cbfea629f83d5e06639d31f639db4b8726cbe224d758829bab10905171c9c0ec370d58031efe4cc5ae72a495acff6cb2ed9eec658ba117088dd3c6ed1df8f9cb10bd4fe0e5e8ad9f5034e34652d98668db15c8533393a6e9ec0870c35666ce54efe2bcb45c34a7230e6a700676349c7b3abf31de7b7b0521f89b30ac4034c2a4ba8218eefdf8d2a5c1f8ed9b701579e47af8a529a95a1ff64d8fdb885c36839b4c5f6d72a99257e8678dccf312754b9d4619beeceb825526de622bd9676fd5f357693abab078b9e03ae21e87ca161e778af77096eaac2d2d32bfec8ec94af7965f61d68ef66a4523c1cc70c9519b0750b3c9eed5aeba9f0a9b7ef52cd4a2de29b395b705fa53f028fa766159f20e75f4d384ec4fd66df06e744c99ac88cb849c285757cc557e2eedd86959da2c1b81f5b2715a6519848901ae4f89d0913c8de57c53dadf2e5e1aa2a9c5f464fc7610e8ef5f5cdd8203a67a93c33a06dab358dc5ae23edfee6334262f47b19b113d6cafedac1b43902539d74fba29aaa7bce68884b72616a0542c9fc69547cd19ae1df01723abdda65e9bfac5da0d04240c6a2175c0062e4e1ed8a5b397afcd4de38e86209272c7a424b5ae8d5a40b484ce1b4704af2831609ad0f36e90e07b2afed01dc05574ad3971723c5b5c1ddd4fc8bd263bcdf568af75e73d8abd1008c9ec712f80ffc65ac34e2a79304eade1d2a1dffec0e4c98c3582468f320bf8f66
SIG: 327196ddd43bb602d04d1964ccc059ed627cef0a88d8ad91be4931f17c250d5529f552794a3e269d17a63bd32933eb5e519c1d506574770ae4a72964e06f7d00
TST: 768
SK: 08eddcb5625ae19ffe7b49a7dc829c893c7538b0885e18f98db78c8beb569c26
PK: 83478b1c58576a0d1834b28d46fb80516d6fb6f9f591694b44352eecd1e7e89a
MSG: 015b1d3eeb00929ea80bd8687d18286f0adfe645ccf25a22b5061921e2a030fc76d033fb53d0937c69b31c5be49913ca1f2c3dca121b2b87c59b3c84c7ae52af19c6b9fa1bd675fb6dd8b329d5668786dc7883e2d2e8586ff4128b90dee84be0ab54d6813f7a8c6134757173981775de84c4dd39e336f8a4ef8dcadec943e90d421b229c11785fcd3fe963037458e76c820b3bc2c9476001262b261d28b65b489d76b4be2365e4a80fa871b0a53b6a5fb243688235acc5f4774db15d47b42dd6c8d9e12dcb0b5d980dab0f3ad8a496f76e5006c2ca82675ff194caf8070d04bd384f97e583e73cbc4f7f257310a61b1c8062322dce8115f6dd93eee8a93ffa5cab6634116e1ab705fa86c4a8eaa556c6c89dbcad010436bffe451822491f1ea86c20207e4d12dfa362616c589f97107ea5d8bd8a7215c600ffc70b80e2abb15acbe4becca20d72155abc3dbe8e37cfd73f7420f21c9bcd0c3273513b5049670874d5519b3bc1db523c1d7e90c165967c4cb2845a2e8b47b5889254f58a9bbb826f94521cdbd0416f5f18ff78a3fd0d7ab897906264483cde642d8e703fd82e5ae70a9f978f64ee80520554850528581ca9a0b38c196fd166dae5879b3f72f59cde91cca2c8bfaa478b98d624cd34724402de578e5754825ce227d2871b45a5117149515bff81a923246f3b72d07bd458125c70a14d87c3fd13392a3bda6553016e8b2d07bde903cf687b445cfd6f761492eba46522ada84a9615d8da3498b258067269b788e559b659d4b48a87d880d6378be6a88746f35b322b047845aadc523beaff3070f721c3c071eaa319b7a47c1b20d300dc0321909b669e57d39a1ce2fdbeaafac21350ec2d6e6d5b880186c028a861474d5076a4adc5032fec9140787c36806ef79c72e3a19d8c8b70bdaf207295542d96825a5de7dfe108ef574599b8f184c63a5a131db19b3be53f699c10fc4ca7c63f3500211b356a0ac664ddfc1a9252590026395b479be9a5e4758423560b65bbce5bbade493b13d00cf8c1d3b7e9221367e8f0eadab6e6d1b5fffde7b2d741fc2c830224fff7ff14ae5c07
SIG: ece75322995154b292437e47d38a6a70af37e2020716fde46bfd393b3d369bddb53253b556621cfb34c8a90254e132fd28ecd098433413a21bd3a9798ca1f309
TST: 769
SK: 2273942db3e5d3221e80d994fd5e1163af55f5455a8e52be852dd3adf762b440
PK: bc58674e996b6f3e3220b3e94f0067bb0e9b0d97d9e1059cf13997a193ac032a
MSG: 8aa0509e4b914186ffff07aeb97a04b546272da2f9ea7bfa659a24cb50966c23eb6542e4f22debe33b65769245c4d1b5dcf3e699c70c5c2baad9734e9d1efe5448ab71c8946aecce5268d26f19cf605eb3bf38b0b3322694ac0dcb76b0f946842f6c5c68d763fce74701bd6b78e71c8c3142add4ed46e0969bb9555be03602d562e4c89f3a919940e883a96940542f2779fbf9ec0a285d9d8a72360146e3ffbdb78d210316038d95d6ab757165aa943c033eebb321c05a399569bcf66b4ddb0b2e0e33c4793d817ccff57f99b3189c60d5d7b9419d1ebc943a79d4d8c394566180594f559a80529cc1ba28877af8f5c0503e943cd3aad99811645272dafb49b9b3e6107eb5e5186e1608757126053debcec75dd9565ceea06a1391a8226d1f4593792240ccd97c67a6c2b1344c22c91f42033adef52861f32a4e0712a917879a0b0518b5424bcdc054b44e972ed24d01689f4f27f5f176f0a578ab2d3c0878272e8c08c21582118654124dca39585337c13c1865814caf0996cadfa65be580dee322ebccda704b2280582604067dc3c6b1f7d8a26978a65cffd1ed3196a2b065fb3caa79e6b5b66c13d7bd7d0ec14a3a4d58413f212f471ecaad3a84af35e598a89fb3447d3324f020fbf1b73e2a986e0da16c0183bf92a398c419a0f9f30537bea0df8df2dc53c154e8ea160689e7bb4d729dd8ab90031427aa3945863a85e89652b9353805166f7c0a18c939954b2787c37094f92512722e52b0c976b9e42af4039d2c0578ff14fae1d8c2d1396beb2d6aa6ebd55474a9349867a03f3a99d78780634ab4b35cfe1b87a9133252a698bc407d63842870e22ccf3933620ac0423c3d1f681dd73c01d06c3b941506c98eed9b7868e017b7f99716b0b77f11321e5ab23dbfcfca9350845ee180444c50ff0a9c965fcbf777708e4f34ccc637c6a08d854384f8d3e2516956c151d031bb1cbe712a5ef9ee16619228bd296f2afe582d9953d590d18bb205f70f844c16c0a2d8318037d43dd80f65c6a753f2a8e27c89c83e7ed70c52f7062dfbb1f544aa236b5c704e7b39ce0a55fd46528083ca61
SIG: 874ddece08f30b30f0d4c8b3ed7c615149b8aa740daa347b55958f1e2119044f695a21069690506448d8e7352b9046511d7f39a5415bb9c57050fc17055c3808
TST: 770
SK: dbfa45abaa55415238b1287634d5eec402dadf622e270c04a8914ced270a72be
PK: c0fe323581ea296750797eb5508ca19a583b537fa7df4529f0804a33c1a4bef4
MSG: e26e8dcb44e641fc20080e95474bd39d716c5afe5a1ffb056d1eaab0c49f8570717db6437a03228a9ad9f4bb0b343b95e16023c0807eb2a15106a6eb12dc76683e69dda3363148c5d7dd9713af6f87a09410ea8f76b6b78a114429bc85f784812fca31acb0309552cc188c6e9697093cf404c6f0f4abe8a1608673fdfa5eb78f65fc1d49cdec4094b1bd234a46e0ec62a4b6d31b829611540127876bff4c173de058cf61004b014a7bdf793dfd6b63c507d2b23e0f56bc2fe6baf637cee40d18992295d848ef498f8a161bd87e60c91f97a91e9ef3f6d97f2b2d2104ba6fddd6c680706273dae87e6eec1af2a45984985069e809e8de32c12889299a32d40f38774599ac3324b7cb0a4ea632c5f910ad87f5adbfa5c3bb20498279fd53c1c267fe0a84773085da266b253cd853df7e963558cb06880780973423c564cd0bcd6b93334c195953d7cd899f8a547d1a1a0a8deff1381b4321574728cf71b96ff209e899daa8f13f41b230e17bffdfdd2a8943aa5d21e5f36e1da07edd6cee92dc48b5b2a7580146a9baf713950ce676255a89e34f8787547d62868db14ba46594da310d7e2d9e7c7dbe17dbd71eb47c56c5721dc96d696470573794809411cdfa276b059d0007c25d74b2a67d38246de11ef46dfe2670926fe4b63656231bc7268bba23f378e84a428c3cbf45cc539678fd467cd33dd0757cfa024e54da1ff54ce820229b778b184be1fa2e8468cc19955940735eaaa884022f6418b0b1f26bccf169f1bcac7d82a35ab6ef847e1dba537dcaff57250a8d1c71facb134cd06b01c45319132745dc488888a1d7761b8486a37e6988a1120bcc1682dbfc89143fc35b46935d8acf6ef3c42f0f4bf679dfd6ff44b6ada26b01a9f89f374c7d2ee48dfe1a410e897cdfd97f626d2668502814400793b3b07c8720bbddc59cb0f9de964ae075b4af3dd4baf6d0e4f94f294e8109d6577c4f8a9c7a5f7d694bf88f1a5ea7eba0a66da6c770c08b3abffc534df219dc3e3323b022e96cc86002b189181a1d2b527d27950b7f425a47da4013778bd00b71105922204921e9dc692c233f7baa04
SIG: a462a9baa56dc0f7a71bf87b95f48d642022d9d1733ee3683777a3782228ac85fcd83026be4ca97a345b084f50874e9124e16ba17dead4ad85c0e56f16ef1804
TST: 771
SK: ef64e17a53f7fbcafe3ea4687684a0dadb18d03735a40a53b3edb04907ee6162
PK: 9186e6bc142961c4d3eb369e9e11578292de5b6af534d423ff240fa26e21a781
MSG: 6882456cc3d1ad0daa9b88eff0969f15e97b48d051967e1390847225f26ac25559f0246bf7d683fa28ecedad21491d77bd2696fa835d0fd119884fece9d803691b2fd3de17ee087c74007a7de9bc6534bbfe95fd32e97c375f4cb65731aa1e8346bea21be9f2c3dc874af0431906ccbc2c600127f4d3b069eb091d165ec453e672e93cae8b72f03371d8b8a8244ec4ec2e09f31df40206a2b1c84caa1b993cc675fde1c79bd4a7d15974fa29ce2e892c2899cf482c3d9663f6d2a79784f41c1f5866d37c8546f357d564d3c4218dfa6d20b6c282b400fedde52439d472212c5767a35da5201032da8730968b0720e8a604de6c1baa3f4e896ac2614fb1ab6e3f6cf387a8eb2ff8a92147ab349238432e509d829cb75b2c1765c51221848e25afff5f16e4dd0cd5c9f713c4aaab2ce836f8494506b5309dc2b0ae745bb9c4798098fb8641d520a08b02f75ad80dbc2ce29e890b4d72a3ffb2a1cbd538e1229f579c29ae66bca85e0fa08c8647a1abcfe8a49f5e508d4d2495556623d926ce49efa4350aaaab5cec2cd885be1d63475e3bab7c7cdc8d656173b8d45602f4b3d281241d17190327b24c3836b19311a193af86a6768f04852ab06e67c8ead591cdcbf3789c613209cfe03f58c0305f63203b487f7c5fc098877ec98a689c9d35af81e84078d66fe9e4eccbb1cc6c71991c03017bb811f41f07de68fad194146061324f3d0ef217a54cf38f7a625a38869f67d0b7431df937cde349c175ce8b26ac88d39a43e279b018764efa4dd627cbf591f6209c4a5bb19ebfa7c7135592d02e501cae5e6b31c90e72faab47f7dced2c48adf88443b3ede60cefb0d6379d6922ec437f086bad6217d4d4ffef18e22523664bf4e9ca1e65a28c2a7a60c5f6bc906b737c29935f9097463048575befd1a2549dc474b13e68aeecf166043e075aac515540f831b43066cef932e63dcd5b37b61578c35b09e45cc2a8def57103edfc5f649831a8961fe4a4b3721f1d6df4ea9f033881b474300e0f12cb9cd3babdcffbb918dd9bb0e2f5b21033e43023a0d2e66da3ab0f07ee988b16889ca5d51abdc05fde
SIG: f58f396ba27e067a5fe003e385582ae3490e05957715d704da0da63a6419d2e4f6dc66b7e88e428a6f21b9ea202299a3c36b242b0ea06476ff12d0b6580c0403
TST: 772
SK: 3347dc47bb3d2e5d0286ac06a54fd921c9e96b6899862a54e5cc8115d3d0ba99
PK: d00b645d86dbb7e524757ec778c62b7e60d0b6576883338c9b67c2c7e4509268
MSG: e2f48edf9d643320ab991c8ff9f6aa75fe066e7d88ff1e472a5ac9c518de1fb62983b1007f6422809117bdbe8a0e5787f66bb057d27f129a200b40576e1719cf9e98fcb72af94bb82ee70f3719a2e2cd9b64777cea5e446459874b74bfbf56b2d2526400592a9b45a5cb798092b60a81b71d82f0685fae7f810b52d226adac7ad8a9183f09febee9d25046c0fe306681ace2bff91b3482b0bc30b2021c4341645d675134fe3081c51e5c59e40b375a1434f63b426e30530da9353bb2a9423220434ae59d7b6fdc143f4982eb8cfa7751b75bf3e9c913c73b760b07d395310c59f3b77ebf12ed2d7b03590d3317af17df421e78b0849fd56d945c5696a040fcaa78a93ecc16d5ac3445063611f3013e9a3ae2e1c270dd01a8ffe3e6126bc1e4c95f6547a8651f26b6404e39ee4ce7618918f3f937a52573ec277b771e91ad096fa15c7a340a809b470318a4636423eb4888a12160c4663fce2996d638896c839b2c7ad4b3a9b2e6cb71e912fe39b843c6e0832eca22de938b50ae863e48582c10851232f75e5225b8896b5a470f818b6fa39eb7bb590357678612d25fe1a40ea1b9d71d880909c1bd4ad176cc0ceffdcee7099e7882a7c907e4bec79830c6771acb89944bd54a5165b31870916921b198acd4432e7eed8ce1deb345b107eda760266fcbda3ba5229400a30360a4645ca8db38c3d5f4a8def157bbdbbf2c1fa1dc6b0514a4f5a0364f928381b40f95579a26467f2282a8a255758402ac9ca80e89b9cc6860a34bb3f90c3237657c2129ea48c852b92569e81106bce461e2024454821a917592d1991b5b69f27bbe019977528a2fc01192c56b4aea873cf8c58dfd7cb4b0e917e87a8704c992820f98d77404d3f1d2050c6743f6e93cdb51a61aa6f45b351b26461d1329f3151272ac396234d0d67c178acf91fc510d86429c69a87fdf101155da8d94de6722238a6fb17016862b11d502c667ee9ca0aabe1c20b97789f1867add78b8b87e9ab51934c0b4a16c2cbc4d2efedb79c05b23e0cf789201ac75fe076d315fcbac20ba0d31e4dc616927d6eab1b1c87a1c9c778e4bd285295874
SIG: 9ab4299b17729344750b69dc6037368c98f47be627fbd9adfd8db39f9964ddb7bc92d674c7be740756396baaeeacbf74947b6191c6ed1f5d32a63df36d542601
TST: 773
SK: ff15d6e74e28e41d05a8663a702f038d5b8578c4275e772b73ba440bc5f55a06
PK: 4747e2e9b82637b3844b85f75b59f7136b7fdb1a62e7b70d6aac17b3c5752f2f
MSG: ce7bf972844f5184ae8eac87b12be9202c7239961dc23cd41ff55b9bfaac0cc06f3f1decfa9571095c8e82b4eb6f8a1c52c8d3deaa61a9aa94e2ecd9ab5b8063f2da6d8015df0a5144fa3a48e305ad9f41eaa11c4d74854374ecbf382e3002579a9a249efa1e1ca04d338447d7f2206703e6cabf5bbd332b42573bcbd3b6f71b7c3bf73d4c774aa01e866841432829d07f96e1f61a20216d968c90e3ed11f663f7d6271622fefcf3ab68f344328515d5cce2ce85e8bf3d1d09043692e1fb8bbddc07a4ab0a3eef8ca6a420e74bff8d3d715596aa821682954fe89629ae27c1bb03b6aa09f36a39a3e37ba98132f4e23888f9f335e7beaa2cb2727acc3d2777309b85295232e54da88ebb6f1053d6de79ac6609852eb93a0a35bc1a7bdc22d628bc86124d696c3f9828b6f8b9aade1a65216177486c252a4b42d90a4e0fea2093489e244d808ef7021a97d5608c0ae1d663c775e8bb9e9a7315f1feb6d129b5a541ea5929a2c633b6d8c3c45441717946cf873e9b4c512180135d54f053abe44c6df39b7b062ef7240162cbd0b851afe5f91536a9499418e8bff4996473d805ebc1ae48da2d0b129e8e8252f1d53c328f32db252de3befbe5f31280121143a8004a4cae631c827409e520e394cd0f8950cd4c3cf3f3dbd4952a4dfe69875f565389061ad0a0cee6b6aff09ceca26d990e896a2aba9f3b26015b63423768684c03ed0de6cee7ac5bbdf9f485c2275cd12aefa8f907b851a02d51c34f121b77f3a56a9ebd1d65ffe89bee381ff2a7480e8968cff25ac8d04e149a9d5027d14b88f8ae2604d2ac22ac67d13e90ada620c2046d28299384d0959fb76e22588796ce427aaeaf4e2a8aaec3e87f84ccd082524c96d766eec66f0bec3e799558145f09d330134f1c63f37053cd4bdc1c37fde97291857551f50ac8e15f06ac1c73daa1e8c5bc9277e3d69cb44a3237ec57dbbccfdf6685ada20b74a1bc6b74ab05690eaf9bd0c4be17042f5cd320cdd613dc08d29af346aa4191ce0b4f85bb2ad7f3bac738a9377ec6b84062cc70fca9ecfbe1f57fe5b2ce7a4f739c81cabcde046451dd61ce1dbc
SIG: 42c1295fafe26de3ea34926bf1ef80bcafe47b21b90eaed19635ed7538d767cbf3a1e5dedaab82adf75120373e923202f7fda0826784292eba8b238b6cb88304
TST: 774
SK: 1ed37b610b8b35417d04e59aaadac688ff81f1e507c89b4f400160941908cb8c
PK: 48e8cbeb1240bdebf0a2d92953aa89b282c49aab2c38ae69044c51515c3300d5
MSG: 1e6767df97db1cfb4088da7b200d9f59ec8dd4533b83be309f37650031065727cd5202cef48426a5f3a11d50b381f8bc22ff101827359f2d0a610a4f755464a0c891cbd98d2dcb41d9779d288fcf1fea62e52163ae67e90428b86398efa218f1b982081fc513305fd3e8ece7f9acb0e10e001d2ed299a48a80870b3d5d8ab9006309b31591caf0583380073a2db61f45254ab965b5e4672c4bfaa86e336c49278552729fb2da76ffe502ec61e1696c7fc9ef19f7cc2a2775b29700cb384294063a17fed4fc635bc13282a90dad0c00aadbcd569f156a854f8ba9e7d607d20f2e9e5337981161d804644668d064fa63dceb9f5801353d0ab9f41d1d8bdc76c13ab2f023ea01adbc4c8168d939e98f64fd8919384abe76709263c0cd7c3efadc2801cc4abd80a09bb3ed6bb78cd620969cd35c6a3a5d01485ead4c45ebb6ac6a83212a7c76675427b21da8a7a5047b30a6100cda02476c186e6ce40d2768a942c9f87305e9d363b524c0094a9e2e29f585894c0adbfcd60690fc7fb0a9c717cf43b484fd45151b1304169c26921db2276ec05ad22ad166854fd2f94085778c470dc452e5cfa4aee04facb770526e1f248d3d15c27280fdfa1fd2c1044bcbc881c3d99815c97fbea46110be02dab774f3a610e5802abf36a49875c682638e0ae4cc8277c5e9aa7307445e6bbcbe549eec2a45b1597f7447107b62e2cee0a5fc51beae3e1fe9befb1885d9b30f9b4f1f56206dee0d67779c57f484c8c3c899a515a9d1c10f6059840c1c73d3f05bcb88590c52f7da391838dc2e73228f0981c289a4c27f0c757faf7b3b89146e33dafa490d9e0f9275b0cfa6a7710a73831459595bf732112b62fc864ca4c829784a3f16eec4e18f936918a7b9891669e933223f745fda562bc0a4e61e3d14ea45dfc327e2fc0cdfe6f2f97546c90fce82f522291480111a1e6b9388272c0be28d20ed84bb84d49bc199cd599948b8f2039d07827a3f4075d3a67ee572a01379a36213fe116e768b4114e8a4b3134c3818960772d727b0ca6f7c997ca99843b7eb02ffc013971cbe0e6e60d49773f1e8c0b30606131cb10c3e04
SIG: 8608815e10590d5504874d8999fd6f09626f950be20c912c27c9de6e79b0faf777a533bd5bb667ab513a49458ecd6787a09ec0df6c9c9d6333c5e3ae61ea370a
TST: 775
SK: 84364478ec94bd25c4bdb82d296229e6dace2b1359d6d21be2b3afcd7bda19c7
PK: a1814f8ce0fc3b236093a50f468c1316211fe6c52e2345d9f0766b3688a03cad
MSG: 7bb7293de55f058fb2ec22b687260543dcaa90f140b9f45eddd4bc22e40977e00ed33cd1ef1bba13c1d0990859005569a80767e4864a2cd288c81393e04ad971782e2bc493108cbe80dacf0b7b9cd534988407a4f9327ec8e9c4043284ef6ee5a26a5b417765d3eabb48a007e7c7f32987d70a139ac41678cdf7a55cb80cf9db5eaa45f3de0fbfbadffc40996370e48b1ff5edd97940e750792164836a4a5ac2e3ff53e48a1e556db9ad0c5c0b944f4aee519a2b0a88bb1c1fc7454524cd57aa5350986243d34fc58e24e819ec0b8545d8dfcf6b20311441d3a35d3e71b3e3ecd7884dda8433a405e3d9969000c820a89b95d197841d98ae734a2e81daf6a7dcf56cb2fc26f2165a5f42b86c7e9e5b11161700a1ab9831f3fae58e14208be1bf33b58ecce81b0c6b7e02f88adf9ab030263e2cc9b6e33ebca3f495492e32bfe372537de6c6b87644828f74942a02b007f14c3fc5dbde76333d36d07631b7a9924f717550040697923fa7b9546bfb0217024ea3f252b515b5d64a62c48e027cef6750beda49a02447039b250a0bda07dc062491a662e26874c8d00f80e6cfc8b30f2c3bf7720b57f2615fc478fefaa6d31705b43c5a54f758666b302a8d34953131941b7957730476794d0bd9d2dfa72fd203f22df5ec6bbaace8b9394bebdaeaa561461011b4fca6185c9a38283f5403fdac326d1f734c6a5ded6724d9f384aebd6cabfcbec12abab9820d080732515e0500cf5d3e2f9ef80a4d7646a7da9eff410f507c69873b32d540ec32b283ef3179a4c632b366576dff058faf8c8c70bc69be808982ec1497ae8911b00165a66695f4d3b987e7390b5cf878e35e676541285e4e13dfaeb2f368cb511b778b106a428778a1b8f2a7d2e093519bc9b5188e38c6793e96bd0d30e2a3db9ee1468c3dc87cc365c810f9dbdf01a4b51421f6fc8dfda3a16e2da7ca7159b686a5e167338937882ff715d3e750d958fc9e4b1f0553129299aa8430183e506cd7f2b279076e0e1cca9749cf123ce507fe07ddbbc4dcca6cdb9ef1b833f61d4bff00bec012158f432ceb75b4f2edb1bb84e5ebb9259e09f9625ce3
SIG: b4c2321ade3c19ed4ed4c639d5a4d6f2be8e2fb13bb7bd625ad6dc87e2c20f93ad6be7b7e42711a878db9d76054bfd7bc25e3774a93da1543c9b4f6633b0be09
TST: 776
SK: 00db37ad2a195f08a08440d059259e539feb40b474928255e7c94ebc3b05038c
PK: 04f88bf639e0f71a57d0d0afff5fe97dde3809ff28ec68eb6fc423f4faff4390
MSG: 5a94f729d30dd8aae2a5c8c28547bf4506295dc61bfead9727746082d43b0f8114c8c18c5edaf2fec7cae819356338f0bf115a17b038acfd7c96ba6262cabd5710fc0efb43d13df4065becbf1b9e279c03ec9bbfed54d9a13fe06a55a3bd05c807858b41e18dbde13b0907d4034132262d9c2f4d2d376e1609ad280de20ba709844dbd12950257f1b07ef8cc3337c01a702693fb4d92d047e698c3a6dd46c4a92a10d4c780e52e5025e09d56535d7eeb9fe7f033e6e9260a68f9d54b6f37cc069656e3bcee06922b349681a8e7751cdecbe1ecb663fbc6f7c861f853dc310f33defa98ee343a68632ec22cafecb7f3212f81e70b71843b9fe8c86a68b5c86f0322d348a76da7f1ba0ca3cd7b6fd15ff89292b3f636cd08cf625c74d5102cabb571a3dba86a1c92f41c7203b44942f5a24625ac37d77e49a57f118238699d807c250d5bf46f7a3cec5779a6e5ae1a6ca160cff37fb3b78388fe9c030c40e7154601081a517fc0aa1802cd3b845b946efe94aa8b9e03f68a80ded0dfbfad4daee40fa838c133841ae8a3ce0d79fa8a2b9434bac5e1da6e0c7193e8dea435a03a85f76184f7ebe2aa749be9413104a178689ba6d27e94fccf61eb3aba0e6a5a63af0ca8f05a35cb63705194e44d9293de3929b0d92be6f8e627c350a83fc9000aa95b93820be9795c80b5662cd7b34822328061356dc580578d1a35b10140dcd248e4853104d2c5b2c13ff683dd5c30794be4a76858af1c0d9af347ce1dcd972ee49aac12bbcd899c9329871d3e7a0683d175779afe35f26a2d248fd780ea851dc4ba6d21f8a171aa6cb8697d9d112161540307cd54f931775d70b33d3b6de1091fc1750531c08fa70f7be38aa110d6746bb565db7b470f900850fbbf1c662fd613e4f3a5689549e3107e9b0f17def7a5bd7fd7596c4d04c7f48c779fc35e09335e1df784084e55d8551d1ff49de5b311cd350f347a0bd2863a2a30e6ea183ad2e3eedebc18dd28c6a596e693dc3389f7d90b713e3a85a62516305a70667fc1fb3cb10e8a955750273943c568e10769cef78199df4450dbc490fef1b304b052221b2db9c44fe00345
SIG: f4d1c80f5e7b91c5c7a82a682d49ba6fb19d400a299748a0c969bb99816998be634e84da78581b06e3470efec39804fed93d29739f0439a8095ac40d9d385e04
TST: 777
SK: 6ca1a1482a07f2a6c57f041197b34a5119e68903cf6dfb51711d9550973163c0
PK: 8034a55e3b6ed799f49e2e703a81f4ac02573c445d765e3069be42f09cbd18ad
MSG: 08fd8487503c3f3296b6f1b64d6e85906fd5986cf9c5d9fa8a59d92f44e6470af34bcdef336ffdc86456ec7a7b5761f1adea027326630e68abc6b8cd5ddf40b641a259ad024321bf3ef98e7632797149c492d53594752c550dfbc4fa6bf47176f423a2705693947aa90d68ddc8efb6cb9dbecafd2830d04fd93b1e9e7c12b93e0d0f3e2634900f25860ddadbaece1780ff2d3f3d9fb838fd0d5d66f8afb305ff1a1aedca2b974b63e43f5b3cc9dfed1bcf11999176ed9585ac829bc6794ef3acd872e8d2e92608b320f894996a562e1eb177e21be57c22c41ec259a3dff9c7c9491db838d76cf9b0383111598e357f44babebf121bdb24ee9d557b7d5af491a0a0365c90361fe4f7e3d13a17da3a39fd43f690dfb0b2d860cab419f775ab7152cdc8f2afdc50e8d5da5da01706eea2a2ffad4babee8b03da336a4d843d9d7e0a93f36a92e6610a368b63133f05a3fdc55e3e1a440b0f87a53364c1d37242c57a109e6df69345b01c21c1089e790a66f4f3380d3b76ffb420dfe1e6200eace579265a427fbd355514ef953e1a6e968e37021b3c6a290dcd0293da6768dad7c66311633051c0accb0b9165464dfddfded23bd13ef908744f9c2111dc153142d2f10534d893fe0b545fec53fdb3b35b518398b02ab21791fa977e30cf4b404e7a299d3787108b836aa0d59c114f1f36719a7acf85ac994d9cb72306f258f78ac0a3b6c05343e0b7a9aa726e52267edf97f4972f7664f43720ad33ce6e615440e36537cbc569bd6ff94ffdaea51e06029dae78c5b915c537caea6f1504147979b8aaae0bcd9618437ebed0b55efaec320e84c75959a37a260a02d4ef1bb62641520f1a03ddea8c4c1de8d7fac58da408b0ab4757a135f1d075c9f7c99fb99db9427ce9b0d626cb1ac189ad8663d7a714fb5cd1585c3bf99a0aa46d763978d0b12d65c438bbb73feaa51ba26a459e7bea25439466c08613e42540c8c6d54367f221fcce0c5eb6af2faa181ea21521809be75649cf8dee7671db7f948f346cbd0302bf9a06eabc72e2e512b3df885f6daa398f93e36dae2d6a04478121f97787d4cedff6db09aaf10f27b1
SIG: dd9bdbadd9fdc81ce230288c4a068df07e18b4c7cc51c0ca4811dfbd04765c56bc883240e46e3a42c01d8d2424fbc332b7c5a17bceb1f6e8dad0bfe562cad302
TST: 778
SK: 2784df91fea1b2d21d713de2edc6652451a0c15954b8656062ea1dedc2445b2a
PK: 9556db5370f8fb3c7478de03d23df1cda96f2740118efdd3d1a9fa4c3bfe8849
MSG: 2e3bc54df416741dbe7916ad25f04e48d5a9d77a623e57f9cd61ecb44f09f76833eb2a3e9ab7aa89ff5d2d560c07177d854d7c49cbef492b7f4f7e567de1275124e16ca4a7980162fa0fd162a8e5fd6f35617007034bceec57c8faf7664f4b3baffdea8d8fc2ba22d585e9e2d739f5ffc99b4e0dbe9c3686547ea04815a59c4a25b5f2390668e418ba0fcbdf4c4a51f33905c74fbb830a19f9bc8636dbaaff209995447996d2e5b1c377b4cb87a4e1efe12de34d33599ff397b74017d711edd3e772155be5a4406e74cbe2931ef51359afd51b5b1a7b3ea22ee8eda81476bcc17ea7680f6f3104703b9f2a35cf2627eb741d1a30aa4beef6579ec7d0b07a4ef32abcb4d756970f70a3678e17e6e5731890aebc8c92b956d4b3b5fe2adfd79b211a1883dfc8c9a4b1b9c8c1bb265e1f3dd392445ea59b590a019551f8121849f435b3ac1b29902fc8392554056b93903d5f263b3d540843d6afa75a2ad8304b7690de99a734c3d130b69547b18b09e98cbf252730e4aedb6dc4b58b2243fe55e80939d37b0a59d72226d8a2cc5153095e15994ad62195aa310f2a6426676b661e47b9fcfffa04d6dc625f29f44c7cf620b378a65d238344b380448cd119cc7f373f62cdfad64149906353f3a54107c5dba65e3cc494b0531f4d64749363f230738b2cfeed983520227dd5bc43be59b3268e283216f6e9c75e0c1c71272e54fdb29c7858d287d1efa1917be37c8eeab5e44c3ad7b36e8ac9f66991eb82a5148e5972034ad01c62615a45154579fa50869e7be9876b5656eaad2e43025a62dd134b612d8f4d5ebcf8056e198b713438e8e0e347cafbfcb89e394aa330d4c788d49c658fcfc80b3e0078f0e8e19aa9b8fe8eb0bab93de785d043e0f475aeb60d62e38fb1f8384a00b7a902daee13d2136269e50801b80a65b2f913cfe3ffb365d9aa2fd19372a0b0225695444e4bc54871d108e09c7e1c2b42dcbbacce24ea5bd5bf1fcf4ac697a3fe09a54677b7a8dc8d5eecb86cc792ee9b6fea2de16a473269fdc65dbb73c258c821440407c642f7d3d3f5c708d55332da8343106c19b230a51427f3b771916ae3688b
SIG: 17d171d946de3516158407e132cc1acecaefd6d092112be653999523e20bd495f7b7f600e8d5a671330d32693d6019c08d2d003b176e6319c35394200e027d0e
TST: 779
SK: 4bb79236fada3144b68296499ba44ae534074ca94d4b581e5edcfffe13b3ad19
PK: 0a8399f1e5a423dcf7b25b2fb0ac9e1e9548148bea84d021e0428760e05d58bf
MSG: ad81abf6937a7acd7f1837f04d3f10e708c61a5fbedeee4db76e1598570384e6efece97c925d2e5c3488cab10b5b52b8a5486e99d8ffe86c1981a1f1d532dcd4d489e5546d86653298e7a5f96e8144552dda8a18e75b5f7355b13541621106e497e51a56d8659d198fe10037e22128afc2714a2cb5a12cc5db0968a343ef918e8769dd6a3e5b9e32aab66cb0239ebe4c17f18218e252eba6162e977049ebac0b38048b3aafb7d4d72263e9212899a3bfe0a69c99e22ac61c5e9612456303d92458b5c502916c34a8ee5cd9a582a52576b6dc9d7d4c642f212998bf3358d4a8c2ea67686e55d489f6a76e6b070e6e995a745326c9aa63630a0033ad30721aa65fac604a6e58c750721a56ca6760c94134d611fab4d354e4f66a29677b1a666601e9da79f213f582037433c07f94d5f0de6aa9faa0b32f7b023fb9fc135a26f97052ac80b39b306aed13926c285419a29b20e2370d8a095b32258fa9893489ee21089c752ec062e120359e2f3515128254c8098cca65a91a022dd057a2c2a1b6b85d137c3c967dcb70aa17a2ff4b37678b382902f0f931ee743fc398ac1b8c10469867308479e40d7f2f04a4b04c4489158488ddb7bec5a47f20ff356d99a1b3e9d0b7fe9b0ad949f298960efa4d9728f8101cf53da3bffdd9524bf440a58b32738d0b6293e853f466ffd42c5607ac9e353ba03efb578cc9963d8aaa9d2e266d1d2ae9296f30c9ef44ec691030d596a401b6cee72a540ef3c42ec0174266ba5401f354adc8e25404437e888b08286939bede308acd30327ebff06270097cc294f0a0f39f9aa3c66585ca47e60c4b8ea36089eb8a9088bb18b0343135bb6a456d2f6a3bf390723e78b42c037c2de2e1432caad3a594021294d43f5b15a2e819dc748e451de40068c8f032f13b4711377012edcd4f11dec1111b12eb6e1b00633818706d7132d991ce20df3b921db2185ee25bb6f5827576ec01ad890f79793baa358c2bbfb6faad11d8cb0d0d2d2b2981fbf4e372349fc6a01c36077b59325f702b380059a65cf2f5ea98d6bdc8152053b85b28c81e413c4cac7e226c13db3267d21830f0e5431102917005
SIG: 698fab68510db8121a465db77e4f8b586aee895816e63bbf0beb242db4e84c157f4be201ae6564517a870d17f60c858370c01cca17189cb4189e814391d1500d
TST: 780
SK: afd765e6aac0146d4811ef9597bc3f44763f03378b7be033d6e64ca29decaef9
PK: 6bb76123d9258922686c53fb6917b9a459cabd30be8c43970d80f5350c2d98ef
MSG: 183b1092c7904e47a1420317a25d0f59110aa84d6b3419ad456865c43b29e9d1dacf755d9e5cf94c5591d5d912d05ca9a52d015d6e8f5dc94efdce0d7cf5651203b11e5427a9f679429e00414a48eab13fd8e58b87eba39d1025d6a18b2cdcbe147436dbf38a1ce86413ae318765e1bb1df7e2b3be97e90408b11717cf459bcd0f3cac58b4a0d35bffb533e20df37451c11401ce1dab02055c7e08c5ec46390cd617a6b5f22f651830a1112a06ede4c40ab7957851d6c66f171cd16241590900b852a3d019957be1b7bb7acb8923f2a357c3264456cfca9b429d71fecb7edae39b252b4eb610e8c718835699754b8d4124b492488ede62610cce44b59218663b6c9646a14a8417eddbb6f4fbe5a4bbbb482b37a445e3c16b65a141cd3e12a5b2c0481d614d6d208479b9b209b828854dae0ea1eded506555fe18e1854005cf001a8077083498d27fadf118286b53b8974d69fa2825be8ca3d6036a92ca52f91dde6d5b1ffe2888f4d60779fad1fb41d8c0714049af681b755f2d4204eecd09e077210a48a195e72c80e127c3d4875095c6570a1f78095907528cf7746f31d97111c6f4cb25b3741299a7574822d46b6e79ed23c2fe057b3ac7290b460b166ee90a45562effedcc6ba8f4795f7395818db56b6edd59ca2cc4aea1841fd9565becd6c08104cdee26ba9de200773d091bc77a57c547f1a6ba0a2cd717ab32561d7422ea7235adb0cb36bf5cbdf88fcae06630a15647d9a357b4e0e502d273f3796a51e0bc3fedbf7a1e64aad722aac5fd022fa79d60fc707325f127eb1f03868795ccdc0b4cb26f2023d152153a97a260bff11745d2e2cc0bf860d4a6e358a6d8176d2ac178a9ae1a2dc75e8b490408ff7cdf991329f33cb0c05e1e356925087e0b8d96a52351d1d17768eb134cdb21a1546aaedcc687dfa1b22e92fb5241a83677a153445b77d5e703508e2abc588a9f42e5bc710673e4dd8ad703fab2d7db1eb84226c89d8762a709e3e9138a1fa790f2929bff61bc1ea6e8aa1ad0e3887d70a56d4e6547fc606a50d3be3bd6db03663e00ca9e4f24fe8cbfd7d8c9738d6367554b7b601f74190b5970a398
SIG: 3dc9194d50811419049eaa07b655b7d4064bcb0e7fb5f9e5326b5fc856fc0ab8705973ae1001df55373977dde2d9b81079551414adc71cc852d499b0cf824f07
TST: 781
SK: eb347145f339edd802785b6fbecd5cb80889ac7ce4ebad2f67076765db939bca
PK: 994a456eada03020921c3d109c135eb961fcd4a0a400bafd32ca061bbc862543
MSG: 5b8b31baf88483f095b5d02e17d8b7b46cf46460e64c6b02c56d8dafe34823706cb5c15f338ad9b56586a949711aa7312cc93450d2fb9af4613fc30793a631a55c14e53c0cb15f06116399398c8dd61876c62915f9f9e4cdf8f7d89ade129e6dde7d63671a1863f5da8f42ea64c079ecb9a2c1b1dd9adae60e96b9cbbc7624532aa17975eba17a7af02bfb219aac02b3d4306cd38933a85060cd62ab513a3965b09150a488c92bf7cab0482eee56463f0139009b9fbb3ff4ecae211f428b5bfb8876f004983b90c447846ca4b74566e979bc30c95e99faab69a3ebbfe4da6034c82d63e9c5ccaf8486af3b5e0d381422938b0c22f516955bdc36943173f5832708a33cf52d8875d97fde585b4917e4adecdd1e79856762033af22f254b50ce9d0c700e77a731554fa0113a0c666683f3fdb19e3a426302230b63e33a785ef24a9289455b3b8fc618fffef49c2c6e48fd4bb422f504149de2b4c0355c363408e66da81cbb581552a411e364fe3e4ca96d7072ab072e7568c13d35e41c7825a13a5c68fb9fb5988bbbfb9a0b51165764660cdfa2411f3d42165da187c58edef0105a6db177420543e958d5d5e8a371f7987051c4e1786d018eb3d732c210a861acaf671be95bb63fbc88bf8be7be5390939cd9fb2acf3981dda61b787a7bbd78468e1d32ca46af8fb32a18463c180f524be1da910da5508d42a0051741227c9b62de6d19b33c0bd48067b035859ad9bdc2ddd97befca31e65a886cfc753afc4ff2a7212a89d37c046cdf3999c051ff1396bd99cb54945639eb6462db9ece84077b0b3d6b3df3952dd36756c6dab2abc25a51bf32c1e9cdd0a728a7985f7b7e0d9c1a6f66ce1216373d252daf5958f2e8973fd268fad0efe251ce76fe47bd0a4d0c4f1017949d4c2b16717218e149154ed6fbe56f86d82e19ef0a91631912f2a8f3debb00766b6177802f4b2e79f6e7bfa9c62cfa2f75cdb60492630a85c9b43177d2dd9ba8d0548abe24923ae8443eeadcd0f58a7b82dff50d884003889cb560f7ac53e710a75575362464b1aa43d2a9b22f2bd2162d302faa7452344ce7ade9983687b6c68eca47dddb289b15
SIG: fdbd15e1e6469df720d9552cb5dd177bcbd292fcda83cd93c88d0114912dc8703109bac0d459ace9957df2293ac16d40d514893556853299b97b4fd4137a3d00
TST: 782
SK: 3208837d1554b6511adda09cbae565da78439a472a5d1b107ce0a9b1d7757db7
PK: 9b525e35368a921e3a2e9a35a4de9ea4c436caba27123e5c369e2a6cf5c90ab6
MSG: 436a3c31763f93d4d546c6d1ecfb7ae45916af754f839dcfe96d6b69c61214d016fc842f56462a3f07f661b2e2505acfaf482a0b0f4f5501eec4b2d2d7d444544de000b990f4363d3f983f5d4e09309752ff579c7320c915951cc3a1e3238c1ba7a19130eabf6a37f5f0bc56e25242f752061f3c63acad992a7501e967deb925b30ed105431e582102fa4f308c2f0683612b56686d52daed6943a7219f3beea2e0a29242e86d5562ffab83b56b263326664e029e961e7017d8e89f5e3e1d10f5932854550ce6e5cd76971fd235cf9c0027d0cfed3315c2cbf18508624d8acf047f9b968f907d9e6f4cfa5e45c80a272c2dbb62c5d4194580dfabedd82cb4d76492344be96ccf5daaf61e6b2b55efdb3f65210a3d6e1f369887ca0ea0d58c3d146ae3cf9b000076884115fa51b5fd66bec0ccbf0d2920196a7d7a38445fbed22dfc7564dc56f60d6e29e592485374c6bd1e5b15931b69ca6ee6b3aa2525c23585f0929f31cbd11fb1a5330216b90ae5a656df7a074cec64e598184f503fb23cc05e65da9ae7e8441f40e2dc26b8b56d2cb523a7c635dc0847d1cd498abf756f5a13ea14f8fab2c410b1a470f49aa8dca4ac0256b11800de0dd0ec42b142c561128d357e783b12f61c668f5e6e06b7b48b7b2254de5bdc1804b723d5fd6a0f4bc7c59e7c5054182613bbd2fa92b4c1da16bc8c97e16bcb0dbf8c92b74899b37f318757140b6c4fd535e2e1e0570a50818cf78fb988e1f4ce40e76e8fe3d697d7a45850f293ce170fd8ab07cf1534ea5ffad34f6fcfa42d0d21a91dfbfe0597c73fd9b9767614ebdfd02c3ac0c49ad10c94be5969ee0808c0a30b2a1eaa90ea43b8575c3056f423cd4b6f34ae51c2223765a9ea21f64573c1a13961321246e3b5349ee048fb62d5fb61b1714391182562b91598360e5f9bf4ac80db246432afb3a43d349650de03d343c2e97a8eefd1bf30c10c25867f53266bd1f0dc14ae1a6be9efdecff67e7d292c6cdfc90d80b886668f04c2a0f5ad7fa17c178b6e9b45a11f4ddfe2d66960a3f75135ad5ed154e513e1a5d138e7371e84d7c92453e6c62dc59b8e1fa93d773a2540d91c257c
SIG: 709d1ca9ca2f742ab9dd0b049335f544cffb2f1a3693d5f53f8ba083b9b0d86e5208fa8e1e8156c9cc2242775abb7e15af3085868ef457634e9926c404ecf30f
TST: 783
SK: 4ec6829b43997056d99685389bd53c528de7e5ff2715d65c956619826e3fb5b5
PK: 7d922d57fdb12792879aec4e8c651463ece064492c721753d22e115509fed706
MSG: ed26b4130d4ebf3f3861491aa3dd96a4eb69752173fa6c84ca65dfc991c7fe44e02bd61650252a1d23786682ec38c1fee82cc350db7c3c3949a1c935ffebd7baa24f35a393fbd27e7c34c2f9ffda60a18df66c3e465d90ed48fbbad3fa7947dee7e659a3eeadb887f0963f6bdd76c36c11ae46d088ee50bca8187a0a8832db7984b7e27cbe6abf12d2c94f337ec78cb38b26241bd1a3d2f5fa4407fdd80227d2b170144b415978e37201d0fcf43174b9d7b2115d5eb8bcec276a775aea93f2340d4425d34d2047494d917e0dbe37857e6c99859b71c914aad5e54f7b2b033e594e272cc5cfe919f888e55cb6157affcf357246d00b532cc471b92eae0ef7f1e915944c65279315729853da572c809aa09d40365f90875a50d31ca3900da77047c957c8f8bf20ec86bd56f9a954d9988e206b444ca5a4434521bfc9c5f3a8a06147eb07d11dfe1171ec31ff55771588b333eee6215d216c47a8566fbb2b18974646ac5a92c699d77584c0defefd2dfa58fca27199e41ec58a246320b35faab75b97951924226da4ab28f01b47078e712e4fd9f77b251c9667858c28e32ef1cd01fcbe435c542dbad0a84a13cdbb5775e62d811dc690d9555c37f15f91767a561357df106eefe056e7360670650fb818fc6adc59973e9ad5cdcd809807ab56397f3c13948732d98d676f4a4470a95d8b518237e226f0cc5f4765164a5c3ef050714be02a126be8f66546481581b9e94a26aad24c693b7fdbc18acd3ed7cfc47d8ab26745d78e701d0cf05dd844b5b345a29dab684cbc5092ba022e3c582dfc044c3100ad02756697a849822915a16e2a2b810e6815f54421d2f3a6fff588c0d9013c76f33e09beaeef60d8774230e8ce7131289aef2a40686c819fb2040b06124d3d9aa419d56788f17fa7ed9b9b57ceaad1337a0101bea0440cff745ddd9722055d1f9bcfb009ce2c2f41a9e7e86806b872cdc2059bc8ec68f5ee56c4bacf4bbd30ea4c7155864d600c0e2eee73b319bda4372e9c603c772c25890c7610489989475d37a77a4574a2ba55bfd9c9cfd146fb97e6165dcc19559f4f85dfca2f97f3702ed8fa6b3c2a9741974aa07ab6
SIG: 159ca404f7f74117c5163cf404110949eb57ae2d7662b1ff4178cc6756e90adaeab71b064ce1dff457b2dba7e2dc13c217bcae8a61fcf8ce1487a649c257ff07
TST: 784
SK: b150a78929ed1eb93269213e1ebc22e2e40a601bdb005499b7beb058917c5340
PK: 28866b6d1c393cb08e464cf5571440a649e50642380ddf4ffb7ad150485c108e
MSG: 1bf55d27f9dde6c4f1c0ddd360a25d9493c0ffdca74a7ed5e5a514e95515cda4aad8f45cd6ed7901f8f224a63b38121cbeac2f56dae210dd053750cb207514a8891e245a5d07e7de78a2e3814463f148d2acb7dc71f995c9299ad0d6266cfefc94269657fd47cf5312b92af2750651c479636c9d36aef08f7d1195e7fa1ba3abb5dcb90136b0fb9a37668b87a2db88d1e2b6440d3e6e601e6d4bc10cf1cbdf1d6169c0dc2c4aecdeb6cdd4567d4250b2afa715b166c9467f907d3fa5a6daf200b309c109376830499caf3149001cf3339448ca3d765225d6b3c1cd267cba936e7aa4832539466fd20cbb38323cbb2228a271f2d282561c73ed79a1ad04698e27efe393235f3456c295407da0960f0034d8deefd1c185736fd3eaf1f9a1e32f09174c1fe12720b7c96febdb33e01b1b6a1c637150194be4ffab159e45b24585576846bb64274eca7b39a3ed9357de7b084213024a9e8589263600a2867c2a7cf8b99076a12a07bd7df8d5277bb04ad72e639b77eaca1ec58ef9637e9a2376ba878a457235a06f78fdf0e0d925cb2fd2a38c77188f60372ef6009792424399c9b67928da2e3ba91cbde407e7e876ba98139ed22ca3b983bede0000528796448e4a1055acb2deaa56bc308254c5bd498c275ecedc1357efe1fda01d34d916dd4d8647e5771995a653e0f8a5284cc7bf73157b3349d59e6f920cad6cdd1719f038025c4300e0210ce249faf3c82de1fd1cdabe61c14ecb1df00c5c466aa6a012a9c10dcfe59b7e9d3b155dab6c7b7c1608c1edd51dbdadf6ba5876b5e60fdf7f19e6ef712cd1a7dd3a062a6574a7436b319efb944e4223f542b2502c1ba976be91e05b0f85a09fd793beca883375fb67cd133f5284d89984ff3cafa7e11a9d85e7893232a524ec54b20f975d3c0a1143a0ef41176b7051ea91d40c5f44fd9e100558bf1212a7b891e68b55ca61f4be945266d9a1007a14aaeb68c48e257f0f46310ad16481467ec1773535d5fc084915f5d004ba0dc7591d2123c62207909d84f2b382f5ef12759a95cd3f5189806e273960aee162c00f73e7fa59363957654bb1916b5709bb0a9d040514ae5284951e6b
SIG: 276dd0962e6ee64f0592441a8af0e5ef8f93bf0baeba20504b9db4f95a00b939ea38def1c797862898cabe9dc4644f0e677e87c0a33b87b6a4d22a807d0e1e02
TST: 785
SK: 9fc7c49cb8c4f0972d6ed970ae2c6ac337e675425cc8dce730fc41444302935d
PK: 4782520b06f93344aa766780e54401363dfd7d967cc3bf06488af90920a30f85
MSG: 82bc2c700db222a4ac914aa2be8fa28e422067f94f3344f5362bebaabed7612b0e464a73a6c456903564b15393485140dd0f3aff90aa6e1661ddf682850d0490afc3d735dea05ba47c85d97e833533514c198b4cf6e66d360ee5bf00e14a3aab1ad0e7b8ab2aacc964d42830c78453df1955bbed1cd68ada3db0ecdb601ad7667d5c5e2fd49e36f7328eaa337dbd6ff70e7898a3f98c159d045a2427ade5333c88fc4afd3819dc82f4daa3c523cb57e35a2a5a725d63d402baef51e51f1ef4f8f9a595c9379c9aba873fb4e765a931da09148aba6ec5b44859b0e81ff9fc229598ac9fbdb0bdbddb5692a52222df52ea387bbbf36ad64d1946bd282e323ff4822ad9da897ff73f01b390cfe2e64de492d55de77f5d7d0060a6872a0183ccba610f53274ccb29ce6dce6a036c5317a1ed2a7c1068c1b246fc1d5881d00de06eb401cff95e6b69148699db13e94bb5b280212dff54c70e56de235a5f1400b5bea56772d060170f1d0657321561e4b49107eb96d9b3bc5adf451c2a524eba4db003b77b632a5d89827a6224cc798e096ba27fb33bf61e3b8eaf18d001ae8eb52f85c90d9e12544803e67ff02047e0d23c22e7f8b980c01c3d4824b2a9a14a2e8f672a7b0ce03bdbb3bd56d754a0964db01ca899d488001508657b7b022ccf042c38fc1949d0e00af4d301d4f00c3dea20e308a0f9dcacb43222b3824144af77be18a504aa8d268b8a5600725e7cc5f3a2e6256a8074d1aebca123ea53a0767a92e1783a4983c5ef3d7dd7f02aa9d1f4f9aac6ce254593f08792014fb867eaf879b88a4efb18e89ba11006ad09d85431cc26575b538d8e7890646c5988647cc105d582907ae625e09cd089f47249e81814da14044c7014e80e7a8e619c7b735f701616b6a3c6f492cdc6ed463e71a3d22291482d90a1de6f097c4ae254876184c562b16575b9d0d19313ed98864f49fe2e1d074a21211b2b2a6d27ddb28611520d5f7123058fd007bb01001def07b792bb05bb741c129c6a36376c3853b8bb4f66b5760c8eb4ecc7306ba3a90c70da47c965f6dccbdb61a7fda18ee967cf8c5f050311092d0fdeeaedd1265defdd660abe70
SIG: 5c783a860aa668184dd22c4f9a546b5ec96ebad2e4af00f968c688671354e0cc9b572c73bc6f19937a05f1baf3434763965c96e103407f0eb642c5644154290b
TST: 786
SK: 08bf059b4da9aa7ffc702f5b2304c4f96ca49b7dabb6afb41dc91c0f00c65b78
PK: a6289ba28e80e8d1a319223e4165dc0bce7352aaf242f70cc968d21d77752832
MSG: bd4fb28a1dd08b07ba66e17f0c4f21853fefef1c9d20ba7977f154641ea1a18becf6bbb80388886294e0756a3c508ffdfe90b51e1356d112d8cde5ee2cc6332e61d169ccc8cc934994f1bb560fa4660c0b0fd4e8149a225ed4883e68fbb69da7af8a524b17141ccb76b50cd8e1b67d3ce037ded7dfa59bc7c2674226ec7e07b78ea3f782fda3e5f1e9caeab608ca387c304654f801d00e10a7c29f4b0da3e5f89513a98037719a1aef4c2506c177af5451a00757a59f16229c4f4414df51580d48210dabc9377370b6068a88e81d3ad1bed4985155c3600ff48768b903022fe02ae480f2e6329f0bcc91d75f5c6a09fdf77bde90499f3ca395cb20062a0984ad6a0141fd01c2d54dfbb1ee584610640773439a1658d2c9f862f183bfefb033a3be271812f13c78704657e7fb4f850175fcd63d3e4405d192242c21f27c51477f3211a9ce248e892b42fb6d85820f41b897836f20f85a1311534b5c404f8b7a4a0319bc6cecaa57fe4d4f20607c99c2df22fa0676f99d1bd87886c928c4988c6e78c57d758330e6922cbe03c10340253d0dd483792ce75e6cd09d12fbbb041f0205e65ad25ce7c1b24e77ee8d6f915e3bc3e10d09fbd387a84bdaabfd1cedb52c0b1733b5f47088c0d35e0ef458c85414c2b04c2d29f63f77586131ee65530f209b518a0f257a0746bbd5fe0a2e0c388a6c480e1b60714fee1c5941bb4e13f707eac487a9666a723b5793134a268b77597786c3a3193b46d355dd0895fc6216c536a542ffd7d7b08010c86f547a5daa38335a8bfa2655d5f71b4d8807f50c8545c583dd0b690022ee65873aea3e8f1a565f3b0e4e0295fb0d321f5c0b397f2fd0528f86a0d1b707f737b175c69e9e7ae3c84d4b2cf3a38a631aa8032b3e65bb4528f66d0bfd34473ed0101d2a61255b215bc1cbab9a26d2b969324b77c8a5464e5b23df6c5112f9d17c587d95559de212ad241d8b126050e5fddfcc839a7e5aa2fda1ca20c0910d863418f195b38adfcc36e92f2396ac3144b537b30fbe4dde614902f89978b7fb42cd99f13d99c45c734fb82c3259f90b88fd52bdcb88f7eeecdde4c243d880bac7614e15cf8db5993ffa
SIG: e24765860137689aad50ebeefc8d6db8e936a4cba62ce87a7f580209384a9d7eec9070905f60ad63a7befd7c70f0ae7c8109169aee4e518fcebfaca723c5b207
TST: 787
SK: dbbd0f7ecb6482cb01c4dbdc3893c0db81e831353a5b01cc75d3b11f2ff3c59c
PK: 2d4e588d31a384b17858c0d784f6712bafd0b41204cf8f0d57973e59c770d3da
MSG: e0fff35975eba78da2b0ffcc5c1b663600888e8255cd208f6dce7e88953b7142937389a337ae82f4cfe32fcb34f552a48fa8899e1a659e3ed3d3d290efc9a0f7dedf33e21d048d8d910757037b76e8a7ee9e4eca30f529ddc02ceffc26d64fda7303cc0d8940e9ef59dc983c12ccd1d2717e64d3006af82ab15bb878bb89d1758be44310420638b96a0b5e1e65009d69395d027a5da4a85e901be9aa2c0b3acc508ee18574c1b2fa9bd5d7ae7c7d830712da5cbf26be09a3128470a12a14909a80a266659befda548fd2b22f24c5fdc206ed3a4e75f5320682ed0e4ce817d63d5c7f1ee2b440643355be6542f59dc6c45ab15772f2219a812ef7527642015bc75fe45ba969e8100c268e24ceef9205a83a3f7b5ae800ad06e095b9b139219489793a7bce84ebeb654ab6669e2855ccbeb694dd48651505b959d32a77020b869533e3256d40685a6120bab794485b32e1169256fb188fe76e04e9efa6d10d286ae86d6f1c87e8fc73ad9b59fe0c27ee92a46415b39d786d66325d7fa6fda712f199da554fc1c89944a4e84c196e979a807553718cb81c076e511e609d5cac23d8f45b38b94bcfcf158d0d61602238d52e3ae84c815322f534f254e63389ae155dee2fa93396f0ea499d5d08c2475908c648bddcee591e1337e9421dc5a257ce89ccce4ceea809d7e87134e039db1be598196d3089fdcfa8978e02c1555832da0a72b08ad07cdd072627409c873937b0e835715baaf2608b2395327467cf69a1cdcce6372418383e7b89c8df4d531f585149509ead1e41b6627fea81c7958cb49d2d3c3e2fc691e0b8cf72679c08b8904654531bc4368fb617ac7557d9db8d329d77e48d8fb4de73abe7cb9388274af585f875c0dab793e4353518bb24695342af0f5df5be4e9c7ad215be90e25540da3489717dd3d29254585a45c13e6dcc7e9c8a3a79ff755cbe465b25e23a1da608e1084fec83bff80cfb7442b1460187307acd75e3f2d12843a77094acc32888fbe5f1fc24c615d19a065391d4176474644246b5343da77626a2d483fe204f839328775b71a4cb567273e169640af93dde3eca9116f400e23a7ad3d8fc3a28e565f125d6
SIG: 96c00361fb71c52305e1ab7707e0465203eb13df3e0655f095fb331942a40b15584143b370a7dd5761fb03c075d04a8348661ccea9ada53365b500087d57ec0c
TST: 788
SK: 748bb3cd477137bc880ea7c61df25c1dac6ebec9e6c3193d81ffa6f7a81ec667
PK: 106f28cfedf096454226b3b01fc24ab1c9bbd7f2b0973e56fe2f4c56a0b1475b
MSG: 00de6d990c84338a398fda5f4a2cca733c56b2a2ea396c2fe667c268e38145878539bd41bc140a2cdfe7e18360411048cca60f35ce510991df261cbf669039d9d25687a07fc0476a41f50eccf38153ee6ae9ffd392b2bec0cc67101ec3696d7a2ec8cbd447b6a6ea063d33ec128ae8b57577dee17b97162563f15e42b55ca4bedbdfb631a9f6262f94ae35bb35f795c35a01dedb4645a73cfa6ed9ee521e4631fb17bbc06ee57316be527427c8aa55c631187462d4b2c8822ca4e18b7a5d4c114c11dc22069bc832656d5f4d39548718c51f5e4fc828f60e37f01307505265acb22d5e8d767b9aa7b866a157c643873e09084a1a404a7bb58ccc4b5a390fd30601c896935e3556f60d2dc6bdffe47da0a687c8ece1241ff6c07d776111ca6598fca968cb6afa0a14a34ab8f54b95d3d8473a174bc725523f8674dfb2b10f874207fee1b08b42da1f58655305a359757aa0251f14138eedbc280cbd385bf4bbf5530114cc43b0474779e204962f8560d4aa423e17e6aecace66c813784f6c898b5b9cb746a9e01fbc6bb5c660f3e138574f59b9745445486c422bc06a10cc8cc9bc56458ef85e0e8a027cb0617d0337ddda50220b22c5c398f5ce05ec32f09b090f7cf6c60f818c6b4c6830983e91c6eadf1eae4d54bde754f75d450ae73129f6c4ff5c4c606f7cadbf4f78a18db2961cc8c8ddab0578cfedfcf95ef0888afd385537d1d0a07648a5ce2522d0633507d77593e1a0366d1ece843de69867d7ac442ba7dad2a90b59d8984e4a946bbe5f172da427638b2b61209041fff50e60ec02ec2c0b1dc4be2edd13e87b64d1d1663114573cf58a17739f463a1c3d6b2123390183b505c8eeffb20539bdfeeb40776d20c459bac4569968fcafe44ea4cd624a84bfccd7876dd7bf55f83ac7040e30f326dce325588e1ba5bc0790265dfdba09839eef571641e8a1234b6cfc3a36a866bd6b92cd71ec74e0d4deb9e74d158201aa502f07c8ba348ac26aaf9b3d070c9a40b52a44e932552b67a2df05a7f0f03c617b48dc2782366a231e0c4e3938a4274b36aa9450ff936be132dcb692838d654c94542c6e047a7f78ba711919f908a15b30b9
SIG: e13ca8e5ce7c268090908d61cf2f0a3e4572412bf5adfc5addfe88556f148b5fcbe3e1bc65ff16117d35c9d5dc3b117198f884925b4035b2c0de6c402ed47a01
TST: 789
SK: 393d44dd0ded71fc08477bd25ed0e6629fa7f88f082ebcef091898e5c9e3d5b8
PK: c52a993b802d84540d275479a1af5e287d19ea13b380fa3068d2f2c68eb97a09
MSG: 142b6e82501362d55a04b89d541a796863d7783840d34cbdfc516a3c84772f92446f5f0df4c45c6e0dc8ec1e9bb0ff7ec1696a09cd7ae34c10f8e61a9acabd4303f0a9247237621c490e8d9d0fe44482c560d051b82b074ac3d8e49bb2ac715ac4cde3d4709d0ea3afc51bfdef4b656771fbd55f89da9fa6dcaa62cbae561208d98cfa24cb81252b895f6a4a92c8e407af6c1f1ef49d8dde154fbcb1ca457a204b5ea5432e4d71fb7eb24d43f6fe25e7b4c659b0eebc4cbcc8b3cfde07c8f07b18a51570e7163e33b317b61360f9ce08d95de2c3156af1ccc9b55bcf81eabf3c40434046bbe82e02992a2ac8b3b425680a23d934726cb1b7bf26ceb52a39022c00acf425257167b821185f68e3ed17903d8d22275498c39a9e8df884ec00558dcfa43b8a119c2e853b9a0318bbea087f9cec17ca49b70817b8d7c170a8906f3ee9e8f8cb27a1d0f575abfa627e88f08ca4b93c3297c4f317072f421c5e602e2f831dfb82551bdce8d71216f05cf9a2773b90fc93b9d855a91e35ade332a5061fdb82b309bab4f56e2d586a84c67481d1902c261b3f97dc30b184619df9fdfc7a329d061a41df332202133d8eaeeddb4cfcee53536e07aad11553dcf5ed1e949d45355f9ef42c7832b0de7c2f1526fbef86b63649b6b85ae5ca86f0cea6df9c126c1d79489cc3bfc6e8bf0346eb30d01643c010150c5c8d0eb5010a46112215137991085e57493b22e83526b7b172c6c7341c40321e9ceb7c82bfbaa48f3bd8f51372d96d47444ff0d8bb2e5fd26514eb639105e33895fdc41f6df1fbfdcb08466ec2d217fc99fb012fe6540c0c5a5966ed3e66fab1202ab9daffe8e27e8f7462828d662659ea3b2c608cf68e30dbac62ffd8229f4a53f59ae16833b81a159161f19369f60f51c43a217efc5efd6ab7a91fe249c7b8a0c14e9faea533de133849a92447676f6cc18bef4fec7f37319759ce80ea3eac18fa2d9fa02309e1ce93ac6cf4cd2cb2c95f1e2aff7b2a8856405a7b8ebabeb4906d9b9734da9fb5e5d3f322bb5b559fa61ec8f515db9065ab4b91a7a31d5c625061c2fd2bcfe17f94bbde4776302b8aef3d5b52db3bc73ae4a30cc4417acb
SIG: 84c716e60de67b020cc1a6a24e6549fe56c6d941a8edeae407626666c31cb60dee6be5a71ebd76baf71b75114bccfd37d163a968bbeec1f76972151296c47e07
TST: 790
SK: 71193640a0a2b22fb22d00a80b33a5514f3d1000034fccd885d8ea8638f0b0f8
PK: b1d36f723b7086d923119f46759b39fa1e4038c6418c379ba98b5840c7ea5068
MSG: e0287948bb85a398e6affa2d25fcff8bdb9326f5d14fdeb60549f5fbf0c1816f11cbdd4e90fea039dca60faad1696003f91515c9b272882c95c9a4ab6e2777bd927e7d8442aea6cea619c9b15255fed612b5cc3158fc705bb7a506f4afecf4e34ed517b2c12b8362610e5ea270485cccb3c9aa97ecd6cb19630900f07d94cb293cb6e089a9a77c0194073a7f7177b0230d25763a2ef98d47704cb2c3af4c3c1b495631b4a5b21b2e56bff2ede03ea4fe7cf82917347e3a9d4dbeef37d1cf17615adaa0fd17057969917d478d03ccd8f8b88e5e5acae6732a8161dfb5f7d02123c8d5a565cf4dd98dfc9aaf5a335058a941ca43073f2659615a72fe78c101c41aed07f3bcf980b0a5b3fbafdbbea92fd889cfd53d403278bc15a59aa140c2d773b8889b963dcea365362e426ef4609845c9bce9f8aeb591d1a469b072b41209f5a8b6dc2395ad9060eb2e370978ae3311d1cf0a8f205142d436bab6b95943a97c23e61bd14b2d95672cb9325e9ab1fc9eeeaaccd58b9f4ac1550bdec8449b036039496c5f07a5ed64d5d85171690144db5c81c81cbc4c16718d52c4dfd1958ca5c9c8ba582cd9d706f27a74744c3a05bf1ccd51f1092010d36f1578b578ae0e9ffa47079055ef94fabc9ff72f738bef68461eb3404ccee953f5ee864c974ce70e9037e3388fbaf2889e1366caa0f651e21b339e3d56b9d95ac30b3592a948912c90bf54473cebc467b09a3943dcac4868acb5b35ea691eff4d8cc1cda0c6c0a9c169a4ee10041f35f433fb53d26067b291056b1da69ff46fbea1ca7213659a990d5d5df1406b093da2a33c8df95ab3ce811afb9c98c5bfd7c4e981b3ea94eefd2e2fe95707d89f307fa76828b5c6774950aee80626714256e197dc7da972158c768bbee7fbd169ec15b4bb7be72976dbed3e512766ef22ef3b812bcac4aa3115afe83d31284af8eacea4ee49afd42d9c44fff2d861c08629b55dae00ff674fb028e738b05dcb38aeaa6963cc3faafc7b69245a2a122a96dd2f03a824d72b0fe0dd798df5c4bb75a87324e764a50a5ff52547ada8f8f88e6f38aee49d58ddb012648854cd59d0ec97bc3d58d0ad4491f08590767ceb1
SIG: a9702a3395acd20d754373095dc61445584d8e571080e179adcba3106bb06a7ce4d460f1261aef8643ab1634f47c9414a32e183a327691e65843dd6c05507207
TST: 791
SK: bfc9626c91f348fdaf469def2302e9e38f9051e7349e48f850cf352a8331a28b
PK: 4e8193061c9d65a82bcb25da089b4a80ba41b3dd2f8ed1dc81e1cfd03c849115
MSG: 2f11f40b2a19f640c0044c7b139680c3c3b69f00ff9f6a4186fd7ded569c1d8c5720f19dd35c7816d08a94c08204e47643e264d425e21cefb83129c909a3d78caf72c46bf1a729765ef4b8ca803fdaf8052ffc6cc4a6b579a160b703b15355c6fcd3b9a2ecbc267e60dd59f6a2b19420e55727a80b0bb64167c83ba0c805deed491d93e723f3b43263d17420b85be86c165c552779db960e0aa9eb4d9f3a164a5a21fab3f509a8f0199a6943c4b223cf9daca7e110e056a81d9ce0e0c02ac265eeac05ecd84448468a4d122b87a3e04c2837e43d212704fd41e7f3d198a2e76beca0e7029c432a0654ecd44f984c5df06741964d8372c86e162a8c5418849b41e571feb83eb42fbbcddb8a082143909eaa5012b979931dc7e3cccb44c791e04b8065ee63f0561da1bbf37bf6503477879cfbaf6d9d7d9a7475553f53535f847a76dc3b2b7a3d1d470bbe17124a88e03fe994ba10c24221e39e3d0ff53c79e2faafa19012d5ef192bc6d5260b66f997b644cf48d99f3899d7c485e684aa1e6e30855cf75c2d80c7a3ee4354fe13c676091c8667373d30e60ff8e09fedef175a1a87395fefa0722bf6c01c6555cff068892afe9486cb1fcc5fb6641e82d87079ba5d7a9c139355d6c14c507dbd594724b55351100965be9e5dbfa7708878c4b29f4d54c217746e326ab2a54f99b881d7da5b11edb08a6d79d885691b1f7085517310b309cf9b1b714aabc5c17a509b140b89b3f9dcee50cab441bf5ad3bbc29990f627406170a7a10f2d47dfc9256154f962308e769a2ab1b2a00e27e327f0d1fa164d1e38ead5ceaae238ba526f54b81b45dea6c8974186b1b6725fa4c83e62f3e254f729871bda4dc444bce78f0903fa318eaac822a95532ab019e9cfc5619e2c2067f258f4375d2e0222ea5bf96a253a2a3fa9eea02c3eeccb028c76bc60d38298b95b9afe66031b1a2a26152fdaa7ef4f837abb51185df8b2ef85ad2c9be6dfba75e37dc7d12e1787fc55f866fd066f12291dff1976afc10da913101e70495d8783348d611b011ec671c0da737bf962cdcc9e4a800b513935a56d084ea64a7d4e8e99ee9440a736132e42c909503c2224a141b25ce
SIG: 660242c1dcf3291369c65c9d7f89872eab482200e344b296e336a0a2e631fa796024b6e1119c27d52264a49815dd781927a7df467e88b801e684fc602296250e
TST: 792
SK: 393b769482375b821427a66d16e4f55185b7a3b7338f1a06f67cdfa7e35c541c
PK: 84afd70678ffa85a9f6574cbcfe3b15d04a9fd15016ff8550a987c4b951c7122
MSG: 8ae8053e03bebeae544043b8414b385364add1673737cf8ab20193d4aabc8a78e1d69b9c7e52729e69307806e927ce3807b07c68c833c4fcf16db15e7dce604d1798915fd4211689b4864642502d38e91b1997b71823318b69abe5bed6f5e3015bfb22df30db371f2260c5c22eba60df39b3edd3c4d7a1e111cd9b8aa46f67bd0cf3a717af06ec0ce567028e06e4797934ad69b1f5be440ff37a8a034b1533fa946424ac595400ad27d3be76dc89ba9d6c49939a09f2e401c8f20f7f7b4b9e63b9d55201534ab4cc7be885f0432a2c6673d2e765194dffd9b6096dd2b2843918750959a8dde4a3ab407eb2f7e1a49c2597e30805f8480dd0cc8272a320c00aa2b210f576e42577d3aa419703697ca406d43a1a4f99b0733664f6d6b2403cba1bdcc51f541cf24236070570540755c7a8631fcc2f18938fa11bc291155b39d7a762a1ff4dca97b448f70e2d3de447cb08f918ea20cb433fa115e30880c96c8cf5f0ebbcf482309db6dc1fb64e17c04d7cdf7a90f4014d15ae7696b44423b0ba084eed4d3fb28c1efb39828aca2f40ca6df342c20e95f8006b2767a83f50c31fcc1581a09753e78291f0d9931d992ad3604473ceb885ecbe7857cc52ad5585334d1485d022e106b71c29bdfcf23ee8a475df2c090532356a6ffc02232317988a2cbcfbc2a36b4b483cb44510e85599b612596b626572b0996d8a61c0ee3efff1f7c71c05fb5a8d8c5d09d924ebaac8800451c9db2456710a279dfe2d22f6aea9de31801dc742534362b0e810e99e841dbb7f0cf9af1aef542a52c776cc51f287368fbe6ad651fad5787ef77c73535f3dfb3618cc8f0dbb549ddca9b9bf91135a3456001a46215ade388e7ceb9fcdfd0d2d0a0356afbe2cec1c2e78b4d998d4554f4621f1151dd3ffd3ba4c0bc852f311758c5dca425d18ba15a8d67ca401d0e6cf280cb88384a2dad49fae39ba2a77b467b3238aa28cfd137e5c5c0ff9000f8b06a2192e162920692265db24ab6aede535e31c2093be57ebf8805df1788914f3a884f884179015808db4d3020f3e78bc34285d233762e899ebff28428215e244404de291728fbf4124ce5b2435260a8e341180075a5651e6
SIG: 31f98c0a08fda8e735b57366aa1b83b93dae63b5810c821d99cb39df521feac07f3c410b27ba3307757d6049f22454fb6de9e2c3c2438d68319097d112cfdb07
TST: 793
SK: 26cbc2510ee6ea390a2cb948a015d131abf4c0954915620b7816aecf4e11da6d
PK: 145e8dd22b4400289dafb626d95a94c2f3b69c65197717cbdcd85098c5492107
MSG: 9cebe24b4f8ade86430e279a3c433e4ae17e008852a24f08690cbc3d75e3b7f200da897c25f7483b37637d4bc11008d9224cd581fbc038adada02d271ed2a5d285d843a0f8b79e37945dc35bc264becd804307e1d44218a643e4b59a9311de985d24b4c26fb14603be5dba1839ee0c8d2ede6cb50af67c804519037b1b1663318cfc6e75d0f051dbb5d3eaf3aad1f78ef0cff48d5c55b2fd25db1539d0f02dae9f25148a8d338b97879bbd39df961aa2c396315a2a86cc783581e67ea844acfe8645428a27b8d32ea3064e3bf62dcf58010ec4348862fac25e3d9fcd4e5d65be59905d816dfb964992ba7aceef8c2075a312e5ffc4f9530ea20f77f93e81cf8a019dc3945634364babf79772045a0dbaa77c47a22b77223b704debd2d003f6a5c7bf6b19cd2c49b614fd4d47fd251fe622cb981785c146bdb7c1d2ea02b116923bf98a1afbb7858adf2df938a790ec1f9074adb8d1afb5633fa961a84764010d3bded1c033d25abdb4b00fb05ed7640fae61879df88f0b09e3abd057b9a52108a9bc985fb73a5f29d84d1ca6921b62f1b703c7eeb4815d9dd6d066738db118baf61b0422f388f1bfc9e3a9bed83a1a727dcc266a9988364846807f4d5518bc2edd0ecb3413c26fd0c79b75d8cb5bcd85c06fccea4d03fb8988dff3ed0cc9dbae78d6ae8d5fc4024617a23f52bd615385d4eee08f9134eb3b250c8f822b47d91e8c4d4c29298016e6fc81f1f1099253d7945e0798955da0dde14ebb934ecfaeeabae87883e1cc398067400fe462a2c4e9f232db5cdd61eba949188cf01b238be7ada938f002dc3ae31fdfd425c8d46ea032323aaf20dd3de2507d36bb45fbb91c40969a9e5da20f7f936b0f4b137b62fe2ba3a667bc0362d93fc50d3f2295e167fcbab0fb3a39b7cb024b578f9490f734b28c9ccf7192f183947d5a513efa4916e4d82b2ab4ba7ec2ffba213ce82ad6ed3b10e48553e733c940aa9b9ce71337c6c2805dfb8dd6618b6d4090a3d6cc963ecea26d1cdc2bf5ac999c11276168a931d816469d79083c24081a50dcbd222752385267ce1bfc1db76b1554ad57e34752b7f8983147c116d4a3fae6f6d57e654fedd7378d2b4989ea
SIG: 6710d0dd00545b444cf714b79144fe79f38cb1c0f5b74248d4f01fe360117a26ffed4a3bf21323b28a393ae9dee07d69e583e316c6a573d37c644a8d62c40506
TST: 794
SK: b1f59e3c2380d7aa414d0bf90893a38dddfc293859303d16f00d9eae6cb3450e
PK: 84e3f5f72f19095b0f533848a5a91d0f0743b8e3a3e2f52fcbd7ebe7c5b5a998
MSG: c6174c9ad3685dd648636017837b8d992200319e9a5a0d26d94d2da75e2c3aff46f42d7b3aba472b7f860b0fe1f695529731fdc8cf0da705d1d09acad04f010837ecef419d57e9ea6cacf168c5215696f471f3caa897607c629d443de099d31753c24677d8d75f4bf17246818b58adc0424b762a191ef39a7076a5ad12614cf54c47eb0908bb866518c5fac1ca2d2e5b657520a2b3695c6fb360f16f4ab357998e4c0e97231d6f89c968dc29ecc1aa91fa0d7543b5d2247b0d85e48743ab7cc815cfdaa82bf68ca6d3e2250bfda27024d61b474c6b8154ac8d1b5a36209782515c1646680d37069b8b4412f951b025a4d543625dd02290bf03c6734613f99b7a4c3af5c5f9e9ac3474465e648423018d40a6adbe88a3301d3d259b04ee44cc0562ee0ded4f5e26ad977ab5631f85768dbce53f616c029a8b8f933e2a9264b1c81f517e9ff58ab9f45a23eeed4204358f8fff0c8f975ef1dfa5776a5f7793bae2f281d7b0cbef240b3fc6be058821ea2b800fffe55a7de0afc93ede9c60c8de005abb9a2c88f4e61e8deb3170f1078a36e2d8f2a58239bdee496e90d137d2110f0ad857a88b3527664f781939e0b2f76634ff9f6c57e1c43f58243171cd862ef4284576172af1f6c3bd37d5d74b28a7a98698bd74e57bbc142e67f703f9d62cde761a02268fecb343fc01418836414f1222ca24bcdd69d005901da2a0f94465e4d4ba68898816bf7e3e4bb79c8ca5997fba9a8df84faa2d24b044c4ea61029a46cba703421e361dfa52caaff3bbaab7fd753f2856d7c083aeb9768da11d821e2d309f7a735c399692dac2f262846b891bf6461af23c8c7ce1d4d9032c3c140f739e5584c36f05eaf4349ff4545f283a4e0fea49430a1b180d0871e3742b88ccb591124fc427ed673b5f27b0b0a6f54af22ba4a6d1c6c1db2a1fcaa6d8a0308b77ef2d0c61bbf51b95f1e8b6abc5041d97b6b6f1b569b3f63cec05cb567aaea106727096ee8a9ea87b8804901f7e88a7409c66f152de9dbfcbe31952e6fd83b2877a775fae425b3851e0eff8792ffb3848f84a65cc317253b272475e717e49e9c6ff6b7859d11bba7c4428c82d1789e0dca5bcadca2fdb259e98
SIG: 60afc1e991fdd27cc472b9acc9d405b4d2b913089290b311c4fa891ae2eea05671fde7a0ef86557bd867d1c0b747caf35229d6ef528fe3e0d0bcf630380ea90e
TST: 795
SK: db461b9f707eb2cd7748c44c99562f1302397489353df5f303797fe0d0b58de1
PK: 635116da8ba5a36a377728e28618e75c5592aecc18e34011c4c42591970b7366
MSG: 1a2ac8c1b9ea099b831a6812d2b4261309058ea5883d70b1c607b9cd3fdfdb86e79902b0fe89e80ea7c478207674b2d803b0b9ca147ffe62e594f506c796d68997ce482b51a46e49b4a5d858cdeae2c6ec9b694198e6822f0e33ed57bedb0335c7890a72a7ee3c23823be79b7f9471e033c79aeed52e5760fb0ccbb9d38fded8b47383c19103ce44705834c59ddd86f7033948612d6662f516ce4e399ff20363cc7281a69b2d5c307b10b704150184ece32f390d772ccfa78483bb77a9fba84425366984171cc2bb60b0ec6c628d4e9030746dac1cabca60f05683813346a1a5bc14727549795c1c926869e1aa25093d591b43e086e43a04d170d942c4165e1c5ce76c3e64973d9136f9325bee821682f1043e951b02767f3fb458d02449add3e8a66e516fdb1ed580e056e0f78ee33fd9ee3280912fae07fe1ea02527cd001d6f6f2f89ee649f517414d56f57359a846891f0222c321d7e70817995a8cd8e94760b6e74832bab68d55bc4641884221fd29f122d87a9a868b6a6060c87b2382cf7bbdda4cd6aaa1bbc8e6d634ab580c865f5add6a1d54e61a607dc2c37b08a8cba6e610c12cfebef9c989eef3b782acbd1bcec5f04e835ca101298b5e9bdd8813a71b0d469fcf12727d3de1c3f97ddbc6ab2658440dd6421019bc68f356d6f25536865851d92d90fe9969c3b7c35a2e88ce153476ec3973af9359f1677a4caf1cc481c71bd90228ff5fc6dd83b8a699ffe514929f5c95cb4f04b00dd18a2872c41868d3beb76498ddc9234b63f599d7071801db2c2878f7bef4ffddd813226f06db84eb30217a7183082e3c1242bb6d01cd3a6ce27bff16bfbfdd75b7e5104312c49c43aadfcd5b4edba0ff50d2890ca3cd9cca33e4fc694c057c47ebe1c20a4ad115f985dc7442c6f6da7be530b6902289cab9ca139c6b24cb80ffdd782324e602c45910db63d8b5c44ca29d27f56dbf00186ba583c34e16031df357546b3ab9a3dd65e91d7128c939195e646a0f0b89bf5df04ba233d6a12a271f7e04aa45cda99b4a55a21cbbb738515e32c56aac2496232b1008a6761c8045a1fe0f9a3644047b5966a58a600466c1b1d11ddad5aa573c43ebda887e16a05
SIG: dd049ca79beb9eac325acf44672ff578a968502fe1bcf5ea19d52c0f6778c7f1c7bbf742747907786e608123911a920778d2f9596fe29be7cc28fd009d7c440e
TST: 796
SK: f5c0a7f8f6584c5d2f2e1d0810e8e86103e4e2d45cf9a721d8c47f67493396a4
PK: 3c6d6cce49633141078696131a8d84ed823f30664b289af9dd30c6407f6f0313
MSG: d68abc609a7a0ce256699eb17043defe1eb822c9708f65718a06581fab2110ec2db09213bb9e0f3612ce4a3f8fdbe757a9f0eb2c3eba438a9088b18f6c5caabbe5c82f7a9ab2fecf0f5859d175e139263033742458f82a6f38756cd5bcdf9e0736db2cab20a0cd3f0f1cdbea8556d84909358dd8f69f0dacd49abf8ac1bfe75940d6939e6a55385b5ace7ce1fde120679ab6ea7a89d14268d29ffb46df105bf3909242c6605f3e3e2ab7448937d6db2ba054c7b14f432db41dc18a5b957336b7f52d978ec03e7d5764e9bd2f4b68958d937bf29823b27efb31e25b43925c4dacbe6718a60fea3b3270e7b76b0de0e70f7fa3c12c215ef72b95dc1b5276238179dfc52fc48859649fa582d05a60df68599a1ceea64f6412d3f8498ae2cedb124245883a240bc0851f0e324965be120486e1ea89a0182dfa8eabd3b8fa66a99c51491389f3c83a3cdb4267f3e4dbc98f0c44856b044dc88d90eeee8415bf73de171afe84be9035e0dc4c80cf0422469fe0c9bd1c6aa654a59b5e34eed351cda2871269ac478e8d382e740e9ac7ab4ddc4c0def0aeab797b6f1a427b8e4a8497a0b9797dadcd35c414fd55b783130f6cded38a44c1a89288307eb8425484137a8aedb030d54b616a82e3c5acffb08d6cc1a61745c29afc68a0c1838b139159c5fa6674d66b9e338115aad4b1b4710aa5d9517bcf7e1cb12d4e6a51c11789fdcae9d9bbe78f69a33e52df1833c876b02687a404facad32841cb2d52554e7b8e2209e3f88fd948c1ecf83957c96f43b034beda6c476096bcb09301ad61f8367cc43e156131862b42ece285bec2dcc2d02d094d042a16072eb22ab9888013be82371569400ec1f8ec7e79108c41b853365268fa4cfbc62c4ac12cc98d2ec38a87d6085859567c0f27d6d431a046e88a9815558660705fd05eb06c6c05e5b7d62347ceee27dffed7141540d608cb975075a9644acc6328439f9fa682b226b186154549011c3b0f0ff4f74caa71c1944e4cb836ce851d9b5d9e727c553e3c723cf98c273e5675cab899bb66f4633a76dea357341f983c53d9158ad319ada75408b41c06f26b7435b80dc3bc0aaf22a833ddedcd6785c87d196b0af2c9a43d1
SIG: d4c30a48c4523b1f84b14b657af8f859755bba6359988b675c6d85ddf35462820da476d84f6c402e65b020d9e8a2c285c16708ae58d1f8dbc65782a898a66508
TST: 797
SK: 1ab946c0c1aebf9ca37c2f4e2a4b337d5b1ebccd24734c9cb2a1608c881e5757
PK: 9afc63dfce0d489b40907aeed6dffe4cd8ef5a6ffa22989556445cbf9b3519c2
MSG: 9bb071b62c04064b0c96e243dd198c39717b25c99448c2c002b84a99204c5a6e23b4b912028675bfdc4df93c5b2fb80881a23e0d44ba18bde99121eee86adc6f842819d6ebc7a288992da3285805a8b8b6fbcd2267b686b3e1bf7960b45f244f852e82492944e3d618bcc4514c17f722ba49aca7f2f3bb4e91f940e9cef015650c3e40b0c855a17c42f11e3a34acc85287dbe0f9093c00373d50c0b3064a5a5f2b1e89206517528295fd871703a8e762b5e76fb9b7473d2149b85b9461f5587ed7e7fc8b50aa09876deeb6e237078502142cec6bddc70140fe1d1f1658d5d3e910fd7036a2f924b499db1756f7c8ce0d5f0d045b39bc81c5c2f1a761f52ff393e0649b8db0bd8854bd026be2c7c3cd63526ba5a80d48335f033832d63376071b6308f05960cb3fc9fac932edd8376dae51f2c661f75b7c6f4ac856753aca62062877609fc4a0ff60670282c05e882d1a035bf9890cab296ac7a8df244c56f490250f020054b8af51be4fc318beba506232bf45e17f5c740cf09d37515a8bc894bc955c8a460877c7854f8be363b21933e16287ae0cb70f222d4e36b8b424975559bb4bfc8dd1d51b3c0faf4a53e302196f9fedb53287d09315dfffa2bc4b3acff137f9a76d6856217f79cbb25433fc97899fd6540f18088e84417e4833e4a91aaba4658ae9ad7f760dd9c5b7191a0d3c05541b83c025a7992138e6d1080da14c2c887c6d670aab374d436c272f9e96f85a9c423379c0d47c46df6de334ea2057158d33231e1426a66d3c70827aad5511b846e03b94923d5f94baf1f8cf11a861373a5b80ad5e317ec2a529e94e636cdc3aa29e5dac205a0c13f68fb198cf9456e6390aead4d9782a1038f6478d339a81bae7af2a04151c2f22e8d39fe071e1a52168d57c84c36293413f8e6ff6934f05e7efad6fa120c8c1c38ad1886a3d00bfc306459203c02cdf4f06652bc8fa0e8b9cc779d43fbb789e7dad5dc99f41d4cc588c1b65426a4e77389edd04977578f8f316bcdd9461d666472cdd276aa569721c65232256ba1cf0e7f5ea55321729bb0e0386a77b865532024696eddef485b7d7b28c1573b9347e414d4261995482e3b312de1331f84e7548607a84
SIG: bfabdea41810a53f8e527acd66ec106ce2ae1a67ff6a9b522e0f08fbbf1252682cb3a1dcc875601944cb88000f72e13907007903a77cd0db0316d419ac38c204
TST: 798
SK: 04bb887a8a3184ffc7ea09c9bc7c1f7c3411556a7c7c398cb8b2d98ffd9ee866
PK: 6ab1e4ae4aa0d38989aeefa805b578806e2e971ac7ac05409958bfe60071f4a7
MSG: b7ab0c8163f478c6cabf2bbd7ca37cb02456d76e527eea1b0d26db242e37877632985a3e3ca41b52e21d79017bff81ee551ad72af277b410e42af822c608cd69d00bf440b75b787a8c915d70b6c6376c3f67fa64d612a1b449a7e2134d9c23230157d576e06a66a8422a611e2a0f097286c199ea2a162861864bd035076ab20bbae2b4408a2c6433cb23433a889fe6598f47be53bbd2c80f07a8fccb8aae511161e609da4d180acea544811e9449c5dc2250e3e5a0cd41da33a2da632e6038bd86f16d5b7c1be49fc6db499076ca91f7aa028fe38529700b21d072d2b75dcc8b43781d4bc4d3bb584d9da01c3ecc85b1e93fce045dadceea5106468bdfe5f70d66a4fad60e4fb864ec15ea50f6cb797223c8c756f7a1931a39464ebbb9679f6b01687c174eaa32b968b9cface8c167120aa7bd0242f003a0c377702551b30da2488eb2944052934aef4bfe115f0ab7405a3d5fa9bd796b371742bc114a9bf28c5bd25626295ce261a6a83ef60b77d2d32dd7105fc83664aa89765b3f8191eeeed878f2ebff2fb97663a61877c093933bbd0731e63757571b0e37cac99ed01fd214cbd4feb977e856e0a1a7ef0c408c20e0ddaf1fd8f028cfa08c850fa7090dca8cdde0cb6903da18c6290c66a1c0ae0a084bf250c51a9d035e5b16ec616636afb9b5bce36a775fe2175bcc2ee07220834eeb31caee50e9f8063fb1fc8468ae25e3966789a6d8dffe08a6f7a1e6726f93ae7482de0262bb1f8de0c95a99ecb95684d44b3f1a332a18d2cd3dcf253c33d735522f796b651c9a633a8ebe95d02bc0465825ee541a7d927bb5b90a6db5499f8d993ab404b1650b75e792a7c834eb41f0470138b0f578a04c9ba5ad950ac7c9b5d328f3408b645ad9c6bf196dd961445596bc78f284b8914b2a8cf9b7bd3a716d8f144bb6b15d831023713b5e41fda9b587ff9d6cc43c08d35a707f495283e1ace960487e7f02b7543b68a731a29bf3be14b6e9c37174a9f46f561199dbd27b46bfe62243e0c11c0edf13b64f411c8e8eced35d8428f79f10eacffb7234e546413d1eb0fad88c0e938593b43b5ee0e4285d4dddf5295dbf1a3ddbe9f4134dd76d3de70462c2f04fe0aebdf59a
SIG: cd84f55e5ef4531924c5a2181ec87a64541388c1059406bc07d53157a168e203cc8aa0f0069d53ff58a95b8a8caafdad26363c7d0f8045c4359e97b43602c606
TST: 799
SK: 9776a467fa1400735412a79b495f9fca078ce1d87a8530d85c26055d3a394488
PK: c7dbe0e41c0a31c0942793ffd142d8b95cc82e5caa92a379ba23f644edf224da
MSG: d78553a1b7055b58b213101b1c84c53e164e39c6e9d36db43f30e19e2a125a9a67709eafef964fa5bab7261ddb3a8a0188457dfbf5159c40e51da8208483245781d7131e23a8bee5e506331816b9deeefe6e556e3f0c95c668d1bedb7da635065458ad20467012f59f171352068020ce3c75878693f6437bc4a09f13b9b0f0cddaf1691b872f82008093ebfbe233d0313e72c8632d7d1793f0b81c7688f54470330f04e64860e6446bfc6d96c87569bf182f0f4385af485d4299cac04e06ba473465566c477f07b9db277ab4a9de2fb2ded0a5011cd06d675c0800b34f55bcf3ec72d21ca150c8bf2361287be81efabb96d8688a1dee3f430f06f637dfd06f151464a05c95f5fe76af2e06d0123f6948a26b3be835045aa268cc1be976697107770208a7568f025c2d53c719e524cc369d9b4a337d8fd1ef345b9bca57fbd7b65a6b997cad3fce4cf06f2ca43ebe2986d09682d47c922b2cb7569d98de97a6164f5470eec71ceda520ccec7732bd01689ef81656e9f6d0c58a895558aee863f5469e7ab97915bfe0b80a064c659b183031f7f1a86fb11a9d528c2815dcaa2f0dec3d21a882e106e20493ee0acb7708eaa2912574ae97bb288b41fc0925053a29b0bfbc0ebae8d63cc0b46e3738046c5a202530bcb15b187a72854aa2d8a7a76c89a89a5db46032074e1bd7de77ef2065a08f389d783cf759ebd5a63a44d919f948f560c3e94c4239e274e051a20485a430cbd529f313d9f7ed679a34187b24f8413087a9021e4731730f5f461fc5aad6654dfa1c0504d26124707e63ee57f931b2785908f86b104b3ecb96000251d06ce1fa45e4cd6df91ac15bbf7ca3c3eb8ee0827612a29ecb7a36d5470c40505182fa9ac913570d0c1050d9a43455cb7bdc17d169805f018956f854f8919bbfb719e1867b36a64aabcdb807f48dccc0672f67887450b3f3e958d78499e0d1ab368aa49442e5e8a332bffd44c169ea67629c85724db6f1586b6c6b5be4864dfd53da7c0f7b8bb3573116be5077d332bd12a6300f3a68a89866b479ec2baa277f9f56f6e1d49d741eb322035ff8cb1de85c8dc87ac8e6e4c5d20bfb6d317ab125930c42609be3ae82242a9ef0568858d8
SIG: e1317ba2a123ae3b29e7b60e8e93beedd7a08451a013695b6dcf358e4034026dc74037afbdd217ff4b148b029138f4bcc8f9836abbae7e6276e9e769dbd8f007
TST: 800
SK: 09d8122697126dfc7e11685a04123fdfb47ccddb4499d8a3aef418cb65aed7a7
PK: f8ddb1c00f6e0f4beaa6fc38e5d0a5775ee28c80dbde3f0c7930a33aad7150f3
MSG: a0d8d8798eba22f56760c30643e9fc6795547ea5f2f2bbd11c0392b2ebf711aca22f0824199fc3188a45bdffde70ece9ab15a5ea89622a5871e0ef7685d10f1274cc195b4fda81f879d1e9bf42f873b20a859c233f9e49adbf057731e11335e9b6d8ed0e069e134ec461ca8890d7b0473c405e8a9d95d15711b12476103762c626d9f2aa5dd519bd825b60b3234ebf651e0d1933371c52bfd8ce33fc36bba328f7f3f2ccc01000a89904af37e4e1e9e15fffab5c2b0c47f37cdcb068db33ac36a5f0d6de1203fbf8949324bd3efda0f9889db00da2317b49fd186999df7fcdc3cb4e1d18faa254561c251178b8d33fdc9dccd8d2d721b93a536ccd3c0e9c856337f195eee7da9a7f6b0a42b7c541c6a68c595bf34704d9fe3a56d2ec8481d577c96ecc08b8e40acdbf050e20c683f39c414e8cbfcf4a0152314c05987a83bde3025b735cca3023abc5feb7e00d0236b4f24b15e679db052c8d2fddb3bef8663a6df819a9815527a1a2f60a0fa4e5078ddc6d435fe89287b30ffdeb5d9ae05d1a8690fbc7590aad57d43d22c12ace2c8196888e354e9f782f5dbb44149e83fb8bbc9da6d89ce206c1e2b6b2b28f933f3e5ff1175a31a8ff5d31e65c8b00c5ba462224a1e09d4f09cb40fc87c36e7d285c774a96976203651828e783628847ac512e5d1c35b35b030171f92396f5ffaff585cead04b6ae210d80707cc6832d98a20d3a947648da2604937fefd25a9fe0fc5cac083ddd7d2075307f4f382664f687dce8c655ded9c12d48ff7601df2a48d37fe214970844c075f2eab002059fc2271e617c9657a01bec1dd38f6c28ba8a617bd30851e3f9dbac904418df1d0215ad45dfc9f02b5c5e9f9bbc6de8b07af0bd1f7fa8922544f12d2a3e1aadff7e9c6b93320c3a61ef33da07eb87b1617f9e77d7702e558bc7d8122e0dfe2ae83e836c5b1a62aa585c0dffe716f7463c0b33da5b1eda556a1ef1e45042c79bdd3ec3cb8863a7bc1b0f7e1c05bd9920f05b4eda86517705ed07f6dca7bb00ae0456e6787d9fae8ede4ecd0bc572eb5cc6d19e891f1bcb229e9409e06574c7df058173cb58c3fdf20f3ff17c3705af62d9b7225c5743f600607f77cbe7d6e7618abc79
SIG: 18cfaf6dc8e4e8582bcefe0cdc6fcefe6a4a87ea629585f37d2fba446b3aebd452426382da0d491c39cb7d54d273005dc132121568d2ab674520adda7523840d
TST: 801
SK: 10201bf0084367590de674cc0ed2648ec25d3ba8db40d00ede153398508bc126
PK: badbd05e5f79e31169f740ba46a58910a1b77705af45717b2af80856457c58c9
MSG: 7bb1470617d11e45eb602a829ad773ee2bb7e6b88da4c04a7216a450f84993a498cbd3b9254028f2f99fc21a23288bdc1e151a72a9130c3dedda1bbbccd4e6c0f48ae9f35318cbefc959f405045e6e0b5fb2e738f2b765be11b1b6a0f1e8319549d95fa8d1df8167cd4a7717ae1636a9df54d96eaf2d63236900fd11338252a5008d5d480e2b1e9861d1f70688c47eae4689da01a47da3dfb6d2bab3cdf505ee5d801a152c267093d17e9bf7137a6ee7b834d0085500e401c17f3286c1575d1c0100fa9807630c4a990654c1e71a8b715627bb13d442c84a449844c404b872bfbac718a48d0ea0945c77166a53139b0ff0098134764f9ecdb88eabe07ccb2cced4955e08249b2f5770ad41fccd7b5bb372e6c33767e07f5be7d10712de81841b134e193df0776a0fc156ff5d0e96f40a704753e1145e9fa083c4ddeef4416234f6e1a2382c8e5b3ad405458e89d2f493a4d7c29a23de2107485b7f56350124e7e0d695c522b6de7a9247a2924ce6f2863236c10cc21264ad54590d314763ea1a19afacd90eba955870407e8c6365a143a5c1b9a8be5e4a4dcadb72e0d47649bd53abd46b5c6960eae2cab773753cc0e04e99414bc2cb30f48bb54139d066e43e2f0e1a4ae963858bef967df8c84140d2d09202b406d5d85cb7a96cc57f233eb2187ffd02f94e92297b5e69d969d3a5936efe4929144f258bfb39dd0ce26359c4549fc218a0aa54f31bd551b8781acbbf61cb3f732cdaf622c6a69188cf557a3a92ed153e69125a4090ac451536a0e9a63a41782910ffccb4e850021123ffd1f3bf39c73460a65ccfe4dba9bdefb5d5f4da6c469aa1322fa27043238363ee72918688d7ca1c4c2952e430d563256bb86d350a35ee82e01504747f31d02e03aedda546d0f1b2f451b870821602d00e819036ade5a7c7fcd21a6de6af35b1f9632a70af65df6445f6fadfbc0f416755c8246640e56b856b66ddd92a60c03538221dc8fb142ce2dbacdb7425f33cb85d850cc02c315cfc111f6f651dde1bdb67fb208e1f6bde784ddcf7bd18c8051a2e0bbf1018b8f39536c589de65eadc6cf379b77cad13f9089cb323fb2e943d06cdd10705c121134c6548dc53415f8c370ec690
SIG: f1d996588b298f271e970cebd2a1b339979cd29dddee3645d07fab8ab465dde3e98667ec01ad7f1c0a6592e0697e665c72fd3814dbe189ed5f4e76c794e53809
TST: 802
SK: c4aa425246b5173f5ef898152eca3d092bb4c2dd02853fcfc7178399f4e2f758
PK: 29b77a3075f419243c0c1bc39659d73117ac00e55e8de38fe9829a879cc5b8a0
MSG: 7df978a1f4976838ffed7449a4dc138b604f4b2a4ae689ce75018ebccdab2eaa0b60768f7208257f2b28e7aa09bf6c05888da46fd396d1c803011750e30eb484870c8806977696f12ebb9feeb4caf92a02dbaa22bbff63f842c3ba147bca7c00314278acd0db173569f4e36527958ef6f1002bd3cd01f407a86531edcbd9f31b3a4ab880a4f5b52b42d0d4a1ba66a2098651ae3e6c9151f40273285f7f6a4e81606bf980f689504b42080fdb97c72846fba9047c7e660ba5c6bf126a9a599e2571fa13505af7581bfebc16513f5c94dc71937e6e61b3ea10939b02ea10859f32d7912b9e3806abef6185fcffa68821478005cbfc1d637dd020425620a318074898bdc30931c59ac0c66c4d1238b097cd5b170f084435d4bae48a03d92fd48fc2caa4ffc505f1bca516fbd6e4f888cced982ae0ddb88fc28aa697b7071d015b0acb2809b01d1d9c7e7b53eee6824cc37cce5b6993d88d83eafc2e928a6f147db6eb80b1a69f01605b046bd2fd1d92c5459d6d3398a9caa299ddd0c3ba2e08941307b120cc13992f7003aced14a4a4d923bbb12fc393ffcf920b9f6d4775e94d4a512267fd26a6997c6062b4c9900f9862b9ea0c8d7df19f05c2b604af5b9864fb2754a8073bbbfb18233e6e150f72a525e3a5760fcda7d32a60034f956e3cbd3436c200830b3e7a14571220bcb627d5a4be72c20b23351b2d920602a51c3eb32c1237039dfbff43c987fd8563777f0e5a39f8146c164bdffce44f3b13ee74d64bfdcf9803f03dd0172ac4fa4bf6c7839cb11f3d34baef0e32b54942fc4fa38f473e2966f4911c0e80d76937b25b7632275ba88309635a60df135489208d3e734b672eda7d2ba21579aba8d8860ea764fd67eaf9c38ea7637d1bad57b2f3d782b91e1d5d92ac300bdba7ab9113ce913d0c793c12a9a726e3fcab05cb479977871640630d459e69e81ca5cf56ddb2a0611d61d481c1b8cef3804bd4e5754a61eb49b17ef2b03c83057b5d20d882058c00f54b6cca86be95350dd7bcb25e4c1c4658f45229c8bb9f5cdfcc44795c978e3388d325760106e52be9834bd81ffc5c62486b6f33c27459df178eb946e7a82db9ce0d295b925bb6126dd55c31f49a68dcefc7
SIG: 5d8545a4be3fd6da2578c2eccb648d83fcfe587133fa7ae4a1cfca9ae6daa49259c952044a85a20b6f5324f827dba2d1a8388c40a928b950913c634fb3092707
TST: 803
SK: f13cafde6f39b963dca96626862f4fbc5c2e00ddf08beceac7a6e2fca9e1ccf7
PK: c1b01a91e8ee0b9f19a72e5e7e0aefcfdc44a157474e99feebd0ff552d73b2ac
MSG: 2bee73b74f1b7622eb096a28d83a819bcec22d9999a32062103d604ae6d78edf8f893895d2220ab75690410c58aab590a98ddff23a94d2350f889e53464200a527d54d62571107b27e574f542ebac249b8e2e3ce08d1bd27bd8d29f2e61243deef0e6938e52ee2992ff2187d7a7f5282edd98fc4985b619acb80aa9d03d6cb84b821106f40d6e5f4c387ab0af6f206615d0a175f7e60ee2755aea34675fdd823eb24109a9bd818ea2d9d9bd199cf8dfe79624b0372ae85e98c60200234bd413f4a62ce68a47b6c9b12857c0d399a448e5a5280e9f22f9b12ea2cd3c68713e77d0a11f3628d8ec5e060639031d3b640021c9c38809dc5f42d2e1c2e2346c86e24eedc5984a115a42de8de7e35c9917539e89885ca916e072afd5d46846b2a935961c2fe28e9eb3c8f896b86fc120cbd3af2aa139c499d29cfc3699db79c14484e9ec257a5f64344b7ad1e3dfb34eee7654c6bf12fd38fbba80fe1762aab57112b3a94e2bee79041d1e88440f85fb72dde68d49e84bced998a2f6335446e4a835e70c5f827fb3ad7823d5fbe3be5f6ec7e434ee524ccd9ff5b7e72a32d091a7e17c8b1ae41a1af31793cce91d84c3622678969c8f517dc26e3cd61d2446912283f9353bb5ad03c111c6233de314c61b831cbf38b04fe58cf44f1d2d0b45f25a6b4e0256859cd5d830fac5ec3c8d76398559e9b26010f5e1da5f25d2200935453ffac5aea51f7e81e72ec8e5f04d2f885c7b45c63f64456cfe231b8cb24aa1620a902639ca78dd391aa4a3d03e11975c8907f964fd55df9bbb140e38d6db93256b4b39c2b7bcbe35b11826bbf8c08f1dcb48edc4bfb70462a35ea8cd8cba79fab8b4c44e73be7ecfa112166f6dcab70d8bb55d8b8428c2da71aaca2fc3d90f3cc5ed01551358d60789b9d571efe10892027fa37404aaf59ec1c2d7111ecc3592467ed1d9b8aba8e229e32d2a00c19db7187fbcb122061961c1fdaca307e9c9c9de972ad51402fa67dc1c2a403b3c5e8b1e246862d6ad6a498db6d761fb566f6065942b60ad4b4309d182bc5154cfc36863185a87e23abaa1d541ab763a4a1066c0a7a8c3d821ae32fd31c8892401046d0a20e91a64779f4bda81120af3fb3486d3fc0a7
SIG: 6ca9f80a62501faf319fb84af471f676ae3fff85565c97981f1457cbb8c49f97b266316a992db0d42bc502f095a5f2d9a4e1cfac0cc935d3882c8a3a0ea6e10e
TST: 804
SK: c846344261a34865393834bfaa3a15a3f53ac9e13833b0b287122781b79de392
PK: ebade0226195ae254b6115e21696a9c65a19d5e040443131c22b89f02f69ab78
MSG: 5abd13e95b6ee1d5514768282200a14f7d1a571f3468e22efec993463066a37aec8373e5fb499564191f3294a9b30afb5f1a34d4d88abc3e9bc303c1aba05bd8faca90ee35d97ac3dd9106f6fa3ca81a3810eccefa6a209ea3f3fc3049dcb1b003c728f7f6374ca98c582de6db1af760f0a02133ca4a010324304d26a0e50af0d13c134da34a03a41e83ec8f10ea5b859bec1f51b01cabb2d16c1fc52b058f8e5defaede128171c2e026902316f871b35e3292656f0e5b39bbbc81d0c0830e6ac01fac9b4539f47f9acfbd58b7ab9f5a125600f251a271d7bf167f2954ca8e1e0c96e16b06e8307df88bb8e9d57d5ba044f27f3eaff81d9f150554aa7122fd10d11f35d2be2b1624e3e1a1d77fea4c5c7f8b983e945ba8c08dc1545b3e6b2973ad041c44d0617eccc871a3821a9ffea9db7c2b0d055da55de0b35063e4225aee6b225ab2a7906a8ee329d1b3972e0d1f70817c50ccfe9403d12ad62c94923b9aa2d7f85a8dda47be4dcec0dc2b0b58f7ac190ae0579b9b13bbb8b16a31b0ab4d6f2791253ab4751b536b88d3b4937cc3a110aa82a6ffed6853524b66b3effcd2f63c6f9645cea13aa23cd1c99d9ffda4cd3a9c5df45ec74726c3471128b7089fbd82694d2d3f08dc9306c0fc9ce7c801138eb1ecb756e571e9059b75ed03f92a31502fbeb5fec51de9359010c4397d28b65e356e38001d0d51ac9600728c78b5766e0f217938b410e785b4c01e86a3452bcb3884aca47540859cc49b000f0b61fdbe72752574b27a22d4c40413a43b310924b1bb140fc9fdaae266d65930e3f234fe841d82b26176ff86c5d2bd8d965c52d728064ebdf68dc8e4834941801cca0b2f256d4f6c3dd19d35d5362bbf9b8a3a1c863e092689dd2852add488bf42685b11e1e1ad5745d075628d731f91cfd749159e2e1c837f4ef83d80ea1dd9bded5f88018ce1d4b3371f954353f3d894370062c0965d67986dbc481715f42dd2c91607ab8b5f0d89f66e68d73d50d640524d72e69134b887298e5cd8c4b905ba5efa0e9d685214b842f50a2a3983a1af585af2ca43dbcf02c40897ae2e1ab51dbce570345e8e135fb7b4eb0a1d6a0bb5a8a1807e425b2d628360768058e61ad1cfaa2099
SIG: d5e41b47ad0f3400709770ed43919bafdf24381b661544e51d8b5cee9e97b3676a4c0ffaebb2cbd2db798532b65cf654a5b6c166ef886cb0fbbf4a4f844c440b
TST: 805
SK: faaf55d3c29714b65c2281e2c22d6134971a2e74008fb94089a773eeeb4483a6
PK: 39862eac6dd52e381bb34dc196ba8a374dcb7df6cb140fd0cfa6cfa39b8c753f
MSG: 94e661c25240a89e823d7f5dc0e692eddd1370c35ac44d5a8c8798d0c9aafdf0bbfb549260568dba1c69086bee636be8edccd3cbb27016244d54d7ed2feb7fa64614d45449d7e058e71b306c22e6911c2ac74207bae5a84d0fc247be49d356e5d4353ba5586b6e4b2b97ce9e2377b6eed92c849e676944ae90dc4208e300e19cc91dc26bbdd5a30cfa9281a15efd873066f85af3a26f310623e009804853cc6855903ea64a909897e315e73d312948980ef6289db21a5ebbec8c8efe20d1d53dfaad6d9f4296532e887c37350105a633abc773188751b28c3a08f1b5ee0472de4627e6b61b68278dd51ced6a61ecf38886e45339dc6c60c31e850ef8296ae80f9d31701776eb9af21693f4c52ec062625738d4e3afbf71d1c81fc4846360363ea541a976623a5e4e6b6a67237e9237173f1a1d543302858885714c2a591d0a786282a0285a3711f7bc2b63ca7987e9ae7d02035555cf3b6ad6f71ca98aa928883bf81dd6f86493eaab5637b4dd569d1ee8de6a44bcedb62b9706b1db89e3f05df16310017d89ef3e4bc099b721a5c8d38043d6e4a22cf04009c0fcee6be69937829954941b8b4a1ebf4daea0d774d0782be176c8e591907756c2cf75dea6f7877dd6875b8fe1012f3050cfb1289cf088667e1522eeedc927ac86bfe2c407432b4a813a6a7a5504e999206db1827e25fafd70ced36db3b281b6f7b14ed5baa0572315a939c5bf4abb133d2e7b16d52de20817af055df5f141207734610a0c6eebedafffd9cc9f069b67f9a1c0454be41d54c138be542e5e38cfe2f293f7d2d3df66977acb366a42c19b3185acfa1b363c6131a4a8111c3b1f4fd7ac406d0e69103ba15b8c4bf29bc2ed9c45cfd1d279d8d931444b2b1849252b8a70eed80fd260edf5a3c01b9690160d2311851d21c9302d985986eaeeb3ae2c07c7c7672094f91db0bd50be377e4d1eb07ee76af49dc136a145a11b172f0811fe73d6259be370c4dfcab6f19e4a64b151d0a6db8050c3de2cc325f5c5f6594cf6248eb081209539e08ca3422984e7bf803de3a419b14423f1e5a54224042ce4f05488a6044f4042bd649b1a08ce10c2006ea76efab4641fef2897efd724e6054a3bd1a69e39a4a5e2d502
SIG: 5b0083f7a82061c65cf6c75640c81c28e8d6d2e87f6d5795c9aa3bb3e390e91990e82db6f07e614f507a560abaa1eca656c678ddcae8198251e6af0b76b88d0d
TST: 806
SK: 6d7855e30f7a13e237b067144346434bb4b05178c7d88d492e79027c4b0f3cdd
PK: 7273293828efa349822392dbbab07879577e1a77a6fd6afe33753a9eec88c4af
MSG: f8b936e793b017580cc0e9cbda2acb6474507f4bca3afc8783ec46eeb82ccd4dd2525676aa6ab5c0dcf7d75f7e0311e6fe6bf27263f8578feb55c5612d1f28e888b76656c41ccd8a70b9bc604b42724fa2bc411d44c31ab68ce84f8393399e34d5408579c2ba2921f2f8d11487aa7e52557feed96757199d3aae6377770154b17f3577c7ac3d8c76cf7461b5e8d42a7185078ed4f862fc57502f615075307b6e103c77c1f6c8bda7aa17e435e21b949af44dff5aa30a62da712fa9966a612ffca14871fd6f860b4a9614012c5369910e0ffd6f0fbd889a9c257c32bdcf90bb80627cb272ecd4599897555955e1fe08cd7ebb21c071be0f48989696cb39aa82ad11baa5d4ac613abf1b6db8a20e686836222833f8b6dd2f0006227be48e8580dcc8de620dacb2f65a693675d6cb45ba5dd1aa70db76bc641d4fb567ecbc7111442e294158be575c71ddc26e94f41266a2fd3a0d435781fc094648fadf5f17cd41ab895821894ec0806b262c393534fe66f21e3783c14a96c88f2e0653fe32e75dce8a463bb97eed6c16f3f3228169abb5b4bf9ea3278c1ff0f86eae71389b6433acd097eefa9e6e05f4955cd517830b8d9870ccb5227415e50f23f6473217a745096470dca93d2b34673c5d6a57ed02c8e0cae119b3f329d8ab6498494c2921bb6f496dd08381e7d39f2db5763b14a2821befcca0a9fd312545de68abf206d12d8e02e73bc7e3cb796e7ee26cc63d741efafc5345f8132951bcfbfddf631fb7cb43ef35b9453c9390eb23b1f9d8b1c72debd24f09a01a9dc60ee6815306188357781af6e1820aa35e4ec121b7ca34d7de7611b246a3e703ed48c7eb03a6fe8f852ee7d32545c9d852d64d5d75930e5f1ebe21a307efa7622edaced6d879026f0f85a9112012803705582269d39f143234df8909ab3d948e76d3daaa24226d9ac601eef277fd2cfc4a19aedf4387a21617b03ec3d3845a38554f5e97036e56ec1ce660df9c062c2c993b77c5ba6a6d05231dae3764183c3e96aa539cfb3415fb163c645b2303b2d6d4bda8ca6c72bc03d5305f9b118e925e27d29ab7dcb196470e6339631b2380744c04d1da348fc0fe274277f82f95bdfb0b64b4cf3b51e571c0ddb3b53ca6
SIG: 0fe28eadd9e5dd574b3faaea810d44522c8b1bfbb3e3d57ed889faedec91d0e14a86b914c4c766f1bf9b8f18b0db890db6c1b125d57804333619b1e0720a3300
TST: 807
SK: 7ee4e7e98c6a40f0e74413f24039bd220df1f8c7f015528dbf5284ab9f7c82e2
PK: 4d5a800f9b22070e016ee23af8a310902b369d589a847f345c2ea2968d6d0924
MSG: 8fb01373c42e69614aea99af49323785f33861b94e90f565389ebf70e219f5dec732e0010b58f7290530df222ac9c73e1c2e92a5e6061de5590caf9c0d5021d729eaa11541fa1d082160beaf611e7cfdc0ebb315d388e538b4b5028f9b30d3d973347ffd44263eef083b81b21b82eca5756a494b1d81c07de849506d3e3b668797a5c544254d4ebe5cf8171b39f8724cbc4189291b3c53c21ece49a1d739563c65b49025935647a7303ae0ef7f6d24554645a428dbbb42449f5399e36dc787b7d6958a02eebbb836e5e53e26e487239de94d1d250e7943ac0e22d92750a0cf3473be1a6225cbe79545048269f6237ec9f9ec307e8a34b7bb34cd4906e43162a3708f329c5b989d7a7fcde1099a542546fe9c33182ba51b843e96d11c79e91ad21f7170e257fdc2818e12f9168a974c968a4d273fa3ffa9f35ff905980eaad3721cae802bee36210b40b99319bb669982e943b270a4c4d0a92ecb5bba2dd8b40ac3d2f0325c469d5e9d483f5241974010c5c0da335f16e962196c2ef14eb24aafbb311bfd5fa8dc8d2d61e6878ad2cce0dc9939e44522723d427ef32fb43b967f5e44fc665792796f8cf934f01c325d63d583dc3ca9d4fcc757d9178580daef53aa3ab21d2ce435955d1c6d47638c5edb62ff5561693d1cbd10ec9e399a71bf9db1c9969fd59e4eeb31aa59bf39e9f184178def7246ed4b8f4be5badaa5db4af867f4f2ec39a13704202c8784fa168ce96f9cfac71017236275fd857cc3c51a9c7ac256215e14b843f7214dc9f824b91d1a5170d0ef1d37696f93ee966a2b7dece22b4f3afd39c16d601e5ff8408d45c1a6ce71f060976c5be4c042b1b738df9580ba5ae77880a70c0b94f0e1c9f9aa34c090d612d57a9b931f50a125fa35ce40a2cb7faad530f80908c73cb78258afd2631390041d92617e9bf64ce96e8e4ac7f3126d8af8a04c75ffd438769de06f74c2fc20cc8192da353e79061283bba08a8d24e6e4e2e83ba5b08e4275226062148d8a02afad65b6f627cfbd29b71ca18aee5b1f97169bf0228b376f4106b50fd91a38a66211d69ebb4a7af0e1c2217f1ba014d1e0cd17508d58155d163dd9de2fe1c64c7f88d5b553e9ba1e1f25430d7e125b07a8c2ed
SIG: ac3bfe3adf941c934d3349c492de70d5166be389f955be87c2883f41f2da146c910651a3b452c2d739dc9b531c5745565e69d98359f1d7d93ebd36d70abbf00d
TST: 808
SK: 1f28d9091d196cba3d4552e5a337a4d8af3f295e629e4ba6fe99703120ae41e0
PK: 814d34bf28ee6d90f039599041db810f7c9daa918e03e96197414bc9aa31ecdc
MSG: a69468bc33ebfef0615c643c49dac6e04fdb6cfb8ec45857bbb7a27e528fd631fc3411baee65cc1f94fcc94aed4a4332fa6861e065e06163541709d79728e01be2b140a022c83e7b23b9ed2ad2832169dfc95690913cf3720130657080c9d5a7827e5660757452c5fc3dcd80cc6be098c629226d5466e02b97126be74a1452ee16815095deb42bf06566715028c11825820a8a23c60da2b68dd9a55dad2a29a4964443817c07d776b244b15186819a3bbed414abf4579a3ece3a3dc7b105d0a9dba37b9eaa78be8e46e1698b59b0940b01f38b283c33a9a4b1d4f8144b16eeb5fc0a7af0d081696645a1eab3a787cbcf88fad93dd6cd46d295a879a1775033a98563822ef1f6b69a581e49736c8d701b4453969340521e4ad4bf94b911b0e2d86f34eece4a6385ff1fe63220cd3cc592f36d6c491fa18f7c1404360d2a7753fe073e09a2fc42a4bbea55bc96d7f05c98aed2cc4a9fae8fd4a0197ff01fa7f0046e3c3eb59aaabca313a4ddaa5d20d27c2c5f1ac6d87fd3cb4bd35a1ec75d104f7c367331a3e295e53c4e80bae14b9792d0d526f740d4ff036faf5487967ffabe8e883d3fb0d16faadb28e1285ded41570c0b07c2559b531e0f9254ef88e5b10f64f4839a9a0b6c3c7f1b7850f4ad9bf0999a7f2ae7c45a658ea53036fc70199842b8e49e60f967de1ff3abfff6cd735b7cd8b8f9e248f156f6c6543869eb99823daea88debaf79f01e6521ec63fe72724ee3c822b88b3968b24852091583c49ab3c15fa1f79b18d98f04d9b6841c9a7ca0de2fcc02f95dd649492e8b56a31ec1e244337af6aaaede8bf99fc814ef57c0d5e08c3c7ecc1897980aa169a9926d20698df6930e2110cb460f49390100741095f8ed00412ae696d98efefd290da5f7d0b728d20a1ebfa6bd7d270f281a98c7b1e408435125aa483c6b7d633ff7588a941658f6129544d62945b9b8af71a8c62c0a50076cb8541ba7e4bde4ede441722c6eb9df8cfd0656339e86d226abaea05ea047f6b8307701f6c9a44cc9cb837b8eb62445925e8a8881d2538fcb2b249e4ee8b686ecfb49c4df86401d249aac35841e914004f9455d3fde375d20a01fba27b197a698d384c76505106801627e8336bd2d76d761a8
SIG: 5be552fa731e836793f6dda895dc9b1e2ccd669de1c843e00ea6fa3c5ebf97a34b26f1f3ac7ff2225ee4a7e430072c13da4066dcdcc05ba2b5f61a6e8d210709
TST: 809
SK: c64dd20d42627526198a22647690c895b5b45b698f57a69dfbe48dbd426aa470
PK: 2e01d40416f78acddb34b8445ea4fd0ab3fa9e6643044752213f07c7f0ff43a0
MSG: 821b9f7c16104b533bd127184fd72ade092b13bbd9aceed29b8d10f16688922d165f8931d53df590fb713b674d805ce0c9d6ce6c43ba6968191d12bfa08a8ce22e8f336b2b491af25d1b1606f930caebe522392a87d42ce7bc167aa7b610597220af31a665353071e8d9e5f42078b9c388bf040258e21f9c3ab38c0427618b2c28d3430df27921bfc58487b3461978bfa8bf586cfe8358e092f8f47466e762451d50164a0d74360f66b4cd3a3575da01da23752430c035da859f577de22290aab4ed7f34d267406ab547eb445cc64df53019427f4eb72bca55397153d01ccf7ec97d7a967d9aff46231d2e2027b38f3b41bd2cb1b798a4ae88abf4896216d315bd5383024259e59742802a911badcf8473db91af319733320cb9521ef9ce437267b6ea17bcafe5d0903b123a35c988f49834f61dd552640a3276da26af17ec21a20296586dd6f4b36c7a4f0b899d70b42af89e29370132edfb72d6834194a1609360b1f1feab89b96b8e8f0f68987c57cce0bab768113718fb1709de2df32177d44085da5efd9da70e1a858c92f245acfee64b71f3eb16e04fc13989e69337999701dd73abc266c9fd4cff91a0fd04fbd8b13b12e6f450385715848e007fa0d463119fd7de6325b640042b654212e0db8da1adebd2a7589f77ee4f752d282ca1119c431b17ad0a021ef2bf95e5ac4704e62d7039d0e651e456d60e63bade401cca77c9a89163174d5022d745abdc76b9ffe2544155235e3063e6e4aeec44ed5d8ab408d966fec12016c130730bbc558732065da800a70cbfb0fccca45d0028cbfd9632ddb2f0ed12edae7b930b106c9d1285a4b870de7507999c74793dd497408719c898abe49f7f33a33e69b50fa5af9480068566d1fddf4482d79704ad8ef11b88b42cc69fce8a557b5ba510e708b9375123038568270de407232e95621e2d04570bec2c41eccfd855b21f0c9bbaa23b5c5815fc888f7fbed482c320ffa1e063e87b55bc8f7eeea374063a9be65f7ed9225bf6ca34cfa311b79f3a258c252e6345ed6ac84748f46807a55d4ba41266169cd262d4f72279ef0caa77ff44933532bd1374756c23ec85f55efe9fc2331f26f881629f80c2692f7f53e4bc6f22efb45457a223f0d1c4
SIG: deacc8c23218727676d540a23bdad7810211e6d57ad294c37d4b1c9af6b337a53f7880d2bafa73b30508c008426bf8d7c965a1f4a422a1bc7d6ad6226fd19706
TST: 810
SK: 0f8e9f3526b4faea9276f22a1779e6f82709808f6d0c612adfe32a6e8a061005
PK: d48c3f0fdef382d1d80313e846fca95e418176bb5dfa9d398c1d2124776f690a
MSG: 0ccd37c4cfd8e70ca3bb3946d09d70d0f6a4b81d6dfb079d7873748071589880927382f7436a6ef8f51c255473dd01feb52c8edbe4d3255713e68d640f3dcf158f2bfb9fbecf71f0719dfe8ce6b601281ba6c20a56b4f8e7caa4aa9f868fbfc5e4321c22d65f0382c4896bf9bebe3546949e8185a4d817e45b5d1293953821bdd98ec259f64a3de53865b149ea01c8f683ecda61da5dc10e7ebdddfe7484f5eb1031b7916587caa399a06b6fea4c5e6e0be650fbdf06c1036df2cc35f62ea0ea713f52809d77f47c2e55c92392481680b6332056226913b0ce88a6c55a26bdb5b8bab3cf4695a8c522302c4eba37d31ff77e58301bccfc7c7be8580c6342687995f44acd190965ae0d7bf0669592b6ad88743ebb360c73e0484a23d2f9e99e9eb038dcbd87ca9b1a498f1b2d35fedd7f8e1f7fd8ca526486911e076aeab4877bbacf378a2855f9c5ac039130dc690e177d67b244cc8ad032379ef71fe05e9c8613d8f5d6ea3d4e3e47222029cc004253be47f87fb5e3314c4898134b87acf10b2538bad897bdc5012d8f9762c871b653d400fee0ceed5ef6bdd16faf3f0abdbd72cd0a12940546f0995ff14b0f1bd54856ff74c36eb4f22d7287aefdc609998c1f41bcc3bb3a5fa49234f4fa8e929cd0f554b315395dae873c61ca70e0410c2fd5a115d2a6ff1f1c94b27ba450b8194b21f095c61a5f215e3c84f5d43f0e736286d33b8c47814db979f9dc00919846bee685337d99555a24472e6b00b3f4a14311a6c7c904ba5889da6c1ddcc1117580f5fbc41f2b8a4268cf0e9fa5bf412534c9e4052aacb504cb86e2147ab8023d58800b763f9abf9d0440788a51dfe5cbd44230ba5228f1f5960ea3a4e4044d36daf811cbdbec5d696463d8e941f27217563bb44a2118a4f5acd6e794de17e028cbdeefdef2cbf03dd32e7899e65a1cf839f5d90e1f8c364b577fe3105353f66768dbf7af0c521aa8a49f7a22082d88f901498c90b9d7777ed2f9f0e8a552d8a1fa5e9632ed853258c9c215b6dbb4111dcfca554bfbc9bba22f88bc55552c6d862556d741dad59f215e37288346ca7d7fd8c65a380d720caff9efa149f3fda232daa5b12ef11c0af0862bd0229e075a3c6b60ef0bbb3dad7f2908
SIG: 2f59a2936073913834eb15a0e0bcb9aa804089468f24dd1b2d37a1934ae9ba1020ff64b72eec03268d0a7c012c4e796300f6df7adda01c8bc5e9015ccdee1a00
TST: 811
SK: fe7cdc7966d0ffb9c76f4a18e7f0bf90690eb76dc3d3d50884648e2e3937d020
PK: a12ee9812d6af6aa4879fa72bc0a69804ea1a85f9bc4a26a5ba7cfbb914d0dd9
MSG: dcb91cf155461a60df07eec29d98616ed1728b34efa9e1f7445a9158a8f88d7faaae0e24725aeff263c3f74f0c684f1858f05b6995d2846b6a832f67085a4276d8661aebd3bfcc73181f1f510293b6de5e4bb23ff2dca1df608cb14ae522ac4b51e1f9b973ab8bafcd534e71c57181b11896ee1061fb369ca4d2939d1e57060d9f4db0a5c0b07d52687f157817e63e2fe7ebcc3e7c95efe05b859910c95eede86d14399e616248a28c24c414dbb693af9be435a3a9cdc33e0e2a586918d91b8a85cedd1612d7c1a21792bdd43a915b157e04bb3a44ecbe23fa49cc55daabbeaa155a737f765b8ddb0f3b15d4ecf2cef7054ca73ec87d91752c2e99195cdb1958844f144edab82a97549fc9cec08e8711cff863b63fc231a77f762e5cd9da9d59409252e99ab04c42bc57097e464e3c6a48d80241e6325e3e4094989b34c0e8b32b1a7829d54df32a050ee87d8f7c4fe3e4f4f7049d1feecdbea67108350db4e8edbe3c3ff8ab2a25d147b1c1c5821b0f8c21042d655db831691f59983f27d2ed1d4906c544e24e79be68653c9b229a7fb61ef545bab16e9881cb4d9265e293590a0bc2dc86bad23007ff40c95861923b498241c10d26bf4848f62ba7383f649dc38af1840d0de928a9bfee5e11b51434163a7ab1ed537415f1e93285e3699205720158f9557d8641ed2bf485b8212c8f82668bac3c228e6924c17d0d98f2e6d9234371c4425eb758689fdb0dc1cea1394a2862e87bb38e624c34799168613278225fb5e19c9247ada35554f2c4addbb61d5a502a708127d6efbca8f735090bdfdd88db29fbd14b69ab1262f0c3e26d263a59c5ae4639065383d5250b54cf592bb7adfeaae0d2fe816b6381e86ea2d1c71813cbc3d8fe2d31de7b30fb6ec2294fe4536a36c6a1835a7162ab4bf89d19466119657b0e4645aef503505b4d55df977bd2c90c64406f4970d5cff245b835322a6fbe234e5efbb5ea45e8f0d3973be4aaa2aadaab077d6c9b25bd4494409e93479d2d1507f66bc8bef82999a13c7943b472b9e61ec29debefbf2241423e0faa42c1a338a7a6131ded935ba03a28662e68593368dde54b462f2a5fb746185ff5503e69ba36bf16f71458cdd057e5c17267f67498d652860b465e
SIG: b52d03fdebcd429737ef70920687211fbb4c04f81e355cec7072c5054175d2ed77f38f466f001422da8fcdf067db1451007cab607f049c2e2607b57d44713c04
TST: 812
SK: f6c9ab5ea75f294e8e0c07c4c09ed8eea3113bdfc2ef759e20a264571604108d
PK: b12ff55bd3ec42610eacea28b313a16e19c9e8b47c2b15170991be088d65cf63
MSG: 71623b39743e39c7e08638806d468a1a8a6f35c2ae388eefc27374bb52538814c4b36c9b8e389ad83183de02a1bbd0325734e4618754092337d3e7dc1256928e3528870ca7f00613a25b71bb15d1d9eaaff9f2269b71c19769e003ce845614b2ec95ed28ca855b5221d4cb80a6ca9466aa33e2510ddff7dce186159da70fc8b1fbac12a26e1fc0942276892ad6e9b003f56959bd313af289e7a0532a664b76b96b919854e0650cb8c52ec4c5fb5053af2f0cf8c0f22a523f9e2c6419df8d0b714ee3776800ebfa70776084667d6dcf541f14cf166262e0f64c4276ae28885e6cfd097b70c0d6186ea5dbd033323c987613da08645de07208bae12a178d8f7f650a25afbd701c85a1ba639ef9f121c40c5c129a4737343386a48183ff3c591389d89ecda526cffb2674f17bb1c23090554b1340849796a6d444460bb419427e93e6585b0f4f065ad87ee6edf54be6188a1dd5ace1364defa561f74e26769c9b291ee7555276501c6a49080da0924f3792c2a728a52007b1c07c95578fedaf403996239e9c55a9a44c3dfcc37cdf03fb485db5a08dff15a7a4f7b7f154742e8431564dc17dbd432e10337c2276fcfd9d70f7c3d570393a0c19f64051c73a870e205584106531d1fd2a1dd1c9d0fce14ffaaa077bb7e260251eed6c62bc6edc2422519440c2244eba384046b0eddaa6cf2c1c7eeebfcd78fcae18b82290552b59c0463dc450618ba67c770dec0e229b8460936ca819562bcb36969c8ff70bf113c11671e00b941355bf01ad54b05cfe2a048b38728cbdd1b49809e1f207aca3098d9942eec47d6c9d413b37c914fedd38acd5ffe496cac757c2ef8b77bd8403d14b1fc98a903fe2b979468233a7f2aed6f8d509d874e1dce05149af9df3fe4595c71e8bc463dee9384d5e0505d2a6b0a2b8a1ed6216aaae9dcc7602487a4c0851fdf09629c1e99118809a9544a6577af9f915d1e65d816220c48c8490fa9b70da422ad6800223d6d8c340f9eab2cc7e149362124a300b40cbb8c0a65da301dbba931ba564f35973ca8bf2d1edb56c194661955b3b68381fa15d4b8dc6ada1a5cebda3a4ccc55123e0057f4f821041937dd549209c82e116570bc908a28e3299a9441443498f74b3cc88e1a62d
SIG: a7f9d08ba14183ef247f2c25fecc2b83eda6de58022e466ce78fcf50f71ce26162446562eea45d63a21c3b22561fd4680058acb825407a15408f271361a1460f
TST: 813
SK: 43103df01a48a03c57f32f52d70c6849ee44580b2ab4ee72d548d848134f7ceb
PK: a3cbe0d64b0560bcb5ae009001e314d9ec907901dd74a804a0059022ed9c6d04
MSG: 738cbf06d00d4dcd5e5f243a1c18dd5ec20278884695a1cf3bea67bb5b05dd7e60a2a24fd325be6bf46b462873ec907f9de88dc2c762620b7e0ef72765d4bda662454993c828a1746e9ed8d19dff43c4c48527ac845f2186a4ad7c1d992a16245cd573073e0940dceed368110bb5fd0a4c8834ce88a77125b9147393c8b58cb16e5ebdc18244ebfa48baba46973fdcd485b1b2e5f3b0e70992cf1999580638d87f1f5b27c4d7f91decf37de2e734e3195535c631082b3ebaa8ce30a9c2c2db016d7d3547e621618850e22040038d0fe0faea2f9bf510b682c4fd14750e89b4c199ef0c990500543eeeab5f0b507a313199c2a2a0262d6d814cbc0933c592e256c3e29d524b066ea5a4543361a10450e0aa675c61408f307f26ee58969d63278f135b7dcb666b93f2cacfd83873471e974a286b09023f5015fa1aaf18bfbfa5f74385d0df6b9add516ffc0c3113e37e097838646ac93054ff4d9602066744ba3396953fd78168130170bb275c152bdd366f73065c0a7ad7ad00758cb99a7ac1b7809d26dfaac758468201eeb60dea368c33f257afe2f1b4c02e37bafe40f5d7fd40c87d1c56a0cb28e9d28369a3924bcef8b6d999dcf4294dd8c4143d75c6c25b5a4544488dde725248c78d93c15b815b01cbd0f31d1b00ac04837ef85b4003fc96d4457ac5a023623e67b66da4700a0859f83fdccd3c7aae09de09a057e00db44a2a6aacaa21746a49b8224689a5cc1854ba3dc4aa2aa34524e7a5a89d11eea356aaea5ef5fbf542c99f544db940f5086838ee2ab218b8d3f2e107d0b29d4b04830eed79c0768e02c2844b3cba326895f4ab38a3994b83ab30600ff511ccb595992f8cc0d2954807972da365b06fbdab539b2e03598b34e53cfcf93990b97aac1d329783366d451f972b8d8a00b6b8ecdb37279644cec1447c0998ee4f7090f34c9cc8530590cae765360aadb0ab3135004941c92302cbb2b350a14e8f30af5325c2b438005e3a9d4585e63265c327ba725754b33256917fb965ae9f02ed2126b481473dc0e931c2522bf00fe6a2ec95c792247b1e03396112f783070e2fe6c2cb982250d13f2d5460c744fde45323e631cccb540cd725f2c55a7058f230e82b79f366afcbb025b492554395
SIG: 195447beb1de4a7e36ea89a6ce3c99bcc89411df5e0b15f7ba0b1d110c456abc6b3f5f1da6106ed887864ba56aab466a8a63b335cfcf4c64d65c0e6fb480b401
TST: 814
SK: f9139e579fa96ebd6287db3babcda60f92e73153566f924cb5de04de4493481e
PK: c06ce335533af8d8f337f2b38e0aafa2ce9b27223cd9ddc5ef32027f04889b7f
MSG: b330764ddc628e4ad67aa4982ae86d4581071c193ec3c58f813d7921b84d2a54562bd87417ae1de590a1a48c4ec7d556ad931d65c0543fdf0607c749859ee12f9952020c195cf8746095e1087cc6c3c8ef9d24052560ce813d6139b7a75c8f4b8ea30a9c4ab888d0a6341c99abd35e0903bfe56c93152340c41276d7f24e0912b12a4db3d7ee4484dfa53afc0b1aea1409d1e0328aa1c8604127ca2eb1a5e81bf31f8c7a51c6052c534efe6b3d0ee74ff5a9b11c6157e36477efa9382f5751be8c8c6454c446d6f8dc7e929525cc3de78cb1ba4aba9bd4be152610437582c965eea48cbd4caa6f308f85f4f8d006a042f619200762e1bb9ba422e65475b33a9494298cfbb75a152b36d2a05501807705b952765350cd14141d35d4986692d6c3bcfc6d61df0052a620aab8cc13205e754c16f93eca7920bbea5157ef112f0b64c1054f90a5ddc175a89e29242f57646e74cc885e81a1cc144c3d782d1152a9e4cfe76cb3ffabe7dbe603fb3869eca8699698709cc87fc961c1e299cfca22e3242eae788cff11bfca61026745f4976225b26ee200c4f1910c4b83df5ce46ef487d748d9c4c502141b7874caf41e5a297b248c2bac6990a15b07b4cf810e59287442d9a3696c02e8d7324d3cf730dda540536beb13cfdeae6180dd7484832dfa94e94aa6cba117aae17270f48f93b2f98ae9581718163f4463546c0ae0f279c36b92bee66f1ca2d6a4f726d2dfee0bc11c1d8a1fa62c3cc8aba266b98759286c1068483b2376b403c887fbb657dc0f255dea90dbd23308f7e0e842b498a8dfc7c9cd5aef0e87d56be40d50fc1dd4c0aa7dee55aebe4d6b6a52053962b87b0f2ee09a90816155333d5c57a14724e001bc3ded17843b76e2c47a176339c8defc54b55b2358ae7d01b0f6e08f31216ae90340694168a5a79ee883ea7858007d17c37359c99d6597efe460c1a2f7738ac32c5eb5e39e500c49c0dff9c4659e8c50cc5ca79d8ba4e5972d67225468fba64167a6b2c6f368935c7a049d35d355c7672520d3c9e4e43c671c3cb8dee259047495de0f56dd7191d5bd4bbd29517e364792ff89d33799b6e781c20193f5a316fb40de74fee2acc25e47f512214de3b1e9b382a86929c1573d3724c25017c0e5
SIG: 051d8d7f0b68d2eec72c81adfcfb31ae8558f60ab63c9f5652a8df638f666f1ebc0c6e0b411953bcda6b5151b2b93a39e3c5330a8573e168792272abd36c810a
TST: 815
SK: c8ee954db5a11b292ed97764fae6b283051db57dcdc0aa0df5393bb60c112ed3
PK: 5c2f81824e9975dd7ea353bc66807dedc7610349794e2fc08e5a31e002e3fe07
MSG: 7ba3fb568315aa81e21f197780edc2c6ea26d8d06a4378912fca2301cf1eab3d803c8469deddf376703ddb7ce06a77dab20e02344fadcc50022ab3c713cd03c1daa93f1c7ea572629f610b5e3c51411bb8c19694bbce903cac4705f9b5dd0f47bc5d0aa3253f908870299027ffbd3449eebad45332b5d0c4f533dbed18a99a2498b9164e245fb65c0afa0b053703a0cf95940ac7a0195d4f7046609cf04371338706b9b1986c0f118175d2cdfce74a6f88659825854e94ece58f5157636d6235b76d32745a2a81a9671a8f86027ba9e01763888fc171cef7c451c36072bc7499839d431cf18cd7c6c9fba3aa712a054328ccd62be4820abd5e782162764611d4539ba2cebdc209b3f4e4b69c3d64073e920d215214fb0fda44185aada5c36127a15ba15ca28a3ad086e9d03366869c60c3fbcebd869d2e40643e833f894803f980a2da7ea4e59ce4d7c06fd2aff087ee7bcfddaa3b32817ce63a63587dbafef380013a6f1ee3734b94ca3df9644dd0434302ecb324afe35f465c9c1c931b27294fc6ee0272de2242ae90d7f2e067027ef8642e8f171ed880ffabce8a20a1b3e339ad4e3f1a9001f20f90026188fde34b217a6e26aaff18422b7f843d0fdda321c319c778f23137f20ccc1bda1890e5bc916a5456d068d37b5acc6347720c56a5a491bc348d6c848a9c8fecfe58c92b1f302fe14919718cd5e78b7fd601d09dc01e6904861e8d68b3c57535b6136676cbc6e839af0dd739db89a7abd913fdf6b00e9ca02602de6ca0afd0913d992fbaa8ff822b9d9b09dda7a29be91910d8fa3caa2a5e518346c167c9f51941cf7353f3f34c1dab33485d0a8c19daf951fd3ef20d0b119d8038df90c114a25a5b93ae40ec44b9a5d2bc1c6517c682500d4cdc197142bec3af8232c071428dc54c0d30454272e7336b0b5888a6e8fecde859e2accb7fb094acc54ffa481f7623d944691f04fb3613a9954980f17e2ad2173d68cf0ec1b67d8a91d6ec82946bcf05cb90681a71627b590238334e3d5ab9da6a089bd72624df9074cdd2309e04dfcae032812fe84f9db882cdeaae69ee5daa5a66ff427fc452edd0769b6aabcc139d0f70af8b97430e644f58a41287a93f631deda82ca0716d79754c5c503e52a665da
SIG: f3077a75101e121e5c3e77d8ed97b578d239bd421803d3455b5654405a4c586a6092e13a8529bace468a305784b373e433fee4a3df8956befa012fd8a8eed10c
TST: 816
SK: 6dbc559e4ab193eebf70c5c32d797be00b7311e8e6691da9afcc187291f2501c
PK: 38a7034476fb9382f1417768c42162951a2636902c3898c029be278ab4c31f31
MSG: 88ee2365f7cf9de33acd53564968b2dc7f7370b7e7033f4c663a88c25f60f7f711d61908ebf1f5bb72835553c8aa8c8e4fcdecd37978238289bf6ca84876d228217a28d81b0b457c922e91ecba8d3e1d2e6659c2b0aea051b9c2e09c7dfeb51d30ede767570341ffac1ecf0de20c82d1e9ed0775deac72da7c2dec234865dec83f6715e1c3c59de2033cc24d86bc2d31aa16649686ede0dbbd8964c3a64a3dca5588d7248b1f24df8d75f09aac62c07828ca431a3a2d77a60cc93cfa3495cabeb1904ed5b563984e8c20777bac8774108a64eda58fb320244a3add3e3e7a76cd137cfa4a09b6e6e93011ea0ae65171af130711766cd25b3c74ec54c0bdfa02b3120ac29087ebac9837fca65ba971bc4281dd557c500e225ea66c3c3fd52206c19a9f9395463169f8c7a846bd9f834d7f337d0b61fb30bce294f478ae1f1d977e454e433ee8729fb065cce03fb2e435dcbcbfba01537e7a6762e55e7ed22528303704beb5ae381f2e181056f25133273cf17ddf2b06e2d9477f2c09755fc8d9c73cb33100468c64131c686cac79fd384501e50f8b0bee28ba39583f42e4fd3799e24f60da5fd3c779aabf699ffd2321ed045a85bc6424f60fdcc49c1cb31f249a4236c09491768181b921f58602fd415c1edeb26f39324addff14771324737c6720cc92391b949dcb4212bd6931d4de51401e7f953b7b036b223f0af7a8e408b04ea635a23fa0709ba042a5d992954c09d8581dcccf52568ad27a1cc71d18aa2740f621212e7f4c5e5e5e5e4532d9a67ec2773ac21c8a4b002d6524f6182dd371735d2c2abe6c95c281c6fb1e976bc17e383fd52aeaaa9fbd4abb82a2cc65395f8c2cc7d8182a0d250c685cfcba93a951ee7c503c6e3eec236ce33e086c610728737c1c3b3a24252da7f21672d928ebda993a94c458ab990f5d19d80023c36aa16eafcab143f352e97d6409f3249941119bfd9f5f9084724d9ebad383b10f34d33ac830cce9e5cb8aecee6f40301cbbe309fd061534a7d0c3edaaea02a171d8b2349dbeec628520ac334a5bfe28a9d5f4c0d740f7c72d4d72d89a97326a03002d1ef38522bcd37b42847a314bd843ec88d1f2f9d39f57f2f1a13d0140a8847450448c880b3ae76531e95c4392973250
SIG: 31f16a7caf2b74f65e057c9333a1a2633dac7346338f798510730eb8d5d325fc1080dd5aad5fce0534e9543f3c93586804464af5886e8644129c77ebaa485f01
TST: 817
SK: c9d416830ae2028f2175d22b614c79198c670cfaa0e7a36150ef0fee21a95ce6
PK: 6e3eb4d01873072df946f1792f7106330895e7a76dd9ae27f8a988039490fd4b
MSG: ff9ad4837cd0bb77d6210fdddc755e6c0f1a73c2bcd03f7a5869e7342cfd73cf7086f865561560277bf6c3421a912d67658b1fa97057c496f4be8edcbe18b5ecd08a1e7db25223abda208fa531f4b280aa03b04b60603411d374ba7cbb020bb9a8ce4c0e45a7e132144843c31f8b45c58eb3ea853c2ceb61376e9df81d9778e721adac77b50354937f34372fccd575e88d9d058e43df942f2c43b523c8098e6dd9e6bd21d5a649b472d41e345fcd5efddd49eab30270cd8788404f28516e09d3acc40048b39d3246f757e482e1459c626b799e04d06727137371e120afb9fec39a25f4e6764bf9792fe492ee0f210b57db9ebb9e8ef41b02c7fee9edd4b6174c570de020a391287133fe8ccb41a83f91bd22382b21e1d7ebc2c7e5018ef5142d82637d02620fbc0569cc09c44e911112bbae99064d68d1c69e77c9930b0de030c8c1d748c414059d5e299b7edc08940651894b303a2b32dd2c365a067c9723585594644d3ee8de1a51faea0e650f2124885a94cb99eb903b7d4579bde591497d953930d363dddbdac627b97a91f49682df8e7250a7073d383a7a22cf113f2858ce6b632a2892c4e88aa9a0d289eb57629b008d3b1b6081e6fe5d3c0a6c802189b5f108e766319e15b33eaa5b8ced4027eaec83b4ac68b14b8298bc51cd8eb3809b7a2d684fe32bbd9fab5c918eeb17cc444d73f730d4c8cc057bd3a2f1f0aebb61632934e61702168829cd7e91de81509629d01a8cdefe0d1ac49e21f0c5fbe1b2244827268a0a27357e158bd76884a21e7f1fac1b6272166d5a9f64f9b672989a8762f512bf1df4b2ab699765f2cd8396f476e7f59995dee7d890207eff0fd27263ec232e37cfedfe7c440555d4ca74e52da246c4b83757beafd2ab2a51efe160bb02b98c26d6b2c3f0c1aacb2f3c34a5b2a3b66fee175b787548073d8b5777c6be880bdc196b3374a2154f94d9360f7755ac6815a28af296271e22a8f23543c74955a609125b02a569218011420295ccf0d7356999a5b895cc88483fadf7970cec6c64240f7079fdb15ffc5c4227e53926d278ba0fed3c3993bc86822823dd581a32ab2e3a07f79430224b274eadd845598a7d1d89676aaf23677774b7b0583bcc83599d155d14b09adcf49ed505e8
SIG: 47faad4e655293eda156b2a1fabbfb7e009fc290aafedbd5652114a47853bc77a8233a2b179f605477d787878cbb15ea6124df8dc57b2ce7be7d18b7162fb50d
TST: 818
SK: 2d277dd55f57195ec072b47cb1448cb582c835739e6c98ba71ab128f70ce6b79
PK: dfa92593ef0f0d974a1137830ad13848afef3b810c2a21bf779178ce4b3ab974
MSG: 14549eddd5f2b7905dda19d74ab207aac6fb3e3df3295d845231ef3aea6e1f04ee033c9038dcb4bd3d5e452c54834d0ff2b7de3f322e5626949cd61d6e890138ff0ea8ad846e8fe887aee15fc48bbe4fba42455f5c17457ae789b405af859611fe1f8746185a65aef2134ea4d8f398d48df7c1bba4304408ae7efb35292409d508dd55ce21de8c28160dc9e877700c763d06b01b8542052d7ddb633554e3584279c796937023c8eac37277be2b8204ff3e0e1031190a01014cf5f5b4d7ad996727f97531e0355b87c9e611525aad079958e9afe2ab10e4a3e7a1b6ba0aff815da2cd81ea9eb9f536986633f316dd06c2503c6b198dc59304807b98b42935f51f637ddb59e233fed566439c1fe96cdaafa49f4412d0c1e654d8c69042470b3a59acb6bf67e40b38a77067d5997b8d35ed61d6eb3cc78b8bdcb9574b1ced9f6f339e9e38f94146ef63f049e6b802bfed2a51ab42e7d489f316ff4d1cd898bcf8505651687440749c0fb7a57dbeff72e64689faa41c07b4ade59933d2fac6d573deb739549eb75f1e6f7385d8c6142894973ed685eb8ed080c2a49f3ac6571161af96635ad057df1486d396773ac8983210978986e1bf21a20806d667a48a555a963221d50614a8976b2eec97512db11a358194492ab5455801baa14a511b26eb0c68289d790523712f2ff8709892695c4db9ad310df8c6ee7bd83c871f05aec33b7ad326f446692a42f7222376246d536a326c4d73eb572feada11b8ac7114f6cb444ca278fcf07b970d2ad465372a687d36b7daac478748ec6a932da20843948efa393097814272e5ca1c73e711973a52683f98c01e55241c154d28e38d3edfade2303a4e7c45c2a7a1c996ee1137af864a98b69809fc9214eea8cf3afe842fee3eb9a9322c3b82fddb05d4d1a2de09c1ce72734453a8dd3a8920d0d0ac96ef778b9e02c6a3f12872e17d3a81ba75fd233baadbe216ea0a58e9dda00840870208ae413540030b3c05e5d0b832df87c8ee7f153487aa11bad9f139c7dd4bcf418f4bcb95bee857d0e96084472387cb39127a947134501963a7071bdb34de6961be2b6b06e403e75918e6f69d08021cf2a8acb80a0111f4d50610c152d39c6621c0578ac689959b1ce6f376f43d18af062e4a
SIG: 73c1060649a7c014ed01945851b53e285324e60d061c831dda41f033b5658306a1f112327afe93caa921020730aae0069c9a2b45eef55cbb4a5a9cd46cda8008
TST: 819
SK: 428066c52445726d0ea2007e504637274d84ee232325b505f2c516357f807583
PK: dd40fe8f67c665613b3c459f6ace8dc28d34e0e77e2f6aa060592819be6a9d68
MSG: e2796c50d93df812bca41bf2a1e1dd737d8cf6f6b4f76242e39178186758cbae0884e60c6b4aaaddaec9a899a912e5c5b9804d7b0497bab4458c585d4f259222498ce9e80eb6a7979bbed6d52cc38072f745cb2c63e663bc3b9d6caf012a607f6d3b706e1557578717ecbb971aeb7c48e1df95711c550e006993bffba911cb64ad52d517ed18be82369e815819d3175947d4a35b2cc7b9dc6c10051326b3f1dc1edb1b68ba015ff7ca1dc361d8967abcffd3c31f7d6b0cb1396ae541f29759c4130be52ecc11d99261c365bf7cdec781494c5fa0526db4dbbe660a432be56043c66ea07c25627a5f72b78123dcf986ff71ed1affd1659b1393d9621f711dfa63eada383430797058f1566a00052d67ba53c1237b5691de3b039fd4476f1151e5ed5f5a98672fa33a1d854fa01566b33231d46acd7f34b8034479981853764dab87f49844cb62c63d536faca920447d8cd1e8113edbc83e4a6b7815e180cd78b933d9687fd5be99d0518a44662989bc64011124f187d43979994a95e0c903a006c1c0bef1c0f3df1eb700f980c28c3c1e997d0c56d113dae196882b05018fcab314d8117fafbabe7700b932d47c57362b2035eddce2d2ef33641ea90c3ea3fec6ea5b87e161014c4f8214fd03cebf94abe122537a98703239df5821c5ab633f98365cc636e3f1d2f74e0ff8f1fee06a3f73907ee504b310fd5224ad4d05cd23c356df8b34647298c49828725ba5fd60611e829b6337bcc9dcf8e8971cab3ee9c26337d38dfdfa036bf6096b635ac1bd5525ecd377a15272a8ac9bbef133107a42258d8b19ec69dc4261be5300a2d2d5ca99f31efdf259f9d079869a34413779f3028824d747686c460ffc496f2010f403e903e27a87dd075ae0a7f1689416d31bcc15f490caf975c40e715d549903e8bc0f7d9141e020f410f3ca2b2c0797ca0dc8d7392bff243528c7f3be138997185a4b36f45376d9fd70ba20989d2d1a911d4b98d160d2b8de592de2f4c04f35860df320c548440d5e3a346a14d3a63fe485c2889126b7f41d55a6eb23d5620babf8564aa79d156e983f36d9ed498da9ca888d946b53cc4768a5892d52d541526960282524ba6194da65941d1ea30f806bb6d97c7488b93fd0a770a9b15efcd12c5c4694
SIG: c938829f598b1ff1b8183360d223f43c594730606876a99a3f31b2065d04e6f075d1396b3c8cffb0e1e2eaabda7da5e789ccd1c020835fe3a71dcdb6af03960c
TST: 820
SK: 3145bc68d82979408e4657b775f150c6d28a324d746ea6de90fd72b17a257982
PK: c776186ce47f30ad08fa1d2c616a3644665ba54ff730fc2f4db1dba38ddeedca
MSG: 2ea8dce1487f45d6ff8eb83c54fb7edd76ad6e608bb8daf1a1823da4f4e4e9863173897c197ac65804823bca95091f59e86d63c18dbcdb85743f8893ee694d815601f8f22f4d7df087f0114bb26c3795e1fe4b7f4a8fa31fd9f4ff10fe5dd452c54c5578c752f888213076be467ba30d2e2fbbee877c4be9b6ec4f04021c006f9266311943cab7cea99a2acebb69eec3e618c131f97430075f7975e39f26d5315178b69a1ddf731761051b93fb8df7e0e8b41e82e7f4f75e91d6c890b14ca533e094eb8ea4486d387185966c98295d3f58b17eef6cc3b4d07e93a3d9f4772ee52f18a5bb30aa3972850e658170bddb676f33266c9fd10f5990bad891f0ceb782736b40f01bd86509b06304a96d93da233dbed18afa1818aaf57af9bdbc867b397ff235a83e857224b15065225eec039dd4e2d69a04ee10bea0695041eda59b058ec05f49048ee324d16c4d6107b6ecd04875eb744e9365471b4c5fe6611b261893f9d2b128e135f92e474156b271b3c82e9a7663dad4953d30e10eda0862607dec3372b39970f2a84b12f60e6dae7f31799086d38a7e34948419c1b07f44c2159c86b8c0cfe8747fc2bad5bf475356cfe69de2dc6ad5a519fd65c12564701c05f7c277ecafcf4c87b148df1f9879a9ae443c55aea52138c6fa01ef0c3abb5f2df90a57ab6624178c737b54915b7aa29ea78e8e49ef5a816d8a92c2f81b8a19632779c892d66f753d518c41cccc9e593e50742625bcafa468805c37a21f8e29a6960ddf5c5e5ca14a7b052a7b6015697a0210ed6f0143e6b484c3f5b3b4726c607d07bfb3d54a09c98043f21dcc5cc20bb4754e2e5a73b2f806c2204b72f36ab9e96a62c6277c0ad66be7abffc163b4e8fafceff5e202e5943f4f0e6b92b4ddb953cbb791f83166036938e6c44ad91a596a5573440fb30741e660b6cd5f86ffa746e6e972b805c10b7b7b9a63c0551db8eb4f8400cde2868c0d0d4eb4cf117f8ec4ab9744fc5879dea7f0ef16c291d55c17f08b731b7c65d0c441b63bc8ff5e94904c026a1361dacc80a93a9b9fba3b403617aeb94a568541848011954234aead700f034c47c7def877905255f18bdb9a257ce5bdcf0e17670cdaaf13b1c7e09d58f92a9663af239e22078e180a23ccb6f64d64
SIG: 24a433337683bc71a6ca3bccd8cc2400c24464fa67714b46515f2a1432712705d570614db6d26bbbd3f0267c1427ca1c2f40dc9a6f1fb0f0fc714a02e24b4708
TST: 821
SK: 5a25ea5e182d9bf8e930a20b6cf55e24e83862789b3839b1ce9a71e938c42d37
PK: c981fc36f1a6d5f7d451cd5ef39cd3ab02087fcc6af27dd78ea827497e779e21
MSG: 214dd1927f2cacd9888714249b85434602ac78453b4af5386eee39295d3d5a2267806eb0cff2c132d364c2420d04e3f6cc0a967bf05a10ffcf1217bbf315e75b98060fd458d67ebaad9380f4adc4dbdf74cbf1c6479202bdd7fed3a946697dc38444d88bfe51d41d7a9b38da60b850c56b48ba984f6a1889514955c0dadb69a8c736cc76cdc49f13f85a8bfb7928ff0a0c0c03f17c74b5e1062d7553fbeb9dd3d5081de1dfd8a6a9976697c6a259bcf7d4bef1c21e0aaf3298b0421b919fddfc1dcb3ec683d86ff3d423d71c8f2d723a42ff68d82e9f391749b82998dcfa112160f52a413a23d95fc42c3bd22384bad77754a710d8b9f84ae0a802fc46509e7f2b07079012b43bfeeab719bde56f00e59b8edf1c472883b1985b2fa699a1ae90cf45d7ac580ceb5f2797def5b8bf4f2b9b3519a727b9f2cd1256a2f076ed2296495b5c2df7887ff89e88e236a14cde6324f43d68d90172b0b88bd28803e999dbedcc501db654544e171ec1f9f32d4d3321d589392e03ca659f96752e1f08a55db553d866985541f5bef84ce2ee323e17d1f7dc164b50515a287d5305fc28c5983b9e5398b2407ae47296fe4a481d22ffb4b865a66b97a6c27935dd8eb86994b79d368363713f101dc37f429eee0fee2441c2dc17bf43924f0c044f143290eaf3f9ee4d946dbe45831a0d83c076e751c14f3b1a7267f5446c188698d2b46d87e6f3b20bb3fdafe24cc096bc312d8678b38a80c3f052a0c96d5ad87a5dd8c133cc9a15be33574cd94308c24dec1a9bdf189ba687199f72ef6709878e10f87bd8a03dc84c8fa96420285898ca3211d8b0ccef64011ec24f38e574da34dab9d2f002105227890f92488c621e5713e47dbcb1a82a6da60d8b2201eb29d494493360ed5a3f4b5225eae7707ee0b4c0407305c16754c7f630fc85c13e4917047bcff3b2a293fe955506c7264ea65bf3a9b25acf343600d8fa0c7c1a290d0271101b7f40b96e7fdaf29def9d9327a5ae05446cb5a6d322453a8b098bcf3aee1f704e14d00be342b8934d19e529218872ea3a2fb2124b52667c01fca5841c66e1e64a1e680e09ba186e04d105186cf6eb728b9d502a66b829fbc992a3881004ecdc80adfd044eda880f8af72a14fb550d7cc74194a945207d
SIG: a4f35b49d7e198e5d326e353fbb01fa13b6ae260d1e48e30c1b967737a5e79936c97ca2ba799ca34e5e788cea5ac8ed10d5cd15dae53e42432321cc26dc99809
TST: 822
SK: 42335c30b3f6b359cef5aab6a3ce2858a151b7a4fd78d2fd3ee36fc29d249404
PK: 301c515a02a4c66bc6401080c6ca7923b7831e3c9a72b55b14027eb2e7b3b152
MSG: 6da2251e6f559536b09bfafb8160a2e8102d31f8b59324083e5227b20c3e5c3a06e2396768dca3ec76dc7fc0eb3d145e62ed07fc1a8b1b2e347013a0527274d0b234fe725026a9d128f8df20dbfa3b6503818edebd7f24934080945a7e1ea02273fe48b6ed1e83fd168d7973fbb7941b4037d3cda555e0e89c2b943fb1e20765ac7d4fa3777f35a0a8bc118f599c847be3fdb2d8e201ae12a30bdefb034ff24e3e2e701a0d1733734078bd1f9a69bbc667e461211f2c769d29db7c4d62d6b1b92b56f5f18a931a926064b78da146e18b48139b9b39862aec37bcce12cb789429e68ea38112d0b5cce30bd2d26c5f7fd415daf7ca317b3368b7617d4525e5bc97d9461d5d64f6b5d318d0bc3b76f25b0605426909f2aa0cd667a4f0e075b9a9fb2e9a6c82704d8a9f1666844edc32f63a3d4e0fd9fdba30b51b3336b96e9eae392a342de49e9b5fa0f9b90171bde09cf1e946499140008159eb1865563c28394b03a8d7a552271b2876687566b80fd3be2b66332fcad196cab8527c56e21536a141652cdc7fa745b26a331d787b93e5e816d8d851a58f6ac07a5827fcdf472e8685433a40cac0c49aa569319a2e57b41c9998165e69723ba77e5c0423c4b4ca07187bb7442e7d31caacb27700c71ae48cd055ed2fe4da363f44821124cca1bf2e63d9b8abd2fa41b1422f52d558bc5f110c863cc600864984ed259b73cddd5796b32979eddf76a07bc59b7368c48e129ecc0d4535dccee2c3b8e56de50e6f5cc6ea515cd6a0ebdf1ca79aa2794821ad2e109edda450c9fc3c84d8c96bc38d4b437a738f818b4ddcb684383c09b11b36052e9d2f76a61eb4d62049ced5f61662c4b9ecd24a67f4519d46528c5b2eb21005f49c73a3370c68e37ac2b18d481fa10f96714fe05c168df11cda54f14f4937e9fce1f516c0371b36a2c0a050bac7fa5122a6e35ec9c40436585f316e6c911bdfd7db4b80b4306479b82a2b243a52b2d2b62742ed11282790cf6fdc7c9c824364cf25636a855150bddbdf7e640f9f952a947ec7974925e8245068b292101b1f4b2018e85d078c2feef4492349729ad4acb38f1c7c0270b61d3dfd7636c6cbf181e4c8a0e64fa06132553c2b9db7019e3b3c485d8d5b7dfd5f515e4d71ede535ae7f2aaedc23
SIG: 67b0f17449039e8c797bf913aae6e4f0bb99c74d6d10c973b990ffe03e7ee4ab5b35806db15a98c0846a827e7bcd539cd3bc09dd118ab3e52663a357b1299107
TST: 823
SK: be6b2babddd2dca1b0e10d12d20a9ce29c6785dac1d60f2edfa94ac2784ba766
PK: 398f22f0efbf8c38355e4791bf670898951fbbd5518f0e2a605d460023f613f0
MSG: 5c9295881b7a670669b04cbe0dabd89693b77f7cce0d4a33f52e02eb26959e713d9aef5f95442bdf91728383325202aaccc037477e3666facaf24eac9534879aa3efe18ffc1a5c54e39c7687d0937b2471bab389b646cbe6b3e5d5961ea63bd452b4743344ce4c793374523795c781ee84d511e2941119bad1f4a746ed9dba89c8d0751a6402718635f6e31d9e18681c6956c5373251d35f53baa1987cd448c9031a07f32c8029119de3a91631dede1d933e0fa32629afe1b42eb591c22f87331e93cc083c23f64a6e5e586ff31cc04e423c56ae3f6a73946c48de4d85ab0017ba24456d69b59dca6d403b64b07c40d3b90e1223215e3f7e876c6701111e37e517770887310ca856f009a0d60654835d94e6587a439da5db0a0c37d7c9d37ca1d703e1b3227631adacaa79421a1c439d60349ae57741b7a8ad09ec293123030bf6bac0689e531ca7e72718223f9ea43becb0ee9d9c1ab845ed1cae443e3c5d4a9b1ede6db3417c3ace281143f42d85f599b3b9d3d05fa0ed07c1ec35ffab0305168b4e56e58afa0617f9a86b1b5b201dccb072b4cef0bb7b95c52daeef9d9e7424a5c0f148f9ffe60a5b23e0ff82c730992ac9c17f97f065cf0ad5377eaccb31d8bb923bd260ea119e6fa9bd6983482d70d9219102402dc6a3499193d0c1cd3ed2a66921a98df69b791413f4970bbce04f639af909c64f4560db0af6003dc46219e8ad2b372f8b5f81cfaa041ab71a348c931e8dfdbc409c22d7ee6e07626e104ec6cc7c6a4116177f93af16f124f196dab619b6f698c2d191858e960c2e947b51f3ac4838759c21fef7ebae35da24f55ebda9b9879aea17a6d8d927de487b175fd7faa21438a20923ddbbca72e6726934bd6c21e8118019f65b3810a07fa27b1cba64d0f39f0bfd49dcfafdefe379bdea82f31a9c39f7e81d294337d10f1e9d8b50eba458ce7b753d36968538513eddb0e84534411c4af3f0214610ee3901a0ebf316173ccaf15cd7ee496dbfc2465eb834df62029d621fe911824d7987df2d46346b4dce1ece7d19d55118c037c9955111d07f1fc362c739f1ea5b275c71c0aebf59655e2def16e123b3eb2526c3ca5e83cb24d5b68d7ac40a67593384c563afe0b552adaf60805035be97b80676adeb1576520833
SIG: 702ab9acbfa75ea2adbe4be2b6847625aeb409eef9596fabe39d2c533a03431e5e579552e8a64fc4fb7d926aa8fffe0640698464c4454ce35fe83ff263051a01
TST: 824
SK: b1e47ca31c64b68aafafb443512e66787c6592f334aa78fa219a3d93c33a4ab3
PK: 58119b38e6a148a936bc5f92f4f29b982ff2cca64a5affa14ca1b6a62fe328c4
MSG: 767ec1b3daf204387f3fd3b20010781afb1f38f614474213287fff11307f5ff5ae7ec945a2b9b4870049d4532f8f61c1a7b5f211fca2e67c374d96219d8ea9de73f0e38704fc94c0e9e72f2e15daba3f88f749b1ed702660db1a352a2667d4dfd4e00a18efa4c6609ee9c9a88adacbbb985d3de8ddd17d4e4eb7cf74a1da91edb390852ea4cb9a424f7fa2229e083033a34059117e5efa7b6613d75e58b702c6cee5d004e8599b97503a5f10c4c4e5b9577371d3d05b2dfbf7cbefe6d092d65cbd405138d9b04c5186235983fab6d4ce85b636276206d74a2ee7db6164dac47cce78f50db99af6ac6e7064c13aab793be87e66289c94a09fb0a31d97971edd74ea9c0ce874d2b7d6c4abaeff07f870225151946a5c476f6b978996b87d8c984606c791287da6bad0aa44b0130be88671a556e2de35c4cb038ee781273530ace0a104c27809aee033c8bf9029d90fe7ba06aaa94e16a52c643dfd92a7624fbbee77a7158b2cc151bd3f61a1a76f32b28489307acf0dd8c26cc4adbbb8de430db4e4f58308b6ab90456111deac2978172fe1fc0ce498088add4c31c21f24279025feb48cbb7a920cff2d28710587af52c844db8a7aeb7df10d43411a3c8eeebb406d6efcb19248887d450b573d90305e1f23753e890511dcc77c740e316ad7f52d4902073db3998e4e4acc4e01885bd1188ecd6165aeded1e778702b6a6a79a94999102df72018f792f8f162007e812aef8f956e123282bbdbd0c35612c2d3473f944c6d76be9e86fffa46ccb1ae13505a4a81f31b8426b8b60de8e8a7c16d1e1665b271434665c442a9c6a977ce986f6993b7439af03b402eeafff1456d151526d9c58f515fd2485e0cbb324a503a8d491344cdb2aff4c41aa8e2ed66e58083bf0d2fbf4877c85a4bcd6b9cbb821242c94147e5fd8b7dd792ad0a28d49d41100b431bb4d8c7833d8505dd9e2649f9ca7051be68712ef3637102036b002649473ce259677d82c6062895e161928b752f13c91a45955e80f007de690edf8a0e5eee4422e162b9d2b4a921d3a64845793aa2229e9c239e57a6b1a90a5254c3512f99345315ac7d3457f9154296c66822abe184d64e572b9c38492958e21b0292675410e7348b2b718a0b7592caee94581a948d2f41fa03c61e
SIG: dfac86df586ec34c7cfea5d5a6cd1140e50b6bf050f8e41a190ebfd3b1432b95a57d5652dbae8f53e037ae326e7f18cfef7c779f40346f7c0d8644610593f209
TST: 825
SK: fbd55fa743c3a5910b3857dd0b6aa584f3b238de056b76ab7617aeb52638fef6
PK: a7a163c4183bd84b756df3c8afdfb9cd5b242352d9499ebdab90785c3bd6db2d
MSG: bf5252b2aeca1163771f766278768066f21971357ea7996158a8d6e908dd59b59971349fa17882cb9224b972d0ffabe85510dcf25a9f9f9bdefad2f4cadfbbdacc1fca9d948cb5412f474cad23b5b9199bf3c7370641339b750e1f78c2adb460aa5b21b1fa8f97714abb4ed5e9cb51d6de55816618abd3fd2b286bc11c67ba01129373d435b3e7e391ba372614da8322875e46a675b645156024cad2dd13f9a081616bf131a24358894e0efa1d56648ffb42efb54031da7f37d197615155aedb69c4e709c8bbbe7fbfcb598347ac5d0c638407847b281cf116433097f5662158719fcdd37beb489268ce71de7d70ed925f743fc63a715f7eee7549fdb909cc454c988b30ae4d77d62f65a07e2c8f9362385d028a603108c945872f5e1a97419878ed49542e288ef07b5c90f5c4159e162303d080f6ac2b058ddcac60746f9e1c9ec1df8eda42d62738586d3fdd65df55f4374f3294e0868d41ef0bb1fd55e0cbf195bbfcfcde5bdb41fad9a0477e4c90ca27fa8cf503362a33fdeca5a4f0ffea26e8d7e134fad3b1ec3d056055bba5e65d81153ee831873b938df7d2c83c2a52b3c221827f961bd008362232d882a0412a047afdfb8597c865a2aa2c2cf5189934a83ee6b752a626941edce0c20b6f7a69f1cf12f9a331cdfa9eda24c8defa769ccce2ef746c307d8bb04891fcefd49af3e6f96991a7a20f27b6c0af1218be31791d1d0293e081b90af3b92ecb175ec8c789f7a8642e041ec3a61aaefef62a807d1a5054adf8323bed942241623732a2051dc01f9a20a29aa48b3fdf265d0ba6c138fb5793e2875002e7de3f5c3ff7e83ad27d111c848b7e6e2e5ad5f28eb7c363f95f960cbc421336ce985f946b0515b1bdd3a832c3fe903f7b44e20c92ea80826fbf97e2a4fcaf2db1a08698dd62edd0a84589d7462c447b4a896fe00860042496bd51b1925cb79cc3b829016a4c7e62790f8058c546f2145aaaef4d4b1e273ff61300f8008e946b622f60e505f5f6290d51eb997d20fc3fbb3e99edd68ff5cce9e8c283881c364ff215cb50045e60f4a7ee45b6c9d86447f38141d342dbc5308f8c66efc47f7c45f6d25e6564309a862db90f4df331787ecdd89d3aaa46053e29f102624ddfe80e8a3f99287cec19fa83e44d557c0441
SIG: effb29da6985971c202e2450301d49711bed25fad85f6199d1eb1e71914d964cbe18e34cc3e32872cdec026bd119a41c1c07ca41e82acba62fb0a7c82aed800c
TST: 826
SK: 5d66ceb7c6e58cac91e288279170e818e787180c6b42dfa168787dd07f809fa4
PK: efc9b35db81f346198a7acc69f65fdfbf4c22e68dd7612e3b8ec68d378553b8d
MSG: 94d72f6dec4f7c9206b41510ce71a02955604f3c5de8e447d5871865a75898a4d207a26cf33d10caf05a0b6ed0d389fee9ed49275098a88e1c0d8304e81b4074214c7a5ce157eb2617ef04e1324ba942129faf32c31cb4aae4a5916c750808726856f7180e5797ede44362d747d70cec159d3b6acec63a514c7ef31b2ecd16db7fe68ea9c5ead9d870921800348f695412f3093e61985a31eadb79b59d91dd9a37f8d4ef7a5ddf223d4b24774c2e44e3f271ffb8500d595381b3df2e8e6b79ee65535a519a43eaa5e52b256c2643305e3170cbe57606a0545f8586565cfb75bf5e9564c62af05f15ee6e62afeef8c2c7a9dae235c9edd1d7c25cf49adc033ee7b583f518bc168ea48836b50ffedd2032b3f630cc56daadd513ebda864823610fc67a72b9a7d8117105c1c71d85a96b1d27a441fa1e7c6cf80233a49fe0e76a40278d06e34347d87be77b98ded5e2a3ea1afb13bee1e6cd6ca63be54fcf88a20ccb7a9fc324bf6143201b44483bcc964033dab71cf8f2a591fc050d5724e95aa50d32896eec0f3b34311d2a9934e9f852977e253f15304cae2416c2c4fcd8f1fecc3f1f64bb79759929abb0e8e8f5f7293d691af22abd3b2a6770b0cf144608f2d62cc7e52bfe333b2ed2de39b99afd37e3acf07eda37ddf0df029bff2ec22544b60bd7db238df1975ffa0075a82abd8d6b05b267180b870e21abf36981ae7768de53993b304f1c5453872fdfa8edad45f8001aa0e7342b3b58ec0f389dcbc271fb0f9000628757abba58c057e1a0899f6faf15f3740f3143f5c0b7a9159680de8c557266441b3b01caac12ec278f5a1025df53edb6134c96663a9666ae3baa90fc835111ef051bd912f67967449113b6a85f71df8c6037724eb8fc7d8319bc0385be9b0e99e95f9aedcae8d45a514476f05bcd7235c013ebc3aea9123c67aa6f3b79c85ea5db159eefadfb75a50ac6b95b496b5572581a76112ff6db263fc14c5818aad5bca3b2cb3ac8116d429482781e06f61e7563e6505e51c8ff998bf84aedb5202e2f9ff4c2689820296cc69603091b8b818fbeb2af5f4c57060d98c1a904843a70bf975b3c3ca6031a4cad5b4bbfba7e9b47491ab740d9ebe41d768810cb8cc51a937f7e3b22e3cf07ceae0ce20831495afcdd8c1a98
SIG: 6ef264abf8b0e5c2d793b2c75279614a39c775eb2bcc0891067abc61f6d644a69ff8f814a30522cca90536f012c6283a76c32b89eee1bd9a4336f4fddac8dc0b
TST: 827
SK: 62ed8682bd3ab3966eba3bffb775a318a03d99931979e99feb2ddbd69455a0ef
PK: d32ada178b3ec7700c47dd6d365322033fe431c302b46f8d58798ed83371566b
MSG: 9eb13bc7facf51a180541ec1dc5f5acb148c8d5eadcd2c4ef068bcdd11b34925eabfafabfe82a284bcbaee1381152af8e5e09f037cf1bb6484ac18e37359bfaa4c87aa07d3d14ed089b053910d1fa473f7bce143e2a59c4daf99b6c6e4e9291d97c864712af3eaba53ce2517a4f75cd7ecf278f34e22b7dffd088fa5ecadc0dd22135e42a536c684f2195d315f6924571e463f5cfc11b9f9d05a7ea11b98a169a1e39360973c50ad45c7491b57138ec050f43cbd5d17eb3fe0013e3d28d526054e07633152246f16554f3054749eea687b9c371b409cd3ecefb111a1d600407344e6d6ec38c60f6e545a92382e46c4d113125dbe5b9826e127f10181a35acfff28ab3764ca7f238ff479fdbc45b7a2ad0ff538c8acd0018d4470febcc6a307651cb5832f326b19241be9867e4eca6ae36f0e2d83fd77b97202b364716e36d1895a36853e7e76e88f62dbbf7726c2180569c66673837ad72ff936cf0e2fdb9ec6afcc79f8829e157f952288f4e00d0410a72253bf605eddceb01440dee5dd32b5a803439f038c06af1c90b27b5fe9843c27ae76609cbf832835c0e3c4bb59976ccede448786d91e438e0775c06a92d0f0b8dc0ef68260f7dd9e6871c4d0c0c09463852615218516f4a6debfdb46273b283382cd9ca744abf9fd439194b8cf1bdbb3175ca9c57a1c373c41fce92bd5fc012b19a0698aef37baf806ae09add8cb972a9ef9a7a5a9b1fd9a41d854c30cca1396140e20c2b98654fe6e511b626a43915b22fb2dad747ba7fe7460d8cebb2006fea19b3284b09c06a6f52f179a32beb56357b929a659f0fe6a26b697033def58ba603f430f74aa35070981db74ccf19190a1fb05144ec0a09a51e54765069730b09a7a2331ffb3de2a7e02c5e184da4013dfe937c371117524f7b210ba60e2692dcdcef36ab227b4c4f02a9f488972b847f0d6b59d02ee54fede8821db6cf731cc8ac895350ac5cd4d6baa3ad036f06f20d10a140c4ad3d10ca985532e3160462773385a2eb5e464d528e1e59c29f66b3de59e9ea28af3f97bfc5589035752a5a5523decd2dff01fc00ff31b30152ff5dafa331c6ab15873af41aa960aace7d2cb4f95c23df44b9e6c6e2f86788a872fd3a5cbe4acc95810daa09dcc1df933465ef040c53d9d959f9dad
SIG: 3da8d14dc4e71fe6c32ede463788e41b826b4e2160ba10c95f1c8a2749aad8f12e98ae2468303baf6908bdb35ef38a5ecd77741e72ee3a427fd904dae66fcf03
TST: 828
SK: 4e57f0311fff0e5d538849b1216f695b1a5277941708204db2f0c15b3c73c82a
PK: e3371fe236ad2f6f42f9e1fa4e1eda2c3e29c36c8ad2218a3c037982f0b579ec
MSG: 052a1f41ebfd4bf65efb0ec8e74dd7b3065e9c482c49b99262e6dfa8407d9e31ed34d229ba41fc49a94a1309f990a99cb9902fb84f4ede91bb64714564a913d574d4a3c286f0a192a78ce2d55aae5c9fb057ff36120018b2a8b54d98085537ea64aea999d5321c7880b36ab43018ea2c92a5e68350d3de8526e2c8bc9141f4349a18a34f21de0abbf2930987567f0aaf8eb19145580d71306ce8a69e79f8eea26cfa0b8beb49cc5aa2bc77b797d4f8d50326ffb937399e94fdec85e192f1272a80e9a0ebbaf5d01f1b97060802bd4af34c0f7d7e98543f9d66d60e0e6bc0bf9c990be31eea1978ffd16733a8abe49558b3add0dce6defd64dc043f1519b1e9be66e06e41ecab168c8339a85e0b913818644ea7c5334468fd7196a01e1d4ce8dd1e7ee313dd5350b8dce4f5d7a6ac09857c4d3d0f10a3d9062609754592ad1077b2e2096fc9e5b1978c98b5660ddf51b46ede9f9dcd41b2ef44e79f6daff7d3626870e2243cafb2f4367939109ed9c01484b79eaa30a1891ea18f984e161dcdd1bda37134bf6735d2b2149b4898dacbfda61e6002d72a6fc5d21f1098213231132d56df68d6a9bfdf4eddc0524db8fd8f248852049a6825a5edd2360c009af24f0a94c5079ddf6fe796945ff984aac36411ce80d987c6ed67b6b0ddb6d417f6e809991e729d147dd0d21a093241363cf4ef3b8e3ba02d486633b6b217f5493e2e432b8c2e27d00c5b56c9b65f9aed49ce93d77e7d0bf5f92f92f5bb4b595d66f887a4880133f970463ab8b7f3d8c794c0406e88e3eab9ae65f1a185d6e39e2dd6abb8a93d2ac4b9208398dab89dbc07a41a50264026412da022b58f489d4dba31fb882fecb1ff8ca1820dda1865af1551e46cd618b44c4e6eb3037a9333fdccef4b895189e4390e93145d264ca5f45202a3eb2853593feed6c66dbb288ff3a3c0fa832b2aa7e529b5568897b3149402a907e741e1011ce0731c915f91446aa0d5caf0595f1816434fa4576db3bc31e10cc2af33f613f03ca7b9491a0a340525271ab537f62a11a84da01c7f5581ad5738c372b5335bab9b2b9dc2fe91e933304d9401ba8e1ce8dc55c4fb466b3a8ed7f53a122b8381d8f29047d7264d06fb51ec3e70071f2736a4e7e1537a52fa256a04ee86fad27ad2d28a9b3629
SIG: 4fdc7b6e2827f64ba3c033c7fb6d1b35dd680f532999a0d77aeb276c31bd9e39c670978be47243c113223a57aa10233150678b40db78591c04d08df57a70a209
TST: 829
SK: 39f0556b1c5dcab387104181bb304de0cf815920b972e871d5f0fb416d8e616a
PK: d85fb76e78c3d5bb7ca6b05b310191821a4a7d2d9bdf02292cc7aea5642e4819
MSG: a8d034e170fc22b57a44aa6269ed1f01cba801f398df1adfe7df044d5fa468bbfa8af4749ab50d24d62e313ac0e73a64b4282b74626af2b4a4b54c274e5a6bc280b6dc25dcfe07814c9c816d2f9e36c05b9bfedff7c6b03cddebd4735e0993d3c3fdc6540443c6005e900b4035e1408a85016aa1b89202990e5d84ed9981c29b77206d7c113052a2029812c6ea13aae8be0aca7a3306bf617242298e68becd0d5d16c8887fd1950b7785a46bb022b39f7607cd8913718b3017fc3f86d6933f75eec5191ad1f1989a8d261786f56be4a988370db82961a9fcc953542e51c2e086db0e02b4fc346694abd9059d5b11722647669e7f17b745a60b02f7339fcc99bc35d59fd0b98b60c314abd4bf8aa4b7eae09dd0097acb9189f02cf85a251ac92aaf691b15cd4a33b58d7663abd0b0444333044af5ce20fd71cbaffc0d29835819f49293fc26e7f9787fc368c4d35cae92747f21ca1f3efd87a0d8104199416482d07bfec1281c66f565285bf672d5e7486400660c017555e9fa2bf6a4e7027f0e7e5f443ed658b75b590612abde0d80d1a26cb8bde76b996eff6a74e3dafc59eb1b584f4597a239cd839fa1f1b7bda1a24d150c4e24b91cec01ee53a3ac852a912de195a3c29dd7079aa7e88aa81e9d31b8fccd435eda113c3f82458b7f7933572b776753c92240cc036158a4ba0e56efed53ecb53fc093fead14343485ae5d9105bb163f262514e48be74159c9fabcb71d1a4280d9ed70d7e42b75f7fdadd02d69198f5f465bf604cb4254417bac3714b3a99e6f1acec9e3b3d097f972fbc36f2eda3926d56112d4e9097d89bdc35937b9a3158e7cdd5da401e180d3ede6b1ff02864192eb729781534f4964ddf2af11800d8b5b6d01b209aa3369366c19a28c79a87d2174ec22fb1489a6755c348a996d0aa56e0f60d58e26befa23a86bef4e3529512e30a9d1c5e4885018cb97aeb7c93c5c41caa34236575c226f3b235eddba364e285b6e352707bbb3b339bbf2a63a9cb9bd333a77e79bd58a48e14ce5886ed0cd07c2d165a81b5e6a31a8ae7806bcf2e0c4ec29a967725e577f1741ee68f345f5f7ab0fad31c8b4b18b431c4977d5c584004b45f7cd1961affe8738e24c382610efe998353d7ebaf919b279bbb691c3052b8b2c5f09808ef3a6
SIG: 0166afed5a8f7c3f7ad6f3fdd2938eff00898eab815c5455ac90fb51f6e1854f0c0753194b7629594cc1271b003431221c574b0c0d19082feeda51b084ae5e03
TST: 830
SK: bab3ff7a4448d8a03d8acfdb913f77fe77804395c3e54ec235117927e32b50d5
PK: 54975e35e5b1d0323f2d6fb5c6158bf6654b084f76bbdcfd72349229e8e4a6e8
MSG: b647b67cf01c2cacc39de5969e199be6d9320167a4cebbf1625950b1e6b7adf5ca24d1349568865fbbfd90f513f05f79f70a63a23873dc7a195d4b285a08f30ee061d0b8e6b4d6bf9b2ecf2c69f3d5a07a6730537cca4a4e4c7ee684702bff883fab8bcaf89311c5498bccb5a0f7c8d49b54f482fffbca6e7da262452ba59a57a6879d81b73cd7adf72a3be28a373cd63310408461c21b907f63e086b292ff02833e8a2f46adbd671d02b03a69aca2e11d287c522a954520442ecefaa905dbfcc8254c58c3954a89bf56cbe01ad5631971eb39eb432a854e691929df7e48b900ca6e740accf578b31795b49a6ca774bd8b993106a9c4948c18714948315990a5f191692420f289328ab713ec19b7ea894d16e6476100871cf3168e4f935b5505d1ed5b0aa29be36fa3a346ac3e76f143c46ca69123b79c36399a0d2ed302772494adf442bbafbc4d01532692c7859df04d2ca78ba55d77fdf3e5ad993786a24cff2199bb49387873cc414b4cf1137abb7e94ae3ddbf97f534a18fc5ae58523a3cc52283dc7b016f31cd6557981c5076c774f303a47c427870e207ed8bd66640ff092db503fa124bfdcf020051dadd106dd245840b31910b8a9060d5986f02b60aa5e33b4d7550912cdc5776c772aac93ae19c73b7ecfca389e627681a8781eb47d84e93460ba891d3ff6eadf8f2a903c383474beaa42b90e032236dcd898d02a40efb44e47ead52b75b09c7da1cd6a2dfd4d1c0452de69f6acac1a68dd78daf972ae260821e2ec522fb5749bebe0adb452bfa4faa1e97911c1299f16568d68eef405f4b1cdacabed59f7b0fbceab719a34b299f58a4ae8154f98f4d9f4f140b1f085006946725e7c29bb0bc6ccf2534497c61d4c1612624a61d70d26c3efb7d7c351848657f7f8eebf8b990747740e6f910c97cef150375765c8c0b3b449c0d09d66f008e67cfa76ea2b6808b6fe632eafe0587f37e36be98dcb17a3f4a15b65a9f6fcf9642b52522077b1fb4cc3c08df4b467ca716db16b737f782cdf387170a5f1f6a7ae0ab3f5b7c585e3b0655a6456a503595ce8eaea2537855e7f0d5061bc29b4e67daa82463c190e9fddd52f8322ddb4e0f26b68778228eb57e1a185b7025da14987d44baa767b22ee7f4c84591032e88ec12eb8c5a4b9e157ec
SIG: d6b4135fc7acb3d7cdf987896d91b8a90db584d8933a6f3029e3261ec1c390cbacfaafeff443b6da4fdb1d84c64a54560feffa2f1c7a91bde9730222923b6703
TST: 831
SK: 486c7b436c1d43d6b703512283c166dc863e5a33802f4ea65fc738778902d014
PK: b5dc947d64337cae82122bd68cc80840596de3be56cbd0c833af3faa3adc3776
MSG: af036053672dcf3aa26e28ec6aa642ce284b896c69887dfdcf0824515eb0848d9d970ca272df77a86b3ff6ddaf3cbadd3ab6283bc37cdf7a5607d5dfc7cf96329299cc53edbbe657fdfa2ca24467050a0aeb8cffd7d33d543ec2c191cc0bce89ac37d33293b1888ccb76c28adc671a4935a846d907e4add0110febbee5aec80f9d2ff74e2af4fdbebbcf49105a6469d7380006b2ca44364814454e445e36dc0012f339c96854f836442a05a50bec907327f74ba9f6fd790ff0ad3783d297bdcca76460783703eb5f2b1f51b0a740ce7a8f00a387e3636270a971fa8f15b4496730d88add807a7f7e987cd41595a2e7435df5195576a35f5e91b2fcfac94ed5d77663783b61e6671d34838b6b5644fbc1c539fe159b7792db967e8352618ddaca0cde73437b59e7801b49eb4609b10577ca2692dd6f9d5e9d4b5e5e62c5913e7b87e6b347be6153b17199c916a13f8a885b378ef09e13cae4d8b079d7d5cb9094199b0f20533c90083bc3acb2667697eed22e3670abb4a553e995c9dd9594e592391a0004b6556544f35612c4971359577c476382ca53b3f262a5e33ed26eec809f4fdba4898a113675cb6af717db62579f3980b21463be029cb4160fe5d257c46cd6664f9861ac50fe05c144057dce2f8df1532aa7af589f41270601cef06bbe4f35c31c782bb3cfff7d5ab64a14ec417361f1d32cbd38b6bd0e02505d1416302b8505ae2a96e8d5339c346c2b0662d350259c50c5e48795914e6f88e97c811c393bdf9aec7ef82047ca28ee971c175c27e36e109727960ddf1a1b976ab44f4851607bd966808ac46d54003128297f5f4487108d6a02e7a16413d2b75ecb42fddfb669c801d23de50a6f7bf658f753c6b2b3b47c0640105d0a801b32a1943cdc15c886555eb75bb7927b93c35c5be1f98b196caac2dad991b1044ea863944d54d883abc3c6de66ed868ee84bcf9c34ccdb80fcd9cc0402747732cd630bbfa3bbe8b038dc1dbdaf436d9ac00c02d528ece2e791ee312a868feb2f587ca44db5731384fa1831142061b2ead2b80c66bd2fa5dccabe6a25f2a493feaacd231d2f409646b942a578545ea4feea9a73473f79dcf13e0c9f1b49fd8912ec487328045bd0fa228922ee6e973e61f6e93365296578dcc21c361479ee2d24879f2e9b
SIG: 31f95cbb7463b87528654227bb1397bf1065b4f576808078207dfaf06d124b41f4c318f4a9315a66085b9e568a71e414ed9414517310c699946db0c976285207
TST: 832
SK: a6e6ad2c379c6fccadb4a49b232a9142618ea30103c33c226ff628bcfd81f426
PK: f7c4323f5c419d9b3f34a8eb42ae7f1faa2333079030c5d64f9ffb1e9b16002d
MSG: 2e857676a5bb1c6e9e94507f83c60a67f547c5de9e94566b197a6af6cf4752e93dbdef6b9f66d1febd957e42a7f5ad64ef1dbcc4fe69ae9525d1a4de67054c88f29c0647bacf8b82f321ff99fe9eedc992ed34c1177fc5421227ccac10feb9ced4082f5658da63714723979737e7dcbfe2e8b5d50f91dfca83e7f95f35d1ad8dd51144502f3df672432611f0e766a90dcc2a5739c805d95fe5b041de9d7fb47b4404afc803a3bd4804c7817ebc5bdfef8add9e250b50966ca8939b22b3c6ff936eaa659a240c0c848b810acecf6181e0e4db8e4cf8fcce7de559cbe8afa9db8499570911a3887e850e509cdb70debc3477d12175014f79f81ba113d0b7b335118f85cf59996f806758eb903cc450f52fee102efc01441e9ae5fae74c231dfd85eb6bad17d6b70e938584facb2172cb03bd5ea07b7f0d371ffa351c0ee4efe9ba4a3fd543874655e7d39c53ae86329802e5c385e9283a2973cab8cf7ac7ff0f91d1d48b58abfdad658d812f07881676bd226bfe957d7df30c4130a448354a6b94405a411650a9c8fc851155ec5a8a3e3b67ae0c4b5cb89bb73fc82974be62da73f0e23092937d405ba4af6cab9465ea43a6253f4457082a06ac12b75e88ec684487f9076373fab8892859d8e8ba431423aa805a220cbfda431b32b1e03121f7fd4de18591f2505cc0f5b2b1a7605fbcc63757b07e299fef5a2b7365230c2e92a25962c2e8012ad3fa9ee94882709625ba68c7b213664ae2532b609d7c9aa0e83d493dbce7632f35580e06d3111ced320dd0190441f62d9e35f50de59c272fb00f568a00b0746c33a9bd2490c074b91cddc487ef2e45a0f030e08fdc1817bca8a9ce29d29279e755debc28dfadc3c4d1b458486e3c8d0c4318e7e6f9eb5a3653b3f7c49507077cd5eb81f10b88107cc0f9316932abe9b64e8886d06856a85be63b0c2b475c0afcb0694426860fb24b5c17ab6ab7733d5e641be74fd5f6a1ff18d2f9a42770fb30750f56f4854e38d58aef18a2a61cbfb49ee576ed97737bc28df3268a334175513d97af009cbbcfdfad5039d69bb46f708867d9b3ce0bf2f569e3cfbcf6136f8870d25208b21a3edcb73393dfcd4172c1402c41f36e3f82a4ea6dcd891686ba66e14320aa0e22ba0c1ef033d662cdb860cdfa3a40f6cc532a08
SIG: 07d9fc244fdab00159ebecc5a00883453f08310171769d297001e877010e3eced9fb60ec91cb4d88e7ba40c530b1f9237978ccd96d5cba9e4fa27e2a0ad9d60c
TST: 833
SK: 9b6d7e28eb051597324dceb7a18941246725e88d53ab2c34771105330cf1f4ae
PK: 8872a50b5fe362f8ead1d40e2045f0d40b2e7b50b59d8090bc47ad68ebee09ed
MSG: d1e1987bff65f62ad67624c6657924f5d673b7824ebe404026c0562ded3143440be637f98c9e01a6afdfa9a47dd49c7cba6e3fd23e4552f7632b14380b27cd3e9606cce350f152ab126bead0a5d3bce4d42092d934c8ca337e987e11d86cfbfbd2acc3223bd16744a927728f485372175cc694df30a73f9d33765ff014ef008d5863210338cc3482cc27ea317eec921b0c568c38ab27c4a564e802b1b94668c651e20a0b55f3a79d215fc3a0d04904010932c4cc68c2a9e7d00e5d38d82df55206bab95cf697bebc7206eedef6fd18d9a20c2cbb285b00efa769a08dab2b3abadf00d198b4f192dd44bcb91431823ae6fdf98458eca39cd29263f0999303e70dc694fe01c53a11c1d1c34c1ee5068a201dbe7e1008d764358968b402aa398549507f7bd1850800e411b1c4e28ddc04a859e179be8ad7e6670e509db027ad7e517e4425954f5a807414a6da267a764e712a998465064982d851a265ea3c4dfb74f992a7cccd9a82687fa61c322c4f589e86b8825213bfa951dae6af354ace18f073995adc95839dac0165511d61753791a53e48e3a8273d44823d2596f2a2db2e5f1ae597221ba7f3ebaf4a7b2888395002bdaff51fa54bfb979de1031404ca7789fe095d4d17f07a35556b10fe8e1417c8a6a631c2ed36cb7a0e6181776289c344814d42131a73b12faa35d77814c681a601374ba71cb9ad5315fad42d3acfc7c1d628810256daf7d8c3c9a2e5bdcfb770082fa638168958523a1c3b035dbc6d5adf26df89a7ccabed3e7dd377c16da841f13c6894d43cebb4e39022f1ccec2274445c78b3adc7bbf70d890b80236cc4468f9569c59a7e33b570e670380d244e4e310e11c392f1e334054b92c8386c161ce04109b037bd628d919dcb62da1435bf94e88b0a8846d486d16778f7a3b880e660f441fdf86e56b8aa0661f55aaece27f9ddaa0e2a22c215b040539726b9853915a1592dffeae32d7b5b67eb6205bb0bd7279f788d5f833c4066780ca0a42d3e4e1aa22bd06bb5eed89b9413771ecab644ca72d1291d00f740901a7311dc036715d23ebd9a59891628f0d87ed489502f06d75bbd11cd1602a35ee7e13335d6a144b08830e669c02e652f3f100d393ef9b4ac05321439bce6ce36ffc5abca890b8796ccb5e16303559c5d9117f0f31d
SIG: c6dc5ca1e8560015b493afe2666ccf6fefa803d8526c837fe7f123c7991427ab030d7c770e45f6de8481523b94ece97f3f161cf5b8c7aea39f5ad826bf8d0a02
TST: 834
SK: 7009edd0795096edc4fed55a17ccf484131e608c6d5d6696bf3376e26924959b
PK: 77574bf069527145e72d3e85ce7d4fcd671a33e0a71e6bf0da7ea471dd6e86a4
MSG: b12c12470539547c2de6bc4eeac7b63e508ed710f35637d9fdd2dcca322a7a5071dab2b2845e30792806035c9fcdafe2783e3b677d6be5aac70b33910a2b95e8b5d59bda615935a417b7ae19a7853774e89a12aa547b4192979a01ef6ef32a40de79d680057a83a074617ca6501f59e73564927c38b58c19585a2c03659c026e4de3806d6c1ca8958dee47bcb889e76d2c3a9ab5b8b6afb2e842298056567bf9b58957415483336233ef4920fa57f496e1f0348cca20366496fab3a75bf4214ece47a45feaa1392db3f254d96a7f37402c9811140d7358b4ef8f20a298eeef904e37d68f378d33cb96d00c03109fc83fd06a876c92482f61ab7914eb7c2e5e84066e0e91e21e42e9be23df12b5c747973cb86442c32291d3d1ae719b36a62faf3abaa2053a313f625d85c51a5198571915ef8a2b199ba37d25884575ba1b72844cab4328b57fab1ec974ee8ea1df7ca9c78a4d3a03bcb0ab4169bf06a3a438d9566c6c501d8d9ccccb1ac26b4da4ae1a9d8e8b9df662821ad975c9b015fe26f6898d22ab912f0e405a5b27cfd39d657dcd92cdebe6791902713484406dddce71188731e44319381af27daf76792273b8c35251d11b836afe8b3ce9b40273f6915ebe6bc95a75bb941a429209867fba8764bf6c40db6eecb4f21747837cf6ae7fbfe36d5023df7fce2c0c3c57af2898885313c5c4bda35c7da6cb29932fb1991f62bbb080b32e2050619311ae69abb3022d913fa9eabd5d5cb4dc54d75dca638cda9af331c0cf4d2007b6ca39f655a61c01039f12a4b9782bc39aec4d22ef0093388dd7d5b56dfb8a7f9d8669004e2878dd8a6d76857c0845245068fee1c5319631e78d3785165c70afd65299301378551ebf613584c6a7620a0e3b6779f38c0940062497008eb233870868c21cccac239501b63b749a85602c28a095cafc749b0511a6c878edb3b780ea174d07b121e315a826dda6ec8dc54363e2cd2e6305a194825c0ea90efd7a9fd89cd97b99c4300bd3bf9353d82fbcceea71b4ee3f1aae9539b4cce90ca477597c174ef20f4b9f4e62d09a570d3135aabee9551fa60983958c0b7b8c3744553ee14e7f3cd103a19251c99bf6384abb60a76afc6658b80dfc5110adc4c732fe0ee32933fb284828e008887aef80f6f813340446c0217c12ee
SIG: b701b8f9a434e06d719ad25dcc54060c7986647f44f3884bcb6e5ee1d7a446cc265cec029b537da7f2523326558ac9ba34f4cc2a97cca3452e70562e7a8f5504
TST: 835
SK: 12fe8e5ce20cafaa3279da7b34aa87752ead679f156128aaefb4afa5db4f2a6f
PK: e77f44206bb0c4c59a2870cfc2ecac63362deecbe8115de5cb1afc2d9a3d47f1
MSG: 6b80cc6fbbd332f8c6197cdf2e6dc19a2130faa2ec938ef558b884ba4fa5e113e5b3e4b1aaf51b695f13effe13f77d39cab3c07d04d66d430d9974b1da3d39df1278c00d6bcbfd4bae75b8c076404dbbb83448fb493df67000f97d247e8f23dc081fce992b65a21b35d7bd7fa7dccc54a560afd14b1ec436c10946f6aa59eae1be3ecf311def51e46b6b4d1d080d1784b2334b80cfba72cd931f55ecd298b05dc836ab12d0ad8b5d6e9b1e3cea3d843368eef19f5c14c6bbad9414cc7a4db6a726e4fcaed44440a019fe12a60573403c0e662dc902d1c873ff30c931ba7e43a3b3bf71d5b094ea504971647ca94356f0a53e444b4c008ee5977204221b400deec37fc273452545f8f218be988725bc38c85df212ea73dc0bc7cbbac907982fefad680fbd975c2093a7fe8e6b37c1cced87f81daa57291a5a18476d11a18ec4b5cbce5d55ac9b624b048430f254f671078506e6989df7c09256525039085ab7c130c240004abbb3af6b481cc1a0617e57e388ee4b1f052f34a003fe6bb202cb87d2741bd8e3454ca73d2f612011ecc74d88343510a63c9313ddc36c25d3fb03e188f560bd029c801585ce552988dc55b7d8522a3396c01d5e715ae26c622c64fed5b98e9c559e4aa78d1ed3b7b890d477ec8c50a0ff107a3f83b07bd35e9ce9a08bcfc0f168eec7aa311f71c66a71ceb9d5a2199a14be36865ca8d07e186b1392b9290c578004d584f191c82a53d850890bcc0d12dff840e043dddc2e670c836020924f58c044b218763ca61982bc332d247b2a008ab570b6565a06892a26cfb0853d79da28ef8b910a9329544b792ae4456ba7765066b9d1b4a300210448660ae48b504441017cddd1f6f00938b1072c8ab824adfe8ae34923c82eec754bee1a6550ab1d3da086e3aebbf21169c44469e03bbae0d72ce863457784cfe1dfc276f1afad9ee53ebab5a3c6572eb1cae099a4a5fe19319290e6a1b8b0e7541ed735b3f21b1e2c7509f87fd1fed00007479b3c1bb78432466302d246d8d031996307260a0c41a0e3ecd1e7fd834dac11a13eb036b39c369966fdef394c183e54e7b0cb3d0ceb198bd0e66c00d38db703aace30cbbdab369dfd1d9e514d0968f100c9f07c315089adb3ad02e59c04b9be46e99fbf5a62c6bbecdff5b381e55127824ddb18
SIG: 04eaf900966e0992d36e3c220a4bd4d82bcc6eb998ed051dbcb9160bcd357409736bcff7e6630e96f5538aeca6ab8b0d0bd82c0cd7c4549917febb9cbada080c
TST: 836
SK: ee9b6c2e0c9b01472ce32d54d1762ab0303317d76d3aa78f5e08a9024ca1e083
PK: 016df0f717bcb7adf626958d83bf8aa325c70518c68bc7efd84253b75db08788
MSG: 772cc25c3b69bb3ff5655664efa478ac414adfaea70ac4a2a887ed3968c54d34dbf1be32cc9a9b5420a4ad3c9a877bc8ccec94ad473aa7a3c7de08a0fdb5ed1e89872be78170be221d279776bbc6ed9c5a67168980d5eaf895e1340f5dfaa3df622d6544b399d74945fd13bb1173621e0561514640137aa7bc9cb7debeff2c626977d447263b7e57d43d69efb230cd25865e4d924828f5e36f964e403e3493f30d6dfea6ca3b781075b5e3b25c05ac50e555f15ba12b0e059bff996484129db6eafd88993d6f0b7ecd15dce2fc99f8b8e43516352ddb461a04b9ff3486452e6aa6a54b2d1062a7714250cd2a88ff6c4c17b6cc6652d8c5ac27d4443aebf3d5fbaaee4521ec76f0413db64421ec8d6949626725fe56160ab307c0e73906c45155efabb47222021f220d32bd3db0712abde2599ea4ff799717811dcdf8182df6716d2a038aee15d778da55ac20f01f25309cead5b5b7b22322e1828ea7c91ae666f2dcd684073148e31bb2247d5f93506ea8085227adc9ae1982e950f006a9da158b9cecff8929761c84f9d976fdcd317ffed36cbf6acda3e50c9b73bd2c8085409d119b64ced7349a2674262a832becb03c2edccac0ec54124e82f810181792da49ea10bd941f9895a06959fde0d3b0ae84c39df05390ab33c36c79ca22e6594d7fc6e3f86922d78eb7f5c25495d822a3b41051b24e57a76fcfc165cde6d096cc7b7e9d055fe864d52942d629a8ac261be1dcd3a21f895f49b67ee47eab7cf1644d571d5ff38c179f5c6a54a3612fb34753412a1b95bf62ff3179804ffbb99051f2b080563a4ae0f27cf996ea8be3bae0a4339dccdff6b6671559266eaff4eff682b8dee89c9d2d45acdbec4aa6cecdbdb1d284609e65efb77bb8f1a51fc4d4568a705fb9c97b2303c1467dff8c8c5ee27559b93ad1c5b9c5c6c7c529fa8c55c75ebb59b2a818aa9bda1e9e79bc66029772f8aea11badd3226565d54fd01bda8cb270e70dc9339b46900b5818e932075be6c28e73a191d02cbdc7454be12387b0d47a1ab14232d2342a6f1518ea97098b815a1ca3f9c70b25722b1bcd7dacda635622fc8e72959f57f767ea563da4c158eef7200109f61416c2e70439923062437b1d082a8c7f4394713c1b7ba0587b841c114475ee3ff059df8cfa12a321d901cb47f5
SIG: 4b001d9642835d72138d680198e6af70b5de7af015131ea726f4e51b5e8b6d48c2a6ca8e8709cc8222a5047c09a66e518ac5e8b6e53548948261f0701f687308
TST: 837
SK: a3d23505d07c5f937f13639dbd818e85145234ee7017ecee8636c7ba76ebef5b
PK: fd7fdb3d022ba36eadfed0daaae5bff04505403f171473e4d361ee8d150a0eb4
MSG: bc298ed69892904028725e21b114462d89d8c006dc884b178756838af4954ff0f1b79517307a258a0e7681e879ac47d7920230b0cc1d66171eb214d77cd97f617c405e6c2172fc589f1625cc5e1b593110531f6eb53f1e6f486d1964612447750a041fe51b332eb3fbc711616ce35f040442b43163b80b751e21ec1245f12e4883c79d3b413282c69bfc6a465d1e7896bab038dc89b4cfc032fccdfc87b07f06110e1f506acca8157a322543bf1ed8906727f28d0d689bcd7dd3df85935204a904ab3f7a0d99c16e5a542cc2bcdebf5b502dbabe33b972480e02e71a438a1980a8766f108bd8ad51104223994d9bfb3c3a4b7a59238ce2ef7d7288383ffbf291e1602b384af60700d7daf0e8fe60f8caede43db06b3f4c8cfff749aeafa46fc61c49b2d5a41204cf86f049254d809e9498aa9d4cfdb94acb2babfcf786ddfb03691516b3838b0d4f201cb2591edbb0b0f674e1e2820316b72e81b48cc5a6b29338bc36681f8f7dca43ee6c0bd2e402afbf967797516453bc01be86bf42299d1b736a0d97bbc922f5a78af2df42e6f8c28e953f2ceadaffc5e93064041e425ad6975f88c7aadf81c368691a581e885f2a6ba72ed68b8fefbcd6ce368626d44892a20270b5f709c2e34b8335d42eebd67a24df73f45455c41944187b6692f054b2fc9591373f19fc71aa7fa27df6006a1d549bbfae7d3c3eb36e5ab2aaa10aa5538da7ef36c8ff354b6058134004d660a4036321caad00a30b1c498ba3d808c4405ef79618fc2212a7b83396a3d7cedceb863c66374dc469ae183c7ed74b3e70d6374a062de0379b21cf25d3c4c5762115cdfe755545e89ad4052bb0279d938e90de3abf504410caad72b7c29f53d01d9dd7f2ec5e459a04592bdd66416613e6edd004569e0e6c98827b8c1d7002a6d1bf303e18259501dd89f6ee94766d18af810463eb13b2efddf1723af735a88716e1fcb4b7b43cb97e1cc903b2408ef453ada4164786f00845fbfa1ffca5cc3e1c4bd9940e7d99aef919166d058b51453c9c14fb9f3251ec5fe4f153c70a4492dc3496296186f23ad47ebad13c66e68727ce50ba9487f1801890b693efebfc37bb5d95f8af548ec8d6498289e55f9883fc5be84c256d2bc5484938c709820d9b6b8059c0aa4267dde69078e487c8865c0b130a0ca8ca
SIG: 67a667ee0d6254ca0a8f212582c0cb8b6ed97cc967db021296ad6aa99f0ad3a944978cfdaff13fe5f8c6e88cbd831a5473d0742e3734b3e2df00ff3240a5de02
TST: 838
SK: 6e265105ee7171d1bd793effd87d1e2c79450d5e188b57be3aa162e2a52528ad
PK: 1f403c7a755031c13ca63af57635dc6e2c4f23bd6b1d67ca65da68b09943c554
MSG: f8b9d4b027ebb10ee511819e6e56fb1ba9584018418d82885a38a449086007b8785b5105caf782bf9b36da039cc60e227c7e1614f29b640b1e9b22747eea7a6725614e89e0783ebebbb7ee557ef36b2b46cf6461e5be2ad1d7a7c2711a475ca4fbc33092ba425667e34d090060518f2fec636b049123876ab21c8bd9c50dccb984ca011a02eea020564fa821fc362bfe392aab50c273fc7b5a042188e331621b9d2f743e5c8cf3ab1faffafe2a0004c8ef7cdf5e6dbb5eb544e4289f71a6fd15c638ce29d28efb9c039e477429a3497a83827e76ce77a49816d90b41a8e152f37a09e6340dfe069a4ac6f27dd2eac747fd21e3152088c1b1ecd32ac679927490750488c291785147b63b0b8ff11d189b9049b8a396b6932f85bd6a15eff9f0ce1808411af0f9c8e6e97b814f110bd4df1386a9797dc511f0aab6ab65071d9ea836532cec51b92ca7fbdb8de1c8436658de2eb65edd86044f6c1aba3178647ad678612ee74f046ca3c7fe2f39c09dd2e07df2b4227085fe936e794d22fd5f40a25f08771580ac801d9889f5a76aeae1f0cc4a9e1edbdda3750c74c850524b32f44933fd883b5372bfb7e761e069fe7c1c0e7fbd4a7f58467ea6883f9d5b7f66d386b0499bb6fb5ead89c9a1fd2cceb973e2879b5d03eaa452e16022d59617daa0486f4d4c117807fda8499dfb7a286fd2f71a8eb5fe64065c41e4e1e2362ab4e477969e3a408a247e3a56fc86f2b01ef8d3cdda87258234bc7f25b66907f364b37b6245296c4fdf499f20237f4864852fc5d8cd5d05418be8b13859ee9a43e17e1f57a4c35ea282ed68ebcda6828174245a49c6cb6590eb1f2dcfb007bfa1c32077956da9acbe3ef0723799fdb869d8de30706a9c026814d16a01e033c91b59070dfe445c5b848a516612e5131fe8486921e36b8e7ef157a88822886c681b5da71fea94d957dafec26f4147a3b2ac383a5f47c8585eb17a8ac65790641b4218d755f8bea4d97ae2a45bdcdc23236294d852c95d08406d2e9bd30c326452538c1f5e5004d4a1a82720da32e59dc3ab18ea08a058f791d24418556086c1e4edce8982aa23b118fb266e60b542780a6933add913265512c07b114978d44af73b2030ec47b06fd09dda8c4f1d4e313775468c451f9ee611e9cd4c0845c2501948a7b14ef1d4b5cf
SIG: b5a83a117a60345a67e4a665f37de722a6ec03913829389959f376ee626477e654ac8d720fc727d4bb8fe1544f5d0b0b850514290b24273c4cd4b73aca4a5300
TST: 839
SK: c4370d2aaf35acd158fc0d1622a399c99f41b9da4e970b354e5ba05cbe844ca8
PK: 3545d7d4c95c3db6a54530537afafa4d86ddecf9cc7e66c319ba9f7dd7d07ee7
MSG: 619f57de2b1dbaee209a825d8ca97f84ee49eb12a0b13dcdd2b3a4ee45e0176d474cf09460c831a8ae1d3f39beebd08808b3ed1761213ba953421860cc07e2db312e680df03e60a6870264abca8fd51301e1c1562023d802ccd5c7d196db39fbb8304b0e59e333164192ecc333387eef69c7a78a5d11258862d6c281b19c0bd336cd3edb2f9faad4021ac2f205c16814b38548433ff9eddfd61133779769dc69afac658afc1d1b416d390ad5b45a1ad5cc4b00b4b278fbe4b59d52e61a6a5fd00241c6cbc382d2d621a3ded002019b330560e361faab28f41d1af9c9c0020f2baf99e8d8ee58e3122202147c0adc57d670c5b380af594cc7ed57b87ec6674ab63f3a9849753b9462aab5de88c948a8b109af4d4954927aac58bee953be0d8d7d71aa11d11f1a87b1477b9170bd735cfc2449f051b82bc59b0bee76a172e8d32670f51ddddb804ad110a565e384cdb76fad04cff67893091e41e69cfdf70ea926c26369a5b6193b19ab0a62558da55ffafeb8789757710644aa19f474be4ada9dc1849b07d5e17b85f921e1016a54aa6095777253a73426fc7864b9955f04907023db207f85dd21a65106cf0d622385870c34c2da9a11e4726395121e4a6761fb522229d9e5cc9dab35aeb87d0d79693c006fde1cfaf116208bba962059cfc0d2d6370aac7748362ee6a0a3ca7bf133ebcfa20f1c4ed8307f800cca7e6c4beaa3fb2ab086125364285c44ed1a737a67cbf3b763c9f8b1427e89dfa96d290e9d4842fe6316afef834cd8cd1fdc1f124ca3fe26266da62e275c0bf7fcc8e5f9bba6c0d38e23fafab1e049481794c14f4a8c53be1c96f769c9b13eaca39a0e49366d2c9ffe8f206360a9d503dec598621112e3776713e7fc0649433e257e503a546059a989da89157d76476005fd90e4b07aaf0db0bc0bc0b67db8dcbadff39374e1afae551634e0e32831ad0e5fa7d5216fa7c644f73e1e8e07238394a416c169aa9d5303f469a5d4074308721ffddeff6559e5adf0c2773b3f5264e7aaa8c2db888e28e815c71069c3b4ce6c29034c0ab3b5c19a80a9d8c2e874813531c422752ad62b3c5a1a3d6c5a5db587270693aa75d5f172eeddf4eb839bd793affb1c796a1df0e442ddf99b780aa41eea0fe6f865bb539ca53aa45db9a856cb75d0151d35edea80f2946d
SIG: 9febab5ae161d692a6a394500a2890d21c7f0ee26f4640aaba4fe66b90b89edcb80ea4cdcabb4d2c3a5c4154e8ff20d0e237fefd00c7ba9782e1748f6488ac01
TST: 840
SK: bd3de1a1d164bd6e9be0a6d107f703a6dd914c8667cd341d139f19578d933b16
PK: 9b024964bdfa852eb2d4144f35b7cdc26781143c2bd7f660233f8b8aa36071ee
MSG: 1769fcdbf51247ed4c83a00bbbf02f4428da6fceddd0161a02fccd1500970665e1c7630ad22e3d9749c792e71a260cfff6053256e02f5b47bba14b761ae53ca7219ed2801d2d788e26419f36c81ef92c2303683735c8a1756adab6a487923153e435603c96b239553edfdeb093298f7ae7dc90f16a7e5664b9e4c02ba731a23cf2234e250ac9742633a932a948bb83dc3d794d059fedf4ec8618c7433c5d8fe5e62cf07b5768c4d9b261c71536804fe2e7ca7098876521d57677361424e47f1b959237f90710421f5bc4f109f7d489c755e94eefdfb3c85b90ec013181a23bb9535feea4941d0a06a540bd6b588e55b7f35757149ca3e640965e1a0ff7f3c8259259957ff5dab9fb8732eae719b624a4492878179b5a83abe51caf02083d737ceb4fcf042f2e60ba0297ac72b87fe3e14ba5fbc54b48091073896823bfa289ce8e16873b48812c32bfea5ff6bb221d1ea5463d325bbe311e7fd1e783de650b7952eae461d63bc7470522af5b7789f8fc2eb192d2cf776c5c24b44e29cdb0cccb1d90361438e4950ff34dbcb3cb0e81cc45f8d0ff570949f78084e1060ff5594ad516f50f1cb0a765e1c0e038d5943b936e4a8b493354e79abc917bb9271266eeba77a93a657f9ad87b291ac7ea386f5d4fcbc582e72d5c23d92ba944b0064c20e3e2dcf504bcc7c6966c63f2080843600ba313ec27cba95e7ef318168c9067dce86c1ef0d5d9eb7a6158489df32ed58b6931030818f00705a0dc55d3dbf8006a8546641b1865d919bc242202cb3ae300bf8653e3b37894c3dc0e477b9d7c41baf8d3887c2eb59b1e4d50bbb6f1792a1c9367c65cdb450c2dfa2145e611a97ad81cff1fd83c6cf7230947eaff4c21dc1bafb71ec41e5bc72b3745ec3e38bf5930c126d060f0c50a895f009aa18e87f2174f58ab5379a721fd83aad5517fd99dff146edeea61521235e2f1a16ee58303e091be8d579094c1d8a20bc74a550d77c00d087571517a63cd4126933a4f09a070bf8ea4ffb846a9780e9734043bac4c0ff47b1afccf5293ac14bc73ebf67129657e4b8a8b33ddac7b0f4d719d2dc65df6ea0a3f24cf44c8338ed601a3939ca358fc4be13e8ede027539712ca23e3ffba706e8fdd62a074ee0ad7420f78060cc96fb2abf30e9eaa241c0f87ebbe3ec73517596f7c3c5a80c
SIG: 13cc158fd061792fced156879598251dd01d575b400fe3e39a700863aae8db1f9197fa501c0cf993e44d6ac55180b869838e8ae24b214fa35e244b7a6cff6d0d
TST: 841
SK: f6ae516a51296fc523cea5f008cfbd09e73f78b6fdd3b69426128041a5604cf9
PK: 376c82ba7b87aa77418727db33d326ae758bf7a135c10460cd8bf8feb83c2b10
MSG: 8342f25ac4b17ebad6f79b9a033175c7f28af09e658e8cb98c294f15c3c8342629cb2a3247dfc875b82f5b380c5d11426a2eeb62450bd885650107c68362a3b72ce823f2d15942b7dda301d2fb638f302aa9570b47911dadd3bddbfed554c1c80bd718078b8bd2c9c314a5166f265e8266ee2db357561a5585c414a7840bfae609d7cddde1fade85560f23d638ef3d52e51f5cf313a072c5ea0f817f7281e2cba5c5c8d26c928592b81f0ff8cd18db5a2c41d880d74473863c7bbd0056fa4d4afabd17a3b89d97d3fe5dc06b0f612a1d66423923ba8dfbb8ec8246624d83784eba4f5736ba385e442296c8cb0f1b68e03342b2c6c103346f6dd740e26c3d13caef801d1b2621d89f069391a078d43ae6ff12eeca66bc32637b45f0ac627c2d7bbf8a49d9468175e26885e02821d3a3baa2c3e3a6bb96b57526e224cf3d859f669573cbd5c87393746156f3d1c7a80308dc1f2405bf0d40be1ca73b767dedf4031337c081bfa3ae6e54f6023f42f0cbd87762db55913c707206034010df2aa8753d030f03c267e71a9dd2c6c19de3e1851abfacbbd5dd5bf896fab8e415317b49f1e4096e3da99a5b5d0a3c42daf9de94847c1e53c8818a5b843323f501e3a7fa68df89a5f41f2c62c38d17f250b02a67fae47daf063f558942377ef8a89052f1a215d768f7913a7ec14e98b81e4b2ccf26bacad6f39664afc0e91a3cad691db2bf56a7ab6677b49596db887c97def43508a7a2ec2ab755ec368e2e53d1e16b60fff09c3b52263f0f7c1ea9cc35373197e95c11e6d22fa9d8299c423736f5814f1e798d227518600df6a790358deae38d5639e1983fe018436ea58ba8467548c929efbb16dfea4102253a350fb84d9831c4c2cbcb76e18d7f3e953641ada41421393091e63dfe66de24c99232c7d6a2837a48983cf5b16331ce00050d1c713958ffce5f2e9348c52f53120579a7c9a16008d134838e596129c702fcd21148bdf9174d48e2da0a8a66359edee01c5009ef6742fec41c1acecd03efe1ccc9b130d6e5ac92576a85ccb7cfc7d0e4233106172931a08699790bc41acfbb731adbb26d56b39aaa5b333bc1a10e2c7064ca86119d8c717148f92441af24cd2aa8f57c86ba38a59a100b9276df3827ec7fb4d3faf58be31c6ecafd69cf1c6410a49cd7081ff6e9fc397c2d20
SIG: 0fe4dd7e1f608ee82b7fe863d1b03a81843ce20c762cd8bb24efd46ba025fff3331d875752ca7220c53dd3c71f2bc1e2c64a2f9c58865a2a244809f4134e5307
TST: 842
SK: 83f789900f040dc62f4d18784cb64b63c88e8d18001696bbeb4707c469d11a5b
PK: edfc2bab7e79f40037fe4d9041de48da9aee8f978098d7b0ae17929025e4273d
MSG: 6c112a20d30657ab5f8c5c04478d6c42d1c6bdef38cd4fe006ac2a57e290ff29287896eea8c30a0139c18fc8c97564563e86c8d34056a6719bfe479d9e87e81b19452331bfa154806882e5039a20c9e954b1fc7c015dcf5815bd7cf7b6357df9280b9bd43f89ffc91945323b5acb2ae00254d4162868d1c83ec6e0fcbe7a8ab9254192149c6bc9e5fe350694165d6638331eb24e3b1390c698c4838378c01b2c61a3ebe2c060b98ba6ee02b519b4eac1e0bcc09b2324ccf5b1a7fe8fd0b1545a9427832abb25744eeb36326be64efed3a7b07d630a21c3081b55261c353287c66c57663a99db466a5dee22746b81c750ef85be51143e221ecdf114fef1b3082ff54fd044bc884bfb3cc5c5335997009867ce9491a80fe696825f99426defab6a49badcde403f58e8317966210747b567754de53076b3ecbf65346cb83905832e16d01b50b93d37eb9bfe20172a31630d25f3217d87d93465fd8ac554cbbb39d982ead7219391234c889f0b92a2e0413d866cac087d628ce31c61c6323ecb8e689555af10de2b656e6aea2cde932e241f6d1f8a9e3316cf13f135acef83a0c0cf22f95ca818e61f92768774c630e0925be99dbd32b499c0fe7d84a42e393287f6f5ce3d0b271f170045a6d48eab316fe17b1858b1ffeee90888f3a37a2480dfd04a4a8629f868b5c0a80ee1f03719f3a47d4095bef10e0234fc300e2af482285d78937968319da94beb6c40e078577c024f3a5cda0084e2f855a9396aaa9ee9bfaf2cc771fe68c40b629e8dcf115ef03e757a2ac9eef073f1bdf9c5a4410031558a6d382b5f16024b151b1c01ee7817413a3c4de9dd6478785b81101df5522430058780207e790f612d78e5705ceed46b0ec075e7c1dc073b17b2b43d72535927bfd271e92e3c93638e40a9601dc2c1ab76d91a4103df657d911c829ee8a5f747f7642f5a915a5f40f630b43039c7d4bd2ad2b32129d94e5b2f03ad4a3d45577eb81f369c9e3e2a4f6a8e41acf8283be58425ea993b8e98eea6330556648618dad98fa255620d836d3c7f29b907895849286167c7181e2caf55c2c184a9a911f8e41cb042e2cd48b0544ea79fe2ef381ebc5b15e39a9b5c6d998faeaaa7773cfec084c0bfaed1bcab963a4ef3d94dbb3dfe724c040ce4d1e2ee7fc2da4b25127ce3a5df693fcf5a6ed1
SIG: ea6582cc23e0460917f782d964e3bb6dcde0aeeac42cc14919d36ce78aa0afd98072f54c795fbfd7a41d99d70606c28a5dcf19be38a0ce2d09bb8f844c31bf00
TST: 843
SK: 43bff3cdd5307ed7d25cf96fdbba64ab1811c8bb934e2187ea7ffc018d85e0f2
PK: 00f1b5d3cac6e56ca5f894d4cdbf9bebd968d24d5effa5058b0e20bb0898f6f1
MSG: 646f8b34182d5e602b51ca7329347c0e198cb747e4da0a6b80f3f6f9f336f6708d85cb429ab2d6bed35d5013129cd100142cddcee8635179021b3e24922b81aef13c1370286939d63d6b6a4195eda1d812ca518204768f87348c6889552c63d1372cde6a5e9daa7f8445ec8d6130a3f5aef0edeace010b6c7f0b9d24162a8d04454b81d48ea9097bd8df093459719ccb54aa10f51c246aa99c580beaf9c9c5bc60faf0ae5cec7f5137f6c5c144df45d12ee995adccf25a9db81b8558bdfb65830186e7b9d4eed9f6b4d732b1b5822d03eb017c0724f48f87baaae1045d6fdb125c9134064faf18dbed58d8fbaceacd4f097df9b342e5c4a5bc85b29597d4b640f1551c5b624ab21b48e94a9030049be1f05aa851d0827eaf8700dfe147fdcdeedbc98c4f15774f0120fb5970a2f8b21794340b628379a802b9f7c068b0df63193e510fc7b2af97ee38de47929785535528d350d88620610cfdb55d249e38fb73c8287113919ce33267d7db924e4919a44e6e29a90dbe3b7b0d3921163feb5ac105624ed852bece3538e99193300c893345699350a8f99e8c6a41095fc9fc08da07f75711f7df034406de14edd8e22a633a86e4a5a5c975ac5d34891cccfc8543771ffa080e0b45d65ab830a361ac4c426294d3685ea8c26039c71c90fc3fb512be9fc94807d76dbdaf8ffaa4fbf9849d68e8a57d30c4a0b9735c23f08ef2e284458467e15d665362cb646fde6937ecba53091264638357a722425bc62d1e30ec5f0dd8fea26b2ea4a8490035de43f274846fb0cf0209ec7437f3c3d0a560373d034e5fd79e25b6424d9b2c1761632b35a12132521827345c55e4e7142dd6fe94d620fe515c153e8395b5d130c744139b6a92efd37f22ba13fe4c095373550e2e4fcba0325b3ea3b9fe25cc7dd92cbf42e15f4554b77ac27a4a346382ff6100451508d602cf643f60b6ca4286356f21a3110d4e2c8a8962a780fcff439b3aa80499df270fc3e6cad8893348872f0f702f9390000c7f6e0627d2bbb7b7cef5c4da25dadfea8032e5023297a70a658e9ae73bddc3b227a1c11741133f012f0f48fe26446fa67e64720fc8dc97f30d0dd026f6dc2164ead857824a0a7aeb20f115d50d1b65dd5d82e09abe834e8ca88957e39984824955a1a13e3b94a00157186dcdc289e34b678c91cb2a1a
SIG: a6b56b7686df1dc5f4ed544a4d97e67036195a32b22ecd5d31ea1730e6ed8f810d258b44c08ea45f032b937441b72cd0dc37556fd7874e9fe64f15765c521003
TST: 844
SK: 063b9025e321e972d653a062be34f99365affdcc98ec9ff43ef422be0f804460
PK: 10d01a63012ac09956ba9ed61df35bb7afe3658bb3004852e47174bd07dd4de7
MSG: a7eed29652844ee0049bafb2cf63402971020d7e65c10b91ac5726eea86f40dbc53c3f0abedebaf6cc449b4fea48c015fe4d907b3e5505cff50a121819a2e4a8a296d5751015bbcd7ef6fb7c2727bb000be1342a7d14bca97904edfe8b18ddb63933418327a5af817e95bad74eb790203615d082e71493ead47ccc0901a2ca9f50133c44ef8508d51fb73c616f0147532245822dd102b337a1b2aae2efc72dca7a9419d598a6475233dc1a4ee0ec6d05da12a2b287cb77ffafdde2d0acc28199933e6621eec16ab4245170cf02da80d4922631a23272915165ad88722750035d2a0977bc791d14fb3d8cb02bc77f7c71be5242629a4c9a588dfdde9578494d8baa4e68f5194b8002c8e378a0e833b7c1a96981c4fb05e457ff48260b72493cbcb82ae11673d14cee85288f6370bd4bca9251a7e214c3eb79e7bb6fcebb16c9e056f29b6272743efa6fe8bfd25597ce86898ab3059eb0231c73b5305903fd1319bdf49e599d8bbcd74a8b9767308b61563ccbacd38fc50c83ab44ca759dc9b65b2a4b547c5097f220c1c88b2b0a48f65f91fe78b1501278e1e304de58b4c82a5c399981098a1784eb9042501859f2a93f317e41772fd52f972e51b07ed94d314e1d1af4ed82909a0bef671f54b55db7b70da1f718c8e648aedd6da64b05770526f12bc43f68b95548dac50809a687db97d73f06f47ed08831b60a28e982920632058f0e6c90c0187ff44564f81efd8fd93e327bc6d80b490e088b9a10036c80dcdad49d2be074fbba31e06f7180e5ad1c8823d60966a9ce15503ce60dd40e91eef2359d83d70d98401dde7be3c6b07e57d4e47d04217633d8e263ca348f81fbe9a4a62f45d77c843b6b1ad28466d9dafb1b910b348ed87c686cab292d480c191d187b404a9b1d132ba4e293d3ada99172acc121fe66b845b98b160c5823f601c7758fb26caee85701595b2d52caa2f5688aa2bf2f6c4bb637f8e00f49ab6c26bc6ad89e1367fd28e4917d250893a7b32d39660bde8db49f086fb739e56012c36bea0b26cf6d9357940b00d5a4528f9059aaf08669e5f46c995e60f887b5c4ab88ac7442ed01a14c6a42006baf1f343fefe3e4aca843a324e176b2fe7ec7883d1cbd068bc2fc962ffa60244f654c77ac5650817dc084465545a9230a74826b0c50eb85252a886ff2b1afeaf8
SIG: 85c81d6b0d8578fa58e13ab391001528b46a1d63a0327c7a4a04087fc668758aa65c01d5a150f935674ef307507e6f4c91e1fc3500b26f649beea87d27563704
TST: 845
SK: 883cc1381757b0fe0455b77bc9cd0dd464d2b4bf0c7a3c0c2dc775fb78aa3732
PK: 83a8b669ccd01245ce3b818dcb1b588f86535850e6c710c79217fe439824f3fa
MSG: ffec293d12ea636ca4c4a0a5e2db15342639c476674d2ebdab4aefd4046b5ddb56aeb210c119afdfb8a89128a34f6d77f261edea0772a2f8db140a2640fd8ecadb0b4792169b6b2810aee2c5cd835288bff493bcebeeea28a7a248c36116540fa71736d66b0a475b5fa92c0d46002fca7a1e69d1b59e81a3a6d4f339769daeb20b5f9d75c4c28f692132d28d3c564c09fe3dcca0359c3c63ec377a33f9ee874d8a789d77c96ac05fdf3ab38b2c8274a902ef8bb7f467fc7e073c77b1db5fc8ef966c120c4dae3fb7f5b74abb990166c812a525d123f76ed512125080a1534f3d8bdccc541fc97590287546096fc880bfcfdd00e65c0ebf4a09fd6476ce1b7c8faaa5a1cc2786719a30d8255811184752a88b08ac9f0ff1d6262f2586940afe1fe45e0b563448a55f3030e4c39c1f3f86a733670380eab088e393de09d1f508d2fbcafc649aeae6b8c30e329ec3fd2829be6db0ab8e637ea1095bdc3df3acc23d3cf705a9542c19e59092ec413a4e2bd5ded28cd34ddb3d32949aa487f1c337d6979cf512622dbfb7da1cbb1c7e5abeea7009e2943ffba2252e1d86eca9d6d5c246cd2e134a3e5dad37efef71ce397adafbd9e72b3f9a86ff0f5d812c46225bebd0703bc5cce9c64582008f7e558c40a3b3522096d1aa2b61bc90cd88c6285d942087d8a4665a0e64d3572f74689b4f24ef400d741b57140613471444decc654af0ffb2edfdf9fdd075098190b34cde28dd166872c6086567a68761cef25da40bd4c3d34fddd72ee565b0b937678ee84349d1160f5f0705f895d0f141ce8f51a1e4fd2dc4704b527a4025a939cb2bb78857eb18d78872edc9ee70e60b2a42700a198f4fff6c31925168be077dc23c322abbca97361fecaa3fcb196e656c128f3982fe11e551a4a0885da60d397d0e40d0d897262f1b4b672f78a2d2adfcdd6e1525c26e7195fb9ac606bb1ba4a9890803b4bd84346ae8d8c7196c90aeccb296a4c3eb4efacbfcb62e383b8a494ac723562d0d8c379187a92e3bda6b1569476aed21aed7a056b4a5826744017cc0060b4d55fa8772b5b1c15f5748ad7298005aecbcbd90a3e5c6159a8674abbba37914415002b5a6ef5df3c649426ea1275a01d80adf490ac546062d93999a6dccacb96a0904ad33d90576dc6a21b672e8ffb06613fb3f14e6cbdde88c2437c9
SIG: c7cfd5c9fe930d15a11ebb34e3431f489da010eb193edbfa6f23d5d14dd8feabd7880d2d5a5600d38546ce3bc64a86291a1ce31f272ff020df8cb6a0fd4d3a0d
TST: 846
SK: 5e40a7aabbb0830a9ab0fd79690ee0433901c6cb0676abe4bba06f5bbe58fac2
PK: 4d4f28fe09c4aabfca01ef6ee7fd6372fb62db61aaee827c43fd1a6d1c259032
MSG: fd4ec8b34fc6b743813f59e2fd1fefa870f5a970e2eb7516ef7c306f4b823ffee92d601f765d79ca146aba8bc6e79844559935cddc242649c059ecf2db84fdc219366688a88fc25b851c3661e51988c2bf73bb8e3dc16d22415ab1a7b35579daac7325e319157d7da5fee87c93a4dfcbafc92fba7e17cc68e3903733c6c801572d907320b2feb51710e856a1f76f85a7ee1a11e62d2e45a352938dd8cfc2bccb902dea444faaae6d84c5f391e10aef76928a45153db6cd25a2bf353d80d97bf4b3808605e89800d29840ea60978d9ec9b2c302749888f9debc84dd1e2a79aa0b6ba02a039193081bdbff0599a14d918c0c8deac4f60b6e99474ab53011741034fe2a20cff4e0f023424c8e5797768ad53df6d01a24011fa90f0bb1d5069cdb36b450f433110c2c56f34a1de4260914cd4696b14a09c0268b2ae2e98e6b4e992b9125f878f1ac09823170628388f0f6e256259ca786bbe144884cb298cc043d02f5c3dc684f787faf16c10fdd8437a8c3097463bdb99b78030f9474fc5c9951dc7526490586fe1c2db05411341460239d5e8bc53065902b95fba282c27665e869a19dae84606d1726675155d38039b9e55db4d5ceec95cd6d87f85e99dde54a04761e6eada6619da895b654fe3845e8a60f3a3b32483d6d27978af54502b220e478db78cff77a9c97fb79fb5acf56289f381acb10de64c3f23842b12bf5f1b283bd25d48d09128fb55ddae255beb7c66a74cf6f0695a4f828cb29e4afdbb3b42a235d4fdb66b963ac8f68e82b00a1c4500863296247178cfdef803bb7b114f0c03276f671669a087d9228a37ae7b99b061549c1cf8ec17246ea1ee03dbc88bf426416d586572ff10a3145606f2784e4357be4edeec6c3a7bf11bb5b0e90cf50edaf891e51d26357bfc853ce23b299155c82c1031dfa64074d72a09d29720ead6ebbbf75d5738e32cda6b6466a8def6b50a1ed9b865a9a88a08018acb501a4de9db54d0522ce9cec7a06bd9a5f86b0b46c07bf3e7f5a426ff6b4bbe1e00313a5ac2719a959ed44ee0a44bd97da6db2cb971bd68334908949ed850fbf73d0e02049da181cce9c2d9ca1b624c8d87cf904eb821dc7959295da5777920660b43ccc25cd389f157f67fa0390feac97a752c1ac204c21df56bb0f4fc01641b480af2b89b5d16d4a0bcb0a50b82b0e0484
SIG: 597672ab8d3a60de5456fcc9c38253f5f37b80e74a007c9f6db909d27d0ead162789244994f35b80d61be199c417c7ea901b98cc63fe3c50fc3c6338490fa206
TST: 847
SK: 3a34136a973480d97006dc279358e6606293d8cbc1a44ee55233af2b5264b90c
PK: e5effd921be8eec530752fccc576ef0d9bcde4b32cc649d3f7954717562860cc
MSG: 981c8e1090e396951b072ef8497062020897bf7dd7ad505b4d6dc11b3e1dbcb0da249984a140e164fc2e02b31da39846554aa8905bc8b3df8a76bf60eb5ffcf22c97b671227d249071da8ff6bba75b2f7668cec19a89e6475a12463dabf368b3ca2445bb3035cc00fae85b7072fbcf595401755b8051e6097065ae429f18eeb13ffa6dde59df6f3c206bfd9ce1f8a800c8590a4021d160f66d6740a369ae835617538b5890231f13c5667baf510a606bdaa84b8d10ee6015e12a4c1ec0bd0421a294c51cf63b5d1f058e1153dc425d10cee8b1b084d6c29347e96f0f31b839607d078b79a90ca3d1f063807a463b7c32f45a534498d71d47edc3b17a4dff27fedcffab301f34f1a64c0278a53589349a233af30b1ec1ae410f7b1630c7145ca42c9663f512e8a578267dc95e83289c17032e09782e2fe8e16efb87f03ca03b1195614f89961ca3939d3bdf737221a22d7a18ec30fc126d0ca663e88d6060d04c6a44e5616e556e07d6d4a847f1711cf43717810c70aa4be730278b3bd6555c954dc6edb09db08f0e211803596280f3c7868d2342cc2308eaae4da1913514664b1db962e99c8a8cffe57931f5dfcddbc1cbb36ce1c842e2dddeadfd7e7d0a5048cdcb961b14f35f435e73a683c8ce25c816812566fdf817e0d336ae0bd247328512b2a8567632bf20553d9bd6fe157f220ffb0b46ebae89a70459728a57eed1796256f1bd50b6d547ea3e25fa5913d389a22583e915eb49de35a97b5acc521db0d005c29575e16611a755f21a3a5a82a20aa900a707ce36825492c3ca15395f1700b4afab94daa7a02f1453b1f9a6bd36efb204d928ee1f4dcc860f3a859badc006fb305fa123d4c79b23a20e32295d040a7f8f6caca25d83f71c62e3af7836ef76b93a83d3c3b493af141753da19e4cdcba56617271034b4f4f394c7c6b7d79666f3afb692244f061c69a8881d1b52b8849fb534990ac2391909471ebbb728e29cd20f422354c4309717ebff3efd1833370806d5bfb53ca2da316dacb50ab7fb739673235a1dc53aa8893072d5b91c9f6db83fc4ea41d1eef49ac28afc1ced8f361890ab9f779d193082831cb8c42fb2792bee3b26296b6295eb78a8d853117661624e11f7f57afd6085a7b9123679fdaca1cf2a78d380bc4c360aa7c3cbfde0c0091fe53e2219c070f2f02f1483
SIG: 425f272212835755adcc0522c6f6e05f68008a3be9ba5974e420c4c5cb56e6c55dec0de347b16caef8bd33b71b44c8357d05b6321d7bf493d25861db487bd603
TST: 848
SK: cf33e7974d8f0bf899ac5b834c7cf96479ce1cfd453af07f970527f36aa85c1f
PK: 578f60338b1f041a97d319fecfa30cfaed369303cc00b3ec8c5c99041158e20c
MSG: e813144bd116f6ac36389217b5171a902f06b7dd7b144df4f9091553c7c7835753a296cbb0d7fab99cef77b61f34a04c8af04e7d5d1f961302de89e2005f299f5a4aa17924617d006693937745539c3048ee36b8c23afec0af9feaa0066c8af8e0a7f09093498210f6d8dcc0aaada5668786910ff7c5b348d4ccd6eeeffa3acd1816d9011a4c4025f6c2fd2c020a10593627520d4dd99e07c62d2dbebe84139e1c7d867c093574fa601e4ee307ac926e5d36b62d7ed84a261588b7e2883c7926612b4cc67e2bb72544a10d6b4929c88ef6c47c2625d2f6816bd73c3bae89d2e0c86171ac4bd080ae555d62740d1d2a761ced86dfc328ecc27ee3db6d404108ef4e0b64906253b4c0a771adefedc8a2c5b53c425a70cd6f63956f7a0a619fdfbfd00aa078418eb4652f8bc6f3c253beec9838b77f9cbe2ef2b8055c5773539e356bd8192606ec101e3f6058b1dd08a68fdbc549dfe6b7725dc2549e8e3f90dc5be3ccfb0a38baf9377cb3f6501d2e15ccb3556a895ccb23f0b6df9fe59311cff55374c3fb3a32981ca26ab426f3663d04e3167e53a537b7589a9fb73679090a205532c132906634334a7e8749793f8c593f3fd6278ce0050383487f3b245067af94881aa1ae968d0caeba5fa5c7be5f4e4b7257518695d89bccdec507b967b4fd64b6893b3ee7803c1d36ea8a02fc426f9afc8e9f24321527ec9844bc3c54a0f7667e034300bbb4fb020f6d5bb954e7b5a3a706a4939db33c154892643476a291d47dc1e6f72ce91d136f11db26b9c9ba736e40df0a15c1a89149996b251dd988b39004e6ef41bdc061db580b7b74de2a651810bd891753b97386d7f8cbdbb6ec386fa2c342f5ef20e6e3a8bb4d5149a7d4de1224dff1d172c87570f776d5ef45959be0938ad79f5d3395cb2721627122887bd7a8983b647797bd41d882641c81431ce8d9b3067adec4cde926c51313f0cf84c5292562dd4908642dd245288484c5568a787d0ced36a352f032da4f7e4de06b11473f650eec65dda99639af2d42d84ee230f4f83623d9c9aaa3b16bda10ddaad25af5c1c10f81c8c51c811a3aa3e3db58a7025e4380e285da474a61ba59173ff042a46a79ab184b070108416f9d6158cf96d0e6db447614a0d9089ebb6aee4ef107be4593d71e79f6798668a740ae4bac5ac7594ecbd5dc82e7d0f9cb
SIG: 97a5b6d268a5b4175fb06f1f37d0a633519296edc30011c954d8f0b9bbe2641800396c4b35d4b0d7d2a1d17cbbebdc55a809462d6cc19a6fadbe1bd1bae88a01
TST: 849
SK: 51b1ad0ffc21497a33dbdb85ea2bc1ce3d0c2d95d9461a390973fee377fc75f4
PK: bad0412575d3801301edee6bc0f276e787357b4122f52de981885851884249cb
MSG: 7882e86ef3402f6dbc65cce8315b39765faa4b1fc876fad5f8220cb22a7df2e3580eab3a7e8fa7fbb6b59482ca0e364a131396df792a3241a060e44143b6767493c6bf75f187a9643aa11e11eba7b0a80f0a68b9f1b79f75b66cc59d9da77955fd7e8799f99d6eb08f90d318f4efcbfe71159b10a83aa5fd69bb75336f5df296ea060a426c9545df940bc1454efc1f9dc965f1f22d947303fb8ec12407fff6b1dbe47e3421c31764fd90c83ac711d19926e229a064c61fe3676af300a1716fabe4e3842264adb32e0d9c9f5d4a65d0d7b5c3770d737ee13cbed21d7a1da36aaf7ec0f36fcc476f659681e5160a5a1f49e759b9d0fcd4fdb854eccd99172a47d2c4efbe0b3757631df1bae175f0fa74dd048bb6a5fed8430284349da3d67df2a6f7e8269bc79fb2c5d5ed6084e9076f455ab638919046369a446d57fcada7011cc771bf6d874a8e5d23c687747de41dd04bffc717d6128183846eb594b3cb1c1a8aa04f0d7eba53af39cb1d4e6fecf3113bd8422416f4c44037aeee9e0fdc517c48731fd04ee9c99f5dbca3d574509d7baf3288f2c230a02d1703bdb1611cde2a766dac193de167443d20090dc34d29277a86b1e998b245645117e5111f12f14606c55446dd912d3475c19876e19ac536d317876c4b0a2e0f98616129a5683732a42317c5e809dca956b2abb484ada810a15c81cc8562b555da9458f9b44338490230c7404f3d48611f84127e73e277d88c62212d2a3a351fc67665b18d77216230632cbc781288e15cebf3ec33a7205eb22b9abe4cdbc7ddbaaa53640875eb763f522c36cfff2eb23ee586d775286259fa94a44fa7ec015096a2a446b6732b80024267fe3d5d39d1c48509b3ecaa2e24e54de4d61c097b70f753b5af9a6db6f975d25f4f83d06f879e17ef7c509a541444ba3eb6867838090e22dafdbb0eb3b0565be1579ceecded20f544256c7c4ede3b62843c65b0466be6b7e27305b963ca914e3b7d21736118edb3d658d9d76f509db3b9ca2eae28964a4b3b3c384a81a4890ee96fbe934a6f2aec8eeb6cfe59ac9d3bbc1646ba32a1142fee59fed6fb7bbc0498cc27dead413b7b4351ec206343c0ab89fcf87243b1ab450e58ff11a1140a383f196aa3976ce17cf34530f049a1de90e31753cd85e7f1fd5cf20426c9379feb8c31b4bfec35ea5a78953d75c5cf
SIG: cfb65b6ff0377cef511fd97b90c3ecb80833f142a7cf5022ced30b3fb7862086d01339b8866a238cb070276e1944b5fe32cc409947cb91deb1432c291b60fb0d
TST: 850
SK: fa2f461ce8c7126218c47c91569e8799797c83368fc842b6e1c22fd52aec70bf
PK: 6b89b23f1e11a75a53f992f6ca5775008c6e9e7e49c0d8510b0e8369b7a20bcc
MSG: 799b39802a1827e45c4112fee026034c0e598affce2c550c193fee73f1df8c30c8d3873340088ce859de3471e9d057686c829b5408795e08b3dc7aa3b637c7de9d2172ad0333c1bea861a6232f47f05a10bf5df80815a271256e37e808a0e62f1f07d9e10ebb947d3efabf8a28fa9dccd9a1d599f5fd6165508efd679cf356015058bf4b34118f83aa3e5bc2ce19eca84f718398adbc0a5276cf9d8caffc27e3e6abbe345b0e9ecf89c6771b0e75d408ba2fbb90fcfd70c53f2e4d52ba54d9784cf71c349ef6f14ae4970def6efb5f30e984d6016a196deaec7e04b47619c48bf49dc02f7fef3e13b756174e90d05fcbdd5e13f0e434efd5421b091d517900ed0d5785968862b4bfe5093ab67217180d97554ccd9cc31429326cab42f3f8398060c19db488b5d1c80b29090afd1c6bac3642264800211bc278fcb99dae9dbf49daf1b24ab569dcbb87d4d3547335e35db98400cdfce6790682e93600220ec499245fa4ee15d843831b56cc26418025bf87001605c6691ca6bd40a4e248c309801b76a795ede8ad5308bcb6d1754ab3371f0003bb8c4e4e471954e28b1e9866379f82e1fbacb79d50adddad5b9778b558cddbb0038a5ff3d5c9557b965de3a7082c45a8ecf3e7721eb690b6c71f3d8975d5300f67c4dc4a736846e4ccd26f93463d5bc6f46edc488664be9696be12b02dd104d10cc6b1d82e8117811214a6487d17367e395ade2ef6b26a1783a7e2f245213bc03a755df3ee8ef9f1eff972c6919065cb7b756678d4ddfd193eddc0b42e8689613643146d7428ca37bf31bdf14e31867858f39d2323709eb3b7d7f4e397022378424bdee9bcb74e9d5dfd371f4734998fc18df4cdfb4b5c21c2e50f8d6c15bc14bf4fda6ceb9d8082cae432dfc98bfb3ecd16b8d74f830b642b042875e921b054bd1aaa581f60d718df669f56dc2f10d478997722162e83940e61a1b6e42df2a4a3a7cbcdd611ce96cbcfb5a95cc473231ca13c0609d0ce1ae5ddb5466d6d65eefad9daf2a36901bcc945847da1ed6e2e240e848b231b7d0e1acd06543ec93e768e59985d7e96c8c31fcd1210f0964271e21877525cb134bc3536257dbb11d30a3c4f949fb82ae0c31ccdfe41943251e50aa4355392ac309ef60fc17432a2be4bdb2fcb28607cc45a52b60016bb1d2e23972ff2c2a247d725585b1ef2b15f
SIG: 84f79d9e8f30e5bb6362239714556b04736fa44465cabaad23beaf5a99fc451ad4ae5a18c7f6f964fa41039216018ec5a2accae1075a6bb3a6ecbc1fca02b904
TST: 851
SK: 1be2949d51e7208175826213ee6ae3c091172742e88caa02ed0f313ecbe5d910
PK: d7bf4748d6dded5b57a2abf797facc560b48563dfd9dcff4be522c717a6cfda9
MSG: 045e2b0ec7bb203a49bdcba941e2b73c23c1fe59a17d21a0124ea24b337f92ab9c923a20576b62d5d0f624e7932c115b5474e0a46a4dc9ec51f6a0ce8d54744d1d52093320e39be203f74a0f5dfac52cf0f995c66df2914b68ad871fbe81525ad2d88ac69933a75aea74ace4e36343ddc06d3208f16d805f5dd786b4daaa166748cfeec5714c85c10478b597ac7f6ae2c98891e38fd414aa811b7621d805eb8fcc46cf4d568a8a92587cbbc1aecc12f10d90ac1e01ae986d14fe82951c682ceac8c925fc6654d838ac9353ae2f93f3c88bf7b82cbc43b1e49e5cebfb1949ade4b22e4bcf1b400c0a8fa8a6fe7670f69fc3faecd4805b8c954c01a540d1a1e788436eae073ae956dae3176905a8f0a3c60fd980dab419d41ec06e5273fbb13db9381f89b663ccc4bd753fd90f14a77b3d81c45dd3561cd1fa0e94d234cef9d7859a2ec942bfc18849d7f2ada3a5d657bc193d2e1491682f1665a534b1ac2083b738be8f9e963f5941ed483c6acc82e959b81b8af02f471c08f5f8b12e10e008192898a4450202af731592e74efe2a948e51d06e44de9b956b7bc9a69b6e74687ab206dec4d35b3173fbc438829d5064bfbcf743c1e2d46f628f2e51c626d8e416d7be6e555a249691abb167f1d92f4fa3392fde24e993ce7ff5c1b8e1577a7c0e73025cc6fcd727a82ef0c129e91e5533e021a3cdbb99d54bf7cdcd3ff119154f3fad9242b6ed350d10372c976ff3a437d097867d9bfba91d84bda55a6bcd6e3641b213a218b3041589c55afbb344de6e97d8c35b5c86cf3be063f901ffeea8cc91069967d2346035a91eb5706a3b53f6d1c34d4d2116706b65c298ec57de82abc4003ce8cc5e0b88ff710dda1dcef6f154277106b83eb46c045b082d113b361d6a625808c9130584dfc96707ef8955907baa61cf88c66b6d1f60581119cb6217a852157336178c685e6ed48526ed5c4e3b7967d51f99df6876a1acfb845c571b898656e5e3bc73980b9bed1198866359c9e9b1efa915f810d1ef8ad6cb3fc21fbfe654306de6ca13a3a6a48e7a13ed8746acbd07f48eb00c36374b1eb4f3f01c19e2e8d37e9fc064b33c0d669bba554ddc6821a77b4089cabdcafc97f60e6050bca444ae8cfc44d93c40ef5318bee6f8cf0c067b85cdddc45974a4eacfc3ef51315ba0f3f62968c7003a7ff444612400b159
SIG: f41f2ef6595f17660bb2fe93e51fc6fa9c31dadc9db90c3f46607a7fb4800bb75ad96325dc7eab782472b04da6d8e6fe64655dea551fbd5049e876ce5a405f02
TST: 852
SK: 3b6ba6d5cc9cd6241d8b0097a3722e4d066fea3d560aeab4673e86f1f8ec6026
PK: 8ca6520717cf363c4ceffa76328a0a166ff83e45ca7d191cc8ef6ca6e5243367
MSG: 36de930cc8e18860836a0c829d89e963a58bdd9c6b6ef5bc61f75992d2075242dca23e28de205a33dfea861fc44a32628e8e7cdd3ed7ff49ea6a7097e0090cfd9ff5ecab1de822fc0a4c3776dd56c1919204516a94cec5638da1d99e52b866f5ec4162a912edb41c1e92edfc353f6705e1c12cd41cb62ded4ad8157940059bfcf50719d3f2ad00848540ce89f3f9afa610ccba5ecc37e3e2c1534fcb38fcd39a2d14d5b5da6fea24e006654e309047a29cad0ae4da8e708f97a18cad5fbdc9ac84400c532ced548886539edd6c541074790ae4502fdfe9f3273a876a218623a25706a1525e67e57a16d22c21b6a45e2384e287ac4452aec4e063056b4c178ab0e5b2a5bad3f463c472c4ea1f9c1a66e5270473a835094e8f0eef680cd7b20d0e70f4d6c958fee08a9360aa6066888f4dd7ce5ec22259fa0b53fe9271c083c6fcdb7283b09061088c52f71bfdd2777ce0801f41a6c4ce90ef131de1e183cb8949ce323c9eb13a4b0cacf99defdfdb68d5ed1f6891b48e21047668d69de8a80f8e5634ded08736a4fb5410cdea9c72596e36df6841f2eea46850c87473c895540205b0921960ffa5d9d8ffb8e29cde96a3ede015acbc26974004d3e438a85b2e3385f64d1814003941ffd363992d3940c6e6d81ff8e45fced6d36ce198d8ccbefee432a77d8fcadd73fb799f6bafefb51a2da798721c3d465b163ef13e6ecc65e603b2893ee4cc9e1c6d1de7a65cab5cbdf536855e288c3ccda8d2fa3ce10cf49358a2ef4ef076e5bfa91bbcf3d966dfa3dc6e712f1956d4e58aa36e712dd3347169b19c8d44bec5bcb730778fcccc589ed5d350d44c17bde2eebb6f5ec59fb240d67d81aea9267f34f15eee2de3f4fa67391479bdbb430f484370fb0e0895b9ae065bbdd43e230c62ac07184e8b06b24b8b97ec02dc6f37ef61641ed56e3f5eb8d2080b5144ef760b518752e19754792e19343a3855e1e2f7a7dc623517eed2f5d26548a68eb8ffd7bf70f78fd186db634928bb98138f2b8fe84481cc53f5aa35e2666c6325e1d2b8ac5e2df2935b7f6413952d10d6076ffc75bb6af63b29b0b9663bec37247b66b508dde41f2f11b84333559dfac73f761bcda84a48d266073aef1638460849e7a17206a25f6800770b914cc026baf9e3255914e13258441cef35ad1d66833e987ebe4431e6a6bb222cbb65af
SIG: 788c9f4554ddba5c7d64ba759ec45694ec79fb85e82368a074bdd8df344213a56dd09f334cd9acb941be283d98c4b15dcfecd14e93f6a2e3cb0c1aa2dee7d90b
TST: 853
SK: dd9987b18f9a922c0f6fea18eb00b896c7a2d3093db3ea31d38421da0de51231
PK: 573921a955feb6dde41b055c8dacaccd1db7fe9e36b509d3c9e36f9735752324
MSG: 48162fdc3abf7319c6caab60cb8d0520875cb4ee8a07092783167d4733ffe5204e5febe7d291e9536bdea3df0637159a653e09fd99af661d8300ae741a3e91a8bd85ead05dc7d9e6f929323316edc4ca624ea7818b25bdc061f71492fd22d465ab226fd9a10d8babfc074c686c436c24a3a53f8ff389ce9ca1dbc8907445889241f8fda3a7a3f5024fa8cb0d044bdaf6716d983a6d839814ffe70ddc55bbba11ac97887bdb4dada96565bb075d5fc1d3c5244b9fff77de58729a059a911fb3e0eb164fb8429e265685d14a63233046d20ecf289c55723169a9d63dda0d5255153d9ef4a61b9212f4b820697ae7c308cfab403b2c3431906226e45ce21920df5201609daf830f28ad796005a9bd8eba620cf839c3ba227b963c7bd0914822df2ca03c2254d0cb8acae0d59e4c3e0ec215c836969dcd1d49bfe197e2f3eea3fa8a373b558d0fb9063cf1568e739aad8f09fb437cafb5a272375f436064eee11bd903d3aaeab4e3fdcd36bd2076eea179a4f0d4fbc8df42bf2660f08de7d5c6397cae10b7277458aa6cfa01e8a6737eb126227856646691681c106a157a26aed21b1aaf0ed2766421cfc3d1c7ddfb72fcdf4b8b490fc09ace49aedd7712b21ac56f8601f625563c784306f3b9174addf764e051aadfe12831af9669e62cab121c74df343724429d6c26660271c32f40cf7c2d08bd0afcc728def4135d4eb55b6a3e7629d806864a85b36a32b9b21ac0d39680a2ae4ec4189709178e349497f39399fbc78b3c6cfaca6edea7c33dda3cc11e4384f1583d6cfc6b58f4eaa2bc56aba42f738a429b93580850dee3fd253994f8b0fa66ee8e273decabd532095fb04a4a3c340af0e55b57efab43630fc02ef20b425ca2187e3c6c5e10f12d618fd243a224f6501ebeb9d321c6385b8127ef9cdcd097ce7fa021cf40d21c39912343f67acce1825e3a51b8a718e8c340622fff65fe0053d24aa3351b6a2400185d7aeb88e87ac4a1d394909d49414aefc22ba009aff6962c9217d755694e4d6aa8a5d6a803cebb15de8f541634b6fceb0cac79dda8a18eefbb537e70ffe9aa5a6a6aaf9240fac2eacbfbef01ad6bdf50758780f86a4e488985362d5825011f5e8b66425a616b7e104eb23fe8f100cb0249823662bda3da47a4c3c1ca2f914b25b9738534026047df6d7ff631df2c4131f680e13743c9ccf2
SIG: 3e9f2b007c0e29ec875995a6309b973deb8baf113ded13f1e0003e9b9bf93916a4dfe47937dadfc78aa663c55f674ec35c3846258f18e7bb93fbba3e826a1f0d
TST: 854
SK: 38d2ef509f93051f145167737c22e1a5bfe8f4a91eba0bb87c39ce04a89baec6
PK: 01115f6d89a5daab54f892bb4a4bda1ce5d8f6c9c88a50cee83bd987a2c0ddf7
MSG: 427b5a01e8597f04fd422f0a662d0be2dfa853ed5f9d3f60ff90f2c5ee08bb59fd03d402b754caf54d0058f5a2cf87af4fef2177d59e18226293fd2af376bc987bf7b320b9d1e249ab9efb75078e6d3df29e03504776354344aa69e72e1ebc52a3c38a4c2a1673b4e974a2e4e12a2e78ea3e3fe50c53630d096da3e2fe8299f71a1b441b4cf0caeb937afa4a0e3915ccab3996c9f6a8f4fd37543e8f75900cfd47175370efb852a5f69d673683f998fdcff85ff8f32baa807066604422027d51a435ddf988ed2fd8eb191f10b46807420008756eb4e300c4099c2d6450bcc6a4e7d0673156b837f0506338f3d1b5734b166ca5cc2f24a4ef026cda2c4ae3105b63ca8570d18546cfacb86042966a00ef52c7299019f68a2df08c8b704e85e713c348d7f1677660e18ebab59bf4e12e6ff2d783d8d5d42aab6ef017b7a1966aee8dc14ddabed49b4b643df4e9b0b60383c7d8b4b88c65a898c1c77d43d6bd68b2a5743f1fedd654dc84496da02ceb69b9b4d3a8e00ccd72e7c75fc50a8dd087e183e6c1f579baebc5c63f2807936791b5fe4847cdcf151774235205cd2d7b8bf4ae8819225ea708b7baac66998f0cbab2c7ddf251f3b1de1017d397692205eea639f12d77beef6c13bb12100ff8906470bc7b21298053be1a61b7b3a499edc310996c8bc0871907ca468e89ed311adca2e2b82930975b3efbbfc03cddf4d948c4765e8c10590882169acddb8f8c36d84c2dac3b798e7abf844712fa458d277c24e814047d742319a834dd9f927a2b4485ef13745f7a60dd6bb337936304c97d3f9f144eb29bb695b8dc31b9d84910611d28d581caa9365d6dff52d410a4ad52bd121729fff52888f4daae1707f6f56dac61ffb9961cda7176af4460a6d5542a20446fb5147fce727204cec6899b9a3d4ff6226bb8a1c78e36fcdd9e50c040d72d0f4007d3fa9aa767e4abd0add62fdbccdeff6721eb259e00a721632006bede0d173d38344dea44f96b67d9a2eea1d2af5f748e8ebdb441bfb4e58e2d42fec740566acf73a303358f7d89c8158cf21fe85b0d4a417ebdc86d0469f6b91c24ad610d486dedc218b2ce7a8b96754723151f0d0076fff9f19d112d9c0592fb8d92c99dcb8ddfaa46fbe0d92df46b8c00ca4345adb69a5aca694a86cf30646451bb17ba6e607a912bf109d5fc2d3e27d00d945600a8a57c
SIG: dec46253509b11e4b52a6ae4f366b680dffc280d0a044fc0cb790b6e751381461e1e602a89e3b3d3064c407f602f1c22404b6823bd2467549314a00001664a08
TST: 855
SK: 43bfb3dbe4d9bdaa82b354dd596334e660d76fc0b2eb698993aef3767f1c7c7f
PK: d00aeceff0ceb832c251d1fe6bcbeaeacbb4113f5281baba4e878f7b95f93f07
MSG: 3f3eeddcaef4e1662adb66bb1b207d793fcbef815005e82643ed70c9855403dac28b520727a901a532d28b9bd1348db2f8967bbb8c9098b07f570a2eae1ee482640c0b67a52a38612133a15e258ede38cda878ff36ed321dff87cc6a01383ba84067d60af41776acf80a8a4eac77f7d87c37a704a3e2aca1e8815e49fbcab797c856529538be07d51696321f69b09b5dc5a15e5f0e4c22d22837f62ee4c8bc7f25a9487b962cc20f133fcb870ed125cca585d181bd39f9dfa661f19be76da7f65f22fbbc80752aeb39e8d59ed96e14f595d04929402b5029c60cee37c0217bc531d80db341dace3cce76e643aac53887473edc6e19cb39fecf6af424a2066393d1c33fc7b93676d7e6105b9bfc967d1e29afdc4cf15bcafa09c295a6f9deee331ab3b0d493126e2b2fffb42a6b68e79e138db550827262e487a83f37f01dd7922be75e92fcf5d9d4803b3ac2f35da210fb38b263b0ffb6c2708d4b55b757af52077a7e3184d01e82f64d32cce4fdee0f8d4e364bcfb958ebbfdbb622b38b51e930271c7b1b70aa9d4bb3aa4b997c52144d3aa62162573a3a1d9ce46cdbeeb8449f1225c449631e8897521cd0f637b721a1252b8a10ab0be870afbcd89d58b2ebb63211950cad7ab82c8195026b50ea8b77b9e90ed559af4484308851a3a156716853a8ac4ecb8c5cc7d935b0f466124143b1177f05d08b97d1ad542ed2c2465af185e7db42b69cb802a71794a3139883029670c956742aaad7907a71d95985fc1d45b65997b4ec6ce8255de959270afa7de90f2929de63f9b17211d7f1ae820ada9ce3e48649179d60b0149493481f01d459db7dad0526b5bd9f4b3380d25ba2c502ba8fa3c4d4131b4662addefb41827f759fa71d447d5f029245f48c622eb7c68c8e71081f7f789de7a283d2eda83a7d1722a05fb72e1760c24040c4d834def5df5f742e02b30451c893bcf7d771db784cbbdaec876d8ac86743b529a292007ac753c99a5799cc324fe5ebb5448ab554b10d4136974a12542d25c6147c67c5d2336c9db75cba2fd608cd43ab95beacd043a1349cefa828e23b5f0b6e0e2951f3353bb92bfd1f0a49c33fb3cf3799a0b543198ad5d03d263c1a06c35a26ade1518491c8c1d27a2db033808932cd1c47b5a126985acb8d888360eeccfeb3bf51b0d189b4190440404d12fba65d0a7a14c620c555f822
SIG: a9995523020a0d222bc48f98d05504e3068f304a6d197006cc9c035eeade099e7aa97e90894ead17e8c30b0aa4a98088f038b92244c4b20fde964f8534e8fb03
TST: 856
SK: 514e070b0190d18cbe981a5a151e7753398a272bcf014813ad379722c36e133d
PK: 6fbde0474cc4810effa50a07820c965aa00395ff3a5b3e2edd7d356b7d6aef2b
MSG: 831455762a5d80097bb2845042f4c876e7108535bed683e8c44619d08154a229444b101e3ed7c01507e870941446af978c0f5341d1ac1dd15b14e8966712df19f52feb5103cf62b6632756446cc754df00a3f6dd719968a2cef66c3adfb7d1fc491fbbf3d59294ab34619e176db0d446151e37eaa3daf172406e983d9d23a6b69e92976030f5ac7040ad5114129feaf97af15b2296fae70492dbbeb2b4827687fb798715c9bb2c32557a81d891b897052900707159751f07db074c77f0719671f1766689029a3cddf39df3483cf2b04f71c25de05fc2d02bb48e539eaf1a321646cd80ef2f0ac703f45e7389530800e5d417ccea8a5c086682f04745d50b5dfc8f6edc87a95c7d202a9cfd998714b746920ebbe2335bca1a0171762016f5e4bda89c57d0edc6910c6d22c8f909da3db1352f0c8bd18f3b5aac25f193b89470f976bc4f1affb3c66bc5876c6fe2ac7508533d97bbcf77119d9aae193f07e0b64b461c9c6c3b9d293bd37de3d8e1ab1e8d872cd94e6cf0eb68439fdcd3b25ce8483460bd8b7cce889fb722b4361e118da983ef4a9e45cebc0c1b8229ea53e6f55505f644e09acaa4c4b8cc640b2cd2b312e1c3a2c02669e1f9c06311c78d360009db9e67c39b49d1e5d770c01d284b0a17a41b4e7ca745d665ec07500e4d9fc8ebc1cc6af53a3fc76b0c3f1431d49843f20e182782c82b3b5aae36fe20ca642618068be233d4b5ef9eaeff401536dc593a2bc18344f55ac5d5fc7b3eb506d11cb375330063c620c5334d723c7d1f042816bc4785b35ac0e6f174f736878b7b491658ca67d8fcab538fc6ecd277ead90d954b460da4253a1c3a30b3d8928f69ac9876a2891969fc2d06a668992b8e2115dfe5358a7124ba7ccf421d8054ea043444cdeb40b716dc7a3659a3ca94347293489060e2cf6712a2a6c7b8ad146785fc40ccb9da287830d011d0d24df3e7afbe972d6f417de5cd75f259ea07cafdde205fc0a365135c232cbd7c1bc539fa4b7e1cce35185237c23f80ae97c186d0d3b10503d5984a20ec41c3cd042c28a4c31f9574b06a872bf959ab0add1f5dee14a1e741ef238dfcdec085aa088dcf39a36dda8f2a85ed0d362ccb005d02e5accc092a376dc11a566170d583db35f1de0be3f15908596e9b781ac81be07b9bd2af46c56fb4d9d84276011e4618b7f76f96794cd0fd57ed414b63
SIG: b6c355c958b5baa7ebe977a93fcf539589a366d40160e4e031b88ab96402c7bd577ff635fc07782423598dca43668124a8b287510e2cfd07a1e8f619f6c8540a
TST: 857
SK: bc790a7385dd1dddc762e3b20221dc078b6c3da8986d4180940727257cfdcdf1
PK: c9264626f68fedb5b39c28f030453b54d0d51a98b17721f2611d7f277ef48b81
MSG: 143dd7bfbff2adc71f5d123d474ea069df14ae923ed9bf8f9891e60bae43f0c9f55537ac9d1ae523ce4ecfd33b20ae445e9c426372050fa5217c1e4fb01353ebf2e32904ef7eefcf72e8023bae06bbb640cf777d5b0e11527bc835493ad6980a157bb2d50be23365e72cbf0b3f209ef0c44a00b41a62262488096cae5a696b4d64cbad34500d41fb4e4bc70f8bf62144d01c2275d6d29f5de75b1721d5046b6829164443ebfd9c1781319d88f54010edc296abbed02b7dad9ba585b552e0005dcca400bf4f459eed7db86ea8612be9e918dfd4e2700c4710083283626fac754417e0087d26ba145dfc45b1c9bf7b4dd70e6c508747ef805c9a02425aebc6421e0deb6a79d89aceeee01ececc9f3ca365383826584c430ebd39ecf0a72866ae0aceca5ad4f0405b67779c04c5de0330614da3470b805d787ce79ac5a696dd6f6b5539b1a651b424cefb19491da6e0889223cc98398b42c00414ff8d6c0627eb97cff20a8cbe7fccb41d810fcfe858ca7475247ef628e84a09d012fe12235b38c1cc9d82e2b69d01d6218cfd48e85f26aeadd195408cdd4c2f806a89041fd0317fb1a7b6209f904270d34e606195047288b0fb11a5722938f67c22b313f7f74b2025c75bcd1ecc5a9add4a640a41f2996eb66e5af196198db58a3fb9938f349f922a24d86f4ed8a96a09a196c24d6d01ed76f3816c05c4f26baca9b9d6dcc79b580dfb75d6c905d480dad76951854bda1caa7f4a819543aed01ae956bf3058fe8b3c7d5d724962f1a6a83143ddad274fda3ad578e98aa967c410ee57575ef01c0258560f0a1fa4b79327796de99420cfd0a415506360f1242ccc58a6880927750dbbff13d7c1b4ed519cda357210f12fb0d1c4d48f0411bd7e058cc4cb93d3c77597e2653ffa282d3c2f128ac33a237af2fcbc9ef9c811f37814ba2b0b85093d0fd18b8c6fb09a43ce52254d23d55f32e1d3242aed1f23d9cf204aa0dfd44a346fe09e55a4a06cf1bef8bbf37ba1f1598a58aef89501ecbac0453543e480ed0adde90c841d95ebd6eb23baa9f70f83c149eab32d0913c79b0993d0e1d3574f0f542e56a20616cfe4a8bd7aaeebe0b083dc2ce0146178c07482a01129bc6fefdc8141c1384894b69cbe2f29da188f7fd4ac341a2df6fd90dee6a446d2746324c75c1ef5b1ace187d3bc16d70559892975d7e47138f0406385ea
SIG: 6d6bd65f372679fe9d945ff56516333ece0b7a25b15ad2487381670e536f5246775eb39a114db2b9cd50f312b360d9d0bea295dc37b817b332890adb65e4c401
TST: 858
SK: db3a44df40d255a25cf23f53c45223b7d8f1f1f111ba07406b71e184a8cd0612
PK: 6b12bd9580ae207a9b0baa8287b8bb86669373ee5e5a625ab4a6ef2d08712597
MSG: 52dd8ba4fffa344d1e0811d9675c313f9cc0e5a138478691989d2b7f7389025068fa35f74f9aeaf1e95665ecf8d5707f75f65f2256eea93398be59c0d538f5e8584bfbb3a240f5016d7927234cb3eac35b391b8b53f20ed8bae0ba11089694bfeade11071656d4cf18ef2d368192e04e08e3024fc1d2fda6312afca68d10c9c336a0e36850be1a4f35b033a85a2a9549f2673a995f2a9ab4bd46c8fd2d838e64f761713427329c9af5e4211a22ab208aaab80e194cd0f6a502b308fed6c583517801a48ed4330e2faddcd41809c3919b30e84db3c68731031e79857dd9f97ffd12547da7066798074151ec88a5fa963b9d9d83ba2fee135833950ef7bc62b3401ea11bb36f25561bc0522bb02d8dad0543f63d547be77d0a4c9bf65d42f3a276144d2e474e2942f3790221e26fbae7ca91efd85921990835fafb6dc674635c9601821038b52711343d1aa25f1c46ba4e3c6e712bac19e53eae30e5246e4f04ddf2acdbb34163c243677690be0bf2e3fa164870b5e6f536b22fb89e5e8e1d87cdb34044977ed2836e544d7ba493dd42a2b649bcf313c5b39a1dbfff3e7f2a59ade87d3e7b258f58e565fdba3e4d92b1edb8bff54dc49d86c53c030cf58b97ef066d241b540530213905739d8e1aa72ed90f685d3958eaa242b0cbf7a2eb976ee96a63e66786464169a742d457e4d9117c7d66428445a46930c28ba7a2658241805ebe72c78e02035d263a211e590b490cdb84415062eed14f13b8a1a9e77c8d7b75515b18fb85386e4a7e053980d30f4899e83863bee875585887c5f48b516ccb731c4bcaa3df07d04795814096c79d7c5fdc4dabf5e26a4ca1838e0e5d87db71309b81ea7ce461e5e44c7ab2f105ad75c543c1e9179c36a5fa555ec922ffed1b76d25801dd74f80cd0a6ba7bc20db0ad580b7bbb9ddcfd93ad1c5f20f3e27c3ea3a1e71eb74ff5f944cd3b98f6d04529593011c4aecef6dcaa60fb18368cb12b6e391b3f5df765cbabff15898c84796fc2b53fa4900dad034a13b0ce1445adda4ef719be741419e231e92f1f667a32842a42db79bd7a014a809c81596e826273d16fe5d40458242ae10e12e60b3489530c6622b5bb44454f29616e47e9a297ce1ca074137fd9ae13e3ee8edbcf78af265459db1af342dc0b2fc809bda015b5a82b2b7c54efe4e5fc252eb13d66e808936f1910f4c48be0ef7a
SIG: cc28b5ef4b9773637fae7e5f084b6994aa3598f8f4a65d0bb201d172d861a30149b3338d3c3ab75b32b25595cd8b289630c3376acd10ba2ab26bc1aba900840e
TST: 859
SK: 77964dad52b579b8966753da3186d1c5e9d33d33a4db38bc0d7a1a6c112c13c2
PK: fc25125e7829f64234375e52ae9f77ae1013f99df5f9965ad2aa16589596d091
MSG: c339e718a757f3f3bd1babdd2e00aaa5cd7fc9005ee34b6fdc09d71fbd9c9289ab1dd14dba2cad58cb805116777bd80c85966433ad46f9ca6e54f13dd3ca7e56e47fea41e5488a45ad53bc5d657427e1d7938f5519f1b09f5bdd98aae5ac9643ef78eba4934925339a155dc66828571002097a11a5cee7b51a441b756b0ce65b779afe19da6a18efc145f6090ce770de9e0e91f543270a0985eab475293ccfdd3141c4142e4722233b267499447641235d728bd75cd1adc0db142f7331adddf8c5eea3d576405d869915b560f964e3e0003c91f5e96bffbeeec73e51024ef52c55c6dcb54d58203e62f4ddb6e137eb08e1bf1326018afd1a86cab6c841e0661ce0a1a7ae967f24c1a77fc7ca505f72e5f7936e39c6f4837e2595195a69cd676510a7161a4dc5e318f3d4f3ac0af03f8c4ae5bce39324e9738aea49f002d32d16de2317e95a9f32ee604e13db8038b264cfc17aed29c9debf8191de9e0efc951ad6d54867068cf50a269c37a241f85206788d23143177f659cca66cfce03bc0502255337f16b3dad6f79132abf80ff12b6d2281e637eb6c71f76e2633a114565240eed00fabea9ed8de28c83221f8cb485f512d9008bfc74a366d4c2b4ed172d367e0247cb65098c110282e831df8e9bd4fbd5f4dd2b7f2420c23b85a637aa2262c3cb88405f70730c9ab4c9d0f227ee4fa4ef91efe9a59b3e6d843db879f5650059e99f0e4a0386838e6f9876f67d50f89832dda5f30a9cbfd710134f9b5b54627496aa3a43212b07f03db11d3d4f875d41d1f4ac45969ddef69f81a06d2b0c646c9cd931cf2502fef0dd32abbf0951ed303f5284825934397fc22e78698d35ad81d82256bf9e15400a1091623a9826f1e57792367417ef02586d64e650da9ace2f18aa0a126d867cac4b5d4c91bf5209e5359556386f827083eb53e8b4709fffabe92c61d78ffb5daf10274e242a70091f3f9b9d596c1258c9a63384f4b05b028661222181c0fca965f0a2cb56e4b556d6fbff71b64d9b358da31aa37c74ff5962fb8d96a383d049724c19e249c9edbb2a375b23ce3104da0ec58d2635ba03b55423fa2db7eb349a4fc58a1ef540ee9a02c2e703c68d7f8475f434ddd3200db1f06745791a3acc3160dba50a393447ffeef6dc7b98fb06684cc90fd85203d119dcd8199e4d9a89ae3467ae4bb19fb71cf747029c24096f9a50e
SIG: 3d1b4b4e820d250be2a8fa971e599e1e98977528b2f930189681a93b05e1a706fc80effa94e929bc43921656897388288a9b29271f37a14be014b873c68fc904
TST: 860
SK: 5cafd817a4410ccb27121723ef3207c1731a0861945be962714c0ed95038a195
PK: 4ea086be43ece1c32d08059bbadc9e9a2b2f4f3fe370f1f5ccd7dbdec0aaf303
MSG: 50b2f05342418046d16a30be4fc62b67daf6c18d2a74242b7cb55ba90ad20b6cafdd60155737c29de48aa5d799fe5495fe59df5a9b8c0a8e5418904763fbad83ea6986651bac31117939cef4e0c79930d52dfd7db43c31addae3cf93e3efc5a916efd0d65fdc30909fa356ccbc5247d7aaa067131b6b4820fd02f8e395f5a9704c9bdd7560a611d62559a8dfe1d2859c52486cc11ed3331992488f417520d920dc73a32d4f08110082500f5a962a306932c6a7802955cedad7abf53b0f19fe4794a31d6b855380284306ccff71a4007859a2328bb19024c43e10d77064d866d9622d142c27354b84ac3b4f8232f7a2f8af6409d5cc757a18ef813dfaf4b9bc040cb006d77f143641aa2036ac7bc928dc96585d9e36c7bc9c564d25f1c2cc0beab9d5f207e84b215f1e7aa6fc328237b79c39923a4e09c7c73dc6b24b1416294d798a4ed5f758336d915a870a7d6b7592b5b88aace2dc5f267bdb491141cbbae2a677407cc0955f961962599304ba0b839671a5c000e920108a05298087e49770aeeeaab3632724cb0fc2285796dc414814fda78a54e67f00a02f77d3ccde1ed9d7b1def14ea1f61910bdf30a1196fc6351b62254d6445e6c90445b16efafe289a2784b92e42b78a4a900c35f55630bbb7762ff9eb7fef7d04c90b9571c4fc760a410dbfc252991d0ba27f2d414fe64eefdff4abc18817c9706c631bfa203821d3b92cb338baaf5d1232b462647954d0902462fb1696e991f07fa9c3dbcf2872960831b4ded92a421cf21b753165ff309efe2ef5438c01270d10c6a03d34f71ebc2dab1da90daa357984d2462bcb35ee3de55c3a55f8b98aec2114f74c84341a64127863c120b5ecad9e329a5756ae4a2555d8492cda835225a8deb3f9c1558f0d425bc172ff7640cc79d97800416fd6294cccc70cd1cf5b6a8e2aa07289bd522bf99dc96c36bfee80e846f5dd746dd4c5003e4bf7d29efeea7508a0161236882c9a82a56aa2c2574669652c630923ab470ddb95d456f7b8e8f07599ba0d1d38bc7f8176e3fdf0209bd6f75d4cc11803afb1856cbc0e91c73730e4fb98f3c948a87d5a7edcc0a6a8ac810ea3eaa6e063cec5f5566cd6dedc537db6d686b8021f6ea825ad7475ec7f1c5dbde45d3ff4b5ee51c0d04f1d74018eb91e5040d01c8b71a4aabbde6094d4afeccb18dfcded73ea75e3b9f8ce167df6209ae
SIG: 288515fa7259f1eb587fe8a2c403434c46f8d7e75b6d22bb3896566c017d09b698c2c807799c2f65f9cdb4eb58151ccfc48d108061a6b3148432b2bfc1cdab05
TST: 861
SK: d5cac85521af781f3d5f66862a04b087d0ccdcac926cfe9e747be8d5c2633f78
PK: 100dcc53039bf05ea0a9f5888212693d4f9e0e752595bbcd020610e0ae213596
MSG: d5e7dd594909375a4be08e74825d598d535bf46ec084de52b57391c127eff5224ab2d194dfb26633478d02fbda74d1dc5821f791bf962d8dad9e4ef24224891907b0189cccc8b133d3aa2078926daef2898c19c2e0bfe02041a904b9f04be7cb50aed0d962d1add20b40a88ab7abad626cf4da0a78f9f53685501fdfa58543ddf2ea0eea69e7ba160f8a177a25fc21e8a29c661633e30e523b0ec01b2aeee2d426e4aead457488108fe5f569cf6e2fdb68c28f2b3052823577cd934e7b062c8a3424cd4367fb315b744ca35255d7f1af4edc9bc9d8837123d97903b43df367c7d418c79347ffafe7c7b1724bba34ede8d3568db505983ead47f62b56e3618c11db8ff0bf492ac67597d2f96a6f420ff985341b786ad6ceaedd105d0d1563b2d53543d78e7256725d204e82ed3a2e6a6e83df61fc282a62ca06e62174b55bef40a0bdf8d23d1c330c71441485ee85e70ced121eac607f580678163e4bd75c6709ff3b41de80594b9e2f2aa278fefc21d73ee3f72854b958d9a8f63e3d70f7fead8c3dca8e71bf4b9c2a36f212b32eb3292e635580386559ee1a11df15293a0c21cd7360869846ba5b7ba85c994f5b2f9cc50e5eea8e4b3691d886062a18cfb182f1e8b611fe1bc263159cb8a086787c811bea4812530008c70ca0c47e64eb2fbad5b02727a66f2cdd6dde86f5d2a9645a1e9aa66ee0e15b97f5fd229596ee02e661cab9a54eee1b81f98fe256ed6c54feaaa0ba047eea353344f6e5c62be1e9d5c09a2a699411110c56d1949e90c07b1938ba9555ac1be8511b510218d7cde7e1d74a68afb642f81715fe9e6c96c50381ae5a9df306518785dc4dbc3a64f60f245c564b8029512f381b56ee787703426803c80ab1c311f477b891708b59fa748f32debf54d2413771978c265c9b87114adf25b8337aa93b0e632a5b6eda474bec16328159fbed067b00b87add61965492eccc6fd3461c1000e4037ab1e8ac89a8524f78ae09d308ea6c94ff883732b712eec0ef07718d33c011b9398f8cfea733075af331fb3f97cdc1e8c99f6a10725a68c5c58fdd8b0baa50227f34d73d23905203698eaff626654ce83d865108499be6861f6141bfa6219d7ab8b584519199f880cfa1b26d9194d301711c30fb446d6ea764a4310f70e4b859cf95fd44aaf8c1e240e80a71611dbcf52da58edc320311de388d5d9d769eb59be093
SIG: 5dc03363414eeac0086fb6feba44217cef4c520db61926df680ca602dc11003ce6afbf3d13c8c5b05273d21415e67c14a2ee5d0b1d5352419ab9b39c003a510c
TST: 862
SK: 159a9eddea5de63403987b5670db6fac98ffe5ec3a6cf01516ee2c70ce3b3be0
PK: f61f4a04a5a12ccaecfaf44c1c9c1888475a2c89fb02f26bb81ab5f78f4ce3a8
MSG: d195e5900dd3931481bc012e77bf060aaf31cccb0fe1a6c40eaf286a6166a166b1ea37053426284b920c67fee1d4b9d86fb861cc6edd34e10c52233734d9cd92f5dbf433512ed255ac6b26e56f5c664bccb260692cf49d08363ee94e336acc489600a6aa512a040f10ebf18f7d2cbee9cad14c4ff87377a3263419d8297529401f15337a4c4d2325ed7def763a0d479caa408266834da242f3a16b79a45866b9d9d71a4829317674cff7ae6c8c587ba4d4980e818613d3ad82507a7ab032bbf99c5e9b640371bb41b91e965dc31e8c7d4b3bafd49570527faaa87abbf6416c47b1b1b09d3401253126cb246ae45acf5f100bb1f92f11a5c6c937e0588d8b146b3e4d3c7e5bf57484e984fe3afc4772f24ebf894cdb39837fbd469a921a96ac5af5e070f6c9624c588e9d4fe6ddfeed1f8fe20eb9c460ce6ee38bf471dd56dcf2e3ee998b8e7fdcf612e78a2e7c7173c0160982bedecc2c621e5f6611b4ef2102e32e7c29803a7e25fee151243158a76ee5d8c1bb2e7d8c88871ba433c5e541c2602693d90110be795b523a8fadb605d8e3d7e493fe245d9cc5320d32b85d6135a44b1168729414c2ca21560fb4feecdeef0cf7d8e071274e8856c004033e80013c73af7177c3197816a5032d9059b1b6e4152c386192dd54b90f9d308be98ed7d0ca9d12e8aaf6f9d869386aa9dbb01593d37e72f090124d3455298e9b4c9ec3cae73bb8ee41eb63e38c56133efdbaf449b84e1e491e496f1c70a44d069986ba8818422069061bb6ebcb7b2054e63df381ba03c6a7674abd61050d693d41bfe3ca5046c65ffb06a0749809e58d4c93a9ff69ed30950bde1f99216fff299f22f16b07c254c265ae0b12e313163ccdf5036d49055f9a9667b0b71292bc3b6260cb87568fd267170bc940c33329d729c9e32d0f9180b134bff8ae93b1bfebfa3842fef20bc04a297b00a84a0f428d5f42fab86142996d4ad9efabc49852f8812f3bfb5e57539e2186eb8ae229580bc60448acdef5723c881588b53789f05b91e02289223252d753f79813779ace705e04aed15265d3bdf2a2e4b15654770a275854e64cf44390607a45d7bba9af3e1a2e283067fcd6e633aa2d2403bd81f7c792765510b598412f6bda07b2a945b9f6d46ab2f7c320075bc6b60a80daa44af391f4cd562131bbdd407d66f8db1259bd76fa7e4d5264e145546c942dfe9007
SIG: 0543712cefa29a220d90f81baa4e4cf77ac65208b2d5ce9fd17ce214ad4a937b7fc5c786413b58051cca3bb8b2eb55657d89572bc50ea2e5ecdc555088491603
TST: 863
SK: eda0feac0f2afe0174491552487f3962171332b822dc3da426f9a5f62bef7b8d
PK: eff27cb51f4d39c242f323019a1234818ef2e4cd1bdabc0f2d8d213458dc471a
MSG: 901119da4ed181aa9e11170b20626e00abf0b548245e3debf94bf5ed50aeefe942b402cc9948947852dedf2b5304017665749cd47c21fc652ee995679ff931e30e94af98b4a98fd44e849e98470fe0a76ce80c61f83fb4e85ba523ee3fd25db000053b49d0930e3b079e866e153f7d86367f23a4c4abc63b3075461e90e4fd896da0492e27d714941e967f52c93ffaec44803f57877d866eb5f8c5281785aa4826792e3964c66590821eea66752074264018a571f5b013b38e152c95c0248ae6036822a67afc9e02694573152b864c56c2f730a08210f85ec46f984a643d516a15fcfaa84840f512047d110e0718d293955f0158257fba0d78eb7df2f0b77e6eeb76db5e71707310e827361cd4e119740e63922db42c2ceb5ee175d50decc7b749fd2325bce1e6a8f710ffcc1e1c9b33c380e52a64daa9585fabe406d9cf24488fe26f3a495fb0ab50e1e2bad82381aa22431099cc8a569813d79c9d78569c0d95da9aad2bfb57758d52a3752752e023d651c9cb66a412a5c80f6ba54793f7ec87b4c598fed2ce24abd7608708895c46727359ffeca6d6c62e10a678caa718b4cd263292cfef535b9fbe2756b7396d697b3146c551e6aac1f5f1c24be9b67a1e2a2aff745301ba6a212217c53d681681bbb401bf4a43656f5d15cde969c1780099a33237eb19a3b8585d6b5dea2fb577845f25ee2a82ccf4b28502f90fe80b8cdcdf2ccf93c434c0e6aa5d8752a44343c2b18d20fe4004c47038659356f87abed5445034d8e2d3d14768f5ef312cf102a9884683bcc0cd8a71e3ec36fbb6334a1bbaed5d2bf10416d82bd6530475380ab6e2577bbc69cebda75faf02ad827b54518213206fd4cd66f252b234aca9eede7e3eeb815ddcd8d519c5d7f5d9d1fb9ca0fa4467990095fa46220c20a2071dfcaad5f024dae3416f7c492d757488c49a2e4df483bc9b80098e0d5d683facb8c960829dff09b303369d46cb57331ff21791ee25d6be7dec7ebaf1b32479a7f514dc647105c944c36f7dbf0a5b589128dbaaa42171d642f25a981ce1f8379f91690b36af774648d5624c08dbd0a90f708716dfab2024dae865b9c49ab27473826cd4a010bfdb52011d8c7cb3f421ca8ca3cd0486889188e67df00fb8c2a643e7adb2f8279f763e5b9a81b6dfc3f721fc5f6849f66736788cc557c4ebc6fc68d6f6ac77bedda8acb362243bda74e7b2
SIG: 6cbc7e6f5e12145b01687ad9ca6bf6e47f9417c2cefad3fbd68fd65dd74faa9750cba992de4cebcfcd35808cbb3ff12c8d930799af36efe7976bf2fea79e3e0e
TST: 864
SK: ec059fc6be983c27eca93ddcdcb53af7286255da91e2a56a684f641ec2d09d6e
PK: ffc6cb751c70071b65ec2ac6b45fd1d55fe836965f80b3e7c784fc704acbdf69
MSG: d1ac6325a4e690fa79536883d5c20eacb7d964c0178f742c2b23727deb62645af7c81922a0e72e5e30b5839a2ed5e567ec31ce224115b82d2bf251b7393f01b0d03a602bc120ae62af7fbc379dfcf95bbbba984aaba34fe212ac99003328b832c3532d42eee1e1874dc22ad67db6c91dbbfb2b45785dbcd39917d36fb48c1b5d6f38bdda5d28fbba64175575afea46c8ed6757ff30164e0df2e72176e8b6c9db5b5ef390b72f2d4d94e3b66f0d44a7e0f06e89debcdf1363c0e75d50db5bb70190d19f66a39c6f7dba70dfcd4a9fed02c2f1d067e7c788c58fdb3e17a2377ce486ec6582f3ba997bb5f70cd621002956f5131aa3a1617c0cebccd9391de1307c85970a8bc155f519872668450c91488689f53c2c1a7ed53f388cb13a2c3896fe5b7d3a0dc1683f27664c8beaea680c8cc54a90e4c6f99fbf05f2c22df60de9aec80c79b7d66207050667b452d7857f9a8ca723280dac7992e2079267ec3ad911404642c4e326bfb96b43c89434ba4bc78c252f4d4ca8d13a8874c6fc8252ea0b56c6bc786847d4318306e1c652c452585eefd0bd9dd3c148a73ba86eedea945f016713ed7df085d0066689e792dacb2bfc1eb5c824372a26c5e944aa7444ac9773d4a1921e49bdd4f8f6d788c263fee04c7b444c5305edb633e1ffe0ba4ea8da011a62f2bbfef4b895ad3f224c3ba3bff0c95d75750c9bcc66ff8a20b6c24bde7581a7ec3866f8716f781f46dcad45a9ebcb6ed46953368397011735d4b52d00e8db397995dbdb3d4f4254687f04688a268c305b2b1f622cf51b174775bad7f6674adc2e58e05cce865f12d7569c8e9b35bcdf3ccce6330d08ce5340a7c630f27a6c8086b5146b292fcbf50ff6aaaef8848a707b2543c618d17bd976c240bc79d33e004e4953482915e7e6ef94964bdea4e02dd7c2f475235f2b99e43229c9ac3aba0db59ac2da03a9ee4f37dbf247a33e6dfe5be7c7f82584f04a46d49f6621da31b91ac3daa4d68d48a56659b448c0ed365cb4aa0cfd908853df5bbfa88e60e10a5a002c32ab3333f2c39bbf3ee01a4aa60d2d01423e6097dc54305f81a2d93e2f6b4e8b351971cbf2457dc76e1fb89293384798ef28234e9b1a47dedc2336f86b8e13c4aef790f5a11239c747d9d865c9a15adeb071070267e5346256648adc0fa4dbdfd787ca1465fc240a324c3caf2931da41499e275fd4b35f6d08db
SIG: a7b88e5abf132824bdde77c5f8df94ab26481f6bee660ea162247082a250d390c71d320ad060d8ef341fb69a483294f0d6de726f0c862fa37ea4bc6dab521509
TST: 865
SK: f16abdbcc0bcc61a1aee3abd8767ab52e5f79999bb77a3976cbc82670dfd2f73
PK: 10f451719db0fd21376e228a41c3035c8c2bc42e5aaa926fe608878dbb0dc7ab
MSG: bfacd7dd4eea467dcce404f4a3520a45b94ebaa622197d02d61529d2b3bf273c4ee1fb95a180c8f87de190a2e5ea70b84ae1eb6fd4447d8a3a8ded10f6ede24f0eb92bd30bc65d4871e8f5da08cbe8cd3c0ac64fd5a57a6b064a89d5159b42f8b3e5a1838c9cb19d88106c0773a275cd2a1d609930bf6b30aeca62b97e319bbfa934f4d0a1e6ac80baebcba2d8ea4bed9ca8562b4acb56979bf885324ac40ab4a50bfb9f349049fc75a0e03de4cc43eae3c6a6cffb5f6ae6c94504415e6c7ed3045a932f47fd20b9f3483a77b6d449d8dfd4a638dbf56f03f0f031879059b2fb49767943f46b3872e2de567d5fef80b02925e9863e0f1d31a80f4e6451c325694b80cf1f1918c6e498878edc47c4530cac466f1a294d55df09af4fdc8072adb1bf26ca8c92f912a2b9febc8b97b58c1e9d32c780323052972b6fbd53304c05193caeb67c5bd3e67479725d297dffb06890abf8cd9e42458e168a6118f905b1d53486016f85dcd98dd339e3460533d0b8a49fae6dc1a071725e6ae5f294479ee3bdcaeb74061841fb2608e88a49fd0f3895b18f85b90f7241dd1387710053faa62bae75e9ae39369c1c02de5d19242efa16e11d44a4ba5778ce7722a91cec0bc0a08c069bdfa130d1c6c4b56c6e93542403ccf27684def57def26df86ced571282dc960974618f0a74a0cde35b653cc6e7730431b825ffb9b8aaab3c7a397c992bc2fa23270fb11ee431afd5f9a644483011173993f19485dd3cbdd187bd3d995ebf0031b1b0de4a8de9c14eb6f780e36b8925756b97906a1969d85e967d880e6e7dda42fd3c30019f11d7081071eee6626422836bbed27d46dd0df1feb6610dc859f513c0bc653d70220fe048d2e97c2e06af530e11bdc7029bccc5c92edecef5e4a2e0be2d251f4415dca3e55b3a850f2630b879e4e036ce8633bf20920b68094215929accc7be40c5778bc554e6edd7e54c9e145b2ee07b65d061c11de0e83f381ce4f57c6483f51069363511074c7a577353b45c6eb71199dce5059fd2c4611b054238aaadf2b6ba534bfffc2722ae3e31ff79ae2ebca99cc3507f8a033cf4fea70c52f7db5de442b42b8d41e99012e42ca0e85a9fb6d4f165b330de6383c5726efca2fe971340002f562dc6cb8f2faf0665725e097799d096091864d66a950a5790953ee16b9ea582009218708c4accd81381358a2c689a041d02d786121
SIG: 33d805290869b8e04ff089faa2d1fab83743bada68ade5b38ae5f0cc58c3374eba43943c1f5110678eb39b4658611822a26d35ffe19e9cfcb9ba9589e4ec3105
TST: 866
SK: be79d1aeea86e86f398137e62ffd79e50eff9f313f25192f89e52f0b4bbd5d32
PK: 187dac855ca442fd9a3ddc3289c24eb2d26f7a40fb29d8e74431b25022c3a0cc
MSG: 6d632a7d3c9be53649d0d1a5eedf519a413b13ac64e9ad854dfa04f2e17329d822be573d9e35ac066f022213a344620bba289f5331695584d1343e815405aeabe3861d63b3a5b92b8cd8eeed2280222abde30a1bccd3f3e411aab922fa1baa097aa5c780d0eaef94ea10fe21f7d639b76d4788aeb5924a9d262dcbc5688a3e43544bec088ca2e0d06d77a71fb641d55226614452b1e0807a9fcd3ca69bf7f25d8041470ceb7b21ead03ec037a1629bd500aa233b59be44978210b6a366f223acfa0797954007b00efb4ffadb5fc92bdb37863e502d7d70681039edf33770df3d1de343dc35f226d5e73944ba0255e2a88ef6c41e472b214567c249594a50878b6731c1aeb5b10fa91fa76a37e1f9f1c00fdbfe3485ded54a009ab6133927115668b59f5115508da9370f6bc92a1185c0d5ca01d291e18c54acfaca738bd71968a342a0cba62e4bb104a5bb379fc83ee1820d1db980253d6cb383e95af15f53c85d175890dde5e4ed03d2d0135e3d60b18293f5b5641ef83c6ece3d52598fc6353686e6f7b09fdec1f6f153672d34b489b48a0db9e42ceda71755481c047016c22534e90c6d201ed7859602636ea77ae8c6734b7c4c5bd99579c508731c7246a29586e406e1d932f6713071d4bea63dc5e2a3761e16024d2c3284f709a1f2ba085ead3200c7046275cb96b61a60b5ac559bc488bd106467c3de50bf5d740d05c9cd701d65b7daea29e64dd5a97adb6b5c82cf7f23017aa7ca1ac9a39e5827eb47e20d359b67c7d4e1a8e3e27c52d33d9303a592623484d797b402cbb458d1ac2ea53e1c4f7abb70cc029554a234574def9bc3b0d3835dc314902e25abb22dfdeddc679a3cc8f07340b15f5762f4407f380342554ed0c62f73b61816ea8c529461e1bf0e9d1c2d5e4c5746336bc0e132873cde0dc2158b54fa1b678a006b4d95eda8a955714273b7cc5cf2add9094d46e49abc096a45f418e2edbe99dd852911688064df7cf061d07aeef42795690f48c9ba19565475d5468a9ef45d7bf75fd71182dd6e640138f182a6a0c6cbbd00c495c4389530ac8e67960eb5c5763f5484eab1c1ab850140da042ba47ed8528800d41787f075fe0d85501a7ab76635d03410d286c0e17db4023a76397468ccb091cc5ac1f6434587913eab922b50ca5567016ddea32fb53255be67f2dcf9ffa85d117f1a655fa70dd3a54cf991531f19130eaa
SIG: 6dab593bb1d448c974a65c6a0b6fad22b4732632d00489176ef126aa590109e0a723a113107b53e17d690a0d40b0fa336cc87fd5fce8f541accec67f7d1ebc06
TST: 867
SK: 269952172c3fa976defbf40bd6edd8f15cfd4be10c758e3741d74162d8ea229a
PK: 4aea57c721e3dcca8239e9ad9b22c19bab8df72c88793b24d8dc47cf9740fcf8
MSG: 7ccb6a0570c533737b9a534a341a7a96dc76528b997a9b48e6e0fde10f474b27ec989912d176cab742d89a848b3666e9277d695b022fd53a9eb89e88c720399e24ed25db9eb35d6da009e9f024ef8e655165bdef1c0d797c74f019cd591a0442a12d1ca893836ca2628b33e854f3428eec4aa5ed84f4bdd2eef8b6d225caf9496df9edffd735ea54db1bdea883ad5d47eb0bd4a6653f0ab037f040a41517a7741f91e82fdb6fda04f0dfa1bcf8b9b37bf2bfbd87327a636f907fdf968d0189d1a11809c4230ba69d5cbd84f561bcac3ad002e558c5b9b097a01902f29ce3f1ec264153d668c78b845105b9cd2ef3c943531b75aa428f179e4b3418b1d5a4aa7ab1203efa495c8769628eb1063a937b73e4b5cd0cda33dab01a50c64febd975c57a1e841508e8606094d0824fdd96cc6cfa18fa8209b30f0a2a78eac9a767176f573e78c068809b199a69ac6d335d7c920999c40cbad87cf4cc7ca5c644291d75ad7a74bc1e6392d1ce311ecfd2ebc916e39eb6aa3e7d89fb805a27a55f178912b157bc01a055f67aefa78e55c806cbd9c01baf8ef92cad2260b4bb14cfe61782dee5c59972506941c462a4da7eb899531cf996bc98ba3629effe6fcd1706d1b4ee4f2a14e921bd408f30e12e73fb7aa860536b03e77ca937823281a16453fe827935943201e6ec143a67eefa4f94e9abf94f7e3d41b70a82be69ded8a53060c2305f42f62fe6a2f704b67a1e8fddc7d98ba7f3457119b311d449663ed9e320d618dc2368d4950875b9c38c5d8c03104e2e32c4325dedd2bc267e2accb0112018e9c5a8007ccab2f6d7c737792002acb730d72e9f730829ebc42ca564c1d9271bf1869c4d35835589b7431ef7a31a070060fe4a089fb11f2dd3dce65ae0fb45bc3a2860917d933ba2d090569ef5ed43bc2532db879e0f1f225eadcbef1c03d9ed78299e233e4cf07b064a7baac34c5a0c19fc3a5542089f70167be2f85b4a10e778525223be8ffd5cff9648b1005a098b4b3924398fb0bcabcc6edf30c061ece7aea35fe98a9203f8711369530feb5e67bb2d4f59d9c8bc993854dd4747cde399bd0e63740c1cc839ad0f098a38a80beadd648e1436deee60e931e68f52979ce49f301fe39afbb615352091c8b6585fe88447ed6e59a020b2bbe66a9423ae5228c203bfd4847b5181e2c3b4dad83a6d4fa76985eef76adde3b34edbdd28d6a0b4a4ee
SIG: 3ac80d1e8f68b4058c3a04dad7187373959f26a27002496f8afaaccd8bea0901c54cab87b2a2302e1f3625c2b06c7ebcf3ce96de3afdf00f5194a35e0552c70e
TST: 868
SK: cc3138e502a5ff6f80d246366e84d65c59f12d4f496397e6eb99b5267b8cbe2a
PK: 9e2d3e88af7b52ddcf00e6d0c7759c1238b8fb3eb14421fe82c34833437835bd
MSG: 585ecf2f09eb923df20a8555642a2bc0b68c6a5fcfd6b8401c4a0cbabb4c6e6a206762b7a39f2c5455d7808ebfbed56d6760a431c7d20c2dc6ef1b73caa3c49488e30b1ca2520ad20b26a19700780e5ef3ce0144388d8407b6a70c1cda37db7f12091d892f2e91ad4078bb4db1762e46285a7b664b2ad3a34d26d8a94d64587a84527722ea83cb8aa88984e1489743b4214ea6041aa18e55200954efc7edb319df947efbfc6c8d0fea48a131613465d8f4c49498f2269145c6dae50478052598e1ca3be0e33611571fa384771eee402cc2b1d84836c8f1ad28f2ad23dee9ff1d7e1f2521635874115def4d93e89be76180bc55f761144360a8b222892d64d157ccb5d8f4855dca56701495a0e1002d340a4a46156b9b7fe06b7c0759e0b6df559b691ede78b55af64e7c8dd908b788dd6ba35a902c81dceb3788b615de225afa58a81181ab24a73705ee838b6e863fe1bcc26c1b943239230c27c6b397b23d13de6a02c97f3645da91d413f916473b018a61594b6f51cea44457da1e3dbbba6de16866657e92ef0202718a84ad0333e8336b052b004733e8e95ec13e5f91b3806a98d3db729fb735b8147c4a982a2d5b4efae9c09d0a9bf891cbbc3c8f531e76e4044ec91f4d7c5cf77310e2b2cde2e07ccf3e0a19dd6ae1b3fcb2df42186e9c72922d2d4ce51b306e81b16cfcf8f00d513fbd2c5239b45afc654f6fe21acb7e8a0c9aa87b0b605074df9576a6ddd900aca567617cb79656b3b5ecb9ff68b2f6241ed0d024ac27aa6eb486b69fdc0a0db92096abf86002dec7afd847a006a3f6955b49569053be9f1d0a49b793a5411e5916f418ecab953243553b66e6badc4e909be0ef5cc7c6d27199ec3f21423bc45773fb40b97b61185b57080e8f0b89a3ea57c8444ab27ecf7006a766047eeff54d8556cfed23def1da2cc8aebb48c94e779e8203ae2c902b51de0ede0456fb73fb4d5f514a4cebc47fec3f948469a545c6bc57b4138db34e7cc006de26ef507b54d28147567a8c29ac1ecef5bb84fb99aceb23a20294d74a85ae36b33450668a5c2609d3a93934586ff90c3b6d27329eeef3a754e9a9cbd5617ef3b09397bdc971370766589a12d890050d1651458b3fc533c843bffdf9754d932c4ed7611d4d27c32a087555b5eaa37ae90c4979ef54299c420ab5e29ae2845d4dcf2178920a865175fb9cc0e6b8c524b1ee495805d517bfe0
SIG: a2700e3895ed0cc2aaf012a40bc7bd0bd29dd79c69c0b4a6edd0530cf3e267c0f82dd84edaf1744dc411d62c0028715258822d7b63d39705612b3fad4b5efb04
TST: 869
SK: 5c692c681198b172df2fac2aec3fcf7015c2bb6830f2a98e30a396b64af4280e
PK: 33b169d4ca271040926ea87835e5066f9f05782f087fca7a556f7bf4cba2e886
MSG: b160ee3a93cf6bc3456e5bd0197c09aa76c2258052f9a34dbc2ed589f8dbe5ff9969a61cfe846b2f6739dc7d4a1496e9ad58605b5a2758ca078c55a9fc1c4eeb5491a84bfd468a2ceb141a773493a9b3ee828b5dde9c00c236ff0156e4e2e45fa07931da68bbd2030a881405c4f78728813a5e04812404c2a19c9b87b1cfe9af95e273ecf9c518c53935f842563b192fae12a73cef085fe19e899e5ba08979e311fb286fbfc7b248aabd40dc61610e1d4fc9806dd21292392db2db40426c5d196a489c5db77e3e9cf0bd041e3c23b5ba1db781a10790be1fe07a2b00ca3af89cbd46efce880e1ef28b0cd79d53b42cd80eaa137eff7df90bcbcf95c9858dc0ccc6d8ca8ae3547bdbf9ff9024f3cf170115eb28bf12b7d3b701460f48d1b4b23d7f6ff72ffdc9a6c52624d15312d7f19ddb6026a15eb54295d331fd79509103bc59a3b6e1ba7ac8c112e4de2817e51c1e16507ba66f2547bc899f69c1207ae5e37bdb0e161b15b612305bc0940f9d1b382a37ec2da639a6ecba1bcdfc51214c3223c11bbab79f3fae3d55e2d4be584fd7601e4e2e558b3be5707115a61f5a815ec24aac18093457bc46c05cfb7a3f2533eadadc9e6c1fe310779e697f683035ce57873df55d791f6d2fb0e2107e6866f839c3a126e9023865ced1bcf6779955af547e1d87eb32a9bf322857fd126b0cdc5d5e904eb76c6706e3c897aefd6e4756fb8aca8170ca5b39669089af1bb141a25d6b8b06034d8b11abf1ff8f8d43375846fa8fa8a34b5f264820744d31149b7d57326c59b1db74131678f634e7232ca5ea5188760a70dc35dc89f8e453b4c65b772c2b6b62768d8373236551baaf24d3c304c41b62c36e6a3383b3a163b73e78d8badb75741e5001d419d30e2ed77c3096e8d8df713b93762c9707bdd0f365a874b9da8ab710495dd56aea93bb77fb222635c63bce9f63af91fac89c66986b8e2176dd451d583394c1907cba1725f06d25d1d0912b3e5c6c7dcd34358fad59dbc6f6b1c2ef33d3ca82f43518fe4ff31378016e578a7bab0b77676ebae0d48d0889d69029d209f283ce8fe0ec23cd832adc12a9c3e3aec2d6036695556d9313f12a899dd59a66bef28ede175f8aaeeeb2942bb90892a04b440d04b66f5eeff61ada72790294ce55c86c6d92785ddd26c7a731603b069c603c92e4fe8ff782544c8e89b40b8b55f90e2a5e9a0f33c7fec77dad8152
SIG: ad8f379caf41f72dccadc3e915357ab0cd304e10f4120e0dbbfaac01bffaf2be893f70072dc964069181bec17fe0251055b21e23dee4363b27ef1fff67aafe06
TST: 870
SK: 9d5f85d2e7dfd03bb689d900285fd4461538a5f2710a13ed21c775f6eff6b3ff
PK: b86797e4be0286ae39e44df0a00c016db4555ef86f2f05d0a3ed89d89a4c3e5e
MSG: f70b5b053a4672512c24b3168392f6a17dd77d8689c21c86efc25829a1a04fab4f76c8521684d32010455907a26908677b40dc6947d654f2914c30ecee724fa68446b59d091e258fc862411c964d668def83034b627ed416dc190bb5a263a6ff8d559e13b8936225fb4dab4f7bda0468e547e708cb04cebe1e5cfc69f76a1d283f28168286f24ecea5535e4490a0c55567a7345ef953ce426b209a3de3df595e80ee61e572a278ab02219551b73da41984808285a83598a02d9b28671210004e31d8af9242c16f90d5ea8f63a1ff66cfe60ecbe537245fa12a9b154115295806ea2d11f3671782b9af4fa86a1288e123cfd2409a5dc98f41b8f6df299bbcc4bb6447dc03a6d60e9b2c5b8ffc40d983956be97768dd0612d47cbfa7571c9969856c152cd3b473ace0b8a144aac2095c0f72f1d3147152b908ef6626d5222819b20bb3350a46452f675490c2a82150eec40d75b66a325d6e929a905ade1e3160ab950181efc66e59230865d5e599698a8a3ff560c4c601a7a9a5da3b5d89bca93f7cf5bcf5bd5ecff8f1a185c8220e4c77821e62adf95a037f2df7cef43a4c60ac75801e9fccdc5b08eed328dd93100904115645ec1ee085cc778b0f4e46e17298984a702eceb3e15283d820004f74a079520d63a75fae33ec3f4b836469e1aa99ea244af1fb08b00a8c9dfd03308dfc20235ea9c8283f4da47cfbcdbd031a02d164160f2a58986700b19526d41e4d7fd458434d7264bc8eb642e6d8dd2759ce2b85c97b3702e70da71f18edc53e9140a645627e0278e8e70539037484dcd18c62fa330717d6148a0d623ff8b65ea8567ec7fa04c892e3a1ecee96e832f4155074c83cbc93e98cc67f1fa112aa06e9915fa4d2dea931551e7c623aa8a3a7619ea24ff914e264f31fc73dfa8c430ac46ce16dc968c5a4085d5c380d30cdc6f43dee806f38d1df420a065574144737056daa62f0c098c9c52fcc04cca642c45d687345a094613d4a3c6c8788bfa218538ad7ece1bdb6c93924eec4baaa3eb15dc1494d65ffa1a23ff8e985263408fb02bfe39a8c55b300b1a02ed36c6714dd5ab750d47f021f65e08c635f1d6b7baf396cb4f93d56c1ca461bb12e94de7e5d98659a8af0bf019fc42280e111e04800ff80e0c157150e165609454281b20007e3edfaa1ea854465547a006a4c3236411495da166098af2823a459cf100a1f3c92c6390c6066cdbf
SIG: 176b9592f8c25135292add4daacc9c4faa21d4f49b278480c4e8881c01624df9a37e23e18e84ca32d0d8cb851054222f10a495419f197e7b3d18df0adfb1b307
TST: 871
SK: 4aaf2d132884f30d1127cf187ee09388b4a5c44a9a9267e6728317398951fb61
PK: 83727e9257349128559ebf759fdc82122cce76746639c0ada9761f0d60b940b1
MSG: d73eaf11413bf4d5bccf6a2e809cd6832a51823aa22bd16e09cf56ff045eef2d1adadda50c2ebd67bbc4d70e493c968cb4de4977065d4463300694c9caa57206d6664693d8462c3c576b525cc7acf79f26f9055a1bcfa7d077f45ebe0b2d481ebd63f7340a33e4ab68f1604975ec1dfec45a791a2abb1044d75a4db55adf59b8394ebde6824c21145b00ef3b1b08ed11fd51dda514ed7e21e54dbaf6abb6d9e317fcf9fd375b18764e64ac9be5b08fec3b78abbab1d12a2ab09d559acdc7133fb2e0008e0c114b7cadb4bf763078674d03e9c807bec1e2ca71adcdaa310d587fa56950fc0fb2e979043d50f9ae23fa8f821cd9d6232789d0eeccfc4f47e3ad804e25cf5a425f94377d17874833e6ae3638178c78b79519d64d9793f4504606a0eab68707f6e1f7cccb515be3d1201bcd19f2f0e255c722eab12b43aff8c8c5561125fbca1f6542076a06152eb7e4b0786324c2495e79d79c0a8e295bb2e3dfd05a9033190065a284552a6e736006ace41f97cc434a2512051b727ce5bc9c4a75529ec53dd7d1f126e793857747b5ba8d03155d4555f59e8baf2f0cdba871ac160e7519a852db004f701641a40a422d4c38b6c0c3cc8fbbd05322ddc0001fb867286e296cbd69862cbccc7447038eb30f8a8123b7b31373984702c3be457a4b8c54e6e5280485a2c4ff84521f298ddeb3b3b2bc91f114ddce67030248044469dc06f362f2919a3fece5082375d04080376fe219d9b4575b1cf1c9ec4dcac5749fc778f515dda13fa0d586c264b9bb61503310762c789ca11608d2fee674c70ac4fc6d5ebcf68c4ab89bd84555fc007523c28a7e1dd08a9862044d5245b91a8778ec9ee984a41a9e13b7abd657ae2a46ae860152c644acd95367678ff64cc54006e36614805ed618a7c6d0fd33a908523090841c230af09846d132bb4c6b60e2441f9d3c498714f470f6bc03a80d14a294b565d1d5e781cffcb1304efdbbc7bfeabdedc857acc42e2762bbf97af839a166752da295672817f10dbd472d381f53165555ac8222a78535a86805f1bed422889f206109aa74772edc0bb51e8a9840cf62c92fa635b90cae076dd50e5aed9deac843fa8a6b539988285ff1adabe4c7b83d9e29ac2d94092daafec9f6673689ba9e9252d864d7577aa89505d331fe7809861277002a0b44a96ba6ae4a52b3548bf268e777780c00209b245f8b1417ee5e701a12334ad5
SIG: 5f11df3906a712a953f47c859806b5237358d08ba95e49f9e530a37165835e9359d9769dc21fbb4d44497b93905bca8d9917c728493fee3acd5b521dbd1e2408
TST: 872
SK: 4bc7daabc5407c226d1920db4afd21b2a5b3e59b8e9246053f6a1a6afa54e7e7
PK: dc539885fc7bee002ac5debae16bddbe4b553fa15e81ee798876940f38cfc4c5
MSG: 6acce99843b241afe6edd5d0ab78d0fb21c8c35aff881389d505f2f1dd91af1eb2ad229254927c7f0ecfb7a8141690573a655d69853d74d0708bf8b1e60a03963028a625b79f3dfea2b113ffcab46f3cfd4a621e8fd8ff0a968143b0ae03ccb6f42e25e2d74dbf515bc358699b635009b01d61fe597f1dc2c35a7ba4555278ee0ea456c7d35fa8757a417924b1d0a8351f226a13ec29d025b42696ec1d9925b769cd59c8e2f9cd3ce4e5c020e051e7a36f3f97c1e8ec71974bc16ac4de4651ad4df2e9c0eed686924224fe6de6c60dd4acc26e0aabd80c21d509d959b80b4353958d00e44c511d23bcf44552608bfa56a9c5ae79de62bb23f11d740f48240c27e101999751f2534742c0a6913ff64b683a18995abc393feb9d57c71f49a080557298cc405d11b7988d7116840c5adaf53bc672b46923cc457c7039940ad4d5bf073c6c886b1339525926d281dbd1a79739b2e36414cbd321b185fc88f18d2f81c809975be9a093644cc559ed2ae5cc0e35cbdd1811f70286057a3f703067edddf5eb1690a7427bb73fe3024ed0db82a5ce8f1716428a76fd292ba99a300c4b2f360da2124617590b10e3b162a6e67dd5d5a59bcca10f610fa064affd55f8483b98a68d076f278abf888a08a014e0ea499180fbc79840ceed13cc6b2458bfab9b0dd7ae9d86461fe215e7c9f63f768cee4a882df0dd84e3eb4f2d7f6b18fa57d8bc7d9afb63c21ac465e7903b9bfb8638a29361f7ebfc6e54e5465a6cef463ae22643ae410258779ca74b70401a9455a4d157d74a7029efe6b519a8c4be696756e045ae4081b77dd6031f0d250fa761e60f859d9063fc105aa0a1a7450af153e705477777c442586df407402ba238752faef74f3345c26a4533be9a61f5fc6bde48e3cba75c04d6f7b333e37006dd0c94fd3b6a130bd6fcdb3c6abe21ca60eb431cc2d8a2ece7169d2dcfce2760825657fd4c26f3c3b830acdfd508011d14764b3be91715571a3183018e0d221fb9532bb2e1711e725a273ae0cc2faccba7d5504929459c992517b05c1ddd03aaccd937b86eb67bc8202d01cab3d489586eea1acca7dc20cd0b6475c258ff673661496a22ea96b89db4bf3fcaae3bb04f67db096a47ff7e1ee239562dc10d40f053944f3d7bcc3ff4c0ff765654ba5ea64f0ea63e45a21d9b12949f14f7ea7074e9b659c5c5d44816842de89698a8fccace43eb6b4135e0b333ac
SIG: a7a6488839bbae04dec92f96d728c464685d7a96df512b0051163d22538f74546fa986b1b60a6d8cc766a26c6984c9cd2688395898e2b2ae72dc6a2d5a9f750e
TST: 873
SK: f26af210e3b20173990c7745922cdf9424773abb374d777a512cf5b97b3a000d
PK: 54586abf041176e06aec5b6010e190916da54a8c4bde288cf24d8c107cb3b730
MSG: 88e26da35c54884b47146f4e3f014ab65b3d71aa7e3c3391adbeb19ef2e7b9302e281991b261b6a0992e2e89a49f480ca2d8e684b12f9b1509b38f6a7a98a5ddb4c2d869fd0318e98ecd8fd9df491baf99a9294de49e1cf8dd41ee85730af025a701143e4f0c8e3d92d55b59ca7d4a6c89ad760dffc0c2189209508ef6c2214edf9967b17def123d8692c9e4e20b1e98268808704f5f9fe1a6d6055e32c872564bd17edb7359578629017f0c30feab8b504e228923adc7e81ae20a852db0ad676a78e081336d6b0402f9cdc5d5e90128ca945d10515ca0c5ef03f731b1d40a710741d41c1dd1ca16b1060febf2a0532e6f5d7651ef446375ec18090cb8418b8202f25a0389031b307f223c5b5f6afe36a9adc1068f2c6e0ea5b2b6cfeb8dc004f7b829c80439069b81a7bd907477c6135ef282b771f141dbe75a0fa056e06b8a1a1f98c25fa54d14c8fdb42d6502595c59d25bacf1a19adefcc13170f7a4317b6ab610b609d414b0073ea04ac29eb10ee73cd71a4ca60409f8e760e60f939510100d0c8cd76f264bb37811f97aa5299ac0b12d4168ff38ecdfa80b1e5c1b3bbd4d40d3544735df7167eb158a9a9a234d445f1d663ded7171edc68d172c92214b82ef13fe6b8c43aa89b739b4990ae947a34f020a8d8943b0f7a5d61dfa76adde0272e98c1159c0fd8a1de33f2cef8edd32857b2189ed96128057ebdea81f7a3a3dffe1893b5ba877556c90383fa2c5a6fd680e8a67dee4802d90dfe971623a7be22ab3ca56067b1e5c694aa84c19f16d69e284ddfa039c108d0435813812390d8ebc1e50138176f259dc0f26bca13bc943f50d5a3500b18d593574c620fc097ace430fb80728d3a1aa644e504b1009ad67536ceb011f2a357dbd009e4a63f524d5b5957f331567c5b4d185a61df22d7071d31ae92141e199c12289515aed80c91021456bcd45ccc634037dcf69b41d6b1ff53471010d99f187f04654f43622287871fee6dcf5f3023cbd0913d99aff43fa95b32ea2b133b4c9ac4b017b7cf8f9be5086fe92b42cb8dbed5b630bf097c18e2e55c3dd93271e09c2d1cc6af87d83fdef3c3e3c4cbafbea9b60fd5e9cf0011de2e9e26fbf09afeef5c69802a6c46bdf54c145862944173e017e30149ea5c03c7aefa28a9cac7767002ea3fefbdeae5bae005c370dbc064244d5b9be5500a35726a99bc9e8c2752d510e139af225580098c8189aa9c520
SIG: ce454530b922ba5ea162f1a452e05c00363a49a9db8a569497c00caf1cbea99180770554ed4e3140dfca4555159ebf48ef5d2a50f394aebd782116ed6569a409
TST: 874
SK: 39bffe007f8df7ce4e56fd176b102b923ba48aeb8269fd0cd520c23a7b236e6c
PK: 9532636800010b3dd4012e341fcad6d29afad484e6fd736e89d5bc02ba0ac853
MSG: 7a8c20bf2eff69af8bad6bdfabc7909c58ce746cc4df78b69b33c105ba3bd8da75244758b5172d5c4501bc39970185ee3d437083a9959f81e7665b829a69a5d72e034d351adddceb3d3fff589988df182b46fa53d26e7c9eac062215788f2337bf90f0177d8ca744f95f28fea854593c4362c82e9ded19b904ff99d2bea82432822e52c3da6d462da754ff1f8bd109942df51dba25b7cde838d5f524239f1331f463194e10ff56795b296878feb1f55d43ec7daf0ca5ab3d684b55bb0aa4c720d4b5c2e830c858694d3d0fdbaad0bf67d873182d95b2412fce5e7b00fa6bfc38b132efb96f87bc6c10070a5716ec9b33a2692cdf5bc41c7f737e28c4220317a489b7323d5e20f65d375d769f9e79376fd02d85368671e7e081eb753f888545ebe5c000b2f80143eb358d43185e2f1c294b9f29c8bb91482d4387494aad176deb85540fd005c97d13e6663f09944eb43a46e6236794bf6e21f81d0a42090f9ccef90a6c4807b5ff541300e5934881a8d92196b4cee85d28092a828ea3bfc6b745ad219be9f5e9574117d079e02f4b748e2cc01a32826a3708231914d2772c764119fd99d53ab5b5a2e9d891a48a9aaaacc26338b18248db8ab2d525daf15ff53acbc3aa98d4f2d4a337bbaf6d1be21985a4af600e29bbb42c8d89e6b389c66f42270c3a0b051bdb623881e02f2f4294cec3476386747abae6c7700b8f9b0387cddfb73668fb57693d8474196b33abd12dce59a57cf72ee6cc1ddbaadfb19e90af8131b3a90f9867f4c7e15bdf9e218477016bd0ad3be8dd059671ff656cbd4ed898086de4d423f3dfb270bbf19d9f53f7f6f2d22c6ac9025cbadba442e31d9811e37e847dbd484d80cf743039ffa7048470fbdc6080f6d381dc7e3fa27122df53cc06394ea6fc446e1ba72538733ed3abb685f16dfd5ccf585ae8fbf9954b50f10b7e5432a22b369406a9b7088961f0ae207495ae7185396dccf292dc463f41f376a1ca89eefbae19269152031bfd815288e8b5baf348c4f8ff3dff4fd6d108f871daa352110fa64188b01b8526a845aaed133e456b4c83c4fd4bbb165b4090307e8eb17df176c322520f37599c2105aa8120758394a4222473476764cf0af7c55183eba9683d7270631443f3c51fb8ab0c130ac436ab603ff4f1d8656cdbed229a202b40008ea10b171542f74a70b7bbacc4016b7f636aa89633b7668058f13312f57c5162d18e399e
SIG: a27cca4b9f5b95ad0e44e4740c15deaeb93f22a9b254ebbd2329365a00966c9f4ec1e55c5894e7bfc23d398d3970b9465e98a8d23e72dae8e350da3531ae6908
TST: 875
SK: 3c4080cda0fc3c03b614d980f2ff831f5be0e7a981d5381a1618e0b8fd001776
PK: f1c3269d870402caa43882135d9dbadbbb162dfca0b3dad197e6b8a7ee679a70
MSG: 0ceebc0e8a47720f25835e2b9acf891bcca4bda38637f363274458baa9e2bbafedd0938f5688734e22ac50fb120f665f6c4c61c6531739b929ac83cd77f8963b754488b9b859c13853637cf025c14e8fdd118faa14cf3930ceb35f104d95441e56489440f62041ef1aa7c4b08b2807e32bb9584b9004d76e76533348506d64f112e1ff6f938f642230bf38af010e41987270248b13635a3567b355bba5b57448c6d13b74f3bebf617915821028fca5defa4ce5424ca191cd54a22944a3d940e4ee2e2ba5d504c85f959b514c4fab41ccb5743d9cb2f9bf33d1d8c2a5869e9f4660c3fb224b39141e3110c9ee8aeb871e14c62c6be38fb9a4568d736810bb9d2073178b6c7e87e3582efc62b53c23c5d46520ba33ffb3a9ca649ef26fe74a3cff6188427326b8c96f74354cb3ecaa611b12cded565e59fe1f8f400097e93ea85951b5b4e9009eea7db937e4349c4e5e00c4456c6c5f4e57411baf4e46e700ac400257765f48dab03e439f76c1499b5108047c830109dce7f740d1393787e29d3716d3c47e755cb828e7d440a971975197ebdb3f9b737ba11f7fd0386a959249017de7234d5e5a9b473bb9583a3742c774ee552a12a1f36eb3f26c885bed22e91c74cf32a8dd3edb08b674bf386ef427727912d57c5fafaa1cfeb740cd52b9dee995e3d0161cd9213f38fd681d538ab8bf97b745f54980030ef8b72696d4e27473fb0f1acd5d0aae0297211680ea0fc59d7b6d51c63292585a1d553d0c8954b42a4bd6fcd3a49575bf5c88953f1f4ea7fe0ed7a579d1697e645e2a61c69d1a56bc605bb04060a2778d509a8aadbf35d94697ccee9d3543dd01281a031f2a0eb3a9eb13ae56ff44fa0aed4f3488747d6af820f3989b7133f449ea56d3a7f731e791b7ed2a5db939bb75352de7daec5066fd57557165adffa631cd3f967c3c7cfc11cc1f14fa23defec3eb0239b45ed601a3a8078ccfc7f8380902a859ee9ce2db795efaca0a01dc0879d506ac97d10704d7757b3ccf3b37c339b42db23782278023e4c2e77d74246c9e544149a55c0c920ebf2986b4c5b4b3572f748c4b15c7f863999bc5132adad09761eb76505019769fb55422f603184e24c0d4f3761987b5c50feafcce53302a3a415e20f56a054803e553bacd242a5e1364aa3b2d7cb3bc1e1b86a47431cbd39695b67f554c4645b7236904094c11aa1b40326ba91b8bf4873e9a4de04e2bf4625972
SIG: c9d4a4728b8fdd240d9c498aa35de95a4bbd51785b73c8403fdf040dfaed9447efad0069b67c783d4b81d966bef6e3d9a808a0584b98ec2b18322c4c920eb00a
TST: 876
SK: 45438f91465d74a2825b0f66a35bd7c8d005865479b3dc10a9b56f297d31b926
PK: f092b5880330871e5aafdd3ceb3850ee7e0941a2a1dc89f4fb4771d75a22f6f2
MSG: 3071d4b720df1093659967cd4eefef2ef9678475f7dec58fecec1d928deaf802457a1934e60455f496cf4251820ed60a3d8133b624d33af26a262784b5a2fba73cca2aa5e519e1f539584780649864ba5fbc1f011dddac381f8d48d0d60ce8231701173c9d2a307a76302ebc69dcbc930d28431475b516f98f778ed2e1fff272909a272cc3fbb6b31c8041a37cb777e062e49649afad12c1b5f7fcb8065a99e7423362ad16906031265db7e8b89751f8a4a407f2502650fed753e42c8c911e50b94b3800695b0eba7dff06b7a710117e4920d4b1c605a3ebf32e06966716eda14b3042998a3c7a5e9f83542d7dde65e528bed6101deb331deb94cdd46044bef88c097bafd40d6921a7c484c8f96684dc371671d94eee7cbe5d587715314cff0d1877272d8190a90e18bfb321d52bf74705137b2abf9165731767a13adc9c85e0397b47aef96badb2ca7fcb8293b01fd1de316ee1e65f356b9d6e8ea1fdd837bd96081149ea2dcd73c4881f32b7deebc3715e2d7cdb643e0d98f4e846508b04b32439ff14b1164f46846df9afae44464cf550104cd3aab3817540470aaa2ab9559a68b7ff6b1b9c0ce9f5869cbdcdd617090942e353b4c77f09395896becddff1ab7f07586a514d81fb096361557566870f1691983485a80c3413da98b8d19c78e6379f943e5bd5a5697aa33c5e6bfcfb7b8df1e1574ee416fab3c8a7d088b3a057cf865321b74e6103526dd9ad15ca5ad3c0f69718e27081d4b34a7c6d1aab6b96c0a754b989b4940638c9ede3d17bd49f65bf783dc85f1c4b144876cdbdb2282a9564aa81b57092080d6448fb6580ecf09f82a755010d55d4a5e4f305e259dbe99508b479250d80ec17c8760a93e05a29571f6856073022c8706913c46a2efd2e9caae4ffa1b4222e3d70e979e81a71951d7cb830bcbcf901af244f64e4ad9f52fa3b62031e3516da50bc2bce78eb9d61bfedd9b3f57e89355f177db6162bf61da0e454c34288b967c3fb4c341b32d4d13a319869b8e36046f9e338b5f36a1fc1a7eda7d7b0d438e0a75d84bbe4d68c879ada80dde23f7155b532cccf7a63f1bedf84f82f440c9ec3cb0e45f32c92f76438f5b4b910441e6738af3f5d2050d579ee96b88f3b00810ab126ff3a8fefd971044324dd4eb3447dac5b77809cda8c71682549d7cf2dcee340edcf9494aca42901e2c11ed97790af48bcea29521ef0e3d03cdadecdc894dd0756
SIG: d9287b7fec017f2ea40a14a1f62dca78b02a3d6632df7c60ebd90fc5e492c5c62c43166bf85658fb30a08b57a5813121b80397571a312b6dd11b653920541602
TST: 877
SK: 72cfcef4c9d6a1986d190311840e55cbafacc8a6eb5ecc72934fda535bdcffb2
PK: a94464d8cc8f3e43393947649f91c2752327e40daca11a9970c5181eda37d606
MSG: 66a6cbe88a8ab9a33847797fc480b244e8a2b8ec79e80bc2637753deb36fa3014f843e22a47db0a31778385ec1f455672e0dff6ca21ca4cfd2b989471b7ffc307828138b0ad4e647c2d13cef724469054abd3740245aea4b789e244e95cf9ecfd08a0d13c7ced393332727a7f3d8fbdabd939de28caa41cc96c7081198e22653d94e024a61f5f3dc5aa37fa9adddc96cf169d35062a0a29ba45a539c87a68a3a0304361309d213e614ee8373dafba2a7d6ed7d2ad37704c0946e4d093e2d94d061364cc1231063729103a77ccb501891bbc3185457bbd2869eb63dc60f196f10a38b7b36cb3f643d35ddbf438a44bf0c8f570fad41bdde267f0ffcf1f2f927d626d1b0d980a0ce223f2f0054845afe41d39de5a457219f276c67e69be2d5c9e070131639561c26751fb06435e0e42e2508c5f49cd12b517c9833ff97f5e51e1dceafa9426d3dc52fd1379c64ccaabb26db1af6ded7153628842f0cbdbbbd6aa0cfa5407f409496c06532dbeac94dab9baba0b3c988fa03d36f911d80e49b370b6837037ff249e76d692cd17737e0d07965d33f17042bbcd1e990e040f71936f6fca2542ae33748367787c01bdea75c9a0e66150281c468fe5c73af9e5bec372d5020c3d37fa1035a67e224d095f066a51fe1f681c3073939272f6af7750ed8d18349178ab4a2eeb4e9ca82bb67296e9890f316c9d9495953d68436eb1c1a2fb6a1cca45a8e88a09bdd65a5558025618b36d7f3cb389d2e2ab1ed233228ec92a327978c0adceddb6c9632d3abd7971621713754758e21013a0c3d009b6e3193cc152c57ef73107bd4357d528be40873027bf1840f685536080f12c5ffa93ca629736780e015e86d1909f0d8f372010c9cb72c0989845fc88315e6b9370dc92d3683ef44d3f75fc96c4b0e89e13d682d1988b685713eada842be9d2bbe2a76bba15d38cbafb65c40c2159b0ceeb0d769b9be355540734ff37736c0f0facb95159309365b9646bc4b344fb19a5c1639a88e87317bfb3b5e7b5130fa7d5643ed4da06430c8a0c1858ccf2f9a6e3d62012253f0122dbab4a35475a6f65589b2b095992826e4f1b58fa050b8f95c4feba3fbaadd2c2244ad4abd410139adf4c153cb5e69337af176a7837eeaea99bdcd59385afded34ffba8063a35f4f558e4eeb48f1487b56b1f8d1f73067621cb548c808753e3526a2f2aabde126bea521cf673deafa792ca5bd2212795bd66b86
SIG: db7270acce78d7fb09080a327941bce7eb145b9e3661866a8683f9a1a3de97fb02b025db9ec76ff32560fe638827742ea2f4ebef6b7cce44f9aaee434fd7c108
TST: 878
SK: a6337e4d3b1a49b126316778c613516c03ac88c96d92ff5cc7e0c8527cce1a62
PK: f5eac4fe0ea1a5f236b49da33a24e2f3a83d4b260c54d3416c644e05c838bf51
MSG: e33430c38c4a40b3c66e20cf3b70e9fea8cc50761f2afe249ec059c07bc3b37e5b94f4a43e310099b19a85f59dff73a7e495c4df31f74780cdef7bd6e47c394c1891ea3052e3ccf5d84bae082d24ba7178ac65d229ad18a84940f6b4dbc596ee63c181b57b5b49698979c18632fa821ca61e35a0d0351fe13d69e06ddcc8d666dca24502177f344e2f440575d39ebfe5e7f10653b65bef291dc813a0434c975de164c1a76bf6fcef98f23181c009b91830b618e4874847d2e21bbdb93f20cd8b1f4baadf99428a22674386a668152b4b9039ff06abcfe334a062f794056172ecbc0794df98271b9acfe4b7da553a87634237630009a05b257c184cbe23d9cd5a038658010f574899f3b2d154d185ee67230913650c3a05b54a2edc243a4287398e376928ea9c6b2cbaf371252540e2b8043fcf556813196ae572c27cfb5a46abb9729af2dcfc29e033dd11f33e86cc6ac3bce6f3f9577d36781a69ed7eaf8c8263a0f18eba0fe8a481f3e15a55599434195f7cb057dd364eaa07dd0dfd266b807f53a2070fd791e872422fd907134f4a8a78a876bdcb031ac860dfe0bb57e105db8287b31a604eb71269be5ba229985ceabc2bdf165ac741650b1f013a66c9bd243d03a8b1c5081381cb92e23f9057771fc07ca32dff1db94f5adfd2f4ff9af31d250dd4f86b22592f60a74575156213f10846c746a920fe39851b32fe4c8b8758765bc5b8b9d5b99263df36f97888053fd10f1d68f577aed559bcfde744bc6511076cafd68944a0ed10552d11344bc7e4d9ef936dacced527433132959b1c7324ad1c4cbc3a1a736b1f02aae8e0611ae23fdd474f5b8ee7056fcb5af6133ecc084bb9f1f50cbdac66244437b4348f4edfe237fc3c3829ab94eb4f14cab1ccd6caee36fadc20a310cf0690622cdca848aed03ff403a6633f4f657994b780dd6048149c3bfbc17889e37d90b1e5420eb3d4596b91ba11bc0229c65d05b93cd7e0454d1f3c6e1e8071983792c4d4368d0778aef4e123335fd2962c657bd0513571a5fce211de62874f27ca10dc15ba2d445f1cf4be5f833cf0b564c022576b98c0a24349b67085f92202675d7dac48b95e3bfd6555a9ecb7c72f08bfec0d220222492fdc9636f036ec4508a365b7b70979f9eb4a7263a8bacb1c1d0155738646cdd46ab9234a170311500d0bae6e55a863bdaa56f51645ad85297a7381f8d20cf96c474d1bb81fce132b14555d1a
SIG: 781376c9512fa33c457047a1f4f0da3176e60ee47782869b7e9fa5841d964f3c1ad66b70c114b1771c324c83ff6cd997aefccdc59c114db9f2f3ca7d84a7b60f
TST: 879
SK: 107da98d0ee8e7c00f6d41ec265944ce67ef8c8ffb51f4f11f4e5f1a27fbe805
PK: 3bec34b161b1bcff009f8cfc50d84ceb6a2d5b203b5238a8aad8a83618b442e7
MSG: 1a7b7f3e1c7c41492a7ce799efdb2d9dc2f2489c84ae28bb7d084f32eca8fbb066885ac6f2ef7449e71226a82e9f153772a993eb6b6bca6491d26aca5dee98b77a1ddc59922b3145c447de737fafacba5a75f2a80137b5594697220d19617674a69113fdf77c343af2b7e3861b5b7822f58d60089c3ca54c749d27f88379c067598f063939ba8631d1f52dc9ab455045fb360cc2a5b6b0127facfcf5b1b4c33e3f194fc924b854168cb1169ab10997b438b71c80878347be887af44810134b514c806908201a3d3e6d0c56120c4314874dc2944d8444f01bafa34aa62ecef0981545e5d02f4016c0b164fc05ae18f535c31bf20b86f31f7a794aba148984c3ff433dc222c443b5d26c1f66e6c5f19d19cd6eadd4dc94101b2f52b58c9d4590cb10dbc5d6eacd11d42ed09f15bde44ee9271def292f731bf3b4ac6cd127e4884c2cb30b285fc9247638a299e416520624d1ec8d0df2498939c719a9e7bd29a3c5c32a3e8241368d6e4f90fea29dc3a3f147ea9f76c5780e73143f55d3dec7b66341d3f3eac1d98f8e7d4e877509b4438c3a52466d242a10b4c27c4a0db9232dad011414ebfbd57906f1a410207b526b0d1f1b6986b3ebd7550a2b3c15fc2409c7626e0dd330ef6722e3ba48b1d9205652ac194c21473ce258559db511efad3e5d55f2a796d65a6ab97d8631062a593a13aaa095dbc93e6217ced619cb16a57e744355a16b15e77d4979119299bb043e48fa3e615460e164882984a223d418ca95340c5bfcda673fcd13b29f2c47d2f97e3e8c613b6c58df0e62cf23061d6f545b755033fd3dc1405e5fef35a13e015f98b1cc42f71b99681f9681258229a4473d86eabb0c17927941e50c08f34a76b43bcc6d042e5632ef9ccc91b6e6950f5d30f670fb3902c3d409315a40b0821ce8a99a97feca5478bfd782e78767b311f374163f5896b0beb95838e645878c64990385123b61575dd842dc76354bac9c6d5acd9935b609bcccb8463d39225da1afb8911d36e609892dd1723852ab9f82758f3f1e4d28dcf02cb06eed26844aae6882ed44bce44abcd1dfba633418c9f155879c97ab27f8ae238330392be5491a078662daaa02a3d5458b77c549c49be201245e7aaec0d94e5437beca6e5ab046d694e96bf51e04fb44379b2b9b801675fe1477f3e089874a601171d8b68f0202014601a53f812f53e581c3b96312b36b9ee04fff11d9eab4e45148dcc8f0fab1
SIG: 53252b923ad19cc39784d3a9ae59d62a6300dcc50ac8fd0713cb58844501d8d3805afa0fda64c73ea0f60e6a8b3445bfffe6ca6bfdc87e128baf99bf6268fc09
TST: 880
SK: 8bc229fc234653b13c924710cb468b8fa9b280e2adb49cb4b36bf59d6fa4a639
PK: 46146975df6704cbf45320a5e6cb6de813469f3131e61d447bbca1a477a0c557
MSG: bae2dc7f94ab5ccdcaa8cf49edbef0f6d7aeb1fa8907800533af4492611194e56cef37b1f033303738ae2c3bc4588f5cb3d55f345b9a407e787742a06af0b6ee20dee3dfe9c91d762a3ebd19aed07907bbb91cd776326540ded9f7ff7dda76615f978e9490f406ed2d9116e2093fa785e971b5062d31cb40fff9e3c551a73b20245d46df4d7fd1303a28180172d9a2bf5593c47917b58690917c1fb0e1e2994d1fa97735ae378de6eafd5c1a25abafa3cfd2df7aeabd6e68fc44edf82fc83694e5d841a15b14568b6110be644bf22b71fc47d7f07e1666957d0f87da17f13fcd63c1c2966f687d25dcbd9963f01eff132d5f2b86677816588c123e9457befcced2d3cd1d1bebe8dd8fbb1587e553cbcc4c8762064cd32ef7a1702410f77f15240d7e2bb582c678c0da88ef4522830b143660ac9c434d95772e6eeeed6014ae16824ccdc4df2df64aeb6980b51d118985dcbbd1961f315e6a9433f0b96b1e6351257ead83e05b4cc89c924bf83558ba7d2e7ca37c03179a8f85b831e7217bf4c553838761d32602853b81593b0ebf8e4b9ffaf0ec405b2a83af7de5554daad28b582ee08bd84b375550cae08ae4a5bda71581fc3b7b54498c4e1afb966b4af1d9c843a6b25b34e04cfd9bd2374244f1fe20ec62be3ccfab4edef79ed64e6b71aa9228127c6359ea1c4a8087890896ffa46e0092dec7efbc960a17b770916f954070132e26d98d9774a2acdf809d586df0252f67cfe8d985a3e248db0f90731ace7abd999c746b69648d5c3b4bd61137e08fcc8b2efc5676bcd856a13b362151474c4a1efdedc592cf3ead1ababcd48ee204d27726ad1bda4fe4b09ab51089d016de6ba259ea81807faf211c87e4c9efbf6a4c753e08f780ed55338c0fde14fb99b30722b5594b3abe02047f466242421fb81176c9c4f0fd2b5e7c5a0f65a0c59aa8c3a986087de7ba40baca77bd36ac21ce34e9fe97facc4e298330eece1c8ec623e66a4b0f2342d2c5a02c5f5abddc5ff1f1f2d03c1d4ee9b4b342ed3b1cc26561f3217bf8500e08f027571c53c9232605a53f2bda024e39929163a8e00791ac0656bb0783825e7105ffa9d90969dc094af46f702e85cc11e442b3d5534c1d3275207d6d29a942c358ed5fa07557c3c014cf541f9aaeea6025b41ecdd848512ba25e721e43d329185f8f94892e9e2d5e7cbb99e7ad25f69e5bef732cfceb078611553cc78377375e74e66f1b9d8d20
SIG: d243b87d1397d594139d83c39acf8501d073bd4be718b4c206980729e720a4c5b0ea91a28ea12604a987e69591c543049f2973bb91c170213c32a64a0fac8204
TST: 881
SK: 3edb50ff074ef9717f4fb0b6ce252bf4bd049c9083775f529eaf51e975cb3245
PK: 4bc21fe03e679abbfcd8c5ea2bcc4d838a787d4840c3bc39de4b04c417c768a5
MSG: 975ece4e81f0015f5ac3044609d0ac3a8df9145b50c42889dd312f563cf6126e36fffaf21eb6b84fbda15aa85c66145f7541e5b41a8e81700be356224fc109327a6919665673534f5c8a4a001750b199dbfd630691af552d4d26a9d9afb33a16af391154124b53426c9f695057b1814fd6d310298af6c830686a4a007a14e0057b72fbad5b803ad353d1c3fdb890a9c81808e89f229187bcb44fee16a4ebcad5eba459b028272a562c05079fa7ae3ecae804a9e8c4f3f315813c5ee0841bbccfe4a95623b517a4b42b2c6d97a3bf26acdbe2e979633f02aac466526a3ebb14da19bc95f2c3fdf6bdb08be8bde97a864c907e918c679ab726f80177145840216b9dc3f981ef17874f08b2fc6611a6346c3da6a55ecfa753c9919f4f19e3c79093bfd78f861598e4666e1cab688e4604d46c9c582eadb92c988f478d160f5a15182b3340201797d0b955282e4a217b50b14b10c9f49067ea3e84e5274dcaec74474c5707c28bba0db8cde3e838d7313c171b85ff2b9a3d2b167e9061f84df3b13bdd08b2d501e53792d68054d048abfe3bce98d978256f2fd2c6c4e76f39688cccf0fe149af9d347e7b040ef241dd5a53eaa5eab35a18c68c754a06b03399bbe56a25268c829a5ba82b28192041d3bd244eb08bf78e76def87cd09f32beac9bb639823b36967a574d8960d1bd03435679d93eddc558063c540b9c2f609fed2e2e3576d19e6209eab466c206791c3aa199623fbae7d3497e80fdd3fcbaf5b89110ed72244234be85cca4b27a09bb70a26ece4eb8dd970a26e5b04361fa50e90380ed65f414c1be9f5064f71429116267edd6976422ad92deb2b804a92e81c9f6522a0f3b5d8ad36b4f87db516a22873e6f27284f2ca360a2f40ff3d8e23dec8ef8a17a43acbb61271a727cb8690d29bb82016736b31026201dd3d388d2c643a73cfbd0a94e20551fb5f8e1ffc39741272aa2308dc8d2133a3fa9cf109796d69d2cc8addc44ae2527781ee993af2a637a872f02aff474a7073f29d9c89507701fecbbfd5101353537eba17c29669dac0427e38e22dfaac91fc20d9e3fee791f462a863bb1908fb1e4204b68880314ddacaaa35a17af5f57a399f1931e78f5a37454fd38c57a68e8d367848a97345189c70077fd1aa0754e703e352618063b9e3faf3b14b5f0b27113633c5d17363741e96a67e816401e8098c17bffe9c6f3587646f40e9fdb6819fd22a743a7a6e10feba11
SIG: deb3d9fc7b2d86ab4b926f99527970abb51838bcc2919e94cda3371fd0e7693fe37e0c40e1233b09ffa903a034dde287c0237dc594f53abc87844869dce92002
TST: 882
SK: cda4ba93940aa0c0c3150b3929b95ee7769ce43fd98ecaff9c4a509e736d5c8e
PK: f4c7a25f1a743daf41417e47e027537f24f481bd1a75e6b1d33ec4c82c55a2d3
MSG: 3a1d668c6688414896a7697f3c2e431098edfc457e04d2da869568ad5b3310e59e4c727c903cbf1817408802319a8c231b58023dfae494c013af0fdb78c91d5b457f8c47a3dc31d8c8594aa08f146203fa2c28b3dd796a11a97adede6a7a709b5a1918ef1bea83533c783473703356f5beea7fd18ac44ec6890495ed170d03f15b418608a7d9efd52fa10918638051c448d98d5724f567c8c67fd5b6ec8c3d636008b9bae5e8b1e984f8ffb8b64beebd6345a105c1c1083132fd4508d6ac0d4e9145501210e517d9b22478e215b602599f803762dcd5a409b3460e7f340f47ef77281ad2383de08c5b809538aaec922bfca0d6752f147972646d0a8d8340772c871d3b34abc06037de3ab4e37129865d5ba70b6f3cc9a059efb7dddc3882f4fcfe13f448c9bc664888589603ba98683a93b4b3b1014992a55c8e4ea1baf9cc00d1badff5fd7f5da5e307fbd1b4c984e0fa0edec5d30bfef5f477301263b5d752001b85dd52df3b4a7ac23b930a91c0a45765a66488d8eb5901857060067b82378188549288ddc61831e5b6841b344cae2250042219cfb4ace023e691f9e48d006e9a07c67d2468f93593b4afc161c0768b6ceb744c24c923da34af3d5ed577cc7f85d491560f4c0bcbcd1d5e3421bd1ccfafb373d651bd61ed71c09e99f612001704d0c630d8547bd970b66e7f5ce7a014e0ff5a337dc5c56a99f131b9129140eeea39397c48caa9a8086f9fd99150be7ef87b6d4b94b1bd52878bf3bbfcceacc2cc45e8971c3a4d4a3eb86af9874d4fa5e7caa7f45d1553ffbb41645bf0f5e9b29772e3dc081b25b52e1cb7e2167483d54fba690ddb29d5462d2a27a35d85f007adede2a3dd7281f654336afafb7370782b29cad643d9d9db2f05f281b53e133ec30eec09fb0d061b74581a2bd2790b137391f19328880f64c53be700d0faddb70dc165d2d62e671eb9449a2e6e9df2c16d8f49fa4b5b84309f7335133dbe872c5a8fdcfbc4980abfb3c9597d5d667ad2f688c7ab24c9e440298d72b28b0fcde9c6f071bccc93e8ddbba7b60a0b544a2e06c39c6723d4f7dc185c21135fd13a72770b976119e49a1f81ed476be07c443de0b0ee76fbd919389328b3eb8607bc2fe38f85745e28adb7482b701ccc6690e4ae5a9332ea44613179387dc6fc47c1d1ec366035e991e1404323bdbbf535f1c33cf57b6723f13ca6ca329e2aaa4b46b42607339906c7ef49b32db82cdf6a87ad
SIG: 31048d334af05a4f275ff827544ea296a4a775fa59efa000c57613fa6e5c493c3a9b79e8ce56e7225b0fa326204f0336c213535ae589177a8eaedb6df8b20203
TST: 883
SK: 217ecd6a7fcc98719210c34cc2e14f5e2d6b5a22f268c14bc4d8a7f2817200c3
PK: d59191ce282d72fe3ac45878e24bb2f28c409ba05d76ce9bcf22f50b0c778675
MSG: 9b5337e78fb382f22ea60e03c0bf3ee4700b6978a91ee6acdf6a409e4918d1684881fa1d118c08c9f6f2ca0cab567402c95010e7abdfe848ae79ba249adcb96eae1dfa0843952139cf49b588647895691a2e9880466b7e77e54f6f60815ebfd5e5748f413c0e15f9d576799bcf31284710636f6e9dc7878500796eed80c8af4be2961952ea80bbed1404bd5dae9e6d05fd4f325a3b83cd4528a0869cef84b4d30e02f941d749a8dac97bb3fa839d25739b97ec374536bdea500484a941db9f2299970658d41148295ca0846ca2366238b6201a48b3e447edbea7a4c8f71020142769e15fa72ae5f287140bc5953b8a9a242d205fc019091f2abed0fda47f52d59a0204ce7401c1829b5857b9a0916fcebe2eef991c413acd71b18d8590d6b6d0fb3994302678c29f2b6a53023f9187e46c36790bce73873c545a72beb553294b1ee5d0d0dff239e28ec63b01e4d8fe0d6e69b1601efa2411f0c0601e7e4f65c984f829f0dc2a8421e7f66d9330537151c7243ca524d7a54735c6e344f1fc938eaeea2779c940891d6d01aa55f40cc1adba12e8a67ad9a27fe63fb4f38dc0f01841925718427255bd665d5eb3bc869896db8625204ad4b02f5a22aaeead6e300471fea61dbb1b55c071365c58b1511f38b09a4671bd66b3fedda9c87e43d1ebf301764e18fc0cf16b2d2d67ed239b393ac71968a903c02477fb2df9ef01dbfc3167de7265f891e4fd24d02c63103519b86a7085b1ec2fb419db766bee7a641a4be429614ab89f20f975341072bf04419fb69be7a9ee71a5b49af83ed322bac68a429ff5c5206773be5438b65e53f609729f4f6a21c1333911264d63927017e8136b4725cd1cc964e08ca0933a561e7e3f5987768330e2e54f8d728f59edfe2c91c4f99aef97d18559195a3d8eb315dff96fe276da7137eff93057ac731e06a60a58bd8a9ae8c7cbaff0cb3372c68daa175c428d52f1073a38bf29465d2a7128bb40074006edcb725a831d812864ef43f3b8667c9fb71093a1673049dec05e09169d86fee92df286008ad99065a2929797a913d0233f4d1a95a220bd91c11dd9c45685dcad385780a0c48b9c4ad2d66303e8de4af1db3c04e4a3dd4219fe773f83a8924b0fcbfffcf264abce32832924036bfabba6546b1df4e3f788ed8ad5c2cd92b2641b47090a103cf5bdc46d8b2143174757da801c360a7aa107fac654b34c860bd54f76bbf43c48478df4fe7aa59cf91d
SIG: a0b169e8e9ce557555e0334a0de7438e553675489ea4ba9cc63a234d00ded8ab6967a3be90ef69e076db9ea3d5ca23b3248dd25991ee1f4d80620bf4db438f0e
TST: 884
SK: 08d1d06f3ec29eb52293907b705ec56c5ab354fb78673773ae61253094b89e82
PK: c1b99a87ad15bd46f6c848452af0fa3ccccb5cdf6e348d816e36c5d0fca66e66
MSG: 120b35573c34914b373051880da27ed241377f0e78972c98d0faebaa767eb7a7c7e7c6fc3405a4336ef95bc5da9225bbd09e9e11f2a1bf142af4e8a0f924d323dd5a49dfe584f090439c08e51511344d470c6200ac7e7ca150d088a91e47c4c9ff74e38a42a332155d8152ae4abd1161adca934c234ce460af8789e53f109d7d31eede0a909bd193fc8d3c2cfec10b143c31476711bbec27e196a54985bc347167acd233508827bad36e548c880642b86a28c6d3404b511da24f11dfaf6a8f46ddcbc9de9e391597669bddfca6560f91acd3459f329bb071dd80dadf35f0e50df5b10f88d267ac9d3062330dd99a6bcfa13187f45c0c214dcde2cdf9c3ba4d59e633a354a4e277c677bbdfa24191179cbcaf05a10d4078d8add93bc9ed8f6c6c499757403655341f904e37d927750c699c269dc90dc26d005625c3f4124bff66feca59d4abff4172ba3df45a874302231030fa783384f50999e3c4baa5eadb451452c888b519272e90f73c6872768e0de20ee2e5f9502f35e49fecc28b75201887fed2818eff545398392f5e5b6876bc556ac13a1903ada1b9d725b04a14204b599ec33d62b7dcaeea8c52877b2cfdc3558a91d2c9157500a3bb6d452e5e2ff093294fc433cbd63465bb191307ed801a15b85dc2ff0bb38312f8b817a436d422cf4607c64ee7035923db6b96a3899910149b0da4aa3e96685d7163aacf9e619dc60813ce4f344f3079b43f187fa31bdacb9a1d7720b939d5bd241b96a177d7b7768ffebf79044cd2956d6f88db1c243a10fede6814852cf404b2cdcfa774076dc125c70a57c6907e99afe39622ae11f557e7d34b39aaaf45f834058d2fe5f15b5eb70ac15a90a3de5850ab1dcb48b06b6ccaa4b42f857e71ec00b8a3d8974b0bea68fa0f665592115b4fa55572cf0b0738641fc868d4a2e714db3ad7219a823d54b7f7c2656ba5c5eebe3594c7db12298c16251d9845bf2f7800b4190b746e21b0c1a5c47a3df9a059ce0956674eb703decb0a0045437da4da10f286d720d1b9df05fb24415d68e065570e6b31503142d03335a807bdca30892edb5f55f8989d9e649659c0744c5433bfb4deeb11c2626a8650e54d4d398ba19b64f68bed06d7fc408f470ac704e2ac922ac1411fee24543e56f2f50b6b08953dc56a7a75edae430a6df28a227adac91ba26f0e198595327739cba303e9aa393ea6618a84f8f503d0056ee8d87e3796e036cc51ccb791deb795
SIG: 0b8edcb8b15a8cd074c41dc2a1ba29d9648d6acbdc338314707eca6fb4714c99543b4907b9f85e57eecffe0f7a6b7073a80946f8087553f4683109273a604a08
TST: 885
SK: f0c85c76b1532e89aea975156dddb1d3d066f6409f841bb4410922725f269d86
PK: fd75fc75c36f83498d8f0827f01d3b457f8bc4d9dc55e4a46274ddf0034fe16f
MSG: ae2eb018d48dbd4f210b16778b5bd2fd14c94e6bbf2b3ff85518e560ab8d3e72201f433420f00f11bc78e0e9f3720875b2e9dc11e04325b8b3f0d465ddab21511c457d6acad8f2fd5fdc0d2823fe6caa66a191a3b6326b32a16befd64d15b361a41513641bceba26bfe93bdf854a4f8f8a0b29f7e28262e2d6e98aa24ac27f6f7883ac01a74c40cce947ebac70e9fef2a16e6289e468950e391e9e24ef58e88a44377269cebafed8987d220dcae2d8b126b6bf812167d023d9baac950d9db8cf52de6306bd48999610c0a433fa9e1771cb832d4197aa340dd0ccd0744fc6b62f90bd3ebb5308cab5f940e2916423cf0f3bf080c06a94f026910460dda809374e6457f064f178e308e7a1b5af4def319007d041778c3d6a419f51badf87663879302b53ff269df442d0e05c958d5baacceed7f5f8afc811c18900ee3b0f61e5dccfd5dac85332d32ebba371aa2d47a606f59546e4bbb605a74677b19a0fe8e95f9f77c0b8b71d07e983004dc2ab2cb3793a323c108dfa7970da00db198674bd34bf7310767f76a224e07bdbc62b9d078cbc75367e2ebaa2c5d274bf3427f2a0cc5dbef0af4e63ad889e131b12bc8ca32d827f7260b0449d0443fa288440efd1364e3c9849477e73ee0ba4240d492af5ce13c34561b45010c109d842c1fed1be3fa9e184aaa14064f43f6dea0b659c5b97893cf2a433bcfb1d2a87eb564bd9092c2666704731f83e56434b2a4299650c7060f9ff7e8aadcb4593f609188d8b467646cfe95270067a1d35cd759fe581af4e62602c02ef14744143eb424f2d9f33a60288c1b25f08e4b2f5feae06cbcc2b2052bf384e1a6fcd8471ce5e5658d77f40c35c415e2a9e09fb583bb7471258e7c806f3c21822dd10f56a640cdc00128d3ba556ba51dcaab47c3baf9f0197d3663de8d093e83173325def1e83a2f5f5acf12ae09f3ce96cd888034dcbe6147dc5998362a4bc406d28846ab1503c17c94f9afd903c9a58e1cebb4abb4ff6f2a41024e06dcaad14f5b70c1b26e69f96ecf14b8da31c621f9ad4e30aeb982378671f7d1f2c4b572c41bb8830840ac5ddced881f8fff210c3c7f236d8c5f2cfdacda29893302fde15282db540cb543737dd77852569221fddcdd68d87e2402179d3a5a77734c275a1d560a462f40318bb6819837da3d305eb49b38650efdc8fe409d40fb94cd5dc3eb02738f38852f671a0c41414b76fb436f3417b8ef300921c009ebbd7cf8e11
SIG: 4218fe4c1dce795ca92a49a6f4798eb5412dc825860314ec469fed45de3a7bf8ea55e853a349584bd95a826a585a503fd50bfe4c635ef183d07301367e90100a
TST: 886
SK: 18e268b15a2501dd4c979dc103ca6a842216132b3b5081d775f88640f89c8041
PK: b34e19c1e208fb48a885079d9fbf37c74f92710960f832154fab18570cfb4c1d
MSG: 424bdcf0b256001439d16958fff648cf7a8604af22cfa5b44331b4dc356dff25cc0563da9d640133acb70b6a1176c482dbc9408cd6793d56bc29cc408823d388ed88b24ceb6621dbac0023ee69f76f8296a7395211685b3ceaa995f0355d9aad3d97358f4a379e5920ec545f469621cf768abf55d2a554c949b0ed70187c2205ad032985c9b5b2e4ba57e0b4a47d344512b84bfe9f3aa560fe6ecfc5bdf8c3b41845293573f81ed3b70edc63a30c70cda3f455901313f6d23db309478f03e34e71356d83fa5db9280cc2b4369c3d24dd9038f247596c391e48b2f3f890a141ca1d12077c69344735a59b1dd4076b22e16189991e5f1be4fb7695af90ebea5df286135cec2a6e99aa1dda328e62c0dfb63742202d63624dcc0c5cf1a5df79e2878dbc71fa96576601af22844f545733126af7d3984c3ed252e6a876445c92259fbb470a10569b49e5791fd0182cfe1c3f88297facc8c31a5332f1f4eb4958db13b6c079aa9c949487263403190c83c11a43191ffec6023fb34cfab2525beb546cf9200a96f5854b2f78ecb2d9a53aa9d287a90d4d410a63ada0e975d304d5148353463fa805b4805fb4687ed8857dfce4bc6e80833c8f9a79cd4f029a2d802bfdc819ed0c0ac8f21023287f2b4bafbcc89993fe46d52a9c6246dead617df797d48ee985f0f0df9aa82ea20e0d0db28a254a9a253f39f9cf01e3db8f3ebcf7cb97cec58c4efe031269b4b37e4cbb361f73ab4b4980bd900849538844c52cb3ac7583b8f89653a0de65a8be91582c55239cb8f5d5318a88d160e1c871e5ea7e75f5a69cba8538221ab42ce2a2c4d9c3b7ec857f230d573731133686ae8a7ed640f42f31029489e4e6af2b3ea4c7948ed537c0c5906726c2b625fd5f949e3a7cf3b6e998ec761dd6e2b5171a68749752e721b788c3477fa190cd6ea81d579dce6462d9c662ad8962e79338710cc8d2738a5fb04adfdb3f1432cfd80e2e967da000d83a0fa85abae2952f3f3683e254d868f4bf809eb2e300e7b209734a3c894e966b16088d5ed354bffbffbbf2ec2be93a32a8be5cfa18fa5653012edae5afd8709ca55c0cf23a550d34ca0f32d8f666fb47a12f2b7353a40c5379f75366c13f4ab9f14cf80a94e1f13d8b09b76fd8d14ffa538f31fd8aeb49d33433f4df7c2ca67399579fe99078aa721d6b6fc0c50e8a91fc71ca25eac1376fc671bf6153e720b25c7e97a3d4ef8442ac67acf58b504b67158f913025
SIG: f2dcfc06ef1d8eccd8e40bdf01307dd19683f214d4f084e6b6934f637278300dbb1889f2d37f53b3aef26fbb3e36bd75985fa7c8ea6ddffa72c8e406f24bb20e
TST: 887
SK: 3c393f9df1fb0b1eec09b7f270b85982ba0fd5e4b1795e1a7fa99137fee24d7d
PK: 974fe23730fc17945670fbc1f80b93f94593c8d44bc75d189a6bbfaabaf5dbd9
MSG: 54d8b8d5fac28cffa77a0916d6333c16edbc8bb74aa06e56dc00e47e3929e40864b8840d912079597eacd81dae43e2785dfc689f3e85f8c66581efc5e853d1faaac744400ab08cbdb5d16146fa60f99905ed84fd2936dd73f4bca2572b7cf5160560ffaa68da7a67e40e08a7bb7aefc4043ebed5fe80a414817edf2c63f62fac0d47446ed0bb584058f4872fecff621559311a270aea37a6296864e8d168bf1e2f55cd3b276edfa612b5d9c3362e618be6e82a6e5f82667924f3d1d3df825f9d23f4d6142d3100dfc70f70603abf3fdadaca69ef6a18ef9092b3c41ec658ab27216fc6147a080acda60a841984ee83f41ac42a80eaac91fffc8228391ef583ab3eddcf876523c20281355300d86c11a4e7c1ade8e50560f43906c9bc8ca5fbf8339fbebd02e33e8518bee5e806b8c10f8277f410664735a2bf556839635492452e6ca079deb9751cfc6797f49bca9613ff2e7fdd3646f7c5236a36bdf0051745e595dc0072fd6651d57627a6004c0f0cfae856bbc28a1231cb839665ff04152ec31c007b3e2ed0a973b24c93149ce701e6fd6539206ae91bec4ce65a89db26c7d38cecb8919f96fb6cb8f6c1939d90fb3f90b887789f29575ab20e0b08bc358153d8c03521dc891870b5f7eedcc1e62bee7da063ae66ff0a4b7d98d1cb758f69743c3db3ae2a2c9be1be094f17cd28f92d8ccbca983c749c75c610f840836e2c430ccdeff0afa54444f12b4a4f002c609451834244c0c07df8e12202a65f94447cd4903acb606d7725a86e4a2343984e679c4af1b3679c755ea50d0abe2fcc0c1c3351a9ee196b4644c424222be99e2fb373f9641e3faebff43170eb03fb8ec4557d151a55fab6c499d444c84be89f2447682de4e6f6353475efcb8fc53256763a948dc75c515fa353545d0cbad29df5e9db5cc457ed3086cffb3d75e846c4e8d88147fcd0d8aa5abab49b5e05c3d7feef637943347ad3f492ee356ef34881cfd85abce8a144ce7761e284e8b8cb08966049047a996e23559f776b1a9f41cba3954108486e2927beb6433a36ff8b2f03aa74b3d209c488e077f924f231e28345942c7dcc2e61d7c9b522b659fcb53662aff3648f66da3e83e59b0daa90b94c515dadab10d5a839cb3a2f1d3cd092de55d995138c3ac0b907af15ac63ec1874114327e21971345ef17031d52617e784da3771439be2e84148bcfea132bde10e6fda547dcbb1c4d8f74ddce1fccf8213e0da6e97b81f75
SIG: 22333e56410fdcbf84f6a8de741337691684495ba69eff596db9c03a281210881e6c91efa91b2183c0eac916152817a78ca724ba7c8b51bb4caadea9a341eb0e
TST: 888
SK: f8669c88f1685bbf0480cc9221ac2ead8f551bfa87ecba2fd4ddf3ba3476ebda
PK: 34723fb8e253ad9c71cefde03628d204e535de479e1048e5188762a1f337fe5f
MSG: 5b4941beec2241c9fb76d8484f4f3f3ab4ffe8ecc8e7aec76de2ab8c368584d751b0d3feb8a1dc8168cdc694968f66b2a0b052afbf8be3a7d95163e9da9141c59ca55976c292c5c74d31318d6a91e7817c5a8b2f812118cbeba3a13323cd9748bf86ed1a85dd4ebc0df495cfa3d4627434bf14aae8ab6781467a56d965d10e6371989dfa0f6bc0f7859f3771eb9004b34367db2705dbd60fa8f7895c1eadf59f53dab168b4f9363979025501ddd9680debc07cd1ca4a0997876e9211f307d9b7b9d904e48d2861a778b879ad590a9a2f141bd568e3a1bb2494628e9ec0c64255aeea6f0eedca30ad38a1f3ffec3b2b5e942e21940104e914d11a44c00fdd47da3e5513aa8530aee247c95ca66d08a2608c75ba9858da14f9a8a32be713d309e0f584c81ef5be040e0065f07b775ae175dfe2c8b90a88ccda17fa4f21c77eadf5d25b6e404bf004479e05a01ac0042b89937eb278c1c34f33028db780ba3b617918595a39c0fcad674b85c40cac8d345b7ca0bb48a28e66c44d8bb5f27941e40b0e9c7097976c62dfef50c98f17566ccbacc87cb03b94dfdfaf32f1e56ffa639d63611e213cebf54cd0a3e2172d811c0ebd75b1a8646264dd8b1abd46e548972a1b262cd95d511536dddcb49729fe7bd00b3838bd2f20a142640edb1b6e765b65da72e7233261c8892e2f4949bb51f32a1a5a3ee149bea26fdcedb991d2cd126637e2971e9b6f0b785df28a48f301707349423f44e8462289d725498230489df1b51be30f08d7e3250565c6ef824bc53a1ba74a57a25c0686adcb6c825ab1ca70c8a5d46dbbc6fa607461e26d16fe93bb3d3a943a3dc05f30ea6dc8bb12d70821d320f1adf1ceba4be657194f7fccd21990f8629d744601cf52ea6d9405aaa2878f1eec4003b45a4218d8f80bb0f5af047326487752e2b76d68872520bbeae7b309d78282a073fe0b1a1a7a98da23df68caf8c2699b1c7d0f47bd7de2c0bb23369963e68a6974c8e2b595b8293a9f4d98df7e9ae3add2a3f64e83039739642d192204e85e6c48d5d671f6c75a0a8957edbb74187620f2aba99c1c62584c59ac00647e3fb40292b9dc1a3346868553392fd3f11d6dc6f5f2f4e85ee25125cdd644743c7d45281edac6384c77cb98a67d9ae6fc9a0a76b9f6fa696fdf4aceab5f794ee521b1e5a0ee57af53bdf176801b4f45cfb3cae3287234234b77ce21edf8680d68c4a8eecf1b03537ea5699acb562777e42a486fe7cd
SIG: 3746da6cd8ca108beef06487bee63584f812c8e0695fc863b86e5db132380b62ff8544f6f374825b0e3ea0620ef854c1331114d667df1f9ea776c3963870290d
TST: 889
SK: ceccc68311fc45b6c2a2f1ff9cdde007ec787fdf25d02ccd2a1cad9de3fb4cff
PK: 6f804734ef92824180da71e55cf3bf1afef65bcf560962e0b0acbb2d8cca5984
MSG: bac186d9fe5abda79c3a35a7a3c2eae6ae6ab28247912770c84efd048ebd3aba57c37cf4c6c7f30a79f68a3f76b20cd8c6631fcc96670522080e6b62e887ae6f4436d4caf56943131c52dd282b251cd075f1f7f8e0bdb6bedfc9a0796f5579042b56e69374961b11dfd61b12de2bb7d49bfc509cdb3138f3356a0dded98f5301b7c4a748bf89b23df4f7472ff8b1f505d765c6ff82dbad74b9d7aef22fbcca0b7f35042f9a762bd06902bb21c7f9f7f66bef38901d75012d61d744dee7afd89fc7e908c40685bd440aeda4204d006f26307d82a496963115f90e09f76688291f4a67d6411f76d16617875b2b9982dfdc5ee9b83b9817009319110b5404c63116fb6e9464846fa009555632f076984c15e1f6081733a0d46f2d6a3cebf79ed9020c9dec8df158a3341f39eaa5fcf1cf42a94849b2352c1a1ecd4fb814c20d07dfda312bd4f2f58c1576b4aa315c96c8786a4cfbb736b2d23c38b1d81c4644ea36afa076e055be5917cd7a92350a7ed66a5ab2253f55c4fd1a0d0e6d4edab5f712edb440c06fac8f07e6d73cc90b2ba713d73c73802361ce46a4eb5ed1060c4cf53207d301f0fcd4f0c9d1580db2fc1059d372076438a01192a7f9fd6f7883f56422866fd9f0afe53fdc910afa5a751cbfa377592579165cb56dc3eb4dce67e3db33a981a56b7d9f7bdea74fbaea3478e6ab2c644fd777b8bfa72aa0f0a52198d36e5b634d2c9a11b7fe0ab2f9a40901c5b148a0192e95a170baf7d5350fe01e569542b93485a41971443485faf57f67f56dfe2c58e539c9f9b449c3f91249a10c1a1be7e0b3eabe8ee0bab1f11f89614dced418c62a07a0b59a1370d6531ba177091c6ad595fb59488204f63344736ea1017affbeb753a99786b1eb64510e2e717ec90e02744bc352d3f1b2ab7be0eb65623d04fb3a046ce7f4da697d829828a52c7b043b2a82ec97fb041bf519b4de316f4e2f5b0db62aed0eed95cad4320c1947c35fd8847a5867872883561119c01b0089213d84db99d439f0f6444d8783dd4b64be3577cd461cf753c8e61c912de2e5d7a7e2baefa258975d16ef3117da59a6c893f3339187df3168b89f0fb0b2198bb6f1594bb88f3d610fcec3e36de04ae10328112e6ff74f5a8ce68d407174b4c0691c7602eab1bb10f3c49dd22b8450782deae9a7315e3b88de79cd15e6c9268165ed3a0fb3f89b183e1a212152003f32a2665d37cdd7f6b56c2453e5580c4d21f9983f38798e9b
SIG: 3c4462aa47010132dbb26311e444727279edade15a4d662cf647f3275cf3253e6de9333830e0517aa5fa7bc2d0e63ea2597a94b0fe92706ecd172c5ec5c7f006
TST: 890
SK: 7b30b42dc2c670a195fe2af879fc5de374024588fe3de43e2dd50844f48f42be
PK: 82a2ac6079f212b5eedd0c19e9394fafacd74d716fdefbfc6cb8a7eaf41c0362
MSG: c6687aefebc5c816d1a33453beca5020d3a97cda1dac5662f0af72bad444e2fd1176a7b04c1bd09d832618209bf3e33e523538d6daa753046e871dd3b3c7acad33e79c1bb7896407865d168d4bc3757bde4f823c08778626f8c71fb7cfcfdf03a82497bd8be7d8f8ef649030b5f36a339459968e246a1e420853dace41ca850a4eeae834ae119610ca4cd0662aac39621586998027ef2f61485c028506714ae09c76399d873e808158578aa59e8212f58865319f9e0d2b8da7ad529e0ac1f1eb435aecfd35f5abb92bea5073496bf4c0bf15baa273bfc5c3104474a2dcf132c333eb36ec2cbf04fa9580b768f5cea7b5617e5880aff63201c274d669743e1bc556b067902eee29d29111288969cffa879fc9cbf66fbf9326d9d925ac4102fa9f1a06081adec079cbc96746d79b63a012ed77d82c9ffd4e3f161f6cea28cc23fac2a543f5b1d0644ec04838327bcc652b858f93ff463f7e949eec8c9db6569a86984f831df6ac6d95f38f46cebb6e6583657facd2108dbcd0af23ab0101a1301beb48a44caccb91094473d7e5a5c88c644fd3420573b678f17b5174cb14e90fac694d1dbc6c9632b5974aef28ac08d720b2ea30440d2afb0493b40db24efbdbf53c430921e52a10b54661e149d165591a7cf91d6508ea472fb3be16395e30312f19b87c47e46804a0fa29b56b5ac950677bc60238b5e99e030b1e552146a0e88c294cfca835c101c55f3423874cc128756e73a5debe8e97fe2166b65cb44642770c6d1d2390af1b0f31b958c830e9ac4fe2f5ad590582fbb892bf949584477ef7bde23f7dd02b63f7c29088a57251009132ffbb78ed14defbefd9fd31fdcab03ba80a23f333983760abad4f16ddf9dd4414f04d00db56ba72d63a3a13d2c442f549fd66c988d2e4601d13b52f77500dd692bec9d6bd3bafa9242fdcfaeb69b98b0b5789b2803840dec637b49af4381ae3fa429fb53461a0c674eb5aa18dbd607a2b77a96d3ab464ecd97492f6de460c9f11b5c1756cb59cb1348dfd77956b71907c54821e303cb8b14906c003e3484be4ea05a6901d69b07485e858f7b471c635f90395b9a3e2247f1ad12b118ffafc7221a57b10e319b61af1c13606a81616ce3f1d62ba932ff4e63e74b84255e3af5210bbd571bda44cbf44b714422cb45c2ef21f98131ba96b7edb9b03e33d7d188d5b8d904cb4136fe269db146988168e7ee245356354f002a5ea8b35a3a99e83a13272274144b33a60ca
SIG: 0a63b84f46935faf3ea164b00af227b00868a03f5612935e18619a84a2e57b8851d746e63fd9100787f5338d51c1073c2fc5303099e1873e5e3d3e5c036fbe01
TST: 891
SK: 6656f4d4718157c4bac38ff7abe5eb1f812c0b986d9c014abad5b09aa6c8ee4a
PK: f3087898e452be9e30aecc4e8ffe0c01169888683f62a45b8da38299014f5b4a
MSG: 94d9e5e5a7b705d9d976fe71e94d3f7fa7866afbf7ece424f136327799b2b206ce4ef4c3f3e705553afc8fd5c1952a4c16658d4a78afbb9a97f27193c65b65b82e8f3b71515fac82640e0f8a5fb35ae6fc6a3db051a22d4a5300413e6e33d19c2013c2983aca8ad6cec2ce64a814164f061a1a3c5a8610a7650bfb5423d4362ce02206dbe4a6fa826f03b42ac3cd9ea4c651401b3cea82c3993f6af8b2c9e2e6ffe69280ab3f09fbe90dd547ccda9d9e8e8a537b3b360554227ed0709f293198982efb5efb0e73e00042d1a063b57452027dce1a39e4b0068f58b111ec5dc142bf419ad893d54f4260cbde7628f783de8496380306a4eff6d82869104259c94c54ad5aa8b067c42496cb88dd31150ea04d499bfac91f4bb3e68af5af7a568a3e4ce7f170d98601163f4952f1d25e12e00ef0a2d8f111afdb0fafbad2bf8e8b9d49363fca68183617b541270dda4609b2616729ab1b8c42dbdd7bf986af8fba52e733e42ba03c892e1e1ec06a90b163f5a79f6165eb7316972ac1adbfcf1dcab07847ef82c2cab1015dbb50aadc79fe11c832098cacc39820ab085b6963bd42160ed6613bae5e201f17c0fd7f32357ae350ce9cbbe926fa42dcbd422ac1bf09a19ad1f69469e4d1dcb124118ed4522d353c174298650ff88382fa2fdbb286c45b18a9baf6f6763ac20c9ca4767d348c4b8ded630076657b85b14c11ae2737ea29a43515b7f05674a0cd3ed4bf6a3d189ae972218f877cd8aa69499d5a08c99e440694ccaccdf1f642e14e90105bee6d98edeeab3b4f339f300188aec0c16bd64521d9287398e648db94330ed8f6b9ab6c7ad93ffc43e8792e637c61bff7d856e54ef4987384e312cb57017a50eae5952abe19d8999c8c82dfc45798cc17c8d9496bf520ecc5b77fe284915566c45685c304a2acd525ef12c86f38aef554d8a2384737cc4133fb7e2b65c13bef31668a6c2f60eecd8412eeff7f6b605cbe95083e233ec1a7bb36de236c8a71ba2872be946cd3b38935f5da64c8fec8e14f45ccf6124bab7f70567c2f2bfdd56667609572037c76146c991707659b5709b074e3451f921a2df283b96aa26ab476625016f181ad64c9919cf41d714a1a9a5e2bb26baf8770b2eba77b778a332677a7572ee3a2b1dc05f7356bdcae5f55e35329e34caa79430b270c036160dc9fcaab5b254543ac94b24681f17172b6159d16621d7ad0eebd895a1e1d09b916a86fb48e4c91661057eee95c0870ed54
SIG: 9c2c39915aed6add004e7dd684ee3dcdd10d87a487f677e73c2bce0fca7d508796464150a52a440f5237850a009c72162d9d2985470a33490e66d3c401704c05
TST: 892
SK: 14383e6e5604c99c248d39be51d164b13442b05e51d78ecd999364221a45036b
PK: 2fc16138220ab74b3bd446f8a714b58d5463d40d4367925007474c5b9e35d494
MSG: c4753b7f7a6f6dea2515c6e3d29561506f4f36e0de84999221f228e20bd5128ed93bdb8d1193237d8e294169a2bc448af9dd36066301efb7fe1231353c0623ffe1115debb6905ac6946ee382a27c3c09e1b1f5c11493dba37da0ff6eea75d9fab0ee926d701dac2fc5b7ef578880a5d5eeecadc1f4bcc4cd4ec6f2f14f52a8c164072e6fde5ab2ee9cee0b48e51af055f9fec7c63750fedf72332b23863a1e54c52b461a21506dfdfc63880e22d89c894412666c929821c0e439e745415f717969e6058554d64b947a4fc9d16acae3e49aec08801a09d972f79ead68d529768069735caa742b45a5830581b80ca061a6c1515e3f7d5a9337878c19fc94eef22698ea6c4d05f9ed411b6b8f052b5ff15dc23a64beeaae99f84893de3df940a4e0b8e993930139052d99be47bca8775f8563bd4026b71343d51968f2337528f4c9db8bbd0a298af04b27695d86b7f7ba6c4ccc6273febcd8f75cff266995244fc1fa13d8d843f0bff49cc2d508f4a2b3aad1d95fb22a2bc6ad1b966b0812d99070bba07c923ee4d08107486dc01a06dba6f1d5f105aceade33b166510e427ebbce52a3e7831f0f78a3c6e072608334d8021c338a73cc0c47f19c9fae403b9716d0d15fbdf6466b08f6acce3f50a703b1dea8d826df842ca1ba20d29f4548acfc754cf011f570681b59e4da25385ebd6d5c3adc930529e166ce6705f6010210db106462b3333204e7adadee6606a56206b47eef2074b116e22a615418ec2cdc331f1e19e07e8a37b92d69df0734e085daeeb901ec6e8c35f103f1d86ef0d2a2652b01d183597e4cfdeedfe5df9a7ef66a1c796a37a27113b944dd7ba17c460015ab8ace451c57850ec6c290c54e5113f55e99a8e6e4711e3b7817bf91a5adb37fb9461be6b1b55d586046e42a54c5def4076f1ff6c31b806fc602474356aa2899eae70f5e5abf1f75a7f24c134cde11793bb162e03a583d5be046acc73456d12d509d92f7705768686f6c714a4e57ec88b71398e23e835d6d6547225996b7ed08f3b7443bb17c899409493d0efe8455bec8e8c284a3b149a5b4ca631ea620b1bb817cedaba50b044411849d260a6f2a0d3f2cceec3842719a5ea4fe18dde0d42dcb33ad21e6453325af6f3c009f2bb978d30ceeae9aa4928bf73767cda9292ab893ce5fa3aa4c232163b45c64ed7977779b1c0cafcfc2b9fa084a324f113adeec218b4735b6b464db6d46c2791af3455f1ca5ea1e9a048c051a54dfa0
SIG: 45e8ed1a751dfc3b9b7bd7a10bf5bdcf8ca461865a490c105f10452941cf87721214bfbf3a35606b7ce35d6f70aaf2d5eadcc0de035e9b2f6d7b862fc2849004
TST: 893
SK: 59b07263b22c0a38bbc591059594b2bd927e805961dd07e1f94245b23aa2e016
PK: 0b1e4cf5aff278ec65b405f5108e1b5b18a969ad1f1e6381912c82d698907cba
MSG: 08ce0d4db5c2aa500a19efbc8dc8549250f7dd46a7a9a5407417b3d51820e4b0d61275583f56f897fd942bdd7311ad6baf738128567af6558d75906a02c4343a9955d59b11088c588dc7dd08f67965c5602a56928dda4ae164293163b517ca17ded04fe4ab2f9789130ae96ab231f07e09015b78f3848cef435db0ad9f35e0fbc9851e3ecfc9fb186d14d8da4dda45d0b3eb3ee4500c101e3194b572140689cd75da1287b254f374e3d93326ae5faf114018ac714bd00375d92a8bb659c32912831f4f20776e9e2c25029f0aff39fddac7241543a0366b84de7b1ff23e8e4dc093df0d2dd5e53e6847948cf3d0ff3f564ad94d9cc00a5ea5b695e408bf50f5bab2f6ea87ba8ad3a1940195cf1bc2b5b34847ad3a5effb8a7823de91ef1633869d1f04643af4d826a59e78b9d186312b3d972263654ac5587b80b717646f31003db81ac70860d3fc8cd3a6a0a0d576d25731ef7b8966263d7a05b55009e8a23dac0f9a21a24b06e13900e444446fdfe56cbc1a026df41066b201b1481e56158926c0c9ea90f0c645aab4bef12d4e072cbfdc3c3d5e0c72cf88f166de048874f3534e040c62b1662821bdd16b0e8582817461cb2689279b446d70c8ac20ad03e598cad4908c52c350d4243ee8aedb87a4af977f7db57cd947b47d6bb51409d80d81f6db03cb9a6a6b79812f470690afc1836a531338094cf26d3c1232fd5605d8f8c55b6f8a2a7ef1e0c78155594b237956d2abad6a9adcd58e11ccd35cc995b9a0aecbf7f5741ac051b04ef6b9744b56fccb46398528bb31fbe84e078843e69bf338898cdef69ad41872395e46b593904825547e00bdaf221f8fa587ea2037ffb9ac9307dd3f8f35ec5386ba966333e2ac8727b0e1b80612d3c7f2cb88baacadfe2163bc38c88842e76a394571d40610e8a297602793763296e3eabf720e984b2edd28cf5c4e0f9a0f76aceba28cc1f1b69ff1d35b4bd3347b7f9a95a4c1ea10734e1c918eb96249d0cc70b477f6f23809bbda901d53f485a71f5086002c1b71efcc41cb1aeb5122a3f3bfc96c51a55d75c02984288be657887854cfa738974bcd5440146f9bb14040de54f5444ad43b79af9bdb24ed6a48eb2fdeed71f31f0ece102e918e95635c7a038633ee348d8b5781652d5059d215ac97f30ea20d277ebbf15246905428a7bec02b8f926315bad6723fd64d71fc95f333364cbe90d4646333c40dda6d1d433b7c195a758dbb4038af5dcc7232d4547f540e394
SIG: 886da33e3553285ea59c1431b6e86ea49bb68b2e0efd2b157e7791b74f35a2421bb359f3dc1e4ce5f11f73652e03bfc0b429c58f0f2d7418c7c20bce2e2d1901
TST: 894
SK: 5cc115d839e058cdb6518ee9c161c004d88bd3908d3cf6d52c8f296a1a076b9b
PK: 1e8f3305bf2fa11b17d92416ab0ea762396d88f2f970ef0b100ed3bf5cc13440
MSG: 533e49c1d5f33c5ec4be84c619f4ec649c25fd70bdcfe257a63c3373a4d089c89af6eeb7160dd77ab66b1ee7e10850ab4fc1f35132332b53789b2b0140c4f20f97f2142072d624aff7aad324aacd068c035aff52fa712f4e74832de031b2642314d17110dee6fb85762dc30d7e97782fd1fbff7179f00917f55af7503a5b7e23c6eadb65e104f1517b6624c9e5204b3fd29a6585e92ce3a3eee2c5ae177920f7b4ab2cac87d672ab6baac1186d904aea3498534eb5ab23e4ac4c0ddb0d82a5ae531d76549d367628577bac4235e897d9fe205522047d214ff6ccf311c4e397827d97f2868e70ac17d28e334999744d359376a482fdcb414b02b2687b962ee8086e573fe000dc51dee06879c684e25f94cee5e861347e7be7fca549a0f765136a2f4b88fede07024dd2fce1f6d0c0354da1a16ef366b315b3f7233031f979b70eac6e23bf3b349efbd0e4f53f4d5c41fc004276a59670659f6905ef03d2fc098d589fcbc1328282fa22b10db83c5d70865994fd19d760a39d476e02330d2c6d19e742267dd365bbe1fe5c711a95b184508ce48c1c96d7e63990b408d45089be79e32f9cb0162fd1e7d0d19d97d0ae78ff824cc6989486c0bd038352551f37499e9e9826804e9d2624ad0c7b7534560f45fd7d324b8e517e01c9b2743c14979cfd512bc3fe667279b3a277fb463e9d7349b64ffc9fe60884c21e481081ed70e6da5a3539c448971f0d9787289fcb0080f219e99449f8298c42475f87fd10aeb509c530cf6a57748eb8f3562161fa4875ea953f09659c7df7a9950f0317467cb4e5366e196e32f5e2696733a25eacbde49210490762060ea231370d4090429bb06bb867399e8d37bf5d21a0e72147e496cf3b7dd6fe6e5edea9668d802190a91c600e29523f8eb904e48b70412bc10a7020984c5ff0f5f383f214ae594dc85971e480372848d0d7e7cc5c18ff88ba9b262d7884698a41c6c7819c0319fdc6bb07b91dc1694dafe3af37a538bf2b2d8cacb27d24cdc6eadb8c6a2e6b7df8a4654ae937850c890ad930980afcc1492db8a0168cbc9f10657eb48d2ac87f5175d23caed4b5e6f10bbeaa5e33fc5f6418d63ba374ab1a3cbd36b729ddbdaba989d4645e3a66130bae417cad086dadd30843352514c375f2571abaf93e9a0771fa103ae92585b04f55c434769b43d6d22f753f9306036e53524f6f4d9ccbd2c30317a8e899f316149035894da945b76d9082bfee328e7a31b66328ee8b94e068c7
SIG: 0371c2d64c5ec0c8276ca5ffa615eff42f9efffc58dd8ecfcf67620a9bcb38faf118932bf2cd5b9205fa551334df2a757c597744f791f371fbedd98b21f73405
TST: 895
SK: 75a503f48ffc221617672519111bf90da39da9eab2e2914fd3755f10f5393668
PK: f680cc0f6358cdcf537aa71128cfadfc0f3a89c100aa34bcd2427e248b6ed50b
MSG: 7b01090423236cb4b13c4177fce52a7ff6580588cc2eb5a3f39ff5d0c73e01e01bf7bd74afe4151250c391426ea507271bea1d6d85f0b2fe35c40500f98d0656c6388fc9efba1837db22dfa29d892676f50e575fe89fd29389d09d080bad67ba544cacabf5a7738237c55e2875ed4916302a2b4dc496e74273bf05191137810e50e48195260bab6d81f9c80562ee73ccb9333cd9b61daf5b0038a4e6c5c958a91f68508c1d882519c1aa4ffcc53562463a0ae30163696f84b97ccbd8679820edd3617e7b896eeffe341ec6b5b03f73b625d741c655fe6e82d11d478a7d543ff6c0fa3a3a8c94a616fb847070d1fbdde6010f026b089cd863c3bd29b1c4269f77659e515728890c973be87f0b833ca5af6b4c3133ad4fa4f91655c6adb5b7235c27fe348284f3f13366a6a03ad22b87c6f5584bdeaea48c70325d6e33a475f50511063875192a87edc388089b84395390c2a3ad89a22595dc4a715a42a2c0efdef67b354b34fc75ca98df913e759e51c7f625ddd598ac22d421decb57bebd54220ec6daa5ece769d2e01be7b6bee2ff5a0b06b32d6da1d7bc057e3abfaab242a3f7e6646a159e4f505e4662982b13d0cc1fba91d10309a42dc1087cf10d36e31f170615a0acb508bf683e2de00c87640d304a947bc4971ff3619c72abd83c7b2cbb3464c4040c2662b58508b74680cfa6de06e8d21e3bec8511199312680009071f706b7b133a2487d5745ffadd5dc0eb2b553df440787f011dda37719fa71315e8b291efd77da3ba14fb995f03571a3db522b63c60be5619941699b39222b59d0f23e5eb37ead4b7f750ed4abf4db87c70da665bef4d7a2921b2c99897f2321c9be6075e744c8228639ab736dbeb2beab440c156a39a2efd261db50855e304d9cfeb99141c613558109f21474d272a2d906d4893934aff8e08a4fcee964a5cd00732fd33af29849c8dfca65979421857185cf629f86807a85973d3440a6bf811a58d041387249811ec047e5e8b343b2387d0181e0d0bd461ef10e8164aae357d9b29dc0ace3ec6d743ae3454ab9f842a28d5710217dffe50344e8d932f1801b0e8f966198ef1c9cc6969f34734aa6a63aeaab4339f75d34ffa8acb937ed9c73092a309a9b84a25011e3114c265e4f602337eb699b5a22d572b03e4dad03b0461c00db9679b72fc5b493ef4486f85535d813a58080385afd4e8d871828034334bfe441d18984e4dfcde024403b5ae66cc50a47301b57f9a32f740bdc7ff1d
SIG: df28e3e630360867864bc41e43fd7ddeb52876dce9b234a3fcc3d8549db0112e176390a685ebd484936e25c08c8a3878a37b3c4e239ad0a0e5019937ffbcd407
TST: 896
SK: d8aa2a0aa514fd845f7aa66b83c0eabb9c16023abc1695773450b2bb332522f2
PK: e4e8d6b298248c15fe08f87a3bc6084bf2d64d7f1e4b2d51599e9fad9cc91092
MSG: 08deb3b832f52d6556f78c3f0abe46f1efe45e3d5d88e7f8edf803670ce4612921749e9ece63fdc9bef2ba483812bb622be744d40404fd6e09c9e1cb7ce19de81a9dadf556352ee89810c76a9b1047ac62b16ebb7da23ddc2d4ab76a020561d02d41b58b94953a23faafddd781b7dca7b7fbee706ec10a73125bf74436056bf3b4f2a0701cfef05bebd3dd8eef306c1ac1b00950881ff05ab5c8248ad1096ac91d526ae59ba0583b27db7d1e390f57a5889e2799a4a1519b15d93dbf0b21d450873c76ba520461e8bb5c83c9012eacd557bea640586efcb869007647d449f91ccd52afe3a89477de7c2b647ecc9bf967fbf5769d74889447d9522d9e8069c3499af6a8a1097a95d3bcc5f83433934484314cb30758b525fe53e90721df5cbe03d96f0d0f98521f01a5fbe57ce8804dbd18f8f5eac8f7dbb58c41789a44433f8a8d1245d2adda8c78d881c65ea661ab178d4fc2634cd6cb514ab6f2543e9112183f3ff73a3f450106b0ee8a347a80cb824ac1f80164e3bb5123698de0e747359ca35acaa3ba0c943beacd7a9bdf8ff73978e9fb002045e8fe5648cc0f9cfa88b0d812e81aa62e0d9c73fe613afd9539bcb615721fb497d62f65c83b87a6d2143f9b1c880ec8671bd42c8de957b1a68ee49226ff717ccc6e74f2eee49c30dea53fec3cd4d90f2cccd8f97c55d5c752454be2ba7b6ff2030be67e0df50c5e883843e71612f2b95359543e2ba1bf2e98debcf5768f2be6fd504d9783ce921a81e09416dbcf2bb655a924b1ef0112d671f084a5b690b0b64a8b9bf50333c359ff3fef199694f9b6292424f00666cef6d06d161a79e3a1b9b9629eea53505f5e36aeadfe0d759672b0ffe498397d90a55d9944b30541a7e1bdac53020640137dc252aef622f3819d36ab498d763e4327ba8580dd9f7e5f47c24cc9928734b7e62112c57e3e0cfedecdcbaccb0c45af8219455ee7223c71e7e20410c5244eb827af2f3935ce4755444747aa945f4c26db3a298519e75fc6bace91529972e8691b694d30aa8b5ec4c1a028d3bd10bd0c8a408fb7d9d703495553ecea598d0622dcc74de489ba7195cdae8d5cff9855921837b528433ee55c0b7090857a0c2784d9310b4825a7993ad9c6f18f83bca5cc6a25047168a8376b062e3a48ea90cad88e331187c2b6f281426f81f78804a895c4ec06c341fe846af4527ea26069dcf61d813fddf0fc43c707350bfb2fc1cffcee7d7ccd7d75f7a465a3d14d57302c146aba3e
SIG: 146f65d43e715542894b7900a2f8cd4b17d3870a6100e37de005b0db5d8151246de4ee3842d3ebca20a5da22a363a7575e7a55128295f27211484af57cd53109
TST: 897
SK: de8f1c99e7f8556df20b59b8504cff7c6c5241a8aeeb30b92eab97bf481d0fe9
PK: e463791d0f567ee73abbf47dd57167a535613b05cd48d92ebc7d24e6ebff9573
MSG: 38d93e5c9801db901797ec75c6dddc65ae7980de210bed43b33eb44cdc6dc9933fb6bec7421db10f0a59320b9e642a21f1dd235601fcd6c53be4a877f4fed3fa4a0ad4dc6e9b391bcfa434906925ba45ecc5b435d9ab8cfafc394bdcca9b07d5668393446e3400e9039435a1dc78cbc08807a3fb24ca8b19f64ea08b8bf6c20a195b51ff8015f3e7c91d08e4bc62415595a5a882fba651dc3a675187af618249747b4680d1d15a202ea9df48b1c214fd403466fd1a265f2defaf8ed5a6bf0eb08d1864f2a28e9472143c6fd103b6b108c0d1d1363b99f9202d11f02056c279cca315db1ab6d31018458f57ba3316cd2738e80c492d857cb1749925e331c65858b50983cd9838cfd2188a5e8f05b471fd3cddcd30d96901194020f115fb469ab5849006dffa2d543a13b3b506ed65cc457532b8aa3ee31d9d8d9e5298d7ac707ac15b827a578c81d434f84cb1b56120d667b2afe6d1530afddfb966d953be7e32df07de389e2d04b232d3512c7db9358fc944d1b118078e6999e891bbfa4a4329f65d807188b59858c431211b29576f4496138b7c0c128f7bef5f79b0f446fc6b4a0e20bca4c40a83571a36644abffabd49cb585fd064c8e509d9a0fcff462676f0ebcb61cec61e512be6f182abd59e09f642aa619634853482ece8f89800f9c5bcfb841431ca0691ed8d80e0a2fcb797a036897cfb6537586b31c00b7965efddfda72861845026459157f79eba1bcaf6cd41d618aeb1bd8da1be98f0cdc7f2e09b903de49c0c1be91dcc177b298096836dcea4f601dd86691555128325438bd9ccbfc0e777920ae8bbd57634c6104fe69a3a72012a2360b6e552550cffb4e2f0b41fe15537ee0e6f37e7880fb4d12bef6cad266ce58df9816b35960cd0bf8652862ee789ccc31a7efc21a81bda46146b111fcfd94f04856ab61a557b1ff7c8e4ea6d9c4bcdd93b151aa08461c568defb2aefdfce96394dc822d4ef6cc4b9a3e6c332039f6538aa0df8de8126d90c312ff496887486111565534346a7462625d63df69fcb5741906f19e00fc8003f08b95985c38b8674af423ca56de5f881b59c466243a7adbadba29caf57fa777122e61823b4e708182aaf37206d7d5ed051c12a5c0f6b4371043f562cdc029d5e1ba9b2bf5ffbf1f5f523db06feca427db7a08819ffb2d0585242e20da58e320b16b16e448d8be0ef7402d24a7194257133bdc982314d83adbcd12e8af31303426c59ffd8269ce4b987ca9b6f0ffdbb4d1d12
SIG: 30abc4e4e4b388581e668bd409ee18a6ede81a136c28a2924df5fc00d7c280d97862ae3a67a935ce492364135e659adb5fbabe689816591f49ac5022a387cc09
TST: 898
SK: 0736f801720a947c5c2f3258ce0d511c3e17e94e37b30adfa52095921171d400
PK: 4f694255920d0c38de6e72e165c33aee76b1cbf6f4837aa5901475667acd2826
MSG: 7f87b51f6ead2d4402a3bd3c3769a267ac8e82f779ad7b986dec82cbfc1ea51291884326d9226967cb66a96873184f0e83b3ab25a5ab2fa805fe3a0e7b190a622d461b7830a3f697c831c29ea7c0cd4b68d8e77aa69711cf864dc1d5394f4845e2fbb5076404e09a88b79f05670551bce2ef5468b79d57888b9852a4bb479a4fd0beb681fd523fc5bf4458abbc38ece72e106e00222015a57ebec55bf47513e25c3c4554843bdacbcfe9f1b8d0ae354e48d03fdebdf20d655b5268d8bbbf33b1288910f0444fcd56c0da7b8903362b7e37a864654277cffbe6c60857f0b3514d22a40b9dd2d3fe5caea5507a0de3051bb3a4015fa0fe4c462b98fef2357dcf6b97dc75def382f901f96f4a04a3efc60254200a2c4cdc8a58b25d94e32954eaff1511ac46e3606663b6875f136499da6a769097879a6e0834d564fa7fdb99581183ed0c9d48fd195d7ecd9f4dd4865565fd17a008718dcd76f68a54e516a2b730ed3dba5c2cf40630bbfe7fa03bb7cdd967695495a7c86e2e84cb017ec69601924631595affaa8cfd048d14267c73e54cfa539047e717691e399737fa50cc4844961257c93d7253d23226b7cd0d1bd31f3f0d2d892d073d8c5073c602f61a04d6437c3903eb4a64a01fbcc0c7e159201cdc4aa42ef3b1ff9c78fc275cfb11a05ffed8f9f22d85ba924d8d32231c254d898da7f0679a64cab84026906e9e85f95efd8ee2a1725633f4de2ba67d99aa7f0550af139e9f8c5293786727d82630296d5daa9e830aa1b3b5b302b8b662ac832e9213016ba493a03a28cc3e9540d0d65acddbfe1252b5c16a84a445ce75415c6cd8ab16fe5eef117097d71eb5676b9a95b35882a7c3506bc5d02f03910a63d46846b213c3c9bb2fc34e6c69017d2065a1ad3ce3fd14ab0014f584e57ea9d903e40aceb230a8693fa2e63641c25438ff7a1638760438844cdf001180f5b177be69edf7ef66b39312805214cb17706cefe545be5a77019a5ec52bbf78850fa3d97de2d4d74aa68b58ca812a1b156a0c4001129f067232a6ec91a5ed4270f2a4c6efeee787004770c859e450e837efb04dc998bd273c27a09855e4eca1a22a9b88c17bdbf253a79761070a76817a7f74ff3f07fb718bffa0b4f326f284e62f836832427be82f483373515b9bf59af4a76a57e2f40b91034dd568ec14ac10e2309b87e2922f9cd9fc1a46a47ed3bc7e1b9feb9ee067073fa5dce2a67530526de67ee0e509663c44467eeb59420103ebcdffa709
SIG: c03c0314851279edcde970c23efa236f235eda960d2c27d3ca946f650c200b4eba04be668ff62eaffa6cea351abdfc54401dccce3dba78004aec9581a2ccf40f
TST: 899
SK: fa75650491047428d363b5822222122dffb5a9fddc603c33c8a608618375dcf3
PK: 98c9641fa9dfa8ea13e0d1c716b8679e264be15dd2d4c06ab43cbee47916ee01
MSG: f54e41b939e37df17c7d6043fded14a915d934e867c345269fdc0177f5bd10c4348f319e0ab9a64cc0b7d4e0c91ca9aadaab2edcba544f14ed2cb539ca8975097d87927095b4ebd490344340061ed93c38167edaa096a230db59624c67fb9a1e1ddac402133f4d47cfc11e2fae6b3f3c5001cba9a8aed90073103240227e716ff71bf68a591ba2ceff2d31b86ef21ab012eccd409ad5c29d659a1b37c4d85505304140fb2c3437a206868b1352c102bbfa3b9a76522a2bfc5406b257696de74ee7d315c8e99caa96bd838006c6da2a4233315a856acb8e80c33168b333551d91d074055734130bd7d14c56811ebabf7d5a250e6072593d9f2f8b97c12a703c2c479cb0b15b7a2775c9dcd2ca4624672368a2e6145467f3be6615f93b8120a0a12da1560663a26a61731966b44b299ebfad2a95c62360f39ce05d9558e305ee23a52fa5ce20f6be5e262aff3a864d5ddabe23ff943f71d5998493d99fe2ac2374b464a69183c3bc4f1ddb883611149d7ddbf1e8380b544335e2b89395054c9f2558dfc56ea93ff14d0f15d2e0bd8937a556387de96e418d8b3a7d666fb190364b2c2190d3c25f1752d5483dcbb5960064f0c87fcf8f313d28781c114a169b690a8701c50d89c77324531c0f849dbad1633d925acd06c16a9cea19a434ebc42aebb1fdb9b0bacc93cec39919943664ea1a958406ff9e4935c92ca7c39708f9cab710a583096b4ed9f48d9e090647240d76eccbaba591f55fe7e36d72c21727acba0f8030954e62bc580b8b670c4457c3403e369ac20e660d662f7f6a414213ea43f7c0105009c1de817adf6ffd9cca3b45a63a822281c6e2772fd7b7809603184b4879b18c887903f0fc8d8e1e2dbf6e772f0b2d9b8a29927acc81714a2256ad8d7b7330527d7dbf8befd82f8c9bb401cf0a90249a64ca6f8833db31bd03b9e7946d06dd04383d7c082d70aeb37ff84c2b057d973b894b4a03ec7bf031aea656a1908488894a4ada3fd7fadf91ede9550d38415f82a09455c0f432fb55987132f00042afd60ea51d1f1c6c1afe0cf87c346e31e63e26f49b137177b2d47ab30f07cea071931274cf010836d683fff3be7134c78b8bfd8b1b8fc2049e18ccb1e18a0a9585a7d8a1e25492608668c96d62a0aca8ef90e048d20378c108d06b03fe3ec4adb27528ae08f7ded9487893ae64ca4b939202aa4c17afe718cdca49ff9616d0cdf8334b6aee2d6d20947ca4bd7df531dd1da99581ff72ea56fe62caa2c95e3587
SIG: 1effbf9299a1b9354fe1f1dec1766595ea767ab8e4da9bb57b4f69bcbd8cb3d86f768392f59b39fafa8a210a6509fe0d6008d6356111adfb3799c1d559c26309
TST: 900
SK: e1c12946d221a194f22f2762c0e51cbe3f98b914a47d3dc41a1f45c54370637c
PK: 10408136a68fc56c7d3b36b7fef122094de081031189cc84a48806aaf6cb9185
MSG: 870f4cd97cfc0aafada40072312fb54bccc07628714e4962d4bef4eeb5de40a19a246b5b7d52d487b7e52d656f2c6403b916d02e02a6d291c1e1828dd945a583b438528d1c39765a572031ffa916b68321f32e6646f0dcc1c60235ffaa3235f484a5c4978fa3e6bf14301d53e12f4cc52118b1f6f07f5336f5d0a93789bb01d162fb3126dcd756e0642e7e698963c0345911a5cf3c9953f77319426cea2cdeda3efe989ecb63cb9eb8b920de766c4fcf6336e5bc4371a068371fed95c8c2b61ee9b7c3e3831c20bffe8707c0c98be96153c8a873d7f28afca1bf71085ce0e3899eef5591bdd666dc2d07641772d745c51644a260815b208c4dd305f05fe463d0d9d5a9eeff9779f5b1d44f26083078566d0e5ff56b3af0e64cc38708af5a65f654352df10437f1ddf945a0da1f4def6a71a060e0c4adeccaacf85e090f7090370ae24e5238d768a08fe6b4bb5ec497a6603198608415c7c6490048aa36737c08503008aece0f494219ddf89b72ea77171c6d3117089eb88907e8c33fb9e70b0dc281f664b5f965b5d2adb1250710ef2352025fb293395ae1d23ee3b592b4c5f2d55569a5458654ce3fc25dd0e3f7e6757aa7b347c1ffd3ba4d4f2c4b6d36afd59863a32a594e74537ece9b8b1ec269bbc4cb54d76238211f62a98a46a4af662fa81eba6f30f514b866b7942bc173f7211a6c014da14e741327a568623d14b8f835ef1d5d62b2523cfe6a85bc69fa05200deac1568b946a816b75c5d7603174fd4e2f9101a79063791bc3d59297cdc10bdaa663abf3c1be2fda17e4e5ce394e90bd76b1f9e0405f5675b99d638abc2c1b2d8b53a6fd3dc8375855ec54ccbda24e672527723b07bb599db54e38793391cf09ef3b1fd7614990065bbd4a19e8d3d1048253ba4c971c2f98d2b359df509087323aa6905029f5cc5e1a0aaf2f7c0108ddb1a40f562be64e57e695ed21dc7db17d533677ef12fcbbe29f3b237bb6344b1109b32a9462abc3ad3c0710b04f38c6f5952db275e77e2f37e95d55096bbaf3e305d5d743d36595bf0567892c210ac7bae7371d164584785dd890174159b3930a9a6ce3a166dda2383e6e2af28c1bf3192447e90511dcd80ebdf9ee2c9bdeddeeb610558641532d07cd13da61254154cc0fd9d481e3b0a237af2ec26256d4ab219faf15ad2b7e8e57ab726ff2723216a574585e2a639d948c2c4f69eeaad283e3a44ff268eaefd7e66b73ede473a8397c76b48d56cb3ccdabc91a8929cf42998350e0
SIG: 8fd7fa400c032fcfbc402942fc78637526be97ab82f237bb393ea39e35738c67d75409543a8b3c055f08bf69199af63b6911a482fb4f6580802ec9d2dc3c1106
TST: 901
SK: 762f06ca01e314715f92c90bbe72a25bf26212c81eb1d1a0dae2c31130f7cdbb
PK: f9626ffd692731925e5aacfa1bded01aa8f730b772d5e46adbc315565b9bf2c9
MSG: 9497483a4fba78433b38e9deb8915c750b6da0f78af4a68b62f9fc0391e338873b1d64b1b7f09f12f056a3c91653498ad56e069b8b160887e8e378a76d8b3c667083c0a2b2d2317d3b874857e57862ef0cb70436a9028f0191ccc616e9d7c9bd869808cf094835ff518677b3fb089f4c9d077cc7742405b4863ac7a59645c9cf540d57399da6ae9d07fd19fca95bc8a86d8b8e24e48733f32158fd19a8a1111d1da1f9b580a39c10484616cf2bc0ec29f63f77c85356158e16da594b5a890e55d0b64599b30293e900ed92ad261969e7df4c4b1d0b6024bdceb69067ef486c20fdcd22a10d5da45fbf905ba1e935c96f50afb63571bcff3130684eda0b56e60b26cf4c0ef9938a92768fc8631fe308236b012f92af24a8f6e6ecbe76629bbaf8ffe54cdbe8671de2ba624a7c0f6193bba4110412902bac2990922a9e5a81053cf876a4c805a04c56a8139d3419e454a622d0342bf426e9802c3dc1b4080c75492afe9d7b1545fe086d963541324ff52a48c6bfaea26668b3e01e5236fd45fe54594535c0b23e287ebd1428c8be0ad141600e91cb51e1ea66271a6421fb689e88a0790a651dbd21ee2089b274666f660ca09ce2d60e39e2ee5f03b6eb82d19976966e79900a810f6d5b5c1a548e5064f5c3d8a9f2def0179df99d143fde69b0712c091c29e9b25f40cafd57a024658d7774037610342f3800fd51f49e79a5b3decc112f58d03e3d2958758588bc4b1c6a6cda7bc5f5be183e41513c1f230f3cc364304bf82484b7cf19a002e150f98c5e97c6166ea15b86340b8c5ebe5c1a183e5588e66f55905086313f37a409e89b47db31ae97453edf69fed7be08113071f374b26ec6043f2a0e9cf8bad802abad69e617e76243b3cc034b099d8729ee407a53eb03bdc6410a039504b3b12c819b64545d405c6a4f084921935bdff4130ae629d909626b062676e538eafdffb1d6229c0889d3cddd3365dc3d6536f7248c49317cb50c56fb57855541d6feebac816c9928fa662d0ae80a0f39e570bb7d22416f98f371b64247968951a8a246f74b3061743c9af7684bbb966ae0bd78a810493ea4ccd71174871c82bb652b2748e5bccb0ab6388a50f053a048087fd97eb15c1a21b1ee1825e54aa130d66318aaf661bbb24763577eb37d310e219b0a9bba0375eb9c9b4af8c4b99a3699e0d3266733b6e4e9c534490a1341cb1990ca5b1c847bc8126026fea903a1f549d65af8fe02a9163ff8ea281e7226243e2a153b921851de10f7
SIG: e842b49e533dbc92998dc078e59793a2c2fa636bdfafdb48934c93cf34797102938d137ab7ead1a0f70e94a67d57ef6a02c9ec77d71f70cc57f1533bec87730e
TST: 902
SK: c5cc0b95818c4bf38da1d65f021627e9e57d262b02ec6d917a7d46b11c7fe48a
PK: 457da4ef14519d541edf92cabed9b04d8a2f2afd1510a92f009bb4e8754f1eba
MSG: d6608bf5ac000ecaf95fc09f9cb7498c518a6e0255586e6337853b1d7d9d7de4dfe1245d59031a317d4e2b6a73c4c3f95b582e72a6420221587bac120fb8ed7348070f2860d85866a09fe756743497f2119bc1bfdf573be35d1091be37f18bcda6741c90d566cc924b72164b749af9a6f40f71d3ea5d8764cdc81714bd7395e5f679973636eff1db1cf0012983f71a2f2b12d45a294e5a389f4cd2483eb39da0df26b736c7af6e41dd35a78e45292c394e34689532888721f863c56db97da1cd10a66a20a670b27fe8ce5568a42b8937790c7be1aa420d203d7a885c1729cd6b8e197189e479d542cbcb9b53656f2b9f539c325c34aa598fd91e7df70f9a74abec467654b1c9a3d14438e7c0836040b793871ecbe9e5f6680ccccd5d4696a87e37e89eab28b6bd679e8fe1627bdc9d373b82f52cd8c49be9bacdc630a32fd12835255a542fb7b12393779d4498aa06a0e7e1a4977939817eb2088af1e19bb0e5aca854c125dc603d835736a03d938051530c9ab1aa3bc779b3bae7450ef57d1b3fc093a37dbe9d1bd6d040f2f8eeba77f7fa88c149f065c7ace33277aa9969c266ea6d85cad62cfaf5508e7032716be684a22856413e0e65e42b6e9e6d865a87363cbb62d5bbb6a3731ddda0fa6ad0293af9893c09a9e743090f2cee2f4437736dd433e2ac7428bdc8c77cb9964355fa4415cc3831d8c7ca5af93d51752e718c6066eca1426a87c29808281a85ac7e0b4044ff6e280e28014b9383d19c9d387d29dc14de433da260784a4944ca76c2fe8a080d0996d9a6c2a3d3a7077280edcee0389aa8e5365d1d9b346eca0947b0ff5265943ccf09939a4b4a8f985f6a5e72723c795da0bc360dce501f673ab6ea8443f129427952453eb72b3a8d0d976c278c5bd1a9853c918e0c240c3c734932953fdb5039fbb04687937c9ff0ab74a16eae212bc6f20e700a77c092d23d2efb580e0c19d65f304129ab8e6cc12e58052257ba09449f30d3d974391afff5633def2f5c4ebd573a9e444bf3a3ddacedf02c05f3cc2e750664a84a1d24c5d28b49670de8a2f2090839483ca38959991a7d3727e21a15e82016c15a09ee71f4f43c0a608b48485c9934a38614794d6291daa39c01c45d3debe579b5823bf3406404b4c80ee6ff342b46b334b0b883b40bfd2f9a53595ab62fd1351ebc88308370497218dfc98ce081407da812a46d6497d7af9ec6d83e1c60eeb712d889dfbed0c805aa11cf817dd8f04396ef871a26112dcb7c0e1d2e68
SIG: 3ba0af8af127c4584826090ecdaf485ebdf07b82bc499c9a2befca28d49344974addbc8d80a52560e0f3d73ff5cccc72c74b5b47ad2e6de9612d1a00aec92701
TST: 903
SK: 61fa8677eedaded69b165c8d277c978249663028301df6163e39b06ac2f5625f
PK: 87339eb57238db2e4e60f3c28a3fd5fb611c65fddc81eed7cf7771df34d92267
MSG: 02c581dee03f2c603935af5eceecfa677134a3e0aea54fecaf4271fb52951a27b76877ccd49ab486dfc227cf31c9d957cc97306573fc7fe1d31b6c7df3d780f3a05ca6395657a9424342c9c6b703127e038df0792154e30a49476112cb92d0d5a2d22e895752a86edddd912fdc81b1e64a7bb750f099182132ee4823fde845802a944539d412b2a81a15b00071a950504c5b55a71bdb8c5a582639e855e8be241cda1ba6b3b4f64554d17824904cb30cd7efd9ac049e390bb79f53598ef1e8fc27dd7bf599c9028c9ebf92fc3be11df329612a228e0f5684687bf41ff203e97a7686126a39366bdc26d50be025d5187c6ba0666e379be4a80a9e62effcd916d7f98de651e00b97adf5d2d53daa7f8d695a291560755c744482364c4f1fa47ec0b1da161aa388f9597989a97726d3ed2cec82f1a1bbc4ac0be0a00cb4a8db1fb7c14ba05d896348dc0559d2a90beac2041dd77f82d6b12aeb2243ca0f419a57d3ca9c7d25a30ff0e8bb0d945155d1b36ad107b55beaa95b7d5e32003407629f1515f8a7089e2488d0d7544c2f7cc7c7f0985da42840d4368ff4f0fa4fa298e3b7229303aba514ae94e7026535a3f426ffbb4e001cd50ed12f214b3abef96e301635c987b133fc5e6184e7b7572bc3d99a4523cbd5afe593cedf4c9cd02ff2e36237e4ee12ef1a22d16d7cf4c072dced91cdd26ee144cc2bef4950026349e9444784081fe4e0498bc75f72e6818f459bba9049c561316c9f498e7b1a994b0e93055fe73e444cbdf96ac35e9c4e92e6b49e3bc0e99de1716df8eacaeb8d2fd74870044cb39c0e367a1fe32a9bb2974416364e730d5248dfb1df164a8d58caa1005fdc91bac2bc01cc77decc14893ef946fb3c81be0832c72fba372062f8360f4d8e6d5b741cf7032d8d89de2edf4c714a29f75abd8f5ff43ecdd4b7a04d7db0882d16e74473a0fb79db444a78ea44aa2631b8c0d7b0300d55cb6ac485f24c0acc647747c43db3b2a8677baf656fa735a575f1813f3668a2aca9175711b525eb496e9ef9711d75f590c7d9ef99e0f59e8483cbf9f284e3f5a33ee7781e62b8b05551777efe0fbfd19e54b6bbd142944bc2959a82ebd295d23d3443b6ce658c2d579a7637b549520491908e34282ec2716972e6f0353929547ef1537aecc96b2df616148599b09d9b81394a13fe7db86760b1e2a060efd484e8189939ebdf6f21640d89d8e736dee082ad72a0184adedd8df21474c9f526bcfdf7e85658194bb6d942e7f3fe96c23f
SIG: c04ebd11c3eb09396fe8d68279510a9efee391abee4081f0d275674a304794835aad7f3e345bcf0af8027f97477e79e6792b8f299846ae28cb13bd887537990d
TST: 904
SK: 7048c6521aefafa4eac6d6c3a702b9525480a66482e4969896757f2cd1ac7d5b
PK: ed93113c1643a53aa064caa631ceb6e20f6d6ec2fc6c0711cb8a1fe73139af93
MSG: 53f74c724db1578a1a296a7ccac904a2504dd9005389b4f8d4ea4b6307298fc6dcce98a6bc07280d20364e405a467e736578965269c81461d61fc6b7e4bad68d2b6dd0005850105f0a67bbc6ee223ec1754af4e3b9afa5062d1c1861048f185b128f1a5c0fb25c3919b4833e29e202bc941a905e63c2c05b1014647bd7ede5be9f996615187a3d3bb2c7dc4c28f7053def9b28b29e2331f16296dce8f1ede484caec996702bd9902e52684c812c87440f69bd141c7e00c6947d1fc7c3bdc0bc5506b6ea462e65f9e743b72c007ddc7a377493777d4eb12620ca6c019c8bfc4c29ec8af382fc3eac841021a74e4674ba3e43e5d7b41e3feeb17da00a7ce455a1cec70b0be6e56f85fc37f64cf0733b7e31241de641a8a8e5b91897bc158fe93d102c01d1f5e166d408165fe3fcb13d5304590ab8ef0dc8d5a8c1d8a93fceb854fc1fa36d0cc480cf8512d80bee69b0650a957daed283cd7638155ed773086e86a8ffb198acc7423b5d1a609a175a56b94c96b731851b93a94977101e255f1ce92e232a05e2e3387fcb4dc13a31bee6ee25507322c73c9883080a74c00f803a998dd530a79126bb144ed5574c4b23180e34e099283b4bb1d28822fce3717046ff32ef9e2cdf967e318ea726a2aeec57806643ad4801d3e0da52a1d77bf043f5ae9f3aea9e4bc4fa795d08401085ca94cfc4ce719dabc7b2390d03d294a65b7af9bc39072285b777b2f133dc11a70c0a9f060e10441f40216acb641637a2eadf1f7b8d262fec1b4d0f0f4faa93f3f732cac382d8ac42e178e2244999d764a9d0e981714686eb4924497e56b50157e9939032c9f88eb657cfde44ad34714af4a51324e5e77d0deea99c9f244d2e09ea425820a746d883a0cf4b705c29df8c037448154dc08a4d4337405fb8765823114370b37ed86086ec5f8bd6c72abf13f518430710f597b06108f65b30a483496e2ed81dab10fee947fe04b5485f2e3074049d22284266651ad10dd086aaa5d452e0d1a61129d1e77c663c26d088962b5545645b7a1a8713d51327a7a359b12daadb85a2cd4b5410d5c20267fa766b8c42a84dc42664588879b3eaefd4cc8dc693f98ac205609e570665b01ea4655e39429a7a7e542efb4f7890dbf4e34c6cff07e4d35bd3eeedf5b46280f4a0da0c2e73c94ea81cfeae7f9bd04fe2d45976500f7dcacb0df2a5dc736a823671db679be66cb33c162fd2c74ae71fbf4d2b05af042b3a977f5b944b9fdb6c34424421bcf4f6223768428fa140fd4
SIG: 7c45703ed3942e44041c7fa1858aa5f1dc381f493a452dfb52708017898f710e31118e331f00aa64cb738836682b7d177e97955c00319abd79a49e0fcd16fe00
TST: 905
SK: 3e6373b265b96789007ad2a10c309a567638f25587d77e28b0823a4f179ae4fe
PK: a3234e5d13b03472165036404f6de80e702839500f13d9c985a077d45c69ff45
MSG: b9d068bbcae7722f828b0f8c98a738e36a7df4c997c724ba27531af34a2f106c7513a44a461a9aa4309bc15c4e0d42759193ea1cdea956bb815985f57867145e9e2c7585fc8d61027e47d2d735e2448af3782909404edeaac0fd73f6045dcdb04f0377758f02204aae3a7220311c0f4723582710cc440c36c9587b5c9ebc4063fea8ca3f43195894f79a365087137282302dbf2e7a0d411ab58b7026ccde198869aa734334c05238e275e3c3ab217083495769e2fad374051452d7f5b1db0e785836d4bd5e2978a3e991af0ff716f43889a07f5df299603621c39e2cdee089985d9e6bf7b2fbd02373ae1b5e9b88f5b54a076e676d7790bfc8f57dcc59ef52850ce992a73ba7bc991deb4dde5eb0b21670b1b3d4b64f36cca8e307098568497d8916f6b5d0e9e89f99f86006f39bd3a810769c8f7801773c9638abcf5e2711b19d1167593acbe85e4161428997a2194dc5e7b7640f0d2c1eb205553be9167ffbc22b7c2e7698f3afa10754cb44d4b1d45b837303b1669073415a22606b50f21f8265e139f2305ac0e0127ae056ce8abeaba20e1d269a2b2e899c49547268a0696ae450dc0267f7f63a8edf074c47d3c2db1da36393737304e6dd4faccdb6ab55e5f8520c3dff5f6beac30ba85b86082351e3ded8400aa57f650c0c33036d65b39b7d2fb6112863d59b72558242e8b045addd357de6fd37a8f6611765c9b5ff19cc4db7e117c65a00458908b0245d04f7908fc73b165dff6e4be4b42032d8cfd7d6f7772c1bfe721d4bcfe2fc527998f34fb4418a1fae1e6c3767c4d0780621f923da1f0a0d3d219c036acfd3709dad4cf24d90bc691d700e6a9c80ccfd10bde8e791c0fea82880c07baaaa311eef79240784f628a7d2a09184e016f81008e77429a8658b153e44e79a98ad248f7fda23b590d646d7c1d841f4927d6e8bc73214d10a7f3c29c8f839a8908d20a74e827af467ac5abf0f1d0ed39cddd969dde9eeb4a4b7527ab3e2475a195e24474a4e36b09052e2dad4a5eb4691e263b8c61bbde87772207e011c4c1e14235fb24e4da438875d18530fef902619dd485d77b545abb56b69c755afe758606971ab97dd3ace1c1a34a33794c8156da799e8224d885e1868f9cb466d802c827cc3e1ecd0ae6e0b01f8f791b12208fcc0fed385b796eb2f2908b58d30b3733f1470f2e2ef12ad43feb72d0816de3c13a8b5a523e14cdf5ff3720bf87769cde7495d226bf38238a825f75a09f6bb9afce516a7bc70114370bbc40f17c7bc
SIG: f51e0f878a5a709647e85fea839fd566e6f35c8a6185d0c9eb13e0d5b9e6e8aa95c333a8f50632a4d6657b518ce4cfde40b8f5a05b2d9f8441fcc9d2d692d509
TST: 906
SK: f5e8597eac0ebfa9d385de85a1fbaa35146395b13457b5b14d3670daca6905e7
PK: ce93e642c2f15084bc83bafdaa196763de2a3c513b0e44f68ddbde378514c441
MSG: 273341f219ff5cf381c77b2dd226c58f8f33c4527048cb006affef8cee151e300efef629fed21b70451f729292627d1f3f1b5257359ee5a671cf62ae57324940f2d0b15aac76ff398220c08024e29a8cf36504e12a4e96438f42c3da0c000541bc11f091381b0b72b58a92083f446eca1991996878de35081cc4ab90958c96cf5c99796cba7951ee186f26527aede69db304ce2941ba15cc00ba2f1411f208dad45e87bcf638792de0a68624b667297c27a343db4baf34a0228eaf0d1022009b5d068b2534d920302e71310febf0df1bb02c2ef0ad1ae149deadf8c184373c0f7eb6b25695be82d12c71b6c83267d9a233667e77bc205983f8b8d877d85aead3f60e820ffcb17adddd92a7712bbeb34ee71966dafd9907d193dd9d725a31a613d29e32be72132808926d9437477fee25eda610aeb1dce12ea316c6aec6689e501c551923825a34b42c4f0675b86ab26adeea2e60dae6c6d1cdd0cb3c347b16384039a8e3fd6087381387cb4bc72ddb5f25b374859b02e5bb1ba06d3cc69ec44cec4b985c8476e35032e99abf001a1d44ddc6e2889c3c2c3ecaced609b2b2680e00b1efa7e9d26d62f2b3ab36f921044790abbd49360756dcffccf230f66dbb701aa164dad6069aa2b8b3309f2fe44d5e0b25bd556431f0df4c2ea97ae79ed4a57578d66fc6939c57628a90cac97adfa8702a4a1c8965ba1a90262567286664003003533cc9314caf7d3b982e0a432ff5aa4ed5741983d9b54323ac7e299b2b4956c1a2c191557b27d86be714b5b68fcb1d41f78ca5ddb6b53b3dfc8e7d6b3c3db059af9f2dd765ef04b6d16e6737c727aa11f3df3774a3fc96182e282acc3d233eeabf8c72d3f246ae184505288fef39b36766b10dd1bfbfbfa70f97b3c901726d1e0d0a837d11f0123a34abad1a79aabe80b125b128ee160b511848f7f04c49c8d5c2f2041da7d9599c29b1dac8c68077efac3eca58bbc1637aadce21c774fea42d2bcf4a0b9892307e36fa250acee795ad2bfecfbf60319b81663e2a26571946f75a8d969af16b3b57c3ec3e66158aaf42ccf5e58b937aaef613318606603317e5aa318be70f8da3c0c16be6c29e3ec9fef4e46e8ca241d941d58049a063d90afc953ca32e8a50a6473632588ac41eae97f20ce9b741ed41c9a4aa6551fd823ce0c811a5bb5a171c1ea4238a0246811e469cf498b79621c323eba7985344fe11e67499edf4967491aa749f8f3fe39961d76892c93aac3b19fa4b4fc174d7d4d4d8bd6ee475475008
SIG: 576543fc21ab0a7c5f63b1cff01bf845df91792e7a9750c5508b51665e7f89f17c6ec3355a0aed87db8c77bdb271fbedc714ffadb78b5e0f978116771ba7cf0b
TST: 907
SK: cdadc5b89cb2b6308a006f2f4e955a91aaf3ba70165f2d444ef1ffebbdaaa221
PK: 0541415ff5467f28ceac839b13a1766e72c99e6545207d9d5d9697411eb6bca7
MSG: 911727036db309d6e2e3369e4f17d98d99ec070c33283bb1244efd62e76bd70a69b9723bd2b520472b98aa065924366de780900bcd8b77b50f87c3c36187024bbc59ccf4482c7b4aadb56e2e5ecc0003d989d6afc63ec10242e57482fe39215261d5fc95a0185f95e9540c55f74d696048bca7ab112681a5558ea93c3b1f1cd364659e9433ceeebe054ee713c47760d7ad132a7f3f8fe3d5041b811a26b65efb1f340e181a4ec720ea136b3af3d9e5461dd24370336f10e6354c8c17acf9998544cec0873efa687cb132aecf70aebbc567ba03c536499ef96cc8412e7aaad5bf96422be47cb9413645df2c1703192347dcbb123127455971ae157e9fa2dbff88745a96c658b865e41f55aebf98395005ddcbd5983e6ae02c4fbb5e17916796325f76edf5b64afa4ec5a7418afed23a97efade68b6a5b3145f08a5d3db9c298a512fabdac68562b3f55377ff44b00c1c2f3efd18132da71f971a953a9318c57523361a160f9b7e3b51c524e95dd5ef4568ef18a800775e9d26e07131942d2be4ef22c0cbc13df01c68b1bcd3bce9bd51c4ced652adc4007be43b37c67a5c55ed4029e8ad15def8305c968621aed4cd4bfe079a6f48884d85680392ca92ba6e12fea6f4a056f79d67b19b05f90d684be7d45725f7967c6a467af43b86a6b1b9d9eed3a4248971c76a7ac29c292dfba4d75c5f7ba709a39058e96adf6dbd760d3cef4024bf3edc441efbf1147a2c108bd6f9eb439c1c5c4d3a6ea4ec3d92cef38136188bec9e0b6c0518d8b79ba59c5dcba393aedfdffb0b70d779c2b9765ce4452e7e3b08c4402b1a608320840fbe96d1eb8656eb1c20d9551ddf533b9f15e4eb5783756c53ddd3b14d807f838ac9680f89f1adfb78d68ccb06731a90beac5f0d709d5b88c75437a663cb962d37f96b8e8928477b5611228015d337f049e8b62e4dff8d0bb6cda24a5df9083e348bef12585f5f4c4d3bb3c7e78d550194a45251a0879a1624bf9dd35eb655c3939fea8909f6df395bebd02b68a17a897c9aaddd6e2e20461e303f57cdeb00ae0f23e60a94c19c771d8aa60533b93cedc1b76d2290a01bf43b2725f125befa575154e986c9c6205a1596cbaa2d13470c23422f2df7bece4e6ebd752e9389ae60857b52969d2ddefa9c034f1bf35ae3316304e949c8990820e26e6cffae4b388d1505f923706297f8db556537919ebbe3086023f12f4ded3b11acf2a6d973ddd8eb27b07c580bf448caa5a2ea116c5eaf36f7a6b17a85b3955dc8a44a620d8
SIG: ffede701eb1829ce2361cda2c8bb63338539d8ad2f6677585531e7bf1d3922382679a1ae84ffeb753fc9754e50c01852f955e3fd609ff64bf05bbe7075cdbe00
TST: 908
SK: 2ddd79e76064c2e6b322afb0c5c685cdbec62821cdfc0cb14db7d01ba3bf21a5
PK: f55b4ab64a2582212b96ccac0640e271944a34a286d035833045810e341824bb
MSG: a56674a1e1f09795251abe54ab43c298208fefc9bb9176fdb23e1e9f60f032647915567ebdcc2b869edb7055f4aba67ecfe7fa19eda45c06047c7a51848be9973251f85ff76f1c59e3654382858c9be123db8a9490c6c9b309b82d1e2ca6f4a07d00120283c6c295644995a96628612b8d6791573518e2556a688a09f149bc846a68bd0ef79279035710031ef0a8fed1dd0bf026125dc6648f86f64309942e18f23b12d1dc68c6f2770ca8b5485b369b0c92007a9461c139fcbb41175f316d4467060ab43d1222f5802404bf63c2df7e004bdc400ca80fe0d2cb68a210fbc3fc0b903209d5476e7a56baefb8fad7f328b72f327113e139414ba6f34e99c2eccde044e7a3ac70c580cd26c7450192ca4c823c7ac5eae876c0d1c8c768c1cb0b7ea41fc9b7d29437bbadab18e0f5ed1defe0cf6c0ebaa6b6d777f4dad9abddbfc0fd6ab5eeea803cfa01c0bd46f65fefa46901abbe0d89104e3bc4aee1f0599c69b67ba545ab9b54f5dee340ac69d88299e86822acddddce601122012f99299774aaf17c964edecb95e1277d462de64e9115a61ad98aa3d22e3ba6f8f1cd69b6b52b83382823f30e966bdad1ff5fc198ae32e9b68055d4392bc7c3df1015f128aee1e4fa3d4999e329f22f0ff6aa778bae0294a1df7436cb16a2bfcd74b463abe7cb4bac5362c89c9d1a378a2cb885cc3b26ab4be881ef1afc14430e10d26539ca358c3676286ad81ce1c9e78592af66f182bb1f7f862fe755bffb5be5c5f2b731c132e2388a76a1a7b1cddf05aed2ac9ec408475271942ccadd32e49d8791edf8b8de117551ce264a60b84105eae87e66f6a401d1322bb21a98e8acd277493254e504004f72c76e7903d2fa38fab717e94ce627947c4ea326bd2575c37310f3b4d843b90fa77d32d9952194150b62f850187a4fdf38466dfa0656c0a2e0b3f07492ac8e37e5d0df95cc89df3085a269291dc2512210d3fe44248d7ab996be099af64c22756666f8dea56c00b90677d1182500dd274fd0769253826d677ab16a557b08b3c52265498d85c4cb2b600ee0481b7c1c476a9daa8b88c71fc21b6f89bfdfece58da9e8d565652e4395bdf4c811b4f4f22d2b9613261f88c604c2974d3e977d140d046e1b6625b7071640d352cb7e7e65d46c613447be8dc5a200aa9acab46afccfebb6b1c31973246c34faaf8d26ea5e83be15718f8fdb0cfc444e2eb60f3659b020161c228e6b9240b7ac394cab812de10515766f22473ecca535594ce528a57cf5dab2eb32ab84
SIG: a4c396e19dd42e039184cd251188ffa245f0367c69c02d12474e5ca9e5c768a7ee3a3d47eb22d1ac9e04b704a74f416947f3f49a3242594e7b6390e82b60d505
TST: 909
SK: 3abbdb0ba11aa1063bd26b02c116037862285babd215d240bc9c0926f4ecea81
PK: b8fc59438f8ce9e3785a473b22c8892c51eac2568c681dcc77b6f0e0799c4e33
MSG: dccd55f922cd274f6975000adc8d98630c6d752c1202a9dd121048b93945af2b1110967788f99ec028e3d3b4cf82fb07173ea4401e3bb4b07b7b0b24b059a766339532d9df3e31b72c958c119d8dfa15a507af6c5f7e78fe270fa81b9df0f2e4af24bd99fbeb14e0033084d7fbf84ddedfd5ce56751d15908475df8af013d091173c1386b9139426cc6081ea165b8ce48194b8e18a9b91a4631344fe29c8e72818b71fa15c9292d13fdf5f9d18e29bd0291b8138de738fd3a36c35239022368b456f1facba90a0d80d6e311c5f6c6f04677e92373a5fc4738894dbed206c30da341b3b196c947858a6d2adc68aac3f20cfdbe0497961dae33470266d17ec719a59f0586f82f99f1c90ed7005a207219a55edc760f4eb8f2402647f6f77971ff7b634357b6b29bbd7ea05e2e25854e99c620f4b8b64739022ff0b338afef35fb6f41a53629a518eb93d66020fb353aef8dd071e09c916d4704acdf776b38ca9c59f211ff88c430a57e8f1713923b3f30ca86970a14a52db4bcbe60df4bc3cfdf254bf10f8afae87bd61b358f43cc296c0412964c4e00f71213397468517cb01379cb729c7b9e35bd50bdd98c3d3b76297a138b57ceb6c77742df0881d07668c08a630a44e6ed7eb206d6a56440710438a5111424b61aaeece40e900f5e3c457e9d6e31a79ec5b4b42b68e66e199309287cad65336fc7fe43f43cd8c773d3c6580d7217e2cabecd3eabc485c4acf47718c39b02c7858ff347cec7535eddcd4fc815df814569a88ae70f2733a6539f208c79cf4e7c4f9ea241a92e9515171361418a4c2e53c076aaabc47e4c971bd04b100c26282308857e06e7e5fbc4342564fb3b1ea4a17a925e91ee69122321d392b246965b86b54fd5c83fa5c474163f98a9f447d88cb59fe2cdf9f5412fcbeb3effac8976791c6a47b669a2fc55abe8e09e74157efcd1ca78fc10fa687010c6826c6e896ef5cd71d0fe4d1bd07c10dac3b03485edd2569a7eecfbc4e5d2ee2379859e265267bedaad69d93b7c1bd18f27ea42483c7e4100ee05b283039bfb9891d37c467ed83b88c794eab6bab9dc677892650e2d896fbfec1b1cdb721be30b0b8e5358709e165cbe3a182c93bc0a0cea2f8cf3a6257adf764534041202241a5279b668e40125fc094585a3c588aba82b67cd91d483e54300428426863a42364049d7c45a169385aa89bf377f0d32b07809b5871395ec053a257d93e48bbf407eb6091401e256546e31f9fcd24d2c5b333cf65785002f08d548db26ad1f3
SIG: 981f20055a457525aee5616264e6af42e8b387cb08f8b4a73f9be0b366f1035bb30a1c874894cbece0a846d849b7ecc556585d0d3d395645807ff2a3ca5a590c
TST: 910
SK: 8a44d6afc6c8eee1bc7d5f69e495b0b18ca7aee007dea7cf0d1714d785a9f4ed
PK: d4f366b3377fa39b36f9ae14da404e2240490dbd8d796b1ab872dfcb83a59540
MSG: de80326966536ce94996af2de7a07605cc4fcb9e75ee0a67a1e20932111de9b356d5beeae86cc5f564c10d66e3de95a5b99e844928ea8e77586cf3c10ad3633ddeeb1d9dcf3f94b70bf1ef63d238df204d705c0b174f83282545f5e4075f8d69a48179c29eabf5c1742ef39e1ad963bebbb66fce9491a984651215c2e750e6ee8365766440a84419e52dcf671f1c52eaa2b9902bcca4b37cffdbac8e7e7e6b0a5c8748efbf452df6163f4ca07b61f9a05ec20a2bd633389e670bb5454acd6f3a06335b5da9ec326264e962c7d9d06ce7e9ff04a0a5bbdfaa4c410866a572011651439f2dbce5dee667924ac4934d205496bd1d4df08bd0cb3fd2de73a2ef342ff0091e10e15b3b760a575df93cf1c97c01c5ab11c094bf34878206718f6b285aa5cc5127bd7f988b84a90495306fd9e99d8955e668d1a3ff10f65b7c479fac24119a3c10122d4d18a805b247df168c0a5100169b5572d17012d751a42e83376115e11561c160c15efad76d21f7abb430366475238631f84c88f838b0ac404c913d2fa12450238485c302fc201f44151c19bcbdc1190c12d1540831fb19581cb93172b0d2ff5c65f31caff20f813881f84e5ef9d5c165e096d254cadf895249aab8d4496c940a40f907bd40935a94f5e55b6dd051154100fe331770eff2bad6545619b8a33ef6462a50c0b2c4ed2fba4e4e383ebf2932e6192766a4aad1d6e2b692d9f2bdc23393e8aacfba323b534f84edf2dced7c94d51687daa27198a9144b312b716fe17014a7bed0c14a2438733d555c6564c8c1a3d997ebae7b3de8877af53c1d1a5029158a80aa0c87489fef270cdffe10d34b15c1a9693ae0390243e314cfac06ef6eefebccf43d42eac24ce9879429d2fc7253b3ed175825bc4da0762b4933a98afdb94b06f4fcd2ad3611aa999d7c1c8d852d01dd9e52648455a04eb2330a76fd942c531e514b5ec0728a89d34ca590ea99c88faa20dfb7bbf65654aa6c212beb8ad6bf7c777391cd49c39cf8ab51b95b419e3dfc8d94a93a1ef0223c6de90bf96218d8045bd4952a0d8372a5578c6aafa74ba662e3188e6a6e567e4d2fe8227d0743982a41ebfa0d310fe79fed27041790efd5afac2243e1d150b145015d9deab0eded6394ac36fc5fb201f5204fbd422a3604233015bb0a48a920e2e5e0d4deed672025f23cfba93889597e504c8887add46cfef4024afb8a26eeb7dcddb2397b44a1796367340042137028c3307626816c2931e61ebb6b69edcbcb612c9b181a285301ce46f82f
SIG: e0727eb72e84d2b82cdbd0a6bd2f49496316aae8351e4902acd5e3cc57346e7ebafdd92a90ded76fd0c6690d68bb2fedd613e44fa222be0126da520acc2c4105
TST: 911
SK: 8a972dd0f1190c2b9d548f4ba58264bb04826775502a8d5c2b209ee88dcea5fb
PK: 6d80375f3cf1aab283551df445d17e7d3baf9bcbecbbb267052e02fdb69144d3
MSG: 30b28948939aa263437e45c5c0254fb20e617ed0f3fa7dace5a0a8e0fe3c1fc4adb2809b61c5e8d92cd2f3de93b173be707bada94240c6262c160e8c782165beef99d0be8ecdad6316dcd734bbb90a66cbd5b1cb4fd8f2226cea948e4df76bbe251d478f5c3fe0d6de4be54f67f502b2804f628b79a550fb1ac483ad2ba16637c4bc9da67fb4f98659c4c4394d16b6d14b3e0b0c1e625d710dcc1c11df5d34147b1ec5a417b9e21f908cfc523d43e3f181c7209cc56bdb5a21628695ed320f8d4c07fd6d84aa03426f21644aaefeeec311c74e9499936047350a9bf5b703962e77ce551336835fc32ccbd2c90ae52e24d47d8dcb987abd121d3f746b5de230f26469603fb0c4a8f6cd7973d7da882ed1d6e4d9c5a46ec2c21940ad3389a186014ee97278e5350988b15ecd9ea7456b3cb55e4d3093f13a875b50d6516378ecaf58d752c6374ed15638409311fcd379d122c8d8c59b86f4e8dc46adb730a933846e0bd248d3608252d970b504c813c6dea9fc88a3de641956dca291204d390b6b39981f8c0a6bcfc31ca0744420662a9b35eb3fc211f810a3e8062500b1e49bdf857665ff32a9ba76194bbb77fb9c15412964244b9865f73ded9f25b49b425aa253d807d9818292763a513ec80747344fba0acfe593cc26b1330bb9ade66c4e88cf1baed6d6e7b750e6c7239d7bcbfa3fbe45405a63b96d5034cc0c07ffc3b50858081d1955e2d2fe5be5fda7a8996943768b055170b7fd52f0a32097fe1b7a94f1bf879a0cbabe10ac9a7cc1f9f55068c48e3ccc065136431018d38d20109dc95d99cc2bbe7c627ab1a8aa5f431613b790c2e6526cf04fdc9e55f51c055f3c2045a675e3a1e54ba409f7aefa7e4aa07a2bbd5e4ab16321a9f099694391fda68a74581e2f1f11dd9a6d524b1b83260db57b72ef29c28c8db5c37fd185b7c2d8455090653af332dbc82bfb0db5dccabfb6b28caa350525cb54cc84e553e1cf3954b612393e7993ff7e8bf5ece3f145094dd7a27cb47f227476f289235251f772b3ba776bb773af0cc5f786a3fb9e931a530cfbd891cb5a5dfe25169ef933cc82c9080f323961a120158e4bbd71134ef1f90108b815c289d4e9a9589ec64c05fbb42a21b23d16e2a64678aecfab65cd9a806c598103d41f7009776317831feddd1c9002d4a92204f97ba9490c61469803072102524b9df519005f98af54d60ca5ba60b55b096a4ac2b16eb9cc81973c3135d3fb6873dd9653800a22bb5d0d6117ca5d916553be39c9a3b511eb3db730
SIG: bd45b3c045850ebef7b80dd1deab48037b1346c71deaf1e58f2a7b162674f94d1ef3d4239037330bd6335fe4f0149250901f00a8e46be5fa0aaec69de06d7304
TST: 912
SK: 12380c45a79ade0f483c881aaa3730438b083590f404dc9e601f7615f375a628
PK: d66fc59ae917f76d24ce8ab8ee03fbcb715d5eea4b08392b591e648591c73c89
MSG: 684523c2e7fa8b4bd7548c4bacaa8678a330dbbb960632940166b2cc9afc1535c80c112c8dc4ada7629233fe909055237d513e292af15ad7692f115aa092da657532f51899c3f7f5d9d407ed5c163eb3950480a4122a0992981f077bc867f906075407ba9849c4ea0473ce540a796744efa3860378e1b89343e583d0807e5a67c4d5bd7ce64129fe902b8cfabd2c21fa3d2a10e9bf9ea5e5473ae250c9160509972678f9a740e6cadb3b52f502fa616cffae1def893d54e41e54d326464c9f435c63505fb15e3eeaf5021c65dcd010f840aab317c8605dfb1a0c8a3d5549861b69af2c93d86c981df3a51c5bf5785c2f852610e44fa4ff1c7161152e5618384744fe83babf0bcb7561789a023125f6242a183cac9549c932733a868aa182656e2ba0a8c0be106996a85cebf1bdad123b982b4e055510879482021daea9d8f26c588e6cd10126cb3196880356bee8f298bca306ec5699c7576b765087c253a60214010c6ed70d871cfc8738018a0edb57f106b4218d855eab2c91f39f858b3f25905631a0eee29856fd34f7b8c9ba51c1c4c6a735d6c7a13d220d7a566c3f506c72bc7417ab37f0d6d796ffc71df9dc7c6e137da56b7a3e10cf0b1abb3ffb70bc66293b5d75b405ed8bec0d6fcd06925c381168ac188d0b8a1af0839f5bde843b6991e5a5d6cd66fe6b0fde867c086ed43876919a1b7233d8d7e1d2742f61c77d8e5991689c8328676655b76a3750560e75d1c7e85e3c0085059331094bba5710032cf679a525c78b31700e6d91f75294c422489297e1735943e417fcd35580582fdd0239b51146530cc09d83b28f0a1d642220dfb99bad62f39541035081d65d778ddf3239ba0e6fa9914b17b397a534cb8fd3b4ff42a8d8c8ee66153fbb1ff0fa54f7bd03278516e6341af80fcd1fcee70c359d205368ac490d75a354512da46ba7634c15b284b24477808f17633360a4b49fb3bcaa841841cf92417eb24ce482d5a24bfd2dac372231da539a05420002ff7a20c476097da06f59f03314e6059fad88c50c3baac03cefa7cd8211d2461b1660ea6bcf476838c91a10074eb4b40e6e974a945a67f6ee6904231ef04188f1ead5baf35694efe301edc7e866da23b5a6c58f01b2a52cf3ab805edc5c1368626b95b94eb4645b693ec880f2b8117a693afbdcd2482431890f410bc580530fef375879c2e46049ca891a2c3ecd6043ae80d8af346634674c6dfe905997de5d05d62009eeed277502fb5a5a3155eeeeb67348b60d89a34a7812639f541ffe
SIG: 02b25174a3dd5219ed48b2c94ca212b63a6a3a2597703c07b7f0c965c3c6ac2eb450efe38716a2a28b3f89846b06ebdca4bd09aa581f24e84d80fc10ac1a000a
TST: 913
SK: d1b3430d4e63aabfa9ef96bcbaf1fa6a9eb5219dd44df3b1a61563dffe1ccb28
PK: c28a05195245290ecd38535585ce51f3c235c5d650c8c57c2f79bb0ac0e80834
MSG: 076c0c8762e4bc003c360a12a19598050551d16b4b8da0fb9c4afcc81adbe61995f25cbc28dca420bfa9461054d3ee00ad78183e7f26df6898af9a4d225fcab67c042e9a13525d1f75ff0e3d8da80896b728f3e2db65944ae0717d775990b59e5b70434bd4b3ee452f10ac0610570b38220832968f544d3e4d119b1d4b5015c6cdf4cf220b56b5c0ccd8e398d5e4a58da3b0e2b270a5d39b82abb7f9d27a419018550b6200ae51c84882f086ae7ea5351671b6dd960923ad6befc13409879a8df619bdf6c88a6fe1ecc0f0f3aa219fb61902be48a53df2bc66c56f1c1d17f7e6167d255165f174baa9caf53c73cbbb7cc2c7c087f43abe2aed5a21fe4290b8d67960a8a9cbc2a57abe22654dc184cff9168bb697270375fe88d5c49cf95b06cf9d0dac81fbd9c0d7b82d05ed2c3fd49ccc29404441712545f9a991e4f0ddb62190838296f967299a38607226d8a681f0a8f3c4384fd18b30257c463c0abd0f4f6f1225a51b762d6d0ac7d59cd2efd698b8d13e23d70409f6b07d695c1671cd6f59443b1db0ab35b9dc0640e4c6d1ac50475d28ef94f81790e2e5b2545514b2a49c5c2153459be540890f53bc18e4a16dcb5dcf50f37a95c606fdf48598e52af3179a2048615d93d97e0599b7088c1174bb9f15e37018f99acbce5b1302f8d8ce2ab85437feeb0caa7784dc83c9e7c36fe059906b030a86a3ded0ab9d8b73529d475e661a0808d6d3f0907f8528873f08d5748be1d69712e85262d77bdf13bfd18a5cde6f71462673ab29b1617315a9a6e936a8e81a8e43bd0f6644a5c69eaaac89bdaa99cca803833705e5afa69b3bd1d0252b854650f2199791e6aca7c75a861283216233a2633a6aeff9d301ee5cb4dd72c08a45cdae8f5458c095b22e759c43b49b98e9f4cb33d5dea879449eae73cb874c73594325ebf68c1ed4064b6f61ab2f014a2f19f32e12b33c5eaa8a29204d5eba58dc075072fe399be7d1ab1808208fb408123bdc0b4ab3130f9f706dc3eb194b605e73a32f125ae491285ce6039fb623c38b81d5aba0f5599f6c86e872486b4e9649daffe3a3d06cb073dd3bc6f4e10a18700e45722d78a6b0972dc94d5c7a7b6641757b796075719d7b8ec36a1e796fb5f8fe6f1b79a0859cb4d67cec05ed914cfa32c1ddfe218ef963436c3a1148ac2cf909df7359890657463a4ea25fed59618a0681a1217e22d64ef9d9b4559d0a0f6b3ce8d847930b232301caf44cdf7a3f18a2ac130b92cfd9c03360557b5f7c4775462a1071f70344c718374b
SIG: 4cb6ff5dd706b1ae816cdbaf9e9e1edc80a66284f94652d50ec14e283b2adc592fd084337144ffa712dc34ce8e610668a65e969f05ceb54786304d0d58d31a08
TST: 914
SK: 033e003d7aab7bc7fc8ac204c733799ae553c3fec53f10dbf795b5f4b87f1c95
PK: 682f46f5c056dd45ba0b5a782031f9596a73aa292ca2326beda74a52fc32b716
MSG: 596aa2c40b3318878938ebc138db274bb38a5201eb7caf875e6c645791dae012bdefd485e6bd9d8499c42a2ae86cf32b18002e76bb582cca0dec4815ded8a1211f8fc8857fce1d57f6151d88787b978fab56bf926b1533e19499e8bb99158cdd6e980f6ba543ae831f9dd134b0fe6d5c24887dc7a8d4781dd9b7fc5dc9464b045cbf9d1ef5036b5bf28b549ac7aa8fafb91adc9feca7a14554d110e310c749e48533f359c70f05fb7aedef136636b8ef7223886539864ee52d34118b4b8b74e08fe6b65896e4b19b6d7c3f2528265585481710d2d74948eb4b1708a50fa74021bda4b361bc68d2a5d202109f8d28d8aa67d78c1136cd2e903c8dfa175af7bd963b73dae495873ccdae62bfef885636dd83550ff9c05c37ba3389d1543685d89483b0c104e7efbb7702c5a0398ac720484c50936835ee9df253f0ef8cbef3e07de969511ccbf87557493a0b972ef0e8e629cf3822db21286ed727661bd31786fca1421106dacdee1caaf49454e854794f704d22a95a4c8e6b1c2feea57e56238c2096f1cc578647fea544d6764482bdf5148879a25f943db16f29021b9ecfe3e090b425c81c7009842e1c7a02d91ca60c1201c3bdae9c5373af03f2f4dbef40de8d9b21fed68dee510de0427234caa1c20a3ae549954834c93373d913b8750f23a03780d7a9454ed6fe51fd2d276b9d4aa32de05e03816e64e9466f4f0e224651428d342cbcc697170a47ef996bdacbce91117ca1f8455b25b2b08443e9914e3d90c489eeaa7731ddea2123d55d67b16683fb7c8236aaa5a1b0fcaf8d170011dbe9aa2857be612cbb85ef69e56831b4dacfbc7a59b465a66dc7412ddb3d6af4ebfd705864e7d4fb99a6ccb48b118368feab02a340c432768de0e067871e9ea808d6d993815829e71f6c042b664995098fee94d543df15e5b16957031bd238bcadbbdcc576affb640303d69c5b250b3a539afd127f7ee2609e52e5154fbdff3e45f9c44066656d561e0f64dff2805df88e30a380530822413a7ab76a1b9a865378d24763069a814002a9a9d03795ca8d2b5bd1090393e9e4b1ff7d7f0eb84e712a018f68c9e384f0a0aef3967879284f409e30d2365086e66952278ca9b6f90e8f69a48d9b28bb4c4ed632abca3af4144da7422bf51992f734731453c7a33e15e59f5308129d6a774a94586f723311179176c0948fff4e30c1b959812cac977cc74347b007940f2fb962a90d66066a6de8801984dee4a532d4b0acd6dcaf06727bab70b3866232234c9100bfdc669f77ca49
SIG: edb4e020d676fac6a845534880bf6136374a8b7f2c5385bb9ee225381f494efb74a55b413ae0ea70add61bfdfb87fb42d5bc0c5359dddd573d538ae93a6b3609
TST: 915
SK: ee55fcf70a275c726bd4856683b347decfd422f1826c07a932cb85be9fa4ef3c
PK: dfcffb5e1553789d56a9f3914bce500d07c5ac311f927854b2cf1e5833c03237
MSG: b8c845cf7c5485f0622d1ddc17f7a0f6f0fd7074fe194b0e0cd42650cfc817f57f095f8cdfad1ebe0dfbc1bd7617ab4f204e9d55d81a7c8a433940ec6f17c8a8e3d56c1afb0af374bd32d54ef7132d26b89c470c2ab5be16fabb4c75193d6da59ba2fd157e9ea4e0c5c08a5202f5edc6a61701f08bb344ca6455d75d145adb244c534c8cfc623f4d4b6767594b39a7690beeec4df9746a57ffee051454c4278ea43c810ff13cd769615f9d05d4fe4a51583e80c015dcfed9af05f93d054d34ffd939bdd8f0518fa3030a964dc9d80df00f1635824072cdf29bc80259209d50f56fca9fbd6ae1514a671989cea4f6846bc19179097cca40c624d7edbf91fb5b2539ebbd502d3646711430bae423fd115848093318b7d087ef1e3b894bc3b9ea27af853fca8595d36fb7299969162f2ed6a2b55075b2c630802857176dec4cb5acf2b13a35a9949b912bb57d81eb0c8a8adf3cf64cb571bf5f3d71f987d64d74e919a00336e57d35ee4eecfc657000dd5b12995ee1b116591ce58e56de25b29c94829d1d68521b9558e4725ec77039069c0cd17b2a003359e9e1e112c7590176cebce7f001f1d136e818f4818cfd94745afaab56f1a406f97dd9e61b735266d682ad7df26dd70cde0b57fea7db2df832fa88a35f539794884ddc41218403016cb6d5221f3feb5d3aee4a9840a913072d29f8d1a9367bb0bbf545f7dae7c00a0d0c0342231ae462bb742e1498ee584ae6c83f2f1f2d0452bead982268cd3cfde78ff422e226bf7b2af1137757797fb02e5275c34809d54ca9ee2a65275e6e5cffdd20ad1fa1ee0bd8b21e04ce829e02cdb63c48bfcdd86d3a08c59789c9d78e36181defeb7227107275ed6b5ccb127cd72b374e17f5ee0b5e47b4b3e14a8ec6d86bb7507187f28db32b3f3fa1ca13446fe5253ee783645e794272799a863b4fca99e443cbaa05de3c50edf3d5cd7c10529c6c09a0c1453406ac7ecafa9b3a1f369d68f3c618f58efc359df2f3fcd2478b55a41a11f2487e7f70ec293b3eccc700ef444a33d1eae9849c5b76d29afd5a23861aef4f2a7ba3f666301fdeb5d3d8f0dc9ee2e014b24c7465dee3c0964edd49ed49edabb5ca7afb99574d001e5812a085231f241b6b08c73e80fb44bb2adf554f14fd6dce94a6f63623d9c1deb41ad101651a6b67ae5234daae81979fbd823389649a3b0a06c68b80468a991d3007748751fa69281db1b94d6c160a1cab50943cdbb8dea5750906b3c6595bb580dedbfae57464cc7a651d4c51dbb5fa980597d17669
SIG: 9d8cb2eaf3ff3e0c2bc672e1d255c5b8e80731bff6f6aba517e13354e851080f4a8bb8121b2624244c9ee95c8a092f103703fbe66f9cba100d2e91ed774ac907
TST: 916
SK: 49c298a2db3d2589c9fe16a4e571e5aa23cbaa777b86470290a3eda7a5d3e96b
PK: dac523d6374c8ff15fc4ddc713715ac35cf5547fc1b1b2646b63fb41a7f21621
MSG: 3582eeb0d371df385de88baad380cb0cdb60eab2baebb3c79837753d08e1cb78c0bd76dd1104454956d571ceb7e6b571a5236835d784b50ff66057b13595e7d0c8f25d08ae8b54b6123ba08151ac7db0c56a980f7f0bb39a54b437f54851979986ab1367835e5c4f3a3b3d760d3827e76c568ae7aebbb612e775bddeccd334ac6bcd3253abc29d4b7c3f10362666f6ae75080370a36cba55db3a91cb5789e4d6f9efea4df1dd7730a5e27960d53b5121948cce5af653fff1d5b4e5b0a88c718c49b31c793d88c1cc45ab8da29d05e906cd0594b5f6638c8ec3f1760ba423b5ab1d08a58770afb0f139abd349c1bf160d8902239ce24f19b4e1be095f7ed165f3931e3cbcc307e9fc5c658031228e55cbbeec0d0bcf8f695154a9eed1bef35228789bfc0d238b8372d318328c1339fea08814db8621abca3aeb82098b5aa87bb98f5e40522a0888532c1748453db2d2b3943e4abb312de319aec48cc1c94775972953fb6496b8168937623510cd48c8b247956d3168486c176ae7a4cb384eacfdabfadd9fba30a23b811bd779f3cba54338c28bb3382238ed3b8dd21beab2f5cade28c5e09b31a454808a5348122e3ae3812296f7869c3865c3c9d8fe18bd812f2e60e914975cfe1bef8dbb8097006f0d7cf3fc15eb95c27854b14312b88d528015af69fb7505b8f32703f64eb1c958f046dd251242f8bea7467fc7291d095e9696e11aa45abe7924e856351535aa0773d3d9e61cc9a2d89b5b0774d7645ee1af7eb6fcd440bc69d43edeaaf935fd2a5295ac19a97d70af9298830f81c0a509f242f473372478fa5879fb2cb8511080fc2ecd8259b8c3ce9e8b640761dc7927c32e7f5bae97a8b8ac935662e5f45d14cad6d34affc9a19414c4566f45f977396710894c5399ed4480f18e90957faa76ccb512a2d07573058a95b42fe1810249d1c85ec431a049d1aecb0f118379bdc3f1ee490bc8a054c32c3dac7659966cdb66f995ac403d5e79eb6b25b3f3f65a6ceec220d66c05f8a8a98b80799ba4f2c6dbbb4dfb5862c9a46bca013ebdfaba7494a30ce14606afc0b0f993143fedee7896d9a6bb81499166ed02e94186aaf32187aeb6e282501bca43b57b7efa0939c934bc8fbbd26c44b618335a35c692ff996a5b95d327df9b2a6621b3b0f190db1f36d911d1a663a4ebf9a2854bb4f4061095b69812c82c2ffe3f92e9b44d2ea63169881cae8453d6eef7cf69c25a28b3f8ddc70148ef26721a3c1f2e62d9d10cea42fca3facd74673a4e7f33507364aa286c0f38d7
SIG: 2a439c73c98117fb2952e2b161f7f3b99e7d39bc697f794075db7b634d29f1ff5724f677f8312ad515b097cca9dfc30e79ee8a7c9dd728bdd45df859c7bde30a
TST: 917
SK: 823f0c29fbfdd3d1828f3055e9ec01ffd1b5a375118ddd7e4e0c43719f573ff7
PK: 73125fc83abb8b7c658559fc127393231d03ca5846e0c88118d13d55ca44789d
MSG: 802c39ce7f2a50bd81622add0df4e0fe03ec3d2d305a45a6165271ed79add243b9a00e52183192feb24c4fdbd22c807ae100efcf165b9c996194e00fa817765ea94a03070e486686b445fcb263ccfe1f5862f3b84b10f390080bfcae447ae0069742b8618fa9575f7e637ad54e834caf0394d745032ce1e255c0273250f1504b37a0add94aa245c7de52c80e05d6e0a96a14410543826a49e9b945626d4e89f55027163d4bd6d0e9bd1a2477f67d3d5668a42e94d8b61193d821e0d1b230fcadc53613b75b02cfb8158456077ebdf5a5f00c3b5b186370cafec4a21c69dce1f01efef23c37ab90f858238aefbe212b556d2f073406559f1a51d84efffdce07b00d01bbf33771cc12c960ac89365a9c82c52343f7603381b89023c1a6e702a5b1e4bd191ea6970b5ea451ea05b59bf83e55f29a1f803212bb2e58f0616333d9114708529e8b6c6081deeb7c299a5a2a53ccd24ed58ffbfe503d80614adb05ca11cf29ded00904ea1239f82ba40c793ebc339775f8b0fe3901f5482e310c793c6e2cf01dc157727af238f49c9862804b047551fd886f4a4899e22a6a65701117a3858055bbfe966e370e733e17efada2859fd8ffa9e01fce5606a255367678f4bd4e21e5da0fef30757f34e389f76b7d57c4e410a002e900e48fb218c8f2778f148fee56965f5b473e25256c23a7af198342cf3ef02b84df2cd5800a461c1b07bda2f42628a68ad29dbb82a470967d7302c993b234136e5bf255e6248b102c2bffb20172371f1ca3e10b0810e8649503546d9a731cf19b083357d4cfecc89bedb53506fe199b670391a620069a3081f253b4d790880aa23b53e97c75dc0c360540e5b0a3efb1accffd137414ff8423d54646fc56ba5f53bd84c7267c2f7ee3e37607544154365f9f85081dd7d2ee75d302275c799ef2427ca6496355dcda1d44e0d977bf68db3006500ae3f400d6a8c7cf47057d4fc87eeecb02116b73eed6ce1fccef6e8fb8aea363b2f6f5322a5f0753f45899537646d58651be9037bf91423c2986f5cc2bcbce4faec903498b40fc2deab6603d6eea585d2720d21bb2722bc05b35aed2bcc0e804fe9d239fafda7ddafe1d7860abb0fb28f4bf2b1fbb62a786e455be024b193b7830be0d558f02c9f3ae31dc107ee9421dc5f0b0f89402b71a4581401536bc47308506d96939a206362744e27dde944f4096a12b5f63dab64d041484d3fd91a62c2f0ef9ae787422eb27fed0802e25f9bc775c4915a837fe3eb7b9d5843e4d8210c6b494b61281637a6be32052
SIG: fa747b6fe3381ad6bc82a95643c1f4a20b76ba73bff00e635d64202d8b0df03dbc56b0138b3a6d4198ffaf58ccd3d388ed25ebcf770443e41e9d2147950a300b
TST: 918
SK: 65676633374214c4ac4b7bcea9f1cc84b1b7e79411e310525ace385f4566c1d5
PK: 0e6ec5801d8bd6b1eb421421a1408f134cf712338e0ffc24cdccdc4f7fa31dbe
MSG: 9d622c206787694093c6f29f93619f21bb64c039416d20dc708a084a9d2e490cf5658e13d62cb0d21eab00e42d851bc6ec75daf405d2373246eea415e866291babf76497680aaf04425a42552b107d58cd18561c8c9483f740744cbfa6054c1b126f5a76659ac19dddad4ab5a09155d8c050b5354e06a4dd3ee3a6f9c91e8b4c7af2749664e7abe97061589e153c58e27cf299a25f2b530c060731ec0f4366bd1debeb4d4e912e76e508534d433ec48f96b62e150de93963a1b3e6c8091b495a96518ce3d3b9a8dbdc2a13fdd077f2231de8d76f56d9ab1c2f9efabce4638364f8fb2a2c683ca819b703ab453b11d37a69fa4bcb8023980834f7b902ad1819fc029212fdea0abf11dec88c55d68ef87a26dbb15dc3d3dfbcdddd5ed71be86f32c76ee2221d9243683df9516564b26bab5c845d4dfe0adcc7cb9fe1ee2c051af5908ce0cc3a90904dbc0d3680ed4992f46ce25c2ee851c414f0187d893e5c3b0189a7bb6893d683f5e3394cc046299a16a1c1b5695933a89bb13030855b81b3c74685f719de0160575a0ff0a91fd94347b8bcbe125d1d3f9ce772a8126e00f563b3189656d5522c187ab831a7ade7ac06fdcac7f1d45882e51f9bf5b44a2daba4a53dbb31970b4a0f1272fe14087e0c3c7e4542312fe74d767f21e7ea487d5284284f46f20f32c5b16e1e0ac8d796ab2f80b344e7a8d84d5de823a50897752dc549a48fc10bcd436a7a93e97cd05d7830138f323879680c343c16467d264d749bf45e40f39fbc3a00c43b00693b0156768ff2e3f8ad9eb6405022f5cada6694e8a33cdc59c6673c44117244eb03fd7fd675930c294edd2940f5f180953d910c55485b2057ae0c9302f4a8e831a5530e3cbbf6f472224083a952a8390ab00dc0f69dfd880eea2d739d218d6a66f237f10d4401aa758ff8120c0ae2766127849024f5a4cc574a5b02b935966812cd1fb6d79d0c4f59ff80f035a0b109cccb22fb08535b874149edf2a0970c14888427d07d1eafa684a6d3454e49b225184c6b993ec8ddb8b5a35ee45f87f69266d49096a317d86ade27f4529fe72364d0b958007299d9de87d6ff9fb04d573aea46bac8eb764752eb465caaaba689a6460c110730bdd08b1689de7b05de59af9fe244ac363e95c98b669359af9031a3a93ba631abf1f61d20ef7fc6883b4840fc926712e13d874b722f6a79b16070c0311325e9a70fcd86916cfa1da7f9d0563a22fe9bfe854b0c186c8663b061b65bc071e839938d8fdd7cf8f6952a6467fad8e58490ed2b26813301
SIG: e0b867c9dbda35323433c046e0830c251b4346c5395972286b3a72310ed4526e545dc09d3918f2eb9920bc9b241e9050d848d3830288651591f936d3bae45301
TST: 919
SK: d2ededcd853206cbf59bd74a25a303fa2d6c3936bb48eb42f6d900cbe80772be
PK: 2244111e2e769eab81871e06c580178c235c7bf4a52d2ecce11887a9b46c45c8
MSG: 8070bc0db089a5925446019b7e403c74ec78903e4bd54bc1d08a54a6f0ed75a85b763ff54dc33a2600ccb457fdbaeae548477f6d6947ae26deb71eacd1d2d62282a083843be4e5931d91c93b6282c58807ce8f0d880b1438dad8fdcba8612df73b9faff3a9f7db3005250536aabd98ae027a895e10b5cb7b69875c0f3993af245192f4393e9c4d3405746e311d3a91447fcdbd7306b6020c933bbab9e39d13491625035c9c636efa1739c3588710a879d9e3ce1764616f1082e8dff57559c3f5a5d76dd301124fa489fb949e9e039dd4621bda60f0b86b311e78ed0ab3b528965044b23d78ee2f81061f8edbd6929933d18c0207dec4b5b6b2fa4aca2747cf5b110df00b0c9827bdb3d9db2c7b0328d40d99e1f6b228e40dadae78aeda0289b6a23d4eb5837088e5d88413632ccc22e21a73768c673201e9a8d8dc6eb6f7397fedbd398d26f9692ca72f6d6cf056aaac50ac2f3b266dbe5e7be7a024774578ead585245daaa73e0aaf833c070ba4b2044ccb5e5cd16f9c0ad92ea8448055dd828c79935aa6c0741f9e2b810324fdc6e61e842f94572268bf7d5adfa7ab35b07fb19e7815a8aa5d81130130ac5cda8a4751ee76038c0a6bc2faba4c497e62b9f1f194b8a599b07701814b6dfb7d84bcdd5b7b5bc2249f1d3845eff9ef8cc7328535d70d53c7aa0c7305901de7c4ed2fe1838265d4a417b876adbd88eb933f27c9aa48c8c7e34e48147ccffb2fb61a348fea13ef67cdf2e039e33fd89e2c1ad2a4254e3bf748452aa83efeca46e780ede1d13ff4cc5e7d01ed45eb8c74818d4860af4759a83e148896ab68734395760e00146b793c3e72898aa0b3c5e0c1d3fdf12158d2e8ff1123a3a0c64cf6374a7f44f11a575e48a379181b30a4865cfd022aa983275635ce4f2cc40bfe066067ec4fe241fa047b55270a1ad0776c5f96861014cbf40a0432c559f22d79342b79f8e7042dccfb1cf50f83085f8063fb1887ed2dfc9db7efc96daa0ff2bc4f52335b02112d16392e134c0223de458fc072cc22bf9e7eabc06208180a57e7ce4805ee4e0fc015840998fd568644a0386b3d8e7dda52abf64f7dd00868fc84f036ca8a78e9ba8171ca90267c74e6159acac7af5bf23759abc53d82e793db87fdade1363354ffdcb0bd4cc9213f5c845445fc649b2a1f329f9d41d8a031ab46b472160f03434b4b6bc5a401524d6179ad66f9e221c9067fc87fe4a77e21e8023b6169ebf1090cd556a9be50b9187fe4607c5925e60b414f6a5cbf8afa15ed0eb34b67b4c9c5d54adbe640
SIG: be3c2b567fe8c208c98e7197117eb01b3c197bdfc858562dc5cd90f8e2c0357042303995baba2f40b7345c56db0b4625580aa8dcc48df6019d23a838ea717202
TST: 920
SK: b569f7c1aadf56ed1b5fa1b6fad648d0dc544ff8fcd173780de41a7d4de60cb6
PK: 9effa4aed9c658e4346071434468a0b8a04ecf7841699d63e8887ce205570cea
MSG: 7c5aa4dc8078aa77e8b3b7fee61084cfad764762f1ef26d8deb7f2f3b186dfc772487550197845fba2f4c23c835b9b58dd0b635c649135137f248f5ef713564de3c966efa5f6db6bea9e30970749f8e872d8d7ae4535b75e176ea0489b915f3471d827eb5b444586488cfc3fa6a45082dacb826495e50a3b5dc6bb930a331f30c385bc3b24ce70b89596db6bfb687d99a581987ca876ea0e757696b3fc03779a658130c410b344edacc4277d44845499d678e1414f15f36e166335189569cef3567ac2e3ab821c91c93274f5c28a5d1f7c1bf5099b10f84ecb13a4e4538f6649bf74f7394b703ef53649d81516cb1db521416065cf9f276ab80c9308897a27dfe37e5e142f1819b8d348df50a046a12888e3b7f2dcc70f5218d15ebb9aa7291a1a92ac445c51d3a53dd691efffcf5a01e876a72aa481eb4f121a072397d8cc93bbc2c9a6c28cc89b11ffc0e910d82d9d6298a367a0e1e3e8c865e4326a319b22666e529f1998f1b3c8efb5fc21cce97040fb6247daa0000ac5554d89e7b27159dd0b1800b760b79c91ef6e970b1e6c5ff42442b1b3ae4d3c439e08ec2f6b94177387ca5c01df6f07f8e34d25edbd49d8b74e31a5e65dec1f8760fa22c00e6fb1cd555be68b0ab43599f0b9f4a54a7ccb062683895d5ef66d24dfb1678cb0d0e8c801d8e5ffe79b9139fc96d118eb39b9c8d4404489325d45b4a3202beadca66f831c68efb815941581930ead29fd5f211b90e7a39f0d4ff48c62a545e28ac2ce29bedc356d92fc00347176d77623e0e1809eff3fe62b75a7d9deb727d86172d14edbf2789a57143c69925c917d433b4683b0693b3cd9e7e377996410727f5e6fb8f5ccd1860a20294ecf33faf97a1e0f85b761447d4761b96e4df1b312bd414cabcf498497b0ead67cd1e5901bbf3a16a8891ccced8a907df88726952d4ab370a6b7df2942cf13615a5bc12b4e106dc3013c68b8fb906399df15f1aa90d56aa974b1d2b28c1a8453b9bf0792a51c97ce8a12afc9341bb4c0c37b12dcb12c639449775d9ac5c2ec49673da5aaf7493ed5f1f2116eaef72bb7fb1e093ede2c26317f4f4b6ad585346205df91a6e96bc66d3064bce952398ffce88071ed9ff2750c65c0c304125ac2cadc4fef71a818732496a84ca574d482d5a3bba20e16dd2fa24d3270f6c60992f7f63e88f52eff6222998eb4416727384375f59f00e47512ee464c3184aceaff3ccfb06bd15c183c5e485926288b997bfaaaecf6ecbbf7d2abf4906df76b1277c5f5a87e6817b1c636e91efd7eccf64f
SIG: 2e32ba0556bde974d7a19b3b9a1e92f183924c4b74c5d751b5ab3d007967016ec03afe91d742fb22b63e5e55b2fcb6c61a46e9dce7fe9fa30bbf66aef4b85f09
TST: 921
SK: 323465d0313d1001a261abfd44fe65c38c9a00ca0f20335d6553de492699fc46
PK: e22f16bd4cc7e94c46ba31961af8c583f9d2718c68f73d85069f608e15ba8766
MSG: bb1082e1cfdcd29bfca2464d5ce446b5ba654ba58c22538da926b8303cabfd284a7bd5994a786fa66aedf0e15f20c382cdacf3d14557ff7a8267fa04672cacab767008650aa9b4a7c9071c4799f1ffa45ca4d586e02047444c14231943467a3abaefa53959da226eb0c15392019760159697748293c025568783588a3910e78e5ea427c4407a8901061b8b992b82a2df58c04a1b2c5fad11c6b379856c2e0fef8a950de7e0fc22310309e08b132b0cce4fc1ecbf94574a388d4ae36675d3299a951554ebf180eb381e1b5df977d938433891bc478d7681850b9dc9c5c769d405f5d8839fc97361d6cb306c203026cf2e2b3d39849e1f4b1225eb25ef8acd40b006f20c644db650c75d38c0fcdd48f598c7b4a60106e69e19cd712589cedccf50864ea5f9e95e01f1dd85c7514f2c94b28359de4132b88c3ee1d10a80a9fadfb690e3d88641b3168f0b896af8990adbf0e4f8e9d3f9d4cd314e12c3bce0cc8738e0cfc1905be5efa071f710b32f8e5898c60eb1bb8feeb74000560f41cb2ebc32b2600b6980a2a4064dfaa3797ec44cfb72d379f8097379cad67ecdc0c32414fa41c72b1b9e4edf5518cb39fe9092b439af3a4ebd5afe79bedc0ea8bf17479a2821f5e9bd91d7f4aa5e384699523719b6957f82367cd85fea9ded6236a207c94cb373e3393cb4fe11f90a1b8779e4ab4c3466136bf21e2aab78f7d2726db6414fa5c4a3f7313ad2116a6d7ce40aaa1001c2704d5b05ae54c7cc6f567217f1a47bfd0ee738eaea5eadb5371075be076c8750aecefc417ea7bfdaac3cc38bf16cc26df7600e3c7e8e431f2676fc2a8c43a6a14368ba62bb32439a06beac38a047b3745e26f407ad823d6ad1c0b6a44341e15fc9b331214ffc89698211b05133d6d3433b5d59f7ab4d109e54e4c5d6f32fcf7230fa4e2528c861bb21ccc9e310e9497e077ea675510da712b1a5df575c5d1bf7362d071180039aecfaa5c8573c24c0f4ebe81c2f889aed3de5a000be12fe3d0af2dc2cd4240e314a176c553efd5cba798d9ff1e3d4bd9e90bb8113e3849d735afa4af6945cc57d4c378db84f206ef7eab11c637a7f7260f122a97dff6747e9b4c174ed0d64f9efd7fcccf981519ec580a8182547d17968c40151fdf6d54bc57a9115f040fab5c100deb039122b7d2bfd98b6adf38f42b296ea3b378a904259b75d60703b4840b3f5da09620a54776280e9ca9e8cd924aed2b5dd2b49834e581caed5271cd78ce08e4bba49b59cd77c1b6276649148ab7247f97fc0131635de474d3c23493ca98d
SIG: da3aadb34360b2da0c26542ea71defa8a0bf7fbdae3ee9e11c84084ad05cce7ba7d94de25d8563982616bcdb5bb6395fac4a7e84bc77e21ed36df75dec990b06
TST: 922
SK: 60ffdbae003fa2794fcabbf8f5b41644fe3a7f44ed6c834193da07a9dc5e2665
PK: 35b5eb31ab556492578b3dbd6cf1687d1fdb216a725818079663482f221ce421
MSG: 3f8ff20bb4f00834c80f2ee6893d6f73bf7ace2729601bb26a0fb272a4d0eea1fae1d306ac2c5f32add60135851da27e4f12e64ea5e9e9960b1383b04ce05a98b0414dad971ea98944871d415cc2c46da403976d9f21938958d4ea8c7903b14f2a4485fd69afb24abe102d8fec266fb468b411eb20a339677d88eb31c997b4dc885613f0be7c70daf856a3df92da9602fba2e6749d2f426beef68662d5b0c2fd31321b22b5ec597da5d7e6a288ebd9443c5f39eb87dcf4a5ad9d56c6baf6080996a77936bd87dc3cb42ed4c4d42688a9e193829b761ff320e2a66cc67648e70eea3a1f2f9b9d5b4202fb5a39e9adc609086a9be2a8323ac66931bdf6c504d3336211e46fdefc481fbf17f613dab1fc5c097c92db0609906d78b25a455a3045718efd3e3b14e252b1ae59c7c3893e31913b2c264c0ffc3b606ca1b01dc47ee828a08e46af604e590def44d27aab93a403251fca0772e9df0fab7af0cbc5181efda4da913d8eb6452f6cecbda204bc72d7c990f60ce0dd83c634e912236091b0a6673a7c89ea59308d55bd7e63a8526774cbdd7a1339fac2124c9022abd6fece7f2daedfd87fa683dc0e3ef40806a0ab198769d3a99fe81a99b68600319087afa4ea79d7ee45da9cd40809f4ee8f4e25a0177521ee9dba8b56212e88719bb7367336f4a7bc7122b41a7dfaa2672f92f23403a10c4fb25388c6b20081093d49f3be8a9e1c634ef7ba96b6d523dd6ff613c0a23b60457026cd485ba8db61d80a0dc659d9af42a38cae777fec68e39c52986ff9fc20789c10585107c04047b66ba14e93fb904ea90df7ac9f0154c96f3236acf6dc8b44f554c0cd513193e5dfd87e085ad4b38aa4c5e36b2427722088816ecd2bc3a3dda01e4fb3ff5eec7a6417322ba6a27773d24495a839194a4a582fe5abdb8b5d533a24262589241fc81fdf5e79fd26776428f8e1ce9e926cf272716e7583abfc67a94aae0816c1000a196170bbff1f45e5ed9e267ace1e4d915dce7216c5f404def6fe2bd8b28b2eccf3e2aea0c0d6626390274e47e745ed3a23bcfd21d284c395379dc02080f07936bc154e7b99ee73db188bd2a394e03a01ffe2d1b330ceb72158f958c716a81711dbf65aff8cd12f5dfa53b376ebb8b98f8628f17ef8b2ab9c0bb68412f4e347a633e2f8da1a556d96f4af7211c078079c10541c07dc3722d18dab8fa8bc4925aba5c966f805040322dfbbbe87fbfeb1961f5ccd40a91b997e54315a7eefc3a47bb0c87dc23755ce7227574996f4be7aa344fe0d17b97bc50c5838f99292
SIG: b8f3e1f3785a2a39bb086ca465c0abf0a3e87443225ac6e966ed9b4531c54a894a9abd01ac31b85757fe75308c9594ff65f97cdd91e8d8a93cf12b9e6dbee90b
TST: 923
SK: 174e993d9b81f2af67e9ffb8ebd5da417966a9e77f66c65c767738fe8357d07c
PK: 3bb7386f1b1cbfae553703833ebcbfe2dfff8c899a0792d7ce2322b5ba645a5f
MSG: a401750afc4837dfe3aacc284a597145dfef02629ef87bd0938d443979df76f29fcd66a5b71ea8ab787277e3056f6ea11b08bd238979f9d3b062538c4d6040a86b6e32047aecc59c2377ad0ea4c40c79ff9fe98c958b2bf25f2fd6342432636f5f7d5bb0d2ecf18183426c73147984d95bbe162e11972ddb78a2a7c345c5c0bbbaba9cf38a2d5dd509a7df8b842874a96e64b5d64f5c41a21d208d14cea7066cf22dee0ca41aa46ab921d4ceec89ec873f77960eda60d9676cfd0dbfaec872c2ade8fba4285aacd527143ae0341d67d0078119653b5d23d46e6ef70264b1b0913870877623716d0f1a59021be74c914b432471a43a29f2b6dbeb6a223e2dbaabb820b4adbe337829e1de0c184dd0d09f9d01d42527e5d40abbdacc8ac0f1b2c5c1cb2f23876d2d1b6b43dfe482f9d45a18f5c22b15f1fe521ef57b08aec6a3033925c7454c93e6319e778ac494fb140ae5f1a31cc832ca2488651004063bcff8fd9ae9266af527f2c31f6acb8f3debd9978ef9df0108e3d50c491990c90dd8ee9d64ea4ebfd711c99d9044ec11342c5383ca39232ed97a07e4dc51db4c1fe947348dffe70a95c99db14751314801f13fa2bf42d867375a08ee9b3b799e0b15278e95e91a8968064d6dfd8f5115438ccb8b516ca0c41dbb19873c6e10a236ecc2dad522f80f01c14e2fa14a0d792b9fc486c6fb0efbdf2130f02df1497db5aba8be61ca70b29388e4eec7e0694a38c0d03c59bb6a2dc3ccd6dde1e29ee2c1b325ac72aa8e6fab9138f8b6f5d324d46af3a3542c8bd87cb04fafc54b5db827de606762a097b622799ca827bda9c1c0bb267eba8254a81c6b858a375b94bd09f39eeb88cb14b8d46e4740dc1ab42a895f86d2c57fc28b07b7f60fc4f8847b8bc8ad83a2481a28f29bca3510ff8bf1dd7581e3357164f4fe920f9de839376de064900dc7f8bcf511dc572e0f0f6a75b929797da41c52eae6fe13750ce351e8767630badf6d7d4eab90cd1904c96c048a9acb213a9e5b864615738a84f222986ac23554cf4ce54e80ab5733c065b80459921dd3d8372d0e8594d4364351bf041c146fa8d23a193eb807ece23f24ab6595e932c9ce1a759bf788914db008e87098dd81465e2610647ac38e088666f60ec5d0e2173320a40cd985f0e00dbc2b4570727483a8c25f6fc1e093bb57ccafd1ca202f2986c7c5540a7c3e10c4a6fc26d1d62c2ca5af8305ceebe42ff96e7dc548214375e8a7f9f712ba8bd875e43ca10cf9b183f0c8519512928538a478cb98259bd8b3e334bcc4635595cad3
SIG: e607bc9a5360b31da56be1c544c2000284951d8689f4b722bc4673a0c8489b84483ed8e76e297ea046e85b37ba5630585e5375566a187afb5696661e5bfdc10e
TST: 924
SK: e53715fec9d3b20e9c2991e54b5eb0a8cc81875569c95e22a200136002176004
PK: 5351899b69b2116bc7f8a8814d1e5b9fc785698bebd9ab14277c3ecc01ef8b1d
MSG: 8431cd16d5c093775e18c08252c43f95b1017eb711fcaf73e1e00c0cd6f3448744ab9b0e64335518c483ae94deb97677f818f0e81a7490615b7141b9c35f80556e6971cea28e9a32c328cc2669fca5b123cb662debab2b98157764668070e18edf761ae196bd4b244fea7b74984516be2c00739e76e6c4b621cb3983765a20d84778d5a4350b168f6a0f712a9820a85a636faf92c789c428cfd2962ed207c3ac8899c258cac1adb5159f764ba37229c5cbf783fc9aa4d1ea46ecc85fe0961485d4fc5cb21df0012ac9b955373b1422e51afa1c550988862c86133b760aa630fc0acee8989117d1dd96e3e6287b69287c590bdca9cbc8eecef281ee6d1c8d88822bfea5fa0f530f23278093c7c85a0d44c3a77404ee79f1c8368cd7321bf148fda4dcf2eb07e4630ea422587586371780514536b894c524e6b83d5a76a15c83e95ab314e07b34b98cd99e0770b4eb9b3f3f505bae8a06f7f950258d790748107195eb4f6b84840f8c0590727396ed14e3f53239476c4d2a7269b2e1f972fbff33e4724426745ec886a32916295e70d468d06c7dbb5ff9a354e1ac903bb45ca526f08b49a65e82297d8dd3fb25aa428f64345bca9740d9078dac9e1138c921bdd74881673d49d0cd2006811723de287c6c9583e456a01ab1a34dfa1eaa963b71e8bc7fa8a98cad4f941e4b37b60eef923b3294882350b38ea4eac0e9232e93c532db5d7eec8ecfae65e080473078777ddfdd11508a6e59f0ebaa3f60441f82a71a73c84bca06a371ff5c9f77213a2db795d4a8897823d88fd92ae3e057e8bbd80c990af8386bdf26f12d973c8c5ff9ed6f7b2d8e6183cf6e68f3bb898f59a93ec4de3bea605a5d8b15dfab713f3585c48dc9a5768242b33101438030e7044880d17c2ee84f89d26a1f7b1986193f9663c587d50ca9ddf6186a5176afef1adb2481b79254b78d3b34c69790eb28b90b1461170c3d73818376cdf371af0a0feaf14fdf7016ed6e7f08c0c14b52705c86d4f0003b5e45f974c06416ccb5ca3e9d529aa9d415c25a446fa2d69e82f4994e57e922c17c1c342dd7281e410052d9e4aa1b309b7d470d458c663e17ff2500d0bb8e46a9c4367e091caf87ddfc062aae08a65cb9e0eaa71c99459c5e7cb112a2ee98a5e4cbee0dc520f87c3022da6549be1ee70a0a73ad8499c97dd06aa14c9fd8628a92ca6db487322db9598ada1fce28f4b9fc1d3cc39dcf2ed1df3d862d87f55cc1016fb9e73e7cc897b970d5ff35acfeb05c1c89192808aeebfb2cd17cb1c94fab059898fedc2fbd44ccef
SIG: 3d0adce77a4e046fcb9b49ad5e6c6809c8ac336c733404e5d3f015c9225c3df46ef21ea34cffb3af69974f8b7eab2d23fcd5a1e1753a4023deb3818629a98a0b
TST: 925
SK: abfd697bfbc5b6ff2bdff3bce1d777e05fbe3ec8b95ce693d623931209313d4f
PK: a709321a0210cb80ab58bf955ecdeb8aaf9ee4c375f959c53089d437488c082d
MSG: 896b7ab8413ffe439a2f4487ec49d64e31c74f50ac83f55da61a7003aa716c2a9df6b438e62f53d8f0192f3736324760d7e8c44ac0baca3ae2a6fb93f13d96886799fd2c4551b0ab36f1730855551265a5a3c3c21d9516a237f5dbc1c8e72999b782c5ca41a4f6e9308e64afdee0bf479e546b89c51bc5e4f71e57fb24ce437a8b81b91dc798b5ab36f29afd5b48e81c176ae5edf95371ba3246fb439405bd10eed3678e3ec62307a3b3dc1badba051f16774b85088188c2a9e320a1618d5f26ce94ee2b933c305f6d9584958eea3156c3d1e0ef39a186275ee62c40f3c1acd15d8be6e074351f5349ce3df69517505f45fa06a815c69ca18f450f42b5cf4ebd99268445e0f68104a7deeb0a115b817b99e1a73e0fa9d87db71f8ec94f8708c9bc2e622b963365ebcfb97cfe7332630070e9654eaa60361a45d402dc0ab297665242667fbd9940f6cd33195246a8c2869af759a862d4b641db144d5732366b20636c4027787f558027d76fcbf8432eb93e6d14567df8dbf211daeb5655db10acddd05eca06accee9fda8d3b70ca1e6dc587fa4b78f63cd663ff0243870570f4dcbaa3fb626b4e113bde47d5c9db2b4ba6ec6dbf918ac056949ef3cfcb115561615771a035a43d33ba2651dbeb46348261ce3c4c9f246d23f94dbc2d0c19b921e24c77da5992f1b4bdf2edea499f5411168ac0c12e96f3b15d2e12ac8d7b3ed8d1e07c4267a25d3a3c353a4208b7406278aab9e700f7b206f48e6ea7cc97e554f15c9be349dd91514dbe8d889f2dcbbfa182c9faf5807a69b2e97fa771a6f231a4c7b31d117b8ed0e630cdf13e082bb4f63c3f9acb3553204ccd76e1835c46eec3d43c561bbf17c92214a6db1212b6003cf2cc26c7ae675fcd053b947e722f9e85762ce8a16e4654ec6342fc646e5cab472797eabf658ba4afd142fc8fc4c8f98f23c24dc99847ae8cef0879e1ab3bb8097e4c3529add2d8e8e2c2069210f50ace1ae32a6c8e6384a2bf7d79c66c746149c84ad75a3a176e45e136d94695aed4bfd08b426ea8c4b9379f3742550e1cf5ac84c18174d680e92af2c1874ac1c13d28232de193768e561947cbd6b79e9b99da65cfb74ffb32f7d3d2025c60763dc07f55539b4d253de1e6c25823a6258c7a9ced1501dce2786898a3e05c9bff8fc5b2125d0f471088a134b4873c8d55c0445f6ca396b3d7b4bc2bf5c4d2240da418293af6a3ed853dedd3bf668d937b35aa0c2acbf23766f9f3e96828475ab086496617a6e81d653589b2fe50b7ba8f0cf1e5a44d8d62f08377abfc26297
SIG: 8c36b5a111c5a8119f2d9db57ebb592dae86ad4bf678c1492e26f3c10fbe03f105cae0dc68b55259b9b5989289db33d95d2ee6b756c760f9d3aa0e68a189de02
TST: 926
SK: dcfad59fc6b697109e727ff66a5fe93a6a226f631a64e5797ad8d8c8b6358734
PK: e79f4f511372e355e7e9e0e8b5346fdbcd2df1fc5c3a1890d27fa1fa928d27a6
MSG: 7d92ddd8133c61c610c1308c23aeaf993884a4e67f7b94bb886dad509869a932ec4a27d410d2c29ca7aeae6f9280cf6c4b067ec751e5e8c39ff444d422ceabae145d42f047453dd402d1797405033409e72cc19f793d5d268fb3fd2c11ea2cb0d70436e18f9e88a01515dc865f6a1eb23690328fd75de26321a38f12197a97201b1d8452944fbc541cb68c77d49515db5326f2b1d0763eda06d250ce2a5e0bbd7d1676d7d41fb3abe88bdbe372f96bf7bb526d6b65a2515e83a577045b5479b38b852fe4ab011cbf21c085ef5f0a7c1bed76572b0f860228067a899f895ae7f6256eb6514087f9d6f5c35596c1f480c73113546cb9cc30f56ab074a9ff28acab7e42650a961da325ac5b6594b81c93250ae7d39267a19c97625407edda0404cbe5a36e959fc820b27ef5cad796c11eaff1c0e2f9d4b3c6491502195de03659b364e4e87b2b2d733ec25e6f9b63d5f69179e0d27bd4aecc8f12a507a91baa48d99b3a426cecebaef37d7361106a8490644309f6eb4d2596443b6b0118b945acecc6443ea61fcd155b54325bc2c31be0250f9482e13fd8eb44e2aed76be812af5453cb7f8632458fc8a02a2f45480d79b06c7dda38b4695d08b5a430504f1ae2275b05c91e799d4470f38abe77736dfa895c197ea4b63c2df18efeb14184837b8ddf48909520d91045b9d9655c225a83173960b4d7cd0d8bae30237557f869708be138ad5246c866c6c059dc597abfd4943237376896736b97b7e0289ef9bbd29477745cb60f46202f1de984f509b1808833f58018cde8c26bef4c005bdca385b05735110ca02e562b50eddff6fde9fbb8d030cedf7031bbeb32b12b242be49fde0160c1fbde99b03c062a1a47062345c92e0b604d080facce9243481529c70597dfd64382cb540691b59b71b094332baf0bbb125b63a446bb97491c0464328cabd7627c46f392f3b124822f2013c6e16d3ca87cc5becf56b0fc6eb2bf9923b3012ba2b61250a633a4d2ee391256c520957382aff970c5d22385c3344c6d4b4561571c96329bf75615297516b9f2ceb9f997a39523aa0f58b488772d82fc0d78c5dd52ecfa6bfac63a76e148088b36f24a88e68385496ddadf3023f72d87c2efa26e877d32f1da97cdb42c8f15718988e428cd02f4d09543bd0bd5b2f409963d0fa373531f78b592bd137eeaea0b4e7f918208e1d59008a8af5058f5d923c4f32df19990f10dd3f0eb206293b2b3443f4a5d2dcc5f7d3bbaf6af43fe45f5dbbe53ecf4bf1b4a13e2d46ef80298d4f01c402e210fcb9ff2084ec03e42008d
SIG: 052ff79540737456c6a42c41c97d6bf517b8cf289bc78b503dee6a30ef5168b38f75beaca1e14d971f8773e3941bd6df5cb9778dea125a4c4fe0116b70ee840b
TST: 927
SK: 696dc481f619a9498563c83d0d0e55565c14a07845fe4a66aba2247b113ff8ef
PK: c9d737abc4a9e73c149eadc195a837899f2cd5019373c30ecaf62e5f8e14b645
MSG: 2d4b3ad0cc99f983e41f9b48c4a818eff75fcfb93a1229ec2740ed19c107d621df78058de7c2dd7251f5ff454340865f6c86da65831f6672db231726fdfe4b9ee315d93c7244a920df37054c82449d310f892932ddbad94cc9bb39ac8937cc76c96521d3fdc028ba23410b29023e8138fd3f524319884ee5dad0d234c8df661f8824be477e21699f6369b15ff3ffefc151aa555b3c3d76adb45f25672d380d472b3148dabdef4245b68e828562f25cc5b81d9bbb241bca9d1934ea353f95f7dbf3646433e81a354e1e2056b81c15aa1fa8ed7a9d1af99238cd5a5ae9e841c48dc348ae1de7c41aca23328236bc38b47f47c736b257a3078d57d574b647a7fc8c4d01bc50302150d5032bfacb04bb0fd155d94d9206667720e180a645af462459e3326d460da3c48e7572678e1919268d3e4740d62a26f7c8559c1c439b4b0b0c5942a620cfdb93cc68aa15520ff2864269d7a0c155780adc6c188e0b565fb9594319e6f51d15caf6b280e7158f25799407f3ba0dd1ceea64b9326d2cfdef017e1f172f4dde0f7e4613501af01ee0ac30095f48b59590902b1aecfe093413918d835adf962ecf18580d16f9fd4f6fa1098af1d8a2bc24dc86f71d0a61ff150010867d086987b51dd030f50ab6e374b8e01184b3e2b214ab1c7fdfaedbc545e38c3cd2f6982979541fe0ff88bed67506da95727af1a2038f3240ae5bfd30ee09210e00fdcf2a064d5db4614946bda972c670081a6ee6a10b63f673c83c915ca5573e0ed687b0067c400792a9bcc3344e0e43f5df63fed5efa85e9aaf85e4d7a2c53a6c92828e07fe63e2d23f1bdf97d84adc36e9fc95faadf03e06d65a19c5e285effd0ea0cfa839d55a0a0dbf6da28785c77f5c04bfd59974ef3793cdc398df7a1bbc9cfcfc3a51ffa9a20d60c47b245dafa3e44623cd711d7762c50a67d650c7e8c4fd3bebc0c498d2152ab9827c700c7b2861565749b5864fec95b7f6b1994e78d8f85d069cc11f85bed9712f7a9f060b0bf67532e88eb9df3eb4a8d2fbbaa85eda926d81c49fb86e73731b7ed2a1905078513f7ca0fdcc3b1d576e6a60124c44618df1890e169794956cb1ec501ba2049970c8e74cc180064c184468be4f089a3ae2263c855863b62c28313ddf9ca85bf66b08a264155ad7c328238dfe614a07ede9155a09ccaff92292249341baedcbe0e6466e2c76045e46dad2fc899a1782e00998e79a83abfae9b706f707f58e730203e1d2cca028c922beb6d157fa7a98132a921a3da21f2f769bb6c1f5f19e9e85a13b781af141039d514ee107
SIG: ded5d991935cd1f9390f1e85929ca16dabfc83e65e43272eb1751671aa31930c728555341430ce7c80485de58006427129a4d34fd681d52d840a16bafa153002
TST: 928
SK: f3f8d62fee3af375669630cbf063bfa930189af136cd7591e24d578d7366bf61
PK: 4714c604aa95e1828a28367ba78760b5896431683ee996cff96871773291953c
MSG: e1dd1ffd737ac6dc24b3b9ce3b79e835bf698e931303d809cea1782dc3af63a0d5e67392823d1439e7b6e337b01c8b215434c2782b3be7443cb5c881e5fb6cf3bb244128b4da6a6f42b2bb2cd75129d56418854348c339dcd912b45557a915e9fd7f37916236510cb6c331c140b87d225311600b8d132ac47473839c720f9ff0f9c1dcaa85815a9d27b9758cd91dc5d3e53326fcdfb2730e52be3103957ac89149a4c3004cb6038c0d80fa72ac630d333be5ad4adb585aeb71aef1cdfd57b915fac4f1af78e7a597f8d1ba06672b19c0b65808a8a071ff8409034379589f3d41302d2d39b3318e8c0090fa36cb958857ff5b211c9666e27bc895ab9d006abaf5950a03ff17ea982178a446dda2466f5a40b8f895509e4f4d4a6a2739997fbd4968f89436cee3d8edb8a6da9bd3d55b066490e8339c78935b77883f95b932fa5e6bb7df303be30fa567249fffb473a1e464322d7c103fe8224c7ec57bd39bcd030b96787aebcd20e9ad651cfa2bf04ba70a1cf648e0a5449567202a937a45becbb6fcded30cf9b5c748f882b5dc2a4d65be69fd7d9c381e83d0dc2a34b6dee91220ba906e512fcd63368e2ce733e466b4b82b84fb0c717dc8945caf6d46ac1c2f6418f7729ef4c35e402422d64b1c3ebd1b32a30fc4c5eece7d4408ff679ff01a1c7b03ca517be52e6ae7650f7bad38901e348a5593bc998f7cf2ea97729cb004f561b3b58fe59809a41fd4b3b76660906ad9eda23bf925437ef452b16f540b3b80a35a7093c2734eefe6fa97d881d79ef5b767d9889f118477b73f58a4c0cb15e0ac8101120571ca32ce871f308ad9057a80c828154fb1bc2b201d0cd1006e022d444dc93f1bcf224db74a5b373e153e851854948b6da147b73287cf17d1fb72b4827611103609cab2a1779e9793b9a70820fc6f3828a64c9eac35ef7aa7b17609d8eff8a9e52e4ebcd86b1e14fd140bea47c6b8ddc41e8cd271eb92287cbd0610512242f76a1ef3eac1e4bbbc1adae50034a7a2647e08b2fd20aa93a93cb2ffdebf2e461eccefbbd1fe894ce70adf790173bae96f5a55a1887e9ae09fced1d4306c291c6b19ecac4707e9ef713ea18a7562c6678326228992077a4669734966108000b4144f45a0c3a2863a4c6a3c07632cb93eb197d294884d9ca3dd4b21f39db707f63a7f9a570f7f0feb99b2ca7da7df92a177abcfe86ec661d30bcdcf1522bdb1fe11673258df7e46ef4d326665093156553f28b3563fe7192f72f5f9b3903d79fea04e2c488b465b4978d69f26e05a59d5ed4ef4cab232acfd564fc6
SIG: 8d6f7ceeb9308b4a303879fc6cfa5ca8e05dfc3defc2b2cd2910dd4b17c94eaee845abe65fd715df05b0128e4316e2334799c6e8fa747ebc8a040c74f5a1480c
TST: 929
SK: 865a432ecce7e78c42709fc1e531df5e3959132b2b6f318fd1c34521f9a26e3b
PK: c7a8caf8930b622a501337f92840ed96611a322080fde5e49f0a2f6e33b88283
MSG: b231b6d2ecde49f513b0df25aafc3e5da45b6a9958d60f5464ca593c03005ecf361ef1696bb6e55d6538e34b38f324c21cea5cc81a0073278bb92727eff81af561802dcef33bec10ad6594e22d9c4418af3988a43ed087b9954bf8d6283e4beae8c096de6606751cbed685846c6630b9528ff364a7c48464113472c9860b3371963c911495a9c628a3e3e47ab0991f10dd1dd33161525262d63bab648819d57d1269e114825c5434e6b2845f42795d4fb083ad79401f2a0761c634a545aec7cdb13b5be449f1d829326378ed1f493fe8c8e9b068cc1dbcf165550b8132c319dac487b87bb22a54cdf60aac71516182a4e69ba083f6e86d1a4f05083a77619ef239f702396d7e46968cc04a3b34df3265ecf16157abe15c642cd7427096d8d40db002d196cab1be304bcf322d9d1a2451b6c11eeaf3e8e3d929f480b6b77804fe84496ca757e04337914ce94475d7990c7457c8e606f8bc207d2d48119c80a6b4a9e07b229226570dcd994989fecc694c6c2fb5975c9a6a9b74e8159c27dd3677dfd5cb651f1e32adfafd810b6e5d5efbace31ae6d9b12191e89398da063f138b7584c58e77e7f9fdd7fb9ef5d68ae49c6ccad28d18bc6009d4187ed1420224a5658aadf135b5a953f2dc3c8bfcaf669ed5da38d0144fd9665e6f0677d3fc8804e21cc25fd5e01a3f3fa83e571eb2f882a7659ce5d864d8bb54072b0986a854f1a7f2d2720df857e6d4219630841b1ccdcfc6726b91bfc17e18c3e3480c23a2c05e4bfeddd4db9ef42388f234fd3e4f3dad666026e2780612374161316afc7665f9411b6c5aa78933b18021c012b084f3244760a4ea1bcf31cc9f5c4044a9bcc75a986707f38f45ac1c7fa139ee95a6d8f16c3c1e12764c4b0b1194c0fc5f7eeff9a848c4050b0e651684719d438aad56019164fae4f48882205ece0b99736791084a753ba7d56e88fceea533566c3a2ca48dd6efc49b27dbf14f2616ced652e13833ab9028ada454431c89b3cb7441fdb8f23e12b60a1a104a2a8cf4a64e878aa26f54e8881a4b151a16a96de8b9807e729396ebe3e3d394f808bd74b7312fe6b84b1312af8a1e4133599d07bdf33db21e016b5c196c1ba3115708f581bb82f4b57a6ca1a529e64d193042c1dc5faa0a03abf53849e1bdefbab64b1cb60fe10a3fc1823a234c45f3b0dce66a46739c01aead12de6f0313c7be71405f3fdc4a507a9d84e8686f6fc92635db0f7856c7373a618a7252c129a7760e2029543d726228c21d00ad4ac52e5b1a6e31200917f15af515859e08f2a79ace67991ed69044
SIG: 32bb7520e2639c6cca19a2b9836b08f8b083ca33369ddf5f9a877d4c7a9eb05f9c3dc34ed4cfa4b283e51922b094066ce9ffa4d9df621910ca37b0b37fbabb0e
TST: 930
SK: 2be1f98ce6553c915b6a0933ec0de347b370e29ca294e8005541239f63b430d0
PK: 7a6f4469c30a63f560f98734fc1906ebd1371ed80125fa3e4c86b43f262cabbc
MSG: 6268201f932a7cd3f879ae6ab83855a2f50291de784d7d9e9adaa1b9afed6f5aea20240e59fe93e5a7088c95ec8e15745fb8fdeb91df0151c7b4605067561ea08dbf00c4ffe1fd0acf103656a7b54fad0f25ab16b4bda347179ed1cadb7b98be0895e050dcbc379d1fd553e99795928b67a752f8d2ec1b9d66bf6ac997e744dc327f242230f92e79ae312745a5ab6ddec1998fb63dc4f6b05f147222d4b65ace9017dc1bcd675e495f9eabb5f602133f6c72e053e9f4ae30d872d78bf71feba37acc595055c3bea53a05ef0c7f212dcf4e0af838ea2928f4cdc9fdc837da25f26966b2456abea66a5dfb8faa8fa091f7331d5436e98a8d6323cc9e9a91d5a02a49511714849b47454baf99c5f850a08d3d98410e939a9e89b15053825f3e9aee71447416140782e1bf3b0d8b4ff62e77a4a03f710a8ab76cf63592c05c440c8f064770099163c12270f3d5ec9a6bc9715bfffec769611d21fa003c3cc8356c975d37b62b88aabb8597daca196c9648a31d15bb0b86cf070ee01e511ef373b4a44c6a00160a797f2e820b716f5ca64464e4189a00fee978d35bf204f71db1f501f9b6e5dfc821a8af5dbfefd353ad3681f9bc3c22c67cb211b430b6a55f3e73da7c3a07ceb7d2fe254b10c2703ab2e2294dd0d3152dc7b21aab87b150f737a947463fb204175de8543236fbb0da5c7d48c57f61744de6f984aa8e61b970c62d0eeb849da7e89a61222d432079cbcf5f8a2ba930301683c0785c26fdf85da3020874604599ac6c847ec2608658b5788c7b8d3a3744fd5442e24c8eeccd420756bdd8b8a77cfd80589605dced9afda2bdb630a0cb612f739ce617d54ede6ccf36aa31e7e373d8a0fb1b7c9906f76b5f9de8c26891de006eb797ead4a86f7016f34bcde92f94ac3e920ba58d6dff772078d802a94f56cb26bf794fd90ca0ad4f2e7acdc5929bc7364997ded98ca69c573991bb9ab85f235b63e76f77e0ab45e78912389869af21e74e66f7c456b827e670beb0f0726688bb1f9036d38da07d69ea3666f76bd605d82e2dd6387ece6e824a569700f01b195d1a9bdcb0f96ab5c54e06c2119b406bc4888480660418bb4288ea2fda96631b0e1f60ac861d6ccc4c844b647a7d7403bc2d15bafe4af677e856fe0d2b5f663be4e480b38f6b766adcd3d05298ef1398d04d1523a68b91dd31cf5dc4b73decbfd7213f981b207e1f6ef225d7948a1aa17d8d57a112f1d4468d2d28f7ec2e54b74a692c5958022e82031a41b315090ed4d5bd7bd0b451476338f739a7d7031af2d36caa09ffdbb7c396507c75
SIG: 8e659a3f535a589a5fd2d217cbcb8b777e5af20b234432f7dac29f810a2b4737c5cab10b59dfd0144f3090f5f9e0e667f0e21a9f573fe13b1c28eccbb531a205
TST: 931
SK: 10bbe6e761a75c935b517f0936fecb9ec6fc215e58130800ea18d1ff442a4f13
PK: 8643ddf8aa8d9c8a78b6eb699fd20a57f6f18636b06ce69dacdca1267acb3954
MSG: e8108c6de4133733dc199a73392e226f712c36a24fa91d6fb09f92df218deb2d2830a668fd694b4809d0253507231247c7f258b4d65c56bb69345ef6aa97e7c59e8153775a5a3cf109c4bca9815569da6932e82183425b42d7483c9dbfcbd8eb38c84729571e8ec93982c317716759598c4f6a1b7f8da7306a7815721caf02e70246712314f766be9cb177cd2fa3bda22cd676c5d2e86e8d798fd34f543c9be3129651f273f484f0b9467b140955cd2981ff2603c0bdbb436ac0955a116c5e5fc30425e1fe78f6410f6ef757f604668854bae79bfe22e1a85ce5ee5d6434b4610120ea7e5d3d137ce207514f8534ad9bf392b7dc5355514b59f835466c8eb56f44eddc5bad20cf0b480b2e822a6f46fd95f30f183c7bb3143e4e6100e2dbc9f2bf0d43073e0fe65f01bcce6a1ae401c12541be3ae68cdeac2a4ac71f1663b5fdfc2e50f0e077fb3a0a8b8eeead627c1c3e79dd7361046f7e57c17436c32dc4432f050028cc7aa4408c2d29d1d7998fdcdda32bb32f704dc263db9b8e06c57630870f8bb6ec661fde1b7da94d53b047701a4588478c1c662346741aeac4c25338556a3d848de5b2a23ecea61b776bd0e8037efb8501eff239c7facca6c8367ed7c8adce919fef1a155ae0d5478a98002c95a16fbf4c0ed016ea5d3866fe1de454832a4e9565976b60b3dd2eaf7fee612f2bc040d93975435eebd12f06eb09ecea2c66768308f58c77ac51ed7bd21636fc9cc3fd14870bd06bdf128a81b14792e608c47ea2d535ca7aa21eb8a8a56d76991663a8190a95057d33671e73c7cbce5a98d31ef0d73bd0b163787b7fdcd2ddfc72960f2be320846d4b29080d7aeb5b7ea645a2ad5a59c012bf7b9515d859e1c1472ef8a4d3c95e711af97ae4618efbab3dffe88c9f6af4a09b0e73387e251b77d7bff5214f791862db6988411e2ae2c75bf28d28602a637c26f49c18d309d2fc58a126667ad3c2ec160c99ba40fbdac17e7e4c21a5d507859762eba09c4160df66f5feefe6715a28c5296cf43e5e771f31fce5133be97cab57301b4c9df9cd9a4acf1c33fac946fa1596fa65c8f3658be47a473a62c52181eca183e4246cd624d8783dcce5fdcc1fea173f8071f7074f55897de9bfe84a6c4fdf802d5026b8145e6c8c8950afc5b40fd0356fc55ee17e1f853a4c2fcc34a1369b87d28dc2fd2010f19903aff8e46de04938f4948245d5b425d074acdf2bd80bfc3735cc34a22590f194af9313eef4ab5fde61f1f9b58578638fcb4f2850b2fce6e03db4d0a834848163c4b27e129f5cc74f67f008a2712d1d
SIG: f0f357410373313b7c6252d6d96600360c23752d431ca8075bcfb772d49cd609b65c9cd838d634d8d9b95d1ee30edecc13e3ca997b2437303f8a33a1ffc83306
TST: 932
SK: 186dcc7efc5ed7e61ae53dc42093bae8f15dd99f0f033326c576ff756950d06d
PK: c8d141acb642aa9bfbd543277c2dca8aa9888eeff04543b3789b21f26aeb0f71
MSG: 974364d6c838842ccc4e749e6afd537170dcd8cc50d66654d105482339cabdf74e32935ee219272ea1684fb93c1fab42b5631839243591bd07d3be949b0dd15e3196df196ba752ad1121ac7112d566944e153a4e0619b3a232241f020be0719f6bec918b26828eb1670ecfc73c66844ea3e404c6a2fc01beb403c9d6ca551ad8a6e71f46647fa6053f0314f8124d8d2bc12cc8fa8db95f2b735375201b816a9cf40f83ee4b8671618032de229ce76271d03d2672a1ae4a288c85dcd27fb8452a8132e9ff29e1e89bf11b1c835192c04b13be14f3cde5d37ce96f1dc2a9ccda0c4d737bca1fa220d21bf360b90515bbd226bb2a6c8d5f2ab018d4084e24ee333ce4e39bcb6b46e7aeb4db9b6c65b244d982823a770f9c62a0bde2cbb7ec36840d455187faff4e488a5c608ebdb7db84d87dad3867e3b0d04b64715e16560a62f1ee03df6183fd5e37555da1972fca062d12bb8420e082dacb8debb9c1438541d0da2464ef7ec52263fb9b9a4c469c83323e4819dfdf4fa0a770c3a709254e05314830e87fbb6736c72d9dabe01a310e91ebbfae767a1fcb62f64fa3ba8d53400d6469ad1ccb811fb9e115f14127b13e8364aa2fe80bbc886a10df1b9cc4ae4601f5461af091f526d272da9b203857a4447eabdef439830496a5759c21de65ba3a3c8b8e939c461332a924852c205c7711f3a68a2367a945def4fbe5f81c60cbb7e394a2a49be9ec2aaeb1f330575979446ad9d0d54abd436f2860f0423426f4bbc26b3b9f650d69b10072d747a39e478f455eaa12c7c6e12bfc4536a3594344bd02b620e3e2b4e0d534089dd7b04fa634804567586c62be0391c7bdb0a9fbc1ef3b33211edbf8ef58c2b7a49d06667959d7e5d44671ee7357a10ba0cb1a445ae5d709ce255e92de715975af94b89d4a29c71f9d88c85b6cd11d8b335bf8f2c658e6dd7c3f6c80ad4d0e5a6c87dba7b5b8a8a47e72f4d1d3c743631df9adfcfa45cee0498d5a44a9f75c83b75b2a3c230ff0767d3888f941ee1b6624dd0e12d06ed1ab8bb135ffd379e9de3788be541aadb2d6a7cc601316f21eb9aaa922f56a8e3526c9bd1177fefc2fbe3e430b628eebd6661e3ba2d631c6a8422c241ecd969972412f74da6b1243bf0fbee8a84d52e40aee3f1e4fc831402c62f3576b22e8e3c3dc4e160bc3b6b9d2ce005853812eafc0a4e25ba712279b00ba3f9130ff36e3ef1971dde7508b2792fe64d475688fc6f3313aadb785302e6b7f9a84f2dbc2f3cf060ee08b463736f836dbb262d329684c208492d17d811221be02b65ee28e11b54692
SIG: 8945069787c1c676a84a703cae1e0bacaeffd33e91bec3603e1f13fb170e31e6d7049eda2bf627180f456c3f7aabfcd36c49a8c04f8ae6929ec5ada07b657208
TST: 933
SK: 0705b336c89ca35ffdde0af0f906eacf623c56c3f76738168e76fcd5882df79e
PK: eaaaf2a15f44b634cef15a638b80207f61099a0796f5d43f3e9d048e6ae796c1
MSG: 616fe15fccb3310f9ec7456447dadaf8e0a5fb269be169b0c3ea2cfdaaa55d37937fe75b78324ac278a65047e0ae4f327e97effcb7bed91d09da720b0a101be9e96d0ba85b1ff49d8d1df362d3454f0db6825596101c97e5dacad07ec492d30f2d0cb7e7de4e744bb6a6100b754da847411d09aace8d5d410758b83087db4b5e6297979a21fb65af390952c4f936260e72d7c78327b94aa6cd617278b0ce9e1bd3fbed93b69bc64985dde0e2c4357b502f055ee7b0a0388474dae02d6c1a731f87785d753aeb0d9cfdf85002df566fc2507de7ba6fd035bee17a2e808b4a7588c583375c82407a40ae9eebdf94df2fb8cabf17606c439ea70459b212aae4a3f530ecadc5e88e2548fa643c7ddf5063b2e10673e59d07fe906892b67eb58f9388a56b370452e9977755fc04dfbc77da6c05beddebf0365256b52c9aef8a82173b8c89fbd98cea36a8b896fe66d37ca79bec7fbfe958fe89f6765085b335dc770343e230caddfa2833daa662fe8208dd885a6fdf72e36ecf22bbbbcbe79d370650236940bc2e6d4ac74fe4d554c9bc232f07d2af6220d157bd2da6a6612a081b4c9904a2869b137ee3a0856f12b2eb8762db94ed0ba136f23e7fb4bd1fcdee10dd84e2cd3b0a49148ac74db466dbeef81e6a8ce0861102de9b1a3e1dcf5c6b0308a82e3ac7c2283c7cc2f34ffa145b9f74b79904b32b79e960b814aade63a0df0167dcd24ed90a8da7b934c772932f5a478fe2a72f945a13096ec37ce764b581eb89e5f6b2bd7eb88b85a89587774d458c58cd879457973d648ef771c5f1deb27a0cc5b29246ac2fa12d18ddc6b9f9ac9cf146c3f22b1e4499adeefbcd2249740e13a224e7b6b3ef15605e7e74e68d7b72642409b90c4ec161eb24c9b40ff9c7e6e5da98322aca52c46a8ddc190f1cab157c4c7619601a6b33df6a50da661bc75360dff69750d3457409cc0241c3e8c4b3e506d426af52b70231cd6c91260cc431e4ccfd496ca14ceaae1cda78721e16339d52682b6951f966c7da5c6e10d919ae66a9f52dec10867538d3df6d593a32db695a8d7745703516ea56f8c1c8f0ef53bdeb7f53c2d944f511940ccb90624922ac599f4619c3046207d605f6ff94de788d25342229dc8af92b5fdf0dd71df2b446cdf1d9a20524339ee1c31826287ef72781a7a35289f85a15ba57c7fd5d885bd0553ab40805f517e8f1b1b3c4fc6771e6f224bc031124b9c9aeb19c5a96bf1488e1e66c6e88809230c83a74155554a219ec379ae54a9fe79dbede3d576042a635d197f4d818c778755b8b45e513deac88f60425
SIG: d4a9bae8ecc472c376bab805c2ce0c1c2ed5fc773715468cb1a4934564dacecf438b1dd2ac1b5c5e336a1e20701d5dcf3c8ee3ad223b139fa90a1b552e1b7707
TST: 934
SK: 95174a0915684cdbb619b055495b00f19282cffc3b05019e6ab709a4a1742bab
PK: aa8c872d7e10b67f7ff24172c3637e80825a0a71ee0c48863a2acdcbe8da459a
MSG: 5e1a7400456cad4f9ba86643bc7cbf3b3568dcb522b37055e8c39d3c80f2284238e5727fd7513cc8b31c57ae7b4050aa819fc2360930eb0dd677a5b2c729feb2da3ad79ae7fccdddb6c08446261ec9bbe59c64e99abbc86d3c4835f00fefe527433a501a3b6d572cf5e12a88010b46a472b9bd8691a407c365f9f71634b4d97edfdff06314c0c1b4eb93c7607f1d6fa354659322c284073f42602518c54fdf26ea2c27c80a6dfa20568391ab357282c06b23bedc1df1264b611c1e9cf18aebe249fd8617c6e3ee98c53c0f6f2175c57ef8e206bd3cf105627a9892eb689920213aaeb63d87663dbfa53f0fb281626948296b2dbcdde1c51af862eecf1cfe8a46a2c4b28cfe7130330ad173f87127aacaff43c0bddea48b0038976e662c04b6b04ad03de12462c2765db535049520cc114afdb6c92549b0546a9027d449755beb8d4c17e6a2a475f9676a337b4e866d96325e389a52c16c51e18e0d8103340c8417b2c57a55d042ff5e5fc65df423e0092b0ea88b96a907c95121c547a68061f27bcfb58ce6c07728d4846bdcbf0c625410edf8dea8cb4c9d0bbeefcde19273365f48d75aec07d1c22ccd23068a97c3fe752e87a30118fe2dfd5218b6b125154e0ea386cf239e3137f8ca6d8b746b6a67d508cf8c1ab63e5715e6721eda5c2bc393a493dbd2f9a1fa926b9a59e45a180aeeb02599a8cdd686f889b4852723cb6dbfb5014cab5f658a309a472239360eeaf64fc8203a3c708970e15cbcf136255d96446c39a927031d267d69ecd51d7af6e91fb4aef9d78c3335e9071133cfb8e2129990c64637c7adf1daef2dc26c1163399f3fe1e792338092ef6f8dfaf25730dd2fe8d978f6f770f52b68238176564cee5fbb9850b3b3a04d948460417826eb2eb24fcc5fe35334bb9521e87bc4dbde2ac9e1c98949dc2d29ad279e3884b905268ebd0808bf418257e75e262b4d01b024a6e9aa7bd501dba94ff506394b4b0ae6081ea73030c43a6a91766e80f9f42c0b68b98419ad4eee4e9a728adefbd79e831f70f41e62b43f0bf42b3b2cd53b5589117664bcebc409a7645b1eedda482f6b6895a657ba789b89e502d6998751d6303ded5fa156ee7c7eafe54626d1032c4d7dff977f1dcc86af89b1e646a4afc2427ed02c0af5d32890f95f13f98c1a5b1d9fbb781a9a89b2d790c1465c2d1520926fdf28c17d9ba1587ad761f065d339bdbe38f4133f45bb5978742642f90c065ee4892573f6059f8b4ce2c13e73b891cd05f23731ed9a07e2b8ffdc963b06a510209c329980949f40d8073a013ef843dfcc4a3394
SIG: 780f40c20fea3b11c9422a43b9a6f79611e7f1f59d1488c15a5fd2d32c07dadc391c38953edf0de48be52da2af335c47b8d2e44ab9d3dfb76ba538b066495208
TST: 935
SK: 5a84af28a5dfbb3233a12f0837f6e8654e7b0de16b02ab3cd17864431e274667
PK: 80d4ba789f8a4b2047adafa5ed26cd8c546733292e8bf693cfd17e284efc6871
MSG: 8aacd1b8a39bf08fd5c918446be576e6a3f27f36111607f27b56a91214e763f9a87fb1d1844898961797644460bff5488c103af605e8740e46588fb93e443c3bb23b92c09870a557653a1f22c218ccbc2f073a272d17a84223ef143f4c7ca258460b798169673da107d71d5356ce9f7559a9b038399951f575c77e5b9d0529578ecaa2e2089266fc526c5d409fbd46bb86841cb554f5bd3c99713b043e404653a7d01344d4db831a217282c4b336405653b85d27a46b259c855cdd85ad6f7aedd835ff5500cc8baf0fb2f0180910c64672b8a8d49d984a78293cf5779c910c3acbbca455a85466e535044f3480262c090fbf4e0b0db4d1ef8759daafdd8d05907482461ff910c437195d5c7fed9d82cb94e7e4ec24da053e47f62b488eb7b244655c7dbb20ed607eed4531449e0780e61cfd574086ffc5dc524283775c44f7547cdab04a51eee4e1b7b65a57573a92484a35900a909f81e415029d22ca937a3acd9e61f8c0e686b2d2ad0377af8ee166e4a20a82aff451e151103e0a1767b271fa9c2b1dd120f805853b3b8a560fc8b9376283b51124324a284a0e9ac49df69f524c8e042df82efbcd16881ec131a15210df73de02943447f22a2ea1dc8bf968298ee97f3ad546d78bc660897e08d2a28b2ba68b54b954f1476451c69207e5dd248ae47ef35694990e6f058bc0017b7495105cc8739066afb11e1f26601942546ae849ff2f56730f1326bbeea640ee178fa247adffefc046494fc7ffc0777d5dbe8a55daee61406fe3c7088d43d9e14da21ca52fd8c160091c8f99a67dad65c64fea9d18b1537d061f5dce879e0bc42648d2eaa02d972185753cb2f6225d8d03bb07f944b10cf4ea22275c3d70848020f30c823b76143acf545999a2cc4b5898d94b4a25efbe5a60331cc009fec0a25bc98947b1b7139e22d23280ff8854a1ec76221b1bf3d108328c8ac463c65263a2d7ca7433482931a1d8fc144bbe9bef678c92e1c2d10921b6ad43a75c53bc075854ed2d99d825f30a5e10d517438e4d4f7113429f1edb387d6bd7aad29274f8d2dc889b7efbeb58686f8d669ceaef92c75ed5307f0c03f5900181ce573c8fa28675205fb1057f626aa230d03e2eaa8cffcde20081475d80b245a1ca6045ba204ab00069079c637fc3fb3e80ca0462e7a4cdd9283ff9008530364816792fdf3b9a4e4dc8379228edcbb154bef387d37760d79afbb736260a1db10138361f24b826dbcd5f0fc9e7830d26d80c52a792189276bce34760fb77be1312ac8cf97d92cbf3d0778028db5e8eae89e0b9bc8778aeb1278f0471cb
SIG: a0b84ca5af7646e6f62a6935379473fa6e4c27695851fcbdae2917b2dc68d796e278d70cd67fcedf6ca629b881f7c4f2aa2559b20d670611766bd65aa4fef204
TST: 936
SK: 793ac88d7d3b6fa7f47deec31f68ddccb701820f1b13ddc652f7c6a85b6052a5
PK: 91b6227acdd183da62c51965c635358b204d683ee06443cbd40e71c1f76ad102
MSG: ec50afad8ade7405e2c6f5c6247bbbccfb2c17166f7884feae10d90f5d83c4b6f0bf76de2f7897ba1194d6d3449ddb80ae74eb8ed68f049b35c6f21916db4dfc2724dc3af7ad8dd5c44f60d2f49fadd7004da1593093942cae5208bf54cf903bee646905fce2eb2e370d0dca48d820adeab16a3b675e5a4a8e267e34ff96f3122b18de0cad9292ab63d26e5f310fa2168c2966bdb63b0de08626767b379de4633b9f3eda7917281dad661e9f772b844a79e800fd842702446e4aa731757107f3fd6547bf4075963d5fd5f58e80853fc42751dca078a9fa8d5bb3d9a34abcab0293d6ceaec48967a1e6224398cad0f605a3be8e6758ea8f29209d8e4c4ca1893baad91e379ba3b17330c12a5b6f219b384a8ab978bf1b37c3731a1b474b24b5d67d4cec28aac6510b11f2cf21bc16963d51f5538727718fc4e2e5172e3c0cdabc277f0d7037c34ca68f73288848b926bde0cf47abfa66600916946f07651c280a2086b14d52570cc8a4b74358b59c302b9d00e1b498f3bc33ee4ecf2bce2c65ed7e8ba74d35b751d3c99f40861968c2b7f3a5be348c57d93b40ffd051edd7caca6ee6bca721dcba8db8d0064f54d36ec5e8d62a71fd1c90f14924f41c163f007afc6fbbfe8645fa47c3c980246d1b92274385953c5341cd64c34ae9717cc2c37f58359c0a9991c23fe637de6cdf0862f7d0329fe758aa892ad4583b9df2f3337d5be570ba654998ed292f11f01772382a04342fdd99e69e0d97c43f10ac9b96f140a6f83c4729e7a900471f2b1df2401bc5c680422b13b0c8007d63681f66a0595a1c5d3acde5b779426e736bc100c5e6f52608dc391e3ef9b1bb6af13d249b7d32ce0680c368f54d5fe039cfe10130251e4db14c79c8d044060465822990d88093cd736532852e447889db89cc60052996a32a64365c0726051c119eda901de576b334fc7049482392e2620b0a3a13fab1d36fc0a5f23db147fd857b26a698048f8b811e23d722e2e9027ed4124b48dc5e578a7aeb19a1b4f948ee5b46f65b979646e2be074714118baa4bfc15b089a0e06627da46e4bb06aa3c7c5dd648e03c9c2dec3facd95626562f3000883230d2b0a1f8a7478cb77f939a5f188f458d1037b90176664d86ea850b8af5087f86605a77e025ef6c7e6a2a59f006cba189fad933f42c532708109bc1af814819595ffcb95fbf5b7e93a71197e477ee7c04b851c1c36622cdd8e6c860d9ab2cac56d2dc98fa69124f2bb2a6471e1c73b661f071f5d86de7d1deafa4edcdc7bf1f705c56300affd058b9697791419e5fb2a5b7f78ce3401ff550
SIG: a84f552bf44322a6db245ca006d1cf780c61680fe7429a8947c35f21bc4b44228ba30aea0c744b866459d3b8acad453b06ace247ba69528c6b3bc4b20e75630e
TST: 937
SK: 89de7442d74ba9385969c9651a88fe28e040d593907dac1a3987418bdfdbad89
PK: fd3ba9fad320eba45d07b84a497be17d3fc7dd9999c968883cd6ac13b0669b17
MSG: 9d5272f0b784882b94c76dfb9d460ca495025e0aec5d52ccfffece9f8173c10558266c498525891a97bf3878e33c3de2fc2e52550b431562cbe4a3d011ecc9e77ec36ad38341358c88321c03d08bb426a7d5854171c027ec48d57819a91afd02a618ccbc25e68e5309d047b156e35705373ada2eb831321a203e1bd8f0efecc09618647b41dff22b39d02235f871532f6085e9cc52ec009b33eebcdc267d7767c90c927e154f72f3f48a34956319b293c8a8b3e34efc5f62f2b4e8019b50a08f5ccf95bc831baf40811d87e5edbd2fd5365b26a431ae95800ff381cd62ca40e1866d950dce14f030918abac68e7916ddb95adc1971287874d07eb0edef64296652c48044b0c5521a8d270d53d74ec63b890f3363f9207f6652ae8e7835c3820ad6d9e3633f4bfd5379a44f29d65f3609fe355817dca5518dfe3bd769320a031902e9cf6669c24f88b01eb36995bdb8dbed6ee0c9b7f32295c61ba8905e5598f3c9e1c8bf7264f98293faea17747f88440c31818c433ea3d23c01f4f7e9c3dd3d5f32ec9eacd71a09e3a997381f1cbffdf4b5ba4979deb7b09841afa3b03d1c9311097b862cae11707cbd3a4ae6c8a26a306a687c414a4ea1e812f115f60f70bda7f8fbe7bc2d50cc550bba291d5ec523229a08ed568b5cee18fe6f46782c17cd828801639215bc5e9be4555c9a18009767a6c5c74a8229d2ffaa399d8e64324e884223d5070f735a75d85ff6c94a9fbc2b3651386de5a23cce95c87881c79399ae71f090737e2187fe904aab1d92d6186795c9b46c62a5914f3630fdcbac3bd4b0da4ec3136a1fb2ba40322d7cc4085e167009cf7450fc6a286c2f7951d51aae23b8f33020efb5e3245ba6a3543a2bdec447d51ae00b5e1678b76093cf216b9507c963ebfc024ccd6ef6c78c4572273beaaf55076dc44a224b58615705791965307cefd48672c081bccfbc1d15b062b38b4fba9b9bec956cd14444ee437e7960cc601eddc02f1a76b68574d5f8843150c0b9009934a2bfaf605770c136ba29f3dc7e29597a2480db23e2b2677ec6c51bd301f2b5a39dfda7b477bedd1cdaed10e29d2954629b9876f8ee54e4047369d534cab54aea441dc947eb3f59382b218360572f2659583153c0e2b912cf30c815b26f05853dd30551eecf64b858a441bb8c6db8a9fde77a32a7b46af66f8cb9f35ee0fafb0bd42d9e65b2a9058241a31b8ca1115434237670aab4eff36010ed0371f46595da1bdd579bbb67aadb68e77ad3a38c8f26d2af5a7103ba5f22b42cc12a8c3ce5c921c91cfc0e63df9027d26229b1047cbc18f6b0
SIG: bab57284d20ee54cc7f9708d717706d8faf6e46332b0691d6f213a8db801155b4e338c1361b592be758501b1821793ae5227cc3ba8df8adfc6ed9acab54cc401
TST: 938
SK: 2622bd9bbef7ff4a87629ea0153dc4d608c31fa5847988ff500d880681f11372
PK: 199758a9c3d0ee3eebcbbda3e1ef5455ff46d736bb4ef0c06a739f9ac5848395
MSG: 891e82122547d61e83b0abaf27c7303f0522a2ec4af44ef0ac196a9978b1c623ef1fa72baf70910a5c51c4f78e0fe9fe37e2439c4795916cfa22ab471a2557cc7ba6b66956063ddeb39c50f14f06348fa66b6064dcffca5043967f05254d577abf22ae8c90000ce2e6a1a8b2e3a6b3abc563ebffb20445f0911cc42a987f8456efba4130e68f01fcdf7bf771fc1d35371a0d75dd5f90002c90b6cbade40d5b23fdb49abacb7219ae27561aa2a879da88df34a8c581f0c67198ffc608fe9195b5555c8ae934c830aae2885bea87487448e11b4f2f172e4d5cfe4fd113f9d2016c24a734512bb918f575e754139718e3d20e790abb942cba3ec8b2db590796dc435f139fc64ddc85a22494ef2bfa1f5c0f1875ea58e84eb374ecf8cec6468b6b09d1e74f1541ed454a2807d3f4053566b0e4e2c6aeced10dc007e9df416f267fcb3fe17b8bace03f0743e0e6d4a48ce76edff60c0e3a308456995413c1076ff37ecf2381a0d4e9e4a913a258d983b9696b5c45af37c8684070e400b8f865a504043f45d78b9713f335aa416a46166410735fb5d82210458d5a08a104d4002ab61188f9df457dd7ed5937ca5077606b418bbc8684a1d525bfa551087640b1d177ca6d4f6471b39b2ce43afbf8285ecd687e438f4425df568ab86fa2316349a1102b4143d71ef4e24f5c530c77afb0100788636440e740675a6174c5f05710b253a411173f9e82ce6e22f4095e7714b8737e147aa0f23191578ffd93823ce4bf91c1d110982a5da0e4b81bd25b9b9c2142a7671ee937c90fd0715ec9afa44d86046898b42f753589d2268d2aaaa985cc90e0f9e827a3923e7716346f4f8931c72821b3eb645daa7452c8afc898d7975545c12da1bdb209045cb00f4bfd5383df01f003680b973440f1a39c9d820959ef6f85bd33639065aefdc8bcfecbd9b9554049738af29f1294639d3915d632995e8faf713ef2ee3c298b5596fa10c99f946ddb32340695df1c194594eaf3778d73c8ba6040c04eb3a4ff8677936b88e0c5f0441480d107d7ac2202b3b694e57ccca6d825e2a07e812ed29b2c20d5c605471579e3edffc223f242c59391db41e98d5f3d6c5b1e32ac8237fcfd1020543a4041e03d92ad3e2ec552914707c77cd01f3e48011444283f0968fa4deeee55c456ed1f877ade04ac8e8d2cb6c85820b4929b25bf31e925435d6bcc50d3e2e9b85102e970d7895c25ade52161a3b6bf501ab01961cb63ed990aeb93eda3828bf04ca52853c7b6b8e9e49e349d69b53be07485f542b7cdd06b527d41dd119c70b564f1a93aec62ae74e6e8f855
SIG: 4378966b7831def4aecb4989bcaf9cae99461cb9b59d19518cc1ec7b8351bcd1f723aac5f061b38363574ff96ba10e196b1b0531e1183036a425e69c4598040c
TST: 939
SK: aeb13ccb90c8cbef90d553da3f6901b3d75c13011f024974daf79a1789c8c632
PK: 5faafeb595f16d338f1c72a9f3e498f38bab69a81b37d2d092b7bf7e505d820d
MSG: 861a1018d6bdc4805a5c4df87efaa462c68b4bf4065c684c2af131c6377388baee58c6c8f8842362ec6e3bce07c8af55885e82db87a15227800dd33afc5e5fd15701e95f53501b1a6ff83c64e8517149bf3ff011b094a09c673d0fc4a39ee55e69f071177b8aa364e1e256064cf70279cc76695ae49dafcd80ca0a14e1691db946422ec75ab4f7865915a69bd48d89b12adf487d4db9be87cddca211aa88e9bbe849da213989eb0844592ad63e281b2e4afe6a8836006609926c0f787e84f2a95b46b66f0e4555c9483ce2176fc63f7cc9f4f2a22db055aae2e68b30a0da5feb80c2a60ea10dbf67fbbcdbe0be33f2e9c13c469e7768f2ff5960a55eb482ec11d47e154b7c42a5fb756c8ad539b33d125a4a65192c6c9bd576238ca72a73cd179e8cf5cd048ed330213823abbafc3682b2b7f68c5bc46fd09a8cb2a3fd099573ee2e6f28c82e271bb5ef934b0b0c381cfaaec666d717106a874af30aa74125eae9acc2f1f24118cb4e683a731e37e5e464a1ea3d2a53cc0dcad4c17cea9a43e2365f3ae3dd89eb39977420045550745fc267fc7dcc5602e914972a4da6ebeb687f68a0cd7d8b4fdd73722106a8e436b93e5b58f5982acecdecfdb382fe98538261426ba64052557643ce9fec71ea43cf5b6cbadeb4953193ff3ed1a1f922a9af2ec6f338e7fb0affe3d13c33e395873e4a7a7fb044981e05a67197b996b199b43011119363e561d5b8a51784fdff58ab80ed4c49e93f0cf41924f9835efb09f64463b65517b67b15dc3f28ad9a9b2d29468de2c63e62004b6a3fd0c5c2e2aaa6cfa15e4faafa1e2c713e98d3fd25cab9e5170359c8365152b474276ed0037cdf771828e2fb7ccec4895f21adcc5b6887c86e51ad05f255f6e9dad2c41f56b98b7bbbf9fcb6ba8cadfd38ad8c62f92dd87740fa1e1bd170c00b2049c5130fe733f16b1f2c7f00b2ef97b3a95458c53f199d465336d5ff5977806e1afde3eaa246d85cabf7e123481e23929976ed19c40e29ff33d80e7deab19271decd5ee06172b0b0a139bd62a2e7c83a8a65601d0a05d61af9c6032df58001d473e20dd6c6afd78ddbd7cd178e9c271e0572f85982823ce6c402930cf80f5e0c7cda85122a76d1ce021b1e3de2556d1b45ac7b01b59cada25291d638a52a5e7dbcddf96bb1774ab0b077e4b3da5a958fe11dee4a02e69b918ddbfa1c5b3b7dca9f8784bb6b0b9d5a7fee74bb03747f61c2b2f1b492452d3b560b48d39d8721e983752556d44da6b028d9aef8bff9aa379c8e2b0a636d748860abd8e64fc8e96520a34a27f767aa97a8f77b6095218ead
SIG: 0611b19a7472a443e87e54d7c6647faab1b79a83fd4371c92b975400fd628acfc32577ccbbaf03d88f893c88f2cac784c722a08f387abc319a702c868479650b
TST: 940
SK: 73872b14762f68dae4fc10dfd6f42d3f9622bf2afe6b34a95649aa387424ee6c
PK: dfab2ce1ab9981aa7cbf3207350007fa6ce6ca60a2ed7b590f3c2f62922d8f61
MSG: 433d71781ceab2b47d826e67d39f9b80d2ffd725f8c5aeb40cbe4f9b5f48ef93521ccec604360b9647323190bfef75ac931562d27f4a4e31f46e57bc99fa5158c82e12b737e45c5de9f7dd7c8622d4a7eaadf7202fb49d819c9ad24f8807313c5f37dc20453bdf05c9bf1a3c2117c93e7f3cc8a2542098e8fc1c642fa47b05543657b85f480bc86ec42800bb1422359c7c3e8ff4be598bd54f1dc586acae45a4740622b962742bc86e17cfa63e775354e7707e5079589e8d108b1f11dace0575cb9a6d26b59fce981465d9bc344ea6945a95b862796384fa8170560857457beff95a9b5ac3d6ad282d44929a303026b4bbedd60e2ef055a31f52d7ce8df2ca5d1851c5b167db0809259bb812569074105c734c85d6231273755f3a8b56dc508db5c23dacb7a06167bda51bc01350f016cd41b21e8cc5bc93343a9bb6ea4738c5c84b78fa963c410e433dc598196c22e5b791e12a4b343f7cd47bbb0eb0782bdb1a4e466846a030528eeb89056f73257193adaabc1b229862034878c3258a532548762e29ecc001abd989649da5e144cf35d48699f23bc46c5b34e04a53e72724b2b0b878982575d688e23cbe3a34067f4971e555972ec2908ae5f03e8831ec67755be95687ce6372939e1e2fb6951ec9ecf4bf7d1535431e259f29ad431222b54b65aa7d07cfb5df162a87c4d03481eb441f221d7f58627a14164e7f4c2e3a1d507e899d5358e00829b08cf3aecb8a75b2a31c3185a580e12b13f0642869fffb056723e961aaf6fefe67b4a7c4c93db3fe1f61adcc765569a99c09a3c824ed4a98babeae43efb1f351ba130e22aa97811986be923cc4180a7c4b78bcc140cec15574654aa6d65a06b97ecfa5f3a9355f96e4eeaa7689217b663fba4dab0d99b19c8d8dbf47a157e5d5969a35ef84dff9562edd434e73aee7d0d892dda72a362a22a7e9fa8634a57eebd1a907485ca8921bdc19ee9ee588f395687d3fc8f8c25f2e9576ca60313fbb2c265a99f2cdd5575b1dd530604e9ad6695c9fb35994a8b87d5c8570549a4d329b9fe087069ab7eb0d714a94e19261f86e448f2da9b1cb0c0dbe41d44c3a824783d1bdbd7326051aeb10adab805c5c59d0e83b1c11a2fdd35e444a499ed15dafd83862775f6cdfc67595818407be55ecbf7bf86c73069aace577626a8563536f605042cf7caaf6fc8e3b545b77414df8d9f649b99ee42541da38c3aae627207845b8f414a8074d70868a5c0b07b070c3c653be04076b83cad7b0305d9500aa44455cb860dcc76400af93c3d2efb42ae056f1428b65f122e1c7b9584d814d50ac72efdb
SIG: 8525c346ca3a6a6c5f65c41778599377659870cb6df9a4a0e55b40c35beba55c8e009e5600b6447dc7402ba27749297e8f9528691856f72d2ad761ed1bc15309
TST: 941
SK: 67cf27155287be6bfab66215e017c3466322f21e6eb140be4f1bdecf55abfdc1
PK: d070aab295a8af935727c3be442b251db9e774d2f44b3c2424c52fc89656e169
MSG: 0ff05297031c892774cb2c01e8ca60ddd0ceacc0b8d591a891e33b19e1be9e363bc6420d6f529f04840b3b08853c835a03e036978b04a4f9ec6be4aef331956190996dea272619f1686d33bef03dbc085a923a0f115b78f653feeb60bb9e45f34fb8be5a4cbb648c7d29956f0d0e96bdd3c8d0649720624cbc2079e84fd6d010241124098459f12af2991d3828770f50b104ea6e5f51fdad30a9b8079d2159e46d64af91d07c10ed19814df2afe660d7d8f2403534e92c62e1ea6d688203bca3d97c2afda83b255520ffe92a33625772513b1fe34fafe32b6a9b8cf994df7e634e686591e5f0073ababc64a89210ba53a4991c11557e0334e6c6a5036c642a318f2295117139085fb34075647006758e32bc00ad109fe803f7ee9f5ec2af4d25c3070abc51cf4d78e13a7ce283d4fb4eb41d3e8ce90238500ae0ceda320ec5922efa10b903748e1e853a3729d24c105439df2f7000123db9b2c01533bbf0d028ebb2fc00dce38ad06328ee9ecd849a6efc3ae884ef6933cfebed055bb2968a0b0676b5729216178c7519ef0788593fc0dcff50d7e0b1ebb3cf49bbd1bfa5c30ea7b88c36e1a1593aef0bb3f9e2091c8589f7414beed8df466a2ed87b2cb5f35f1d31246ceb968609253615d78043517379ee6974a669cb48da6ac2f96d700b7e44a435cfefec402a1e3110e76981924f2601c01dc03546fd4f511649302f0633dfbd25651c5a599c90954489c76a65ec05a7e4cc74616ce25601cc37b804e1f0bcc8651023b12e13568441e8b8ef4c305fcdad3d2b13fa080324b2fd6b61998cf864b658bc7fefcc48a5a7681d7c866c342c7f5d6cf10881522cc710257d25a4c1e352d270e902082ab9541d5900ceffa0914b16b55e0dd3786e98d41720875a148eb4abdb0153856679fb98c0ec485e5f458d635b7861a2b3a8ba5ec2c1444d353980200e5e071808854a268cc76c605c94f37329c36187a41fddf92aabdb4996a0e10b315526afeac80eb2fa32af786a34316b36111ee9352108144d70f7d1723b32f4dbaa82201353411d657713e55e35df78580b1bc08680f0159fa116faf463566aafe8aea69857e72e44ac809ac43f5c45939d85a1a5f4a370a18996c8514a46f34371ef9e5fb204422c934a1d293d101b8c16f99cc073ea366a13a45c437d620d132b74409cbf8b9c075b4163f726aa67e509a24874fc1b1fb6fb7c7355159c02aa13e64badf150356b1841b321f8041e13ed77e8461cfbb8e828488bf517a5d29ff82e7367480a8edddeb5350e7a83423bd0b1c55f7bb424ca04c205723cd5405671e733f391600a
SIG: c934a3a1aaab78d9269d1e9d13392f72c637bc5de54f04691efc29d473b475025d8d8fe3c523d2d29c41c5f3dec6ca38ce6d68d7ff09b6135ba24d0d32cc1502
TST: 942
SK: 18c21c0d0de13d4c64497ef0260d66cfd34216981a1b49391ae5cb0e41436e9f
PK: f7d4dd1e059c36f6d121c0affeb21f0c572b45992f84948b09aafbcd86bb535c
MSG: 68abca7c166afe063e477b80e37db224e1a235de8fcdeb7f427af67e001247cc5e057182fd9b6db8babaa658cf3b3fe4b0763bf88d67311b1190be834018cf57a332922413764620ace05445ee019a06dff98b238979ad6d30901befa3c64f6bd8c6eb092c2e62841388fd8c4e8419e2778984896737ed90a2cdb21996aef7c21638d6cbe680322d08996597a9e303f6f5f47940f8c5ba5f5f76383e7e18064a3d2dff5fdf95e90c5eb30f4d8d459ee1d506a8cd29cdc69b6754963b84d67494b35305d10d12b9487417b2ce28adcb10b65cc931fb3381ae02e7af79a02bf99e258a56361090e0b71222b3ac60bf2fb7ba832d034f5b6bc6fa663ae741f76d97c1ac32bcb7411507d518d2f6054b578328c5f67f758ac01bfe6f4d35900f50a5dcd30d2f9261b6bbec4c1d1fc18d2a7e70c4d36c21faf8cf94a587c3a0d1a9cde7831ae626775468ddcd40a8ba18f42b34188de5741e1be8307b1084586515ec015e4e371d29443a40b0c069c641d8cee5e4611862987c3e356b1293b0518b4a4c8ea97fc5a4db1f0129abee72fb8092ea35c2dab67573850207b8e82718999ad99c4c839eac14636bd5e4d8436a270dd90b8e321302e52a92d891ff1891542ae2caa0d66e0f661eae37b25b08bb2e0eeec4838009778cd525984380983b2baadd7102a1e356734e41d76183829ea9ab8244c336597ca2d67988f281438467e453f562c67b22d0a4dd9fcb46a5f80d299db5f01f59160a19d74c644fa5a940e32c9d8d983bab7efb0d7c7da4e3fda1cd0d18a4558eb9fe46408aab5085912bf2f46ab63a9354f9027c93691223ffaab8463bac4c4bc3b11abc46ba68717c91780d3f30470dbdd88b3780a194c8a40a2c0a81a4d56dec2d8962c34d2ab73369028e1bfeaa6bb58241ff4f898f80ad3bb1c691b8647f2c6983954c1c77957458eebf1c5055c31693abced05384735a4f741968bd6ac31565cfee71c884c1e29e9e7ae0f7ecd04d463b1dc389c36037e81458dcec61d0764032dd589b92afda2fc9028f41ab53cca2d04ec6a9565955cbcf1a3463989c7139bb902a5921e8b2c99c48e13711f0bcc399259516c81ae942a679d4ba33979eb12fcd2860602e4724b1330f1cd257b5b2891daee8ef4c92fc3bfdb34e532d5870f3805986ac97b503fd85873548e30950000f8a70be51fa757603501f2d30e852efeac4826862aed7f6d20c9a8c8dbe362dfee41893f27e6fd5e91d0e7e3d4fd8155f44fd8ef17af14a848d44a87631aeee751462b2a54087068daeab3ea3289ece6212b3b52ce7a8886df2a727b72a570c2fb9c50341
SIG: c9c099e21d095afadd4e71c9abf6b7083324776225b587b60a0e6092ecb3d33cff39c67d34776ae99dda754a3c2b3f781135a38c78ed6455aaf0ae0c313b6205
TST: 943
SK: db9aaee198cd26a52b1181fa3fd92abe425e666d890bf969467dd2ce280ed4a7
PK: 3c897cafe2b499ecb2e1dd01ea55f3fc88f68c25b64a636b31a1fd1c78f37f3f
MSG: 47fb621561f8b7eecec6033f2bcb6f43ac68c958dfd2656f52a0c29b4acd44f4304c6bf77eeaa0c5f6d3b22db19699c3dcdede698abde623ec4b2b90910c80ac3af39c550b6dd409e63d77706655a9199cb5c0258f5ba38285ffdc64b8a8f373d1fb29ba87f84ddf5f34d8f140bbc17b3961682df5d0a8f9102e379a9998139dfe40ab8ce753bf5626108237771a7d8e109e9e0afe9b66d0420942e163a4f3c03f71813ee078bd090ac3d0772e2622c259e682552c75b08dd055a4a5eb5e609440bcd3f3a6feb876fd16921520c6cb6884710d2e15cdad6daaeed95962dda21c6788f784917917982e1ccbb5fdd9bdc1769db6b6db57ca354e01a1339d8e77e9dbbb5812fbab6a14c54085c0659599f150e22472470f1e5e672c425f375f9e0d6e8d52fa17b7a8d7a4d7ca3e12f4db53836aed2bebd74589baca8ce9100291bfb7e456db7f2f0a84dc0a7488851366a9a5fea0e3efc74b9cdd4bd97b65abf361393ce1703d8571805ee68a13d3654f03dcecfb77a53430d09496ad73ec01759957e51046aa7396f592338650117ac7b4dd3573eb53d9c9f9dfa62e2369c77af9c0d42f61bae74b287ddfa27b7f1c1be9883a044691d56dc13734ad4ee3a32a9f40e328c500d0fed8ea0510e938f2758004022bcaa6902bda1014b8ae3365272829ed94faba63cb14a36cf81390eca83fc1c627172013261b3993779aa076a5c5d81d90d27062e1a6d90b5cf1005c701917b7adac180cb75bbce0f27f2f180e2cb90140c14cc6009d2d41aab1db9418f91d4cf394002cd70ac9dc11ce865347fa3f56f87c149e2b17d2c72b663a58e3187bb19b9bac2d11483ba12f770ac04dc46d388518fa54dc152e9a9dfbff14f14c61cb375897e30c53e6de42d5e1401dae1b22baaa0e8a41c6af9d0e0b13a91a23d9b7d5552047029a3521946c7120d3d258b3aefcf754d1959487a1fe7743ac7e1cc89e368b197809c3a27317e0ec48d546db1e21eb629a29bc6247cdd4a1371437563edd12faea2c5cb77eededbfc58008fad1f65af35843fa274c734e3fbbaa9cc50d683748b75a485f94d630b032a5f1067d1deb30e9d2218c935c981d01c0c547fd68413136edf4c0c770286e823442e1c513651929213c121c1de700989141ab4af3b3fe7404b4d2a38c530bafb498e64953ce1c0fb7d340e21135bf8afdd8dd65b1b18cf1c8fb9f402b2670400b86ddafb184cc51d5fda273b80c26521f912f3583b4ae301dae151cb55c75703aadef032415227d53e395db6c150a1ee839ad26bae552e1ab736214dc04b0f3c41b7cfbd049681bc84c3d16530768
SIG: b2e3d9c5d0ff329996bc89d26fb3ac126bded313cbf8df86718638c199e057273d09eb163c6c181fd8bce51f72d4d9d2e84abbe08330773b9fcc2166f140d60e
TST: 944
SK: a804c33b4d38cb3ce31cf3bac1049e0d4ec63a1a0b7b59fd8a36ee37541656aa
PK: 6072256d6574a293bd7c221c551c32cf2f7715e19e433a49d9b8b0490e56ef62
MSG: dbfe307f2aae9e07ec7c4b682106d2c9367b0c4aaa58ae804e0a3904754e6cf8fee73cf9e2d45d0289e5078293dfc469d46ea67026c5aa692d2f2c9fb4ec57cdab4c043ff9ae6185f27a704454e5f53950aabd25c9910474d45af8836862723e0e6a27823d82bcbb68a96052422a1819512e3b43408cf48957ad6ae235b7233df18284749153dfa57de35074a30edfab8a56df28ab2e2940306c221aa55490cc664e14683f30ee615e2d93fdf971f596663465843b3add6392ba3390311ef8dc59f251445d669e10a0061991e113561923aa215244463d8264199ac588924e231e8419d8685f338e599b5f40bf9bd1aece772535bbbcb8f6881c2e800491ab3b57b44b8ae43aeb5c4ae5e7edeb228fedc9f6b9cadea176e134936ded60af1c228734fb00570f2374bbbfa1bb170785805d6b6c701e820952eae45b8c2366113a1dfb2e35852af419b754f9cf7a081c3dde6c8053bf1ce0c85339d5699c422476fc21f26ce75d2a7fed09fc0f4175789847d876c51aa4e0bf7ce842b8308dc7a28c8239520714dc233136e09f557c7ef3e0f83bad63cb28ac616d3928f3837dce1dd58acb8ddbc72e822deee45f00776acc88e00cd3a9db486d92d535a57a0fdc4f903b62e517221c308cba2e30ffe7b91937a99417721f56fe6df44840e9e41136929c0ca3dc28ddf2379e4dcfde83723e2d4c9e23299c056afb31d3e70d085d0a312c5cd570b699dea8717458531348c96f6eb52d7ee61d5660f65e909a14ce1033dc853f2f25d09cf4e40d07eff72e15a390564a2be3c042d89a68660a97ffacec4967a4b618712d7060756520c29ee8d9220ad8615c4fcf3969bd3b2e0947e1f0be7e2d80e0a61480c3166db5582218bb0a8be9848efd41b6ce0cd795c486abb67210beb60cd078b46aeb7f4f485031902bcd7131e00b7035aa2d43fee063f7f30bd570da1dbb65c0ca92a4812632e432778553e35e856caa8218221fd6316ab0869173b38409bcefe6d2db9210f9024173b66dbb92677cbc71c8a1cd583fa6f354d3c93fa8b16c71374f25a00c332f85a8befd540388fb50db9f5d96e4e4e698833ce3d63c10b8eec70a243b9015db459431b62f5668bba60f0704f6bdfe9546ea475cef2ebccba4b7680848e82beff5854e49f65bb773a4922e90f9b8afc7cf818730588ed5aa7b399826aadd54372fcb761458b64de66857f4adacd4c32900cb77136a535d7bbbb554597aecf39ff698b45e6a218df1d2abe615eb8d9e1824c0becce90767899ebfd2c730144b32c74604c0e53e2505bb15d28007a87b9931d6eec0a6cb5b0f96d3194b2423
SIG: b1b44a142a7c4c3d0bf4661edac5b767005726c14a2769b7c214fb58737ec2e4bc51c3a195d2ba1b74a54eff4c33a90f41ccdefa9e9365fde8dd859fd3978c0a
TST: 945
SK: f820e6f24a8418b6acda165f29a360f767cdedde8f64d768b95fc2a5f3f404e7
PK: 79c4b263b2e58f678628d4ea82b175aca230b9a20285c828f94e1ffd63d75b23
MSG: ab6bd45bb06dfb9069118ff998f3bd393ea8e944979e89e049f2505cd8931b93086b7e9d8ee764e9b447ea4ea12138bb45275a21a19843f75dc5421d61ffd861838e5833825d67162f3259c26447be51dc1802ef5a04ba73b783935706abb42c513b65f2bbc44f83da1061242f2d5e5198f38c10717a86a3a197e7cd9034f636114499037277acb4722c06a91cb2f65e21eb8d22d36ad73b4265f7a7947e00e722bda67043cd1281bcd87e763fc97b54c8f86836cdbf08c9a1f700f4eaed9ea59a6fc1bc0df8c9ec1fc2977cad60f978abc0c8381aa9fb060e3f99378a51b2d9afbef358d55162a38922ebb87d2a3e0f0f4000b1c39b1502e95945e8ac9f4a3ea7c9ddb581a5ec06c00ba87a737084b384faba09c84871ddd67dc1bebb2f7fbd94a5597d019fe629e5bf12bea2e33ca84c680dc5a3989bbf3af9eeece8ab8fc861e3b8bfc1e67e2aee326b37fb9b51cfa0b5f5fc160069b450b704e0fab7fb6c5ab3c40b8f0b3d0930b9112d64b9dacab4dd875f29d8c58c5d2053ad9148ffde22d90bc0d50f5deca68d3ea25c5b4c7688871c0c77dbceeacbd0a4229f4970ec87b34499e278303c06694c30ac68524d11b172794b481273a5dac46122d2472095a563a435d185d5e91da726e74592999cdac688a33f38f7c035588f625dc6ac73d0047ab3d6d12f1ae33d8b62d6d6c6cacff0bdd894b57e318912ac0cf4a534762b2f6d263c935804423ed868cf8cfbb8be8f6d8a714a268a390edc2dd509d2dc96851d1bd43249bd0f69b0c4cb2ff4080d1fd5622bc238dda6e930025d8a2b12b972f9eba17421d4cea642f40ad9ea8547ae59498c3ad1b9a0c34ed8c01aae3bd21ac17743b577f9515cfbdde2704dc57e80f125323d55100b9f697927d431dfe73631b58e52aa6aeb0478bf459552438689fbeb9c60d87aae09954362cd02a2b0b479efd38f17821af39b21926ee02f7d972ad0f54ea6572cc3ebd020b1ee26882533bd19114323815f672ec8c90568730a58e4e1e35f6821219a32b8a6c52ced6f9573d9f3beb28513ba62fb201f7fd41bb10ca34bb1c70f2fd7bb9299a7c5f7f2e0fa1d1af0e9aef5ede7c16950e860ecd61f1842a1a22c9831c0c0d4eda840b088a54520c9b18c76eba9bebcd591381c180d7f86a0e58add92b9b0c8076a7cdcab60dea4c1afb18c8b94b1b392ccfb4dae2711e7d12d2bc7c7825f63992ec3247163c283b1075e32245f69cf47240aef0db43efae86fc1fd3bb99cf5b789f5bcba9504657d9e622a4aa16f01d4d844413124447d6d1a4423e7b55db7e6a31a319f4bacae430a33a9bdd4ef3680
SIG: f9fd72f321ca2133bf8585908d9ca7b8e336227e3ffb3749a1fbe8c9b1e5d50ef01f9db5f0d2a7c7c1399b97c9044e1bc1adc32b8bea46dad7b8102646960303
TST: 946
SK: 0a056be039fd55dada441d037361273f206e000a74a05c51c0cbb62743f1f340
PK: 73140217a493a17866fff5154832273df79d5811543c222a39d056b8c970dbfa
MSG: a5ab147684e4d4a7bcb5a96fb39818e23f56c2d8a744e9123d62083930ab1d0bb532e68714fcec7e6c41134b6b19ddd867fe635c9ed65393ee39c5e8fab456cb5b32797883f3cd9a0902b9796348ee66c691fb4f2bb14764410657c74ab364567879b6fa0a6f4dafd930d9234cd7834fb9d0eedfbb5a394bf0846ec6969c2ef7ce39e3853895ff5b4da31e54341b4272e4a26049189ff28241ceeffb7d2e1faf4f779fa65cac0f5783c60ae77de30ad4465fdb390d42571eff4a63136349937d6caeefcdae229e2f28cea8abf3ffae3c3eccd90670a4212a2bee1ca6a5b54f094fc3231058f5cb9eceb9993be47027d51c18deca41cddaf4e8bc56a99fd270355ff45971950e3437a198ccc3254168dfc1574080802ee101a617fb604e868f8fa8fb30daeb43074de11f2483d916de5643b7cac23d9340508a3fd621ecd25004356a53554ad3ad7d5d25817ad7c9a610008c67ac16ba4211c42f5dadf86c2c3aed825cf2a9b523bfc03dd7de400c67807e139ea5dbce4ee1f7d318889b01a9f44803c322ac3b61e20e6312d0a03bf9927fa33f04ed7e207b16f26502c2983a3a961f224461fe9b64923b1d09189476ae8d001d0ecaae4df60db35f448bb612f9655a5fb144df11d83aa6936886c304949e59aa46df65c22ce7bf289b3c77c25d896be6d51dee10748261688c8b071c856f9962c66775ddf16083dae06587e32a6361199d72097e383ad7439491b5a563a3e6d58da3d5abb1de84890a36b421ce03d484dfd60039638d46edfb60659e3a25ac6e9a935ad6dad50f927bcc2ff99f9924a5b7995dc23c8f301ccc7769f71c18260904a3dcfb817d2d805cb1f196be8b6ecf352bc296bc3f76ea91353f8cf35bcd2b57eb5942773d6834ac50eeadc7e66461d1da098ccec75ff7205215f52459d97620f9f0289e93911db39b21df818fdf0bed45509244633df01cdddb4b75972fa7ea6f73281cbdbbd1bcb00c3bc1b1728eeae0bba172b131f5d30890a341e6b72f7e89dd4b6db3e79b6927586cf2c8ac38dd14f374d7f5bba9f4353def10ddc94d3d1118c5699e38b6b504918e589efe3f7e973fb40e2ebd057de1385e39d699a8f683b962fae4f3902881f1afbed7c783823558c36d68c6875d166fa243eb2ae14f7e6315a6d2ab4e79ea8e16e69d30edc708f1e7af7adafedcd3168898b331878178c4ba8833d20b3cac9d32b8888cc6783206397470a2e7cc4c9809ff79ceac9dc24ca1438c919c8a415e82f0902b4d9cf4ccd576968d5bee81c5f19c7d57b9bada8eab4756ea270dd26129e6122ee2d615242bc7fabff4f8312e686c8f
SIG: fab8e5d93d7d46c65ee117c5375e73c9705f8754177fdd46efed4737c28768cc4b95a9c84c529b4b916b28dabd8741183144bcdb483df98af89d8240cf094604
TST: 947
SK: 220524860cb89ab295bd884f988a57911868693d6b105a80b230f21e57805a7d
PK: 4ab32bc1566a7677e799734dc84181fbb654b813379180f1dd35aef2d324c12c
MSG: 024a54ac5e0163b3a4fdd02f5936888ae2f9b74a6414b53c6381173b095a4ddacfc3a69f19167d0f1ae0c120bba7e9fcb7ccfc796d89ea46ef8058866ef6da7d01a6a142ea69d720c4f805ac5405a8012c3c2a8263b5372d59bf7f4099299013d26259dfd5193ece56179777be51b86bd1ce5f1fc9156f2b3a32c09d86bc6132de576102e2f03c716db5366ccbe742aee3552ac3b39d0ec7d4e4e9626bf8ece031d678d3480905c0e338fb7cc026e3e79cf2c2781ac2a5a40df4284e235a0389e928fc63557dc6f199fcec5f361ea24759fa7c5f71978c0ba245e4b03ae435941c86c81a51430c2dc9927e3b0f4ec4eba7c2745b493987154d7da85b67de21c598407fb2a760804ad05bfdfa45a613224b22a08588ccea3cbdf47a198bebf8cfed8649d6d5f3fa501376bdfba4003dac2237dcace5315b7fefb879a89a85bce6da526fc360cbb4fd554ef013f33b7384cd2b22a88577f3a2d366422aae46417ba916e1646e24404a88b5d53ff1aed2a47baf81fcb4286397991394b2ecc39667ac46c2bdb6d023b33db013457c4005d839015d8851f028ac334fb24bbad2902a4d63ae68e0eca7eaea1e856529647baf1412213754ed50af3f436e9bafc1601639b39d3e52a93a898fb6019fd5ed6e7dfc050e7ce5f3d35ceb5067021c0fbdc708d3f26bd60568d1ed2b612b696235d5333318f9a6c987235a7a07f8c6a9354fb8e734763065afcd4d937764a4f037cc7e7e2b93217f1641684fa81b7ff7986a28b38e95b332e74649e83d0ded795c57f24cf276e0143901bafef0f1693fe7cf10904fb0d880d72e44716a7069daaae742cf0ff3ed92f5f7d1e10e049d8df043631ed0ed4c4ac4022d8403cb0421b454cbfb6f48a30e9ee1609ad7b68211977acb33b9c1a1be735814c58f66db5f0b8ac773b1d58d4e6bc45dfd48a294bbd25e92671f56f302f29b50d80431c8f2ea33996257b208e057ea7672cc2d1cd4204b85b2ab509027131359aeb42e3eccdbaecfe2cd3e5a3313266e761194ff69cae9e37e51cc0a54f086dde13cb33118e34fe33c74d735582752d68d21c79e5c3aaea94ba107cb7ee8a70a3f9a01e9808c0aeba6665315b45625840a033a6e2a875495057942ed9bb2ce6e4ee60bed47cd9d584bc24524397a109498ee2a973aad6a29b70a1cfbfe9aa5c7cb9f35f0fa00227f43988d07619b6fb2f6d3bee28e10ee705347015a922e2e88d34fb0ce515b08df3a1b634ff9ec15d0594182c86ebb0db783612a7d19e4b22e822d566245aed72e694c3d101bfa4ca879862e5f99c23a5d66083ce06d87f399aa7888ab83b8664472
SIG: db1cc0c5db773ec51689be28842fa6791a7d75e29c228ae9593a580e0875b1670f09b03442929a18f1e9414ea34315ff09d91d922ee47f10f71da4ab13b7d901
TST: 948
SK: 4ef60f0691d737e64d437bfd3398330e55e3c094cf41fc557b0fe0b643909ab8
PK: 306ab146e5c8cd630f9b48bf8b685db0b6b553ef69686853b6b531960118548c
MSG: 0a188ac26f3c5d89f3d588374fac5ecf9a467e2165b31d0b0f23501bd22e62bf3555ffba94631de74a6a3c3cf63b03ac1bbb37d233eca5993b0970a0220de8d6c41a970307309a52da0576dc334d806447aa09d0b245eacd0b42c4e19fa3d6fbdc229430eb3c7558af5331c6e7fcc2e552ce35d579073b548dc115bbd27e5a33ce1c47fc8461e391b6d767953487cc52ee673bc4be96569c8557369ebb6e02f79238108c3b5856ee381a79ff464c8f6009fd47e67b4c80201e11e61ab8f59ba5d07b15ace3fb374c64b6b4c345e2b00e9151ab8e1c5c98568bc58dd0812aaa3beee165e7eae58fbde63077203c4fd6e16068d76e3d3a13f1cdd73288bd5e4da44eb119a04c4d32efa2f13e7426a2f41c5623c9b066b1303639b8fcea0d8774cc08045f7e346365ff31d3b1ed99e97bca5f25c92b2843ac585d02193a2fd39466f73aaa989b1fa05b9a157fd0277c5e745d258e027803a524ad94309425c3f4dec31c0efc547752f4c7194cbb272f849a52169c6a078d20ede1432016528477b58c2bdf6063f9447e33837ccb437d8d6b95cf4c44be70c8193ad980a105f3db6f9930bab4678c776342faf170edf74248d3b1ca96f731b9d026d8f0f7c34ed372c1cde176f55f558675cc3180c23902f4ba9508d1c91c3c9e688730327f3f7b637a8fee54373759fcb17c9217ea44ce43691a8f6463640a4a5e151e6254c4ef12623b49394da7cc79452693817d6baea9a0a75876948b1f8d3b717f9ec36753f53263710383b98262ae6354ff2a2283220ad42c5cb2cbbdf12c879513710b16be856f3b1355b36f4b80c017c21be85e96053da050c40312100abb640b873d88fb6ee0d19e9e61b04c970bd1f060dd311bbb9a6e35b985fdca17caee8cd5db637acd90cb8e823255c056018fef5920db640d2201c5eddbd8a9c9474da8def7e1325b3cc436c74f815db1e42b421faab626a4378c2d84261bf649a53b321f598c44bbd3002b06cf7f1fdef84ab35f73ed7dc65096cb1dc0cc0e34c561c8a15cf5279abbed9b16ff24a9744e3f5e649cc9d8884f891c3fb78902031ffe0e0121c72080ad10c247b7c93a9ebb2d84d4f877750d7b3416393d03045226bb7994eea58e272dc18c46b382d1f97b23765fda7a8ce21fc6b98d723ffccd99ac4655cc5d10105a2a5b7c8cfbfb90e27a9a809e41ae640063286405a9be83ac5d2907a45f163c7764b09f99a55593220d6901292b9b5803a0fe71b0e4441cbfef841c33cebc98364d666e5a9f5e7e69a1508e4380ed361345b7248a4c1c1ce08769bc7152ddb332fba176200f5abbae3812f406da72dde5db
SIG: cbf7cf22081c5f235dba35630fb3f0408fceccefeb28b99d74dbd98c902c7d99ba9ca7fab3747c504cc219f4dd101081f58ce616e29280e362539fe49f34d705
TST: 949
SK: 197e15dce4c47d734dbce4688a7ad5fe41ebf2aa29a2bddb2bee628429c1bc02
PK: 30fac323048b0c781a9f63c1ee69f2b9e75a2706d249512a2739607f26db138f
MSG: fd971d48946b51ffed7b62c5d099c1e56b1358b92235e1010e3f23844ddb73bcee8d2e1c9977353bc96a221c05602931fa16ccc2ab6d0f01c846c2920e99de026dc2897f3d5f3cee174ce751d4a805ee1959a3c69cfd42d7c9afd31fa9b1cf05786d8f9042a4f9f81cf7ac9c1c39b36f1ee95b98cf7ee3f43e2c343733d1d82cc08b2cdeb78d982034085ff4dc6536cd154a790c85c8613ec4e5e1dc377d38a745d938cfb15c8b8aa86121835f2e25e9e6d0de68025d810c3dc9df991dadad39dc6981fdbac1ff9b7a791c3960d8564366e5aa39a9e9c7cbf1d3f0f820d1b90108751ac764dabe05c51c18529da1b0349614668424ab4e936440c4a2513be528539372eee78754589dbe7994faa1f6229124f839950ed0923f4323315ac963bbe4c8e177dac516e7342238f1cdf140befc8acdca3d002b16c1398d868600304c7e9853b23a51b17d9fd06156e1d1d08a28460909fa209ccccc4cecbdb1a46348089115318681a95ae580ab6766041384651cc4e6145103923bdf4a32a93d93eed318791f20805f7ea84b743ee11ead9e4ca03da76ddd249fd4475fc1a353c70a83389bfac52098db066d1029c4effbed864ebe7f107e0103b3a8f3fd1d6ab4360b99e8b140c5ea133e923c392b8e4063aa6e522638f61d7a71c9225897d9f8a1e16cfcc801e7d54104eb10e61a5ae63c5c85a5b29392ab3ab8e5c039f100d0f4600c610e0209436ef2ece4d0bdb0bab437b2db5f3708fddf96660f6fb1a90d6048d395afafa760ccaf15deaa0effeb26ec17681d172c1330f78e78a8736b285f615f15d4f2c313d25f30aee9d1db39f535fcdd0ebc8e71b89ce6b3fcb567cd0fa288f48ed3a759bb2ed200fdc23091502fd9ca651ce5e3422a98335a81d74a65cc1500e9070abb609c1c1f68fc2ca94cdd550f99bcb2d092416b9bd388410b8fe748fb8c9a5ab8615f2ed968f85dcb2727726984beada7a18afdb0c72aa65de7abb7a86f11169a6eadf1c21d614e52c0c8f019747d341a05d85e37bf58d8327e9939c2387c2744edf838563cb37f0b16e8a06fc628a97230506fa4183954dc74815f3be2eb2aff4a13c065f743b7d85de804eb28efe570ed5ecc71aba97f9763b436173247f38e0cf6297209b65128465a382664ced8011fcc3d0e563f155bc63c94dde73c7b17247b8c3a4e8034ebd4364635185ce9c7081dbdbe8545f79d01aa532a0dc52cb790a31fc2ff41acebad27cce9244554db652fa287bae7decbcc8ce9e01d1a88ab412b6c6578203b42dec982b7f3b82314db2cc7c5c3dc1d3d8b17144da7fe60e7a8725fd0a97c610607cf413c72
SIG: 2c3c8cd299c9060b65999b03a6579bc50ef1fe0d851f23be9cb58f8fb8c672ee086a539ead949e087df091122d26faaad206a5c52fcd58b514d7a935be017908
TST: 950
SK: 08b5fd4e419d2370c0fcd6c3b92f8db3afd42268f533085d9fce32b522824e34
PK: cd0da699379e4f9425e84b9757300a51a163f358734cc37a91ff0ea488d29779
MSG: 3ceeeea30fa401563df36b198b9b59698c10e100a2f30e6f78fe62b92ecac989e8aa09ec760e89cac0a16bde3cac73622a8627efedfa4ec09b873f7e1000e76982910ca0aa4afb1ff5a8448b76f7b0d2a2d52a7f40dedefc68d60ce6622ca080d6698ea6c3bd7210b3b648f53252291494b35a55ff40fa1a631a57c510011a46bfb9e271bae1e78ce6c6ea60c55ba0cce36059bfb01e394556987f744b72aebbdb4b1bdbb3bbaaee1b8b2f3174506a793f0a511b2b569049b30a2e0841424184a48eca9e2d83783ac5b61eb947cbd8bab7ad38b0c68427d8f94ae285190dbb6e0c6d580a25142394be948158d8da83b4f34a8d258b97075632b3c28bfae3105ed1872e356e43aed59397b9110bbf9d8ca2a044d5271e6cc361e14e69a932517683ec81818f02cfa0295e5661cea3e586afc0db41ba95553ee75b200b0f9790111d3757a739e563557aff9b70ca14e87b795437ba91a95dd07ea69a11359f36ca03298e0bfa4f912f64a2924ad901975a2a960ba1be89921b1f5485496b7ea5da6d8a6937ac105bf3760e4876990a0f5c5a634f74cb57df7c172c8a415372e6d903298717499616f8971c68bbece92ea878a18e23f327c3649b6a852ef23b7b3e603cdf80452dbf1be2fb77e814d2525496bb31fb6e4ed2533248b39d5fbe2390a9b6fccaba997e8b49b59836e3e09529ea5e4113eee451c9c6bb26741d0e4c586f53d604c6ea0c0e60db02e5109f3734f51cdd8985afeb3ecaff65e059e312cd50fa349ff28bdc9b70b7f532dbab1df43b03167c1d2e3fa6ee8c9b174a0b2cf8aa9ffa406bf5bd7288780c9c4a6b697949b48638d42079c8c66e14d9b572a210a093eaf1d2f7a703b5cd20adc4f9927a6ea8ea78faa61bc62b3c5cbd3a53252566d043ba556590d9a763be7fea4b20e1e9cfbebfae15439b334dc539b17dada2e434e9c83225b1e8f6beb7d556b47d7f69f7eb7df5ede2eebd84e250b7c9468c21fdc0170ea8df662d6180581f657fe76cef1858b6b02f7325c7219643fba2f7e9963a33322d6504ab91bf10a978fa07b47d5db0be000dcd002bddaf676b77259c9f60ad0b11671cd5777c1e80b13f82eb0fb6a180b5666293a43240862fbfa3978d95311971afab9e1cc8ab14a876b6572ac8a4b7e0b40aaf6b52a1cf4c1ebc6c1c487df5a3cbc4005a0ee329cabc286db10f17d0f1782e07d3324f0c73efbd3c2fb52b71f98ad95db95062d91425e73467bc1e4e9bf552e8a24429d97db1d66dd4d995e5f8d24e9c910b2eb1758ef75525c3d65a3f430a027348820ce3053b6f3af4ec96d0493731c818c6b1a70c250ac686a4fc
SIG: 42a13756b75c6722485fa3f694041b39b7d7c5fd40ebc06a52e0ff34ce14d8d40fa82a9508b568537d26d0dd7c0a31be710da80aab35196a039b60641db1e101
TST: 951
SK: 1e85c9e451b7acf801d16bc8268eb42ae85c72c68e9f90927aa0f3b50befd229
PK: a69d057f4b743811e07ac74561c225be0381c7d5849e6018793701a8cb6c99b5
MSG: 189ea9c8d9ed14b0de82b44cbdd58757a27c68383fba597761f9e862e08de15b1e44c3db1badbde76980ee39e699629f6fcfef32d36b3393da2ca5a81f959c8b0f1b801b5fa4c47ca39591e612a2435c5bafd77a5c7ab74359210906f47533b1879e2a5af5864d961c8146e25dac772555e042a887261419ab8c9f6f625625481da5b93526a131f37b534a0050a8a462b33f20a7e94b891530b19bf654ee9534c9a8361d03635d8d27d46be7bf84781ad0d42d1e7c4854a49ba1ba458262fe5ea19021b935a6949492d70b605e151989ef2641b2bf81ec4b92020fc7074c2a63229d51a944186a28895e8ea95292c2f872bb21a3149399e23ccd8e2fc4f17a46b59c282c51b58d00266a5c16b1ce350d5485e8d8016dd0a50a5984cc948154cd5ce7cda0ee0ab1d7251bdc70a1785b8e9103917f4b917ab2b494f3483389a2f9237541849ed3bd565cffac9e756db56ef5e23495bc771e88bffa8707ceea5c09becadd059ab889d1df7e887b71a9e6c238378fbe0c3630386616363f207b16c3270d39acded511529992f4e598789121d316135810636baade8a28edc66bbf5ede3f404a70b47d35988be706b4eaa03023a39093d583cd4cd8bf4c74341a028c19d60da31b6a7a034c081a2b030feb3cd2f03d0faabffb58e3fc36c006cfb92947a7de5ba87476c1b051e18283c03e9c6e5a5c3c2777d9a0757372379664e82f8485824fedb70a4bc4e356edd1b5ce0fb6e41de0171621b84fafa00189afa8a6a900b14c70758f7aa4fb82400e0d18ab3cd7e48acfd489cab0e72e719f79a07d066c531a891c55291f2245dbbee44e52b1dfc8727aae387ab9e71994a3854e1add73d9a7965c775521c2f540842276dd309e2f6a341e7f0f37f22bb6627b6e9cb25ba24c6c4f4eb9f5e7622d88da1984e29c5da001039c44042b59351406a41336dd772d497d3fc8aac41172eb5aa6417fe422ec7c150b96b0454ee331247cb1538aeff3eca2d50e53d6d13170a76a0049ea0c05904a6390ed14ce7491e97f754c5222dac4b6118ba381f552e73ea8491e3b7ac949569b569cf2d29a80410e065b5cc4a466bb04eb7a15f596792e8490ba7002ec361571af5d8f57675c956449470a2f9955407367e409a232899553120a277db863e9a82ddabae87b789145ba898df3c28b96fbe3014cd085c6e60ee8831701036d99c5425d58e8bcc9fd9271d46aec1eb955130102eaaab44e0770c30b2b127efb0e5f8a3f7a0ca34ec9984a46011bc26bfde0c0819bb54706b565638b7542dc4b8bf8098dc01f161b3b129618b59aded33cb59ce9189a6762dbae5b0d34b71c8dbf
SIG: 6c36da9ad6c456343ce642aca454923a52a2844ce5ee58947c8df7bab2ebe467823c5633e530b167d71c47ad9549df05943f99421e17475c4d4f08dedf6f3205
TST: 952
SK: 51cf868f820eeda0dbd10180f777e6065c93a483c58a778b67e7d842302fb767
PK: ab088f502fbcf2150e4846b34d2c8097ff013c02a8b97cfcf2b95a1c72df3e24
MSG: 7c2d8ee82d9abf8aa9c724c75b90990473f131763fe93b30cb04723588621da2a327928b22649fa062cdeabd77761538b2709b8fb7a2006e503509134c929c3011e1d728a57a4e175198075e214253f3f30e01b6e04eabd4de06789558e698b186efe34b32129568b3e8d0d7ea3ff00b3f25a42236893aa8a41b674a0ab5f41e7b28cf5a7cb765e18ead6de6a353a7824a3c49786038d6f4937f3264d6ccf0c0a2465bb693e52b3d1e6eb9ae4cb65d09cff54842e85362857a59f7198a688a3df38513cdd61e21dfd859142c8344a3b8b2a7c7db170f39f87ca3ff8ed427962b2b1a14d122fa2d5aea2a6640117dd258fa0fc54ac6e940bc16d211ec9adf914ab16578f521f655d2127e79e871bf7fa7544719d58ed847850cb27b99eb8f29b16cdcc28b15c1259ab4d589705a406688f605a2ebf58051c43a77c4e01fd6f749d32db4e89f263c2c16de181f0e6bdd0a6a64ffe6f1829444096d9f3e2b67e4bb006650b5929d1f82eb11bbed24e8f1018a7384605a3cf29ab598337939c76a3be861e483c5805ec3cee45e3424847a08558dcc99499fb9382acae56cdc87fbd5b26ff94c86f2e108794383501c8b33366850a76a0dfc0a7cd789a03f01a3e9d9e9ae39fd7245dc29299d24f3b4b167caccd223a99b6b20a3b673dc5f7466d0b2f815098a497ccaf80420168eddbf4da57b8666e9d33c48eb304b4cfcf457cd7659543f6d1e661890f562b43b8b6d1c4dcc077b60bfa533ffab928dbfd955dc5116d770950b690e2106ad52d42c31c22b8848894332b5c699e5c331fb381e5812e7526fdf4b8aa2daaa2ca2cfb9c92111b61cbc3d1eef6c8c6737f05588f04467db8330843acc98dc1a16fbd9d9d94bd8bfde26c3f71dee72b50910c36b240f802a61ca16372f6ffaadb2be4e853c5ed69a3d1f6c7b2de513c53a3fdd0a676f83d09d5c51176047d9200716bf22bae45fe01b3e0c2c51c16e46ad0637f79f9b4d83867704feda9f227831dea263399ca2771a4e78b4df8ac0de6a941eab370b1fdb47daf6642aaeaa63170fa9b3d1e1628f7c4e7cf0ea8b8a8e518cbacef9ade84df032484847ffb61bbd07e8727cc4c25da577b264519b4999fa7c0bc323d4f3f9739f780b9b2c23c77855ee5f6dcc401544d6b64b2770158fdc6c12f4d89beb044e0e85ac7a68d42917b1345114b9a672d1231b2c6c0f969f203531e71bbb4005b103a7dc3a58b5b824a7e01b6eb9f496dfa64d64d8c6777f53aa58d5da046d726f55454c88b6d7d4ab0d2198a89709f118a6b32460b9ebceff3fddc605da77ef3d1ba30fecf07be2f5313f4ee635af5e9561d877e99c
SIG: e15342a11caf892895e466228863d083b0692f010610748c23df2f11d29475bafce927cafe7f07efb8c347ed5663e73bea89531cedc0c348e79b6e58a7574907
TST: 953
SK: 543d5f1d4a6e1029b1914138fb1f4659e69456557207406688a2035cbbb2a68a
PK: 3c83790c3b4553deae4f843b501d26f6167093ee54e279759ffad8cbc061e720
MSG: fe0057f062fc871324b8bd5d427e9a5276231bd309907e5881d7ae53b1f370c2a43302a16510b46064a30736bac90951f1d9881af62c701483ebb9272ad77212eeb5fcbc7ec228d969f8902732113b98e3bf82dfeadd0de5e765d2870b12d1f9b5a28297c9fdd1495cf87789196a7d644eecd93587dbf20c28eb09da286603c582d2129a657db2d17add3558dde029ce27b88352de3f95aba17e1ed1913722db08a795dfbb70d62a8802724cb0f535f848d052aa3dde9166963a8041fccc4e60bfb11de2bf286eb602a4af842f4d1a340d78bbbcb2857f0c308f44bb101e7bc8b741d506094e27bbafa72428ef666ea6ea16f799b4ee58278f045974d86dc72cf5260d96f9c09b2f1181e1a4500f9283dc677f384ff64e51e89f76582020326c388c08a0fd00de73d5d49c06c0c684191a264fff726d872dc3ae496c7b478cfc61b51714192f76463e3d0aab410ea115e8befedb997ddd169921b3207ea66c1f59450b7623129fd1e2dd3da8f5206391171338ea0ec8ef3c59ed8afc69f3865c29a0723a9bbe95a742681ef9857e81abc80c92d2a718a804f5304fef3c63d799a6ef8782a7db46681d0de3506446982267b2152b0c321869e23cce8c4ebebeaf4aa1ebe9283b692605260ff621b03c10822aa5f6d03bdef49c462a68d471e849e164e3874f6e9f6cb3b5f293eb38ae5245a159ec4261a9bf6b5f7b7615fd339ea12733113ce767f883ae6675417fc770b50bd60e6f20addb29c1f7506233e32a7ebfadabff98cfd09b2b3bbd3eae0069548b9d8987af46ca98eb095bacbd874724ba10f3633aa08ab6ec26494ddf6854309b55d43bdbd29a7556f12dfb23cd0db4eb3937a65c4aed96e87b346555f9fc6897943a0faee65ccf394bd89b381beece25d1ba68f8fe32c23b3354f5be7e3ea3c0dec0f7ec2dd83f92b73058892b638d4c3b7242bb8f55bf087ba45a190a698bae675e0cd5e8446f2b21aeb63d2caea0f679a837e79357308d9f0b8af31f9d08008c39ee8d347528713c8850017a7f4ab98a35c7531940fa7621e67203ee782db3a2faa30f3aa850a5ff7aaed84c00ffd214f2c9261735fac3259d50e03c2652505279d91251927de5e56a8b9064ccf9f45dcbef46e1189ced2bc79e6ff652e69097ace5568bb2d5bef3ce21a25b3f79ee275ea34e621380566d704cd93f24dd9020932cc05218c23b5b22fffa7e99ee7fe457876a5e3364c9a8e8b049cfa20969774f506d1996cbe6ef5a37793ecdb04cfdeaed7dcf79ab278474dd770822d4b36fc68e4b2dd661ef99de01de6eec57fa573ede10fbbd5ac6fd6cd8bb4eee509dbb4610374401
SIG: 55201194026fd6448b1d52f83ed20ac284e7e77fa92d5295d33825cea3aca47ec7aaca2fc08679f9acfcedb376fda4619be3272c7445e8705c306141cde16c0f
TST: 954
SK: f8d257fdfcf99796f8ce4d8aade3b225a53c26feecef395b9561d9d587f5a33c
PK: f66bd4877df78aec04ca7e77732899de06777e698629f29969f8fa9c2f47ab9e
MSG: 233e1ef901abcb69fb486085d8db0233ff78f37b136f0afe24f7dac1944c3678e74fed58a1ad54835b7dbcb46fff6c3524312273300b6d878a93e0608a4abaca4e3194722bb9e23d17194d8667b84f2db038c24efb8f53409cf5594fddb8bcd61f74cf0726b51c651ce01eb66a59b455f7d8a7d60d3927e0c6c54b138e01925371d2d9d962aa982f5e6085280cc05f356993911fd2039dfc342117970291381d82027db36c799100057d9352b2cd879d9c82af734b7fa297d21149c978aa5e125b20372a9b2e0ed357337efaea1391f3b9ef11e3e5135bb70bdbe32a9bdb7c3c42d5d57cc8dab6811628a01089495cb8a4a76a48296cd8dfafc005ad49d70bb19faca2084a1b6f5e48d23c03fbcf6f106db770f07c33e8e7f4757da904a44dd0e738f3d5733a329375ced74f3c42bfcdbb910100455d6aa7d2e3e3aaa58a829630d376b0b466dc85aac48fe269946a7bc72d91eb37ded2f4a77c684be01093fd12de9d9d83199ccc50959a48d6e9a41427566092f04a0f95ca52372e0762b966ce6232055a4fd757c61b8bad83baef91a3c2772fb32ead8f591ac1e02bbf90a7f6c39079b86fb814cc242e980f0b8b1a2cecb8e6d4e8a5211bf8babf38e829ab9883608bd6d59ea5e836a9b4a4fbeded1bea2ffe977e8cf3615ca4a50fea1f05f1fe53c8eac500323e1f52a806831539957988d79acc7b54f7d02b480c469fd69540fea4bdd68cbdc68cf9c7872fd792591b01e9d9902d8a614f4c21823f23508ffd49ff218bea922ec141eff60da177ccad7d7b9d444f3b03458115f116cc6e37625c39cbadf09362f31d33f4c13c33b6292007f2cafd194f62c643e7a25571564febad7d33e364b633d008b090d7a091358bc69c567b9522b5c1cd01218d38529aebb03d9c2a5eb2285a7176f98c28036f21e19e92b406e94895fa281b35228fbf76e73e1758af1b434a4df98e8cc556b9d83f6b0b7ff52c680f65efe4e00c59b46ce593bf98899805d02b9165b7429849e73953770ae393e4f1f97cb90cd6159cc93952ae8a4d3d56a9a95df7cfabacd4d030d736ea454dfa4b4aed1bcd885d2fbea5ffa2cf2927c137c86be4fe016412628fe7a0a0f02b6b6a9a2168932b943ff8b28dd587e77287790aaaa69a98506c764e6f5ba6338c09f382e1b987d99f14a3e1958cb62ae6705a577f9ffc67306401128741a8d0af03c0aaaf6af06bd88ee4b0af6703e0ea60b0409ace24572fb386e07e9c22c9686bdc66d4fcf3c7461d3833a4c3013243607d4d158217187326df51725a6bc5116e990bef8a5a9579600207206bfc3a6dcf0746ef756fd939e187f668750716c0
SIG: 9235d44807869816e28e42c81c801ffb121de826c0d33dcc4a4e1c932d5228b639bb294e16090a93d1f6904a7004222fda0a55446d9901c72340007bb45ae103
TST: 955
SK: 8da9f54da0b6a5a38985b88b71339dc7384cfd5a60bee159c394c22363bc7edd
PK: 1ac1a8edeb217ae9b3a3de530d24d83e11fb6538cc709b52994fa9c3f1faddc8
MSG: bd53baba6657d8db8becae6eabffa52b015a5a05fdd2e070647de96f9ca4dd219fe0da608fa0447f46d17c9a358244cd5408596582ccd3cdd0151d6f0923e63d166837845f273fca7af6c89d8d5246175c2167fbb9c2ebf6a7595491f97a9713b02bdf413e209ab22db7dd2b37fc49436918ccebe5746bc64ddd6dce19ec4558c40e0896e21909280cba06d16b72f31d987685d071db8155e99ebcc6c821d92683fdcee08668a5ed58f839d9edafb9f1459d48de8e1bb6f7ce84da0be411c8f7be1b9a24bc5d0fe3a96b02350750a5cb250b49555a487672bdff3c3f784e3fb63c1c97ba6ae43a10e196f188dcc635e214e29df509e5608a5367aa2800c1a96ad936a9e2a579b8592ec13a359336a62788c3ec55c0ffd6a7d49ecb7c682efa308199f708d79d0e8856366d269fab24eb1a075c96c881cab89708ced279230d3f1f3ee173672283eb8d8a824038f648ac437275d75a0e15f71ce56a8aeb771f07a7f32afc9d612a13bd83b7f93990d38fc3f4f4ab8aa9430c65736eb64b16806e995c1ce9dcf4c5544e7b3d01541c5721bb4be4cf0ae382a0c1b169d8e418defd559442acea14b00d705bcfa78be0756a8f377cbf183bf25906874115d8ce4c3ba874102938a4ea16036d91a42c5f8f188655cacb00c88e3a68508816e5e1c31d27180bbba9518a9630726d7d047dd8d2c0401219e14e6badfc9b95b77a6ace9bea71d1b47c218903a115ad029e7f2039ea23cfd1fa6a44d089fcacb678153d674c0e081764995595cb6894895f08e25b984e3a694c92fc7cbe0ffc4697230bcb0ca408c2d7085c11badeb3e6c0e75e6c498db1bec1ed2a3e2445c32b1913a89500f69e7f23f41d62e5c189f39a056cb9fc68a452023a333f75220cb9b94484acac6bbc671f59ffa072b71a1896a1b306e9dc558da0ec20f373e4c355e0c5eccbbf1350c8c07914892c454defcefb717be34d087aeb244a86ff49a6c470afb36b40fe8b71c505a4ff7af2984c65284938ec0e405231521f4810147dc4e373fdab6647b86f79827502fd087e27f310d6b312363113842155c57a32ba03b6cff965530bd795fc292e241c9b6ca085140032efe746f37d57e958421184b8a4c1a6a1e37d45e077319833068ddcb89d38c75beba1a6e8e4052888ec18162dd6ff0c59a2fd0b47f3119195680ffccddf5f76b35f022aa66bd1ac56f1ae333e9b9d046f0b79a892ecc4f8d2f31e17536c4c62a9b5e063dd2dce37d3d0acb42023eb2f2ea329d3876c2386a02276fff9d308abbadb7274301a6962ecaeeb20bef5e36afffc387ca8e185e562b865b49204c17b2a70119b061c29c0fe9004
SIG: f6dcc2d27baf16c4f4817f87499157d3ac1f84ed398a5e8b0d50f42edd7385cf06337a0236109970b79ca09d7c9831c876a802799421c2abd07587f5eb66160f
TST: 956
SK: 7a2efd390124d3fbefc54a577106e74b2d1f5dd504c050d0d359e53c0f5c872b
PK: efc303d922e88f70f38c1a2b920684ef663034a1b23ab9d69b6ce8ed8706f7f7
MSG: 238fbe9fb35c725c6c1f329248094bc7da1b273edc7699a7e3452b5788d87867defc40a00590e87580d2c0275df5abcce0e1aaa18290bf93b44e5ad9d760dd21f1aaca383178f9fff9130f73187ba9d31ea3604a1cdf3911e14377a0ce8b44189adaa7aac23b6cdc7a425b7ea745508455704f9ad7a8952718c398b421b6e09cb78cb52a1814ee2e9639ec68d361f0a32041d6e7425b4bb33c70196e2400eb812db8506c9f3245bd988fbc891be20cb0691559fc916b57ff96c9b14489e0993cb739a39da246d01a6ebd07583581f250bf480bc44b2c3391542d595e4d399490195f8445df638f34698f1a96ed27b3533e3eb67e8f865865fa9555ed34df11157641a00e6d60cf623fec1a92b87a15d765185fd9055acb38d75c99db4fce7b0e39fdc3f851daf65c7a33f464816931839fefe8e58d9ab742b861873fd229189e59cd4ce8239fc9543f539d2d296114266ea8c6fd152ac6b342e5d1a557ab35cac51e2d1212ee317c4d26716829e25746df17d2a622c243f3ecbb65f57ab0f4270e3d0668a962502245b94c06df0c5e39e353aa842ea080cf502708b1dda2d001824de458d37762af2cdfd5a6d3f35e08a18e14aa7a642c51e4047e637517846df646d07336fb172434e0883e2b77d8ed1c52c9cc636a56a19e57a5f161b92d1dcbfa496f344ae6d4dfdc9569ade457a49091362e5a0cdd81b3753243fdac30a2d27ea026a5e601441ecd5537a7201bdcb7fd58b240d0229fdd9babf112b5694812250e768d7c0ce6ca565ad06ab8f78a5c9950eef538726f576c4bd2e0755c7f983929372a5fe11c73f9e1fa453ab54b5817aad3596756127d84e3119453e8825bb8460d851f1f7e4a2838a2be786b233504a691db0fa22a5f41fe3fd3c9b538b04f409e091809486b28ad0deda7b38a42cefc48de7d8679c03bf877238511820d0770cc8d7b4172377823a0b99149abb8918bfb66d5abfcd10060b05cb4f239dd4281d93483504b731eaf5add515f1f3c3b52b4e3bdaf976a17b3c9ec61bfc8e77116715804532cf2dbf20b7ba5ead85afb952beec2fccff85ff5072ba4ed6b5438ab1520c6ef4b0b26f12e84aedd65ce5c7bbe6acb6772f593a6b4f81ddd9d502746505047c812a0067afceb8dc9bff30d4087f8d5a375eca605a0622784d8fea278cd1a5241ad4b3f1b914f74f73bc36ee7cc82d96efda63a3b6799730f20656c12356c79069b2be6f9b77be101983118823ea66e7c2098fbc72fc9c039dfe30f2daba13c3bdefb8a780beb5cb1b6c286a6b3ef48fd15c66c045ba29f0970413b988d0ea004ab84c93919f04f9bf8caf58c4eb478f358ef8b68
SIG: c28b34804805d81f7aef784970670edaa417232bcc67da9b51e9c3d74fc4991bde97a06bd53fa00bb440fd5616cd0de6e9b0d19f2f68bfaf9d4c5172c4e5200a
TST: 957
SK: ef3648cbe73402ab450cd6ec37e545d0cd2c999ecc1fa381a45c660e18533032
PK: 52a1a45273872676582cc767339926414cd5d03d980cf629dda2d1a205e9830a
MSG: 6a93378f880cf0ffdb8e07d683cc352e2a1033c450baa0e8c4e16205fd0c02743b0ea064971d911e494713e6d94a02172ed014d506592ec6c70a9c97855246bf3d26f3cf74f493c1b697a0c414160c341412830985430806a0cb3c8475e7e5a973686c24d5ef1be7d0065096feb52eab260b5c488af09270de6decd33fea8589dd1021baf41e3f255fb8fa1916ebd8531eeb2f886bb3b3b04f9af6b276c35923f10d3a0af1e3f58b0d15aed165045f206f3f430abdff09449097e4b26d00a8f9f1e8f7a19f38588124c328ec43a9cfb43d3b2c6bdf6a3c1a102e0e333de1ac214a6df76dab44ba76bf035273b7ff6238ec82483b2d2d9d54291a72270f88933b786cac051d990b3cf740845fed3a67867d7c7c05674e7cb02ca5b7acdfba3852803a3d56c4d5c13bb1d7723467741eac1f2a7acd3a95f3a51610a486fc53a9851628c557d36d8a4cd37aae9c4174dbbdb6bd885cf40b382b8ded24a4522a278fef76c45319067e55286e7b08c603486e38a0acf47edef848ecbe942eceadb8636c833feb882a51a4595e24f607ca3c9da1b2404ce5c747e06264174d64504331709bef30055a5d695e09537c8f8c1e5a3a5db06599e319dfdb28729665273bf868955ea56427f08bacd777f179b302f3f68d04f3f3883d344955b655ddc6d5282b6d4df1d83630210e699178e11f722e9e5cda672892ae9b23e8169cbb548093b83e643eb499d937d28f3811597b6484102f0c8eb8c8888cdac229aebf89086a6495ac551f3bbdf2d1c9a93ed1d3a861eecd9eb839949bfbe6a4f6e6486ededab5229d532b58976d67512f9f71ae79b4145ca2fa497a165f110717666ca3340bbda8df1f82b8c054cf7654c35690168f96277d41c1c236b68198173c6e2b0a208ef83c02a43e473d90686ace75b5bd321b3f54281327a673cad4d4ad3040d48cf493ea231b3fec06f39932d7f70a38428df8fee4370532ae5fb112059f0a1d4fbe11b5a23bb87635429ed33ad1f6148014cbc160d93ca2592053a6e95378d6cd3f50db52be928e4092fe5d2b7095a9566864adfda59fd5f2fb6254bd5917b70fa14699665a37297c983c1bb9efe1c67b413dd1a8530cbf227297a8bbf93a8a02454e8e461ac212b846a70d5d56d6c3a6e65a03be0580219bddec88d4038911fd9574563f33e0f9e6044688d3dd48fac703869aa09d96efee7d6c68071d9922d5e8ed8dc40f1b798f1c580f7859cb84f1e14b5e74ddea16ad5cbeea4c48fbcffd29531accc0633938e3bcb2212676b61ef901e9c831a41774d8317ef35af76990bd24931fde6d407e22e763cf6a5790b23761908eee609637a2c11059
SIG: f670792942ec414428475638853c42728e86ba12bbe85948b39134cf6e2bd12813e0d83e51e657c90107ad93a4788aa38313fa962f6767a8f7805bde65ca420d
TST: 958
SK: 2c8ee7fa9ba28ce7049676087b1163b241118d34cdf534aebe8ba59282a62ac2
PK: 244c24f5ecb2dd1d1463512221325d73c81ee4d8adb8e01e23345caf9ca5353b
MSG: 07669a8964f06380d2d4982cb6349de550b38cbc35db2ce572de887f663055736faac7ec07c32df60ee2598422bf37e7cf319ab3c9055608ca0c49757d7688e2013b8244f35404f45ac219497fe924de93a58d0f721aed7825f63b2667077c161eb4dd8bf7ddbdbbc19a9eae5978978d5aeb33a06dde18e612e05bdbcae0161aa2389038026429960dda3aa17e967d10773ca49735d8ecd7409be165c09bb0b509691d591c185c93cdeeae95352316544680523821458caccf528ac0454e4cddc6df0d1ea5f1f5cc1eeee05e19a2ad0b6a49736ed8552336fcfcadbd931b0b8e963be05c8e7037388552512b6823583e4a14384cef5029232d3e0bafe466351b4bb3f567545ab41fa46bffafa877a12b38a27abd64f77fbb4db466ff7f706504141d3add0d7372f16fe3d8c69f6299d93966d624a3070eadb8b49f29fab4844c7528a2a40b66987060695caa66b86718c51049acf4cfad3853edb492e368cbd073968ecaa4a1ee6046b5e826e901f4a808c0427c026fe2f7b2e1968667b53a7d36d702f2ff82c642d34919f8e9aaafe462a3d4f92692deac752be348f54cf089dd9cd051846b04b71931e19e89d125864bfa8948ace0eff33c45110569a0df3753f4c58d8002b5bc38102ec2ecf695fafa8916da9002387e44f96dabf8a982c53c9badbc37bde437f146f77d8f7baf12873196b0c36193af55f542d9968aed8069ab9fbcd6814ec472799ad09c730d41eddeca3b6269d31ab523b59547077376345b05f2ae69b4ee728c863d1bc04e9b7d3d0fcceb359cbd0858597af2d6063e253fae2c3f25034c33ed59edd2782868298681caf564db8d19366f34eae85ba73c1e2389b0dd78a9d2caa0f23c9ad5f6cd9f2c4ad5d58946adb718cb83da58e2fcbb6025bef4660a83e0af55e2030802932f2a896a096079b754c99f7b6423b45a86472e6723ef8896c4324c73d34ad58a4c01b38a97c73be5aa7f74a2fa4d0795af6dbfcd6d4eb442a7e204db4ecb1f8a226bdfa21b6eb171c9e59f1a192e23a76c352b04d8a80233985b77a29c020119ce651c7f4183d0e9c19fe18aa1020c25e4589dee34b901bdaf9ff9450c91af3c1db670b477e0ac2107696c9ec0d31d82647b68ea19499fe34a8e2e7b378dc7e75424e8c45645b0c2818e9f885a1c58415bba1c3f2a77549bdc4680dbcd1650c75d0f452a6b208591df0fa6e181da2abfab444621d5f77c2cd79556467246447a89f0aaacad660c9a925ebafbad43c478a3c850a27e01019d88a5b1dc81b5d2e9f740a028ccb72c1acf897ea5ad89e0f9448888d5b15ce6e42977f7a729155a284d118758ac65f3fbb98deb65
SIG: ca0bb6c12356555f6e1d8f5c8aa7b5e80cd280e8b1b9ba2ec9550f622f482c3a9ad3be03a4c9dfc10d0112b0189de94bffafd7034114e0e0d42c23f32dc81807
TST: 959
SK: ddd8e9ff855679896a1397b427db8543abe8bb5dd122e3e302ccfce5fdc63e12
PK: 5a9a312e892a10b98d0dcdd28db3481c3c28add5ad0b194616da4a3df7660109
MSG: 5e8feec509350d2ee7955b6f3e278278a4cb48ae72b46589e478be59747df5394a169f19e10db53202a6a52320b63a9a2b723fd31aa2db6d58c57332da3178bcf966c53abda35f12daef9edcf399e4a8c5f83d36f44a17d79846bfc96ce690194c219a29892f0367a7ab3844837879e3818db8d70c4e3fba4d28073464df2085951038fea43281b6b606dc8846b30b0763f2ca82bd5021f9117035a77bcd1075477c5f43214334d4d4cedd18f738d676c7b51a185ffa8d04101186a4952bbd8722f53990b60637041e114aeb8ce7111131d4db3fb4d35d995ad8d6650c0c4ccdce9dcc39db188a68785562740626b3ae3e023f40772ded876a45cbef74a058fd78c1a1ff2c2451e111ac1b4b7ee4c81cd76310d4d298fb3c49f5e6401908a630fa85db7471804fe990847f0f759472f593dcf02e113e15e564d30d5984692da55b0b7f2219c4ac1626511acf194dc7026eb9d367a4a2f1dfb515cb2c08da4fe595c85811120cba2ae7b66e67c91fb8fbcb9d99f13e50fd67464d90c8dcf6935523cf6d13fdd10635b9232b7a61dcec9a2b921061410df1de6a45167fb9f6f109dcc08891f203b274a3b68271b3f35e74f94bdced0c5ff8637173a176e7dacc81f2cdc4fb0d52d1dfa7f27b552fd8d87a1c55d6947fd92ed3253f9594db7df17a7fc6a75ecf4faa4d1e21b676b3727d77fbd43fa7be76bfb58fc309e5675f0a859cc47f37b1bf455932d824e86378de7a7e8c40ced22090044dbbf91c70e528eacdef3785ba3c69a3735af6709cd76aab28a6aca6e844974b10b3fb7b0986007a727c2c8fc95b25f31f146b36acd4c537074920aff247de0f179c13ca57790a6a71d62e23321ccc75b7f3b0afa0d03527c9114a7d4e30c1ace6d7712013dee66699af9c561c44ae6198ed39104e6061ae2c45a9a3c74b5d0fbc4a33e8dfe2a8acc9511ef7e6567133f9fe3554284a75a059a649dd24ec04a57730c6d2e9bf114ea58a8994abdb0c1943241572c79ead043ad1c8caaf5c9da53dd05522febc403354d62fe3ff93882df75fb29458d22e6996c35b69faaef2e0c4163886cb3c3d0f60e150d363d6db59fefc626b1bbb1e052a62414c4b7856d72093432b08f821bc784a5a6b0bc2649c2daa508658980d802291e734abaff06afbf2795e4e354d5221dc4f52cc96d6b8cf1808b1a8208db7daa80ab710c56a8b0e9cb8081dee93f5f015f07664463a3dccff7c8ad19923a97e39045bcc4dce0a73d49c56d5e937bd11e61823401c066206e313e60b47537e34704d7d3515559bb9d0532d028e28a57a879fd617cc61f7f776bd6a008cd4f812378ed37f394bb97e6e756da819
SIG: df849b7bd29745f8becdddf6c9baf094d7a98cc9338c344eca17fde075fda8d1543299f625982317db7b3c773b64f7d1f28692ac453b81d7ec7b7ec3417ace04
TST: 960
SK: a886f4d3f34e320ec6d5f4caa863f81477df772eff97e64a37a05f4211d190a8
PK: e9bc96c81e878110268b55def7ea4007a4ef9f54d383d5fb0f6d4343e1010f38
MSG: 8b831b877bc3a99f613c89cda698b3759d643822b5a88faf3822ecb2ce98f671d7554321b24b74b4e30a663f7a5570ae917f479bda29894b1a8c028c9d193e4e7ac11916dd8e9c3f0ec0ef80bd27fdfeee80c170c78140b24c15271415acf75c26956a4d4bf99d40e861e9078320d097e1259e5ec17b583a95e52430dd8c008ed8c7dd1de1becdd1e6bfec4bf3347a22dd249f3ac307a2945e9137fa4a8c26c8021077239cb324816a8dad32b01ee34a08903098cb9c4245291b903c9627074095249e782813477032ba32ef041a07486eb4478c57b9d532269a4a47cb5e974df7e01096fbe4f1ccd4e663663487974c62cdd94d77716c8479d79f6b6a7d9c155988cf3902fb697424963ec4ec34ff2a35d742c4455a593bacffc4d9699ba7626c76cb1a616253751887f6ffe2be208c713df1ab636d722ea06c1c03a57f2cec0803866cca3335c28bf41c7def81acb38858dc10e59467208624967e2e22d9e5661bb945f9e0517687dc80f9b8fdecc8a97600b6c219a3b23a90b6d18aaace2c78400ff38c8c05967f544b6a606c71ac199eafd07eb5848df1657efb233fbabae63a05638191a0af7484a1bae1581375672c571e264f604225173a54a38dd62ae7130d05dd291ad12354de86a6e113e83f6d668516157b7967020dc6517d8cf42dd7b1a897fe1b4e04553ce26e299980aa5f7ce0179bf4954f01c2a23654e5e9731e1447347fa43aa8b2cbd6d4b2df93fa54af71e5028a6da8c71ef3c50c0de24dcaee785678e92aafabeb233b011f45c1064965085d2547050f21c652aa533afe918aa0f9bdaa2607b873ccd3dbd1d3a8cc62172ceb43b921ef6b25c06b0992e4df2b91e371b0ef2b3947388daec8ec6f7e3867d1f61072af590154fa619a07f87e02bddc7406314270af1c15e8ee88b39c01be602e4f0b52d9a0724e71eddd7fa9134169c5faab915979eea9362d0f1f9160268162dd38db02fcfb41350aa08e1e1409b2288db1fe4a0e586b5910f4de894bf9974f6a4983013a190e7a736d14ec54c3644a3ee958a5bdfbcb6297aba43af6c72746bb135410507d8fdde73a2a48b746f918bef9ed92c5be62dd5523fe14b16d6384ca46ef59b2185fe933383a2c7a9bf02da9d0fd8b0c7d7bde6b439f9960155e345d685d4dc3c71404d656811923aa3c47d4b09a0baef0a12e75b6439ba8135db15865874222cd7aa428f5ca5ce5140e22ff92697f37fc70b5b4c94d3314e6aa16b2146bca4fc94157951fc49245da53f6c43d1bebd894e31a1349884d711b55dbe778ffa727165cf7cb676435866c2d2cb839745ca40166a2f7cfc77a842468b51a8e76575fc9ddfb5f
SIG: abf283db1f80c54c583b499dbe20aa04248c1dce121f3911677813ac3e011fd159ad0bf76b1aa7cc7b14d7b550848688252acc7fece90487240c3d399dd34308
TST: 961
SK: 497e3ebd9e4caa81c5a8973d52f1d23f60c134ca53f62a853a0ac043e51cb517
PK: 71c0ca7cfa05cafabb143d84ae41de83846f42c77caa7a91a2e348397d07d52f
MSG: e132f9d67b1729389b828a9fae05a67aa57f0ef7e7d4d1ba244dec8704db969565d1cab809e48fc0abf950bcd4a37d97aeace6da546d4914cb5b86d6ab181d831870c309bca616468f2a34d3dfafcdbb7580b0c5d9ff98e2c54ec803be0d3fda1d4b8c0d7709c89e680b008bf9b8d903b5e934b019705fe0b0c8cfbc3c0967843b0a1fa1b3f162776ebe96b740edd64ad7c35b3fd1a085c99d16f5416782de17358587470dd13b5194f20f23232b2f702f10aafcaa59c7066f24c4c471e42fa86c6b9c5c3e1e8f8365f4dd75acb32fffc053c9af41c6fd2efac30ecf6a2dd0085de9b1d8cdc50b1660a866df7767198bd9c87370615d2bca99f77b84d98d7b24c9c20fd7768fd0380d6b37360340d13598047820dced88a8d42d572937b6efa16921a1b2b2d0eb931673070838e611e6c023290d86fe902f14ac3acd029e3397feb97b17166245ab407a766d2e0904424d33cd3d6e2e62a52c65df7cf004d1415c0b430c1127623dab272a2c2e2b43e02b481be928e89954272832be098b502b8b5643c67482f5de4403032581f08afb0aea48868582607bb39198c1bf13a869b63258a75890b69445ffd34564023e47f8b1884a5e49b7d9425f28d5153013fe3755c6cb114db180e60b3dc4adb36a21428128005a772fb57189345565bbd1759813523bad62855e7928eef5880d3bfff1d0ec65c24592335cda47cfcc5b5fa652b47263225224846a209a3dd7766661fca4ccca59c456fc9cc3e1cf804255aa5f397bab199804336bde29e55c6c377d583f082ce64723739e4f024606f906c110d0a5b610e5fed96dab5f08f4cb3cfc40a35557e1a740b8c7c01f7d3279dd9c4e8764c90bc14f4161db5a37f0989b7bd8035f8bea394ea1d6002ce9c34f1e9c52c6a15d15bc5b25c6c15ab00dfd6a5b1bc917af0b1b05fd10d061b3683d75b5f9effb22ae72085be4f6797b58cb0cab561844121f98bfd9583e0bccb70fad76980a7a73b23c70b3fd02f7757c11a3c21d19e05650ffb82b9e0df8a6735d480156f47949d445851baeaa5ee23814a41b25234fb92cc0df1980d023d51b5cf4c31185c118e3ee3c0c0a46e0a2be6f1d3ae452cbb66f0fd91971342da7b1b996589d94096781552195c433caf19c37f9f14fa0ae15ae0b02b939e402034ff81885939d944e604f474f21524389390fdada06e30d69068c8848cf0a951eab25c4912562944f402468187a23239d33632f29123d49b7de13083398dba97dede12f7959b95247a08fc8e4b5399d1c035c0894cc75ae981c2dd4935413bbeb6853fe04655c77d158c1237b3e0deca5636d69e0dbc5acaf72b60c10bb98ccdd60098a03
SIG: 12740839b3c9f1ba879896dff6d725e84e0443ef96c349eff94dc4833143e5b419804da9db118a9592b1b1ca48af18f75bef1ca468a1a5c74c7ac813bb2cf306
TST: 962
SK: 85b4d764169128626fd9c782ad6116229edd77631c2bc9b8ee54b36542c149eb
PK: 6a09897e629bb43704debb6715c9dea5d892b634306440997c3c9e94be8ab547
MSG: b2a0493d471c3391f7add1e2cf0bfb32ab05dbcb14f6e4f5f3463aa8d99552f433022046d2f8eb763c0171fcb1e74a049ffeb4b8f0100b8210fce856b2e1a8e739d2f93673ef8f8f40498b3081fa1fd785198c6d370e162d41abe83186f2329783408b9b880d00f81d53100b42d27a261f20cdeed19cc58cb8631281d80db1925310e235e44966309b879bdfc232221433bae5cae46690cb527b6779e11f1bd2a56b59c56ed4d94fdf7aa89dfa9bf20dbfa6a4398b98384517e1dd5d2cd9ce524a47362ef32ac792742a129c9e06130876ab5ad5518eabc5e80b022d8fa13e50d55ded589533e6ea32242c1b3fd7e65f80dee720b6d87dcff3e3df04c802d2e914a87a3629c90bb69e0a6f8bbb5ee505f143c9977375adb065c3e3d391f905fa3c336c9da41e4a2320bcf460976fc7eb1fb6c6a3c395dbd1d28a1b09cdb9ae9f9aaee4d9c566a2ac40add870479faf54ad1b7697710b4eb6f7320244b59757d1eac3d922b7a730b1acf0de9a45d4ac879d21fc616ef3965d74345ed70779eb683280cee25bf3739beb6b4cdfa25d202da13a4a673040d97048658b9205479505d0bee4880a73997c70825a6ec5fd9f952e65fa02225445fc3bdf4adea3d4d22551cbaceb3874798d6a33a6663fe3757081d6243dfd7cd2eebf60a3899fa1f8f6c956a3b183f89b9e7d2ca36448584d53aa8b44e65ad3e527f78723fa6f59224298df31d5e8ada567c8d1b11f3b1314755331c1732dc54a12a4356edda47e3c130b325282a354bfe15c3000d207822931794187e0973ab8ef87bf89c354a035a81f45911223563bfd99f90a75e53d010d8929f4f85a5a5a4f9fcc1c78f0a2fc466f5f1c6522cf62a7be37880796e9b3ca0911ecca3f22c3b24d5d9daa6888f89a8f71a15859359cea468ef238ecf646192783a257addade9047e13edd8bcc1fd4177cb20f88d11998d9c7262d648c2bf66fb227b9b3a9ed46962d2257a420f64bead9e28657b521db2e22165287791f3a1bec4c7822a6cabde5ec770188cb74498a4f08e5a3a7639d240ae3f4fd0353c0dda8ae410b9fa7f43feed13e9f13e6c9410a1d24cdfc2c8e64a15a12f75545b0a575713523d4dfa1a47427a8851ba9acccad78b4ef6a185f5c3b001190dd8f37088a000accf448be8d49371d9da2e1cb5ffe07d41a5c22e94660ac37135ac858cb1769cb66e8269fd53358ecacf5dd92c7eb6186b4d4d6130a732dc10bbb2be32f9b1d6951014a635c12d22f0dc5bd5c2a3f96aec62e7777947eaa022812caced33a5bef9ff8835f880367a37b0b76d2dde396c614e1a4721e000c00f161935b14a738a1b70f6ea54255b7951869646212
SIG: 4a79c442a4c39c62892617ef8e80b40911c4b9d3ff0a5673b57bdb8454ad736769df27c78a4bf7ad566040e747278b11eb65cf9ec7eba866120a3654f4716e00
TST: 963
SK: 33d477602f296305a6719ea694c044e90d233c2dea85c46abe1920e88c317849
PK: ff6feea028ec346dd49107bb713fddbb282ebcd034e2eafc7cdb1c5adf926390
MSG: cfea07a779f1537e498123c676290573efcc5db70245d93dea5c05726f8713d002ae66c1c9690747ca9230b1629d3662ab73d66b949879164b21a35f40cf3799041908ed6f9229ecb390c5f22234e1c5f26b3ab5ba59e78c64969871b428b78516777555af4e89c6fbc193a94695226c6d329991a11bd580d18956089b58a0e42ca35f6c6d2609ade0d0b619d48925c68cd9d2250dff27cf2f0d44448709b679f35bbdce0f496b0a16ca67eaceec258b1aec91775a3a2ee801b1c9a226a6b001926a057a06306727eedae8c577531df04ac09b5b49bcdeabdeb8ac4e8e82cf1e7af835fc611ca7a684b83526042415b1d6652e8634311e194627eae78d011e6f40f645794e36895a23e1bd84883a393ecfe5a248026aea86447059f7a429368f21c89e0145207978b913c80a22d7caf2673f7c76f6c26cf884412e17d0c255430f502bce74e3a310d17f6f4d485da280ed5b5eea6c49ba748d764814b9e3daf6fcc218c2740ca77018f71344519da82ada31e001924fc77679e3e9ff9fab67dd09a61924c821a1fd999f74dfa3f819adb31d15e5ed8aaa52c1bd7cca266711a74dd62104ef3c2bf737fce6942b348a33c3dfd6d92a724b6d5878421aeb230a533fe21c8b2fd3da596a6180a45c986d7ece4cdc8ad681ead69064bbddfc20f3c52125f83395bed1557f67182b9fe99138af3c356c5e652978dd238b761c742f8158e2314b964208330978b0620a13a16d761d52f06e466a4094b65cd6f26854aed6f9a8c2a884a0d0bf4ee587eeb8b602487239a7e58172c809983a8db1c1fc7ce8c48bc8a6fb812d6aa9e83a3ab4ddf7a8d40d3fe00ea16e04062b8aceb9c99eefa41f4f87447828126d0d9c9f8605e8467c5e4d671d5c6d9fa70d747098d941211223b9bcf261938d6704a32d22c61e30f3570a1f5d0998b4791080882aa5623167b63a23f340f0e7c6f9a830a75b74631fa5b57afdb1e6bc22699bb03156675d598353a5d1b55897e4c11061dd145f23e8537c632f75c10df05b25547238574017fe7b64b8e99869157fee35f7ad7e63e99593302929503a96768023b4125ad749dff4b992ee5c2b4f3ada4889e4ae62ec15d2db5969d730db307547f638c3185032b12f75fbb317e47df7b9292ae9e76a2c0a06fcad108cdd235f6e38d967b6379511ff6965c22f2c6680a12b0304eb2b296c99a76c2729d98e0a7824b67f3fe842d6f6ab273e894845b32dc6ddfc7a220f76bd965c69858183c8f357395fc57dc829defaacb5603a757868d5e562f9781ee39e0e94688ad3545b32dd7366b6b047e8d1d3d565997b236e7f7596c5f8d7c1c11bcf4a244620cbd21d559a7c9b3f
SIG: caa2879895d4f620b9eb5fed22b4562eeb1ad63822968f76ad91076b166c05ee20864d98bbbc6e79dd0362cacf7a21b4cfc230d6355d43120cfffb948b8f6c0e
TST: 964
SK: 7074568611a66dfca8307cae608bb26995844df435e5300e5b4d7291cc22907f
PK: ddabddd15eaf83115ddd065d7e220b1efc262a61c52e914347442bde6d002506
MSG: 6c137423eac790b8e8e418b290e0579c7b86b14aed818de8ce53cea3f340a1a95391f984968f2b4229282a8161c09ab149cdacd66970b4013f52e5e68ea8c9db685b2c53073500e5b35e29ea0ba1f4d159a558d361b06516836cf7b9ea501fa0506b985f036a82d9e084489d3bfed34093e2d6d9edf55785ed35a90ce56c761686cc3ea1a2c76ada5ec8c145d818b047cc516eec5d2d6a93a55592d892e3d5cd10c250c04b049b38fc7ec0f39aba15824007336c2b0f7f81d64d5ca3e29d6fda4c23d9ba65d9fe3cb4e03913697287b46a0b1fccd2624e397ae95c5254bcd88d2c7c8f70fdc8173f64c1de32281ab4184693b48a349e6782bc8992b43c7de7cb9d33929bf95306c2af7e938d8486b386f9fd3f0f7161e0e6862d4f9281446865a1c9be2460efbc20151b06e79d014617d0300e671d48767458596625b76dffc558aa9b40612196ec827e1c6fff518fb7ad4bf8c46fcb278885aa491b77a28995cfb9d79640aad174c6df43938e3f1385205c54595b33dede50143746a1705e7e0b69af4a26c3b76515051892b15ca6e48c3d91fbc75e8fe4a0fe8ed2c26c1073beb70ea38d0927029278406755ae6e11da378653649515e0085b5ea7db3249208e33a6c8b6ae8cd80c9bd6b983e73e9b91dbec091fae995f8032427edec02cad9055eb8b7dbcfa80d4f64f5727a152f11c47e52d753a57b6e5fddf774cea4da910026819c41e32b4f199727e23c54ab5d70142b854a27b04e64cf44af2a8995e1200bd117c7a1674edef59bc53f73adaf638e0773b85b56334aff6e11743e3a3d3614aa8a375b3781ec814cc08e71efa7818519cb24af82c331dfd6ac78ec17fd7174b61021e8cf901a2aaa6adbc902a916b2a2f4f79e551501fbf01df6b8518504c1e94646938bed1a8509c2a38fb6a798a7858f409b0f2fb9b3f4817e568c52d9abfe2168cc3650fc43e0f9975fe29e33aed1a7bf30d8631150790650a3cb78c368f1aea9ac60c5eeb969a45f84aa37366a83977190f41ae421e0c46fda3fa01b926fcef8224fda36df4f8a87701fe79fe0628ef0cc02df2bd783207c7db87119a0369fe16eeb38fdc9fb35d9e195fe14f8c1038208ab97700af79f2e2e05496830207c7da8dbe8e9bb73bc471a43f1be650fa92819aeb5dc7eed7eed8171270d219257d19610b89d2d62d3f5b648e139eedf1ff74be01a5ef1d95f812922601ee92515157c4ecadfa3eef9f2a677c003ca4ab9b2c45472ce55e18f40a21fe1b0d45b50b50c52a0b1a5d7c37d8ebc15e020584d9edd7b56505f82078e0f899389135014c86d1e2ed49f9cd319076943553a312ae05ab333526e136714f09a402b3c8
SIG: 7f653134c0b90f44a489f0b05fc40707ad9f1398f340b447a3c9861f511c9f1568803b7684a04a898c45154dd486bd50758998e126439378b3f59ff367492a0a
TST: 965
SK: 7d7ca8e8d3b84344a5e4dea08b338d8faa5ffc119ce566ef656f0f4584775b21
PK: 0bde34b746d2c5490853064d48c6b4c1cbbc3ee7beff5e8f684c120f315d7e4e
MSG: 0b727075345d619f5cdc7fc4c43cdc19105811d95d069f81c0a62fe1e1178cf1c35db05e2de87d11ae1a6f53ef38b39bf4ed8fbf56ef017a1d3c15b64fe4b2610bf69bd19ac7afd46a2b87b488b6c78ad456811c1dd6bd4a6b5da698739fd1a14ceb9f27f124b69f6bd16de5537aad80681c5633580394da3b84e9b7a55ebab8522d2d6bf1aa4e7b159cbf4e20b50bfe9c711aa047119f1dad8749260b87639e9c141def62026a990373dcfd99f77b0f5ea6adfd8f594b9ce41064a5ed307bf2d8d17370498ad7f45f9c4dd26c420f450f53623bb6d7f3f46a149d8f135bc2913310fb8f9043d099278bbeba39179fa367b01673e1c953effd2caea7311c47c0372744095b1c8f90eef5f1929db1996cd584f615d56fae3aecac3ee88bd0b296f449cc2713c52da695248faa8e389b05a0bcac69dce9719723194f433b0297eb0859019f141a207ce8ccb59882caa6e18f0b43bdddb90a0a85ffd577d6394a1d80489410f92afb85ba506aa9f3f427445d21224b9cb046c05f1bacd7b749fb7b1024d092e4ee4b30a46edf718470c99491c68f4879d62bfce7046d8138cbb9e7212999a4498b455fc90ac283e935de04df6fc999e4434be11063d6e4ee9e096a87bc716d2c819916c37a4e6298c49945366ec3f500720b06dc99d3d8ac303e6c264e28a7c2d419ec622a97a711544fb1f4735b11f8bb1d7e2c816a156287b4cc0c65aaa280b837737f0a84e36de2df2fc3a50df980918fb9e5834b42ac0e0c7278d7fe8db4dbdeca0141d5fef5dc6151f87b8634c241a8fa0a82717899773ae89f537890b9155a7a05bce47866ec2028a47898d485823a2e992319680eb699b0dd5358f546fc537c73d3a4b223a0941518b6d1e66b27676c1b1fc76a08320524a72e297fce17aa80d8ea7b388a55168e7dadb836e9dee707ed25c0ee4db25bee3c485b39649204efaf2820b2736368fc773ce090c385378002c471b094795cb266d39eb7580d701be4c8916f6b38bfe25fdf36d6c4adafa9ae9864c57bb737b49506ed38d62de60cc0599ec6bb1acf24b1d37d60efdeb7d942c53603a2f0476e9512c938b28d495a6f26a907c396b841aedd8e14ac447b495df1f676daccd5a740c042f5772b7db17f4f1a3a1c8e7c488370e736b51e690fd2ddcb5aa61957a7c7975acb2dcb915d074d744279ea1c4169f868873ac5c20890162c1df9656419975a43d3198e18c309a1eb7c1d87873fb15c6da47f548a01f69bdab9c39ef00d418a6f619dd73d7db45cbb6ad225a2de787ba777bc73d28fc304f10009f4022c2cf84de008d70fcdc8ba7f107c369859e9c90ca8a393b553f26605ffd7230c921490700f
SIG: d0c3e248a8cb2ddc7e9f21c9c5b009f70ea29da6897cd92c260f047ed68aa1c8b9657f9d826e88f4a512c5003be6406880741263ae7ce6860efe73ad54d48204
TST: 966
SK: d21fdd7b10e54a8b6be95a0224ad70664dd92112e2683a4fd279c407db3871bb
PK: f89c272e7d1cc93d69f694dec9cce05ac247734504829c56997413c8958b9330
MSG: b8644adbef9c7cab9120acedc8e75c433d036ffae0f955be6a488f1f427a68a8902d026e63dd6c9bf9d97de786b31dd4f4c9a4f8a622f1ffc84da6967ca77433c398f4d3f1c4434989b7ac9d0f3b1be0c8b352824f4e7a083f342ec1be1da8fb755242a654880ef298f05979ff026ddcc044860e6757a29cfaa222a3597e38f1779962a41a4c8ce6a65b878199b4d80f4a0390cac19c226eea4b6036e57ad830ecfc00693e2613d3edf465fc8c4fa293fd8cfc36dc8e37bcebabec0349ebd884e1b28bce824e0d55b6d015383801668b34f5ba723d2ac0a264fab2c728608f162de01179259be2ccb0815002fded8e0d78b02807313e910eb3a7337c534e846f9ee155426e4aef643661b0edb44596fddcd0b3e814c137817a422baa40c9053d0386c6ecdb589052594742677c48dcfc8cd4a93667ed4d87646001eda079e8b99d52ba21c5ec5669fedf6f40447a7ff8901db0ef1847d3cacf0198a2f3bd7bcf2dd811a097fc5e5188b03fdf54e517637a14501000d0d35516caf0699402b48f8d8cc3afb17a56132d08237035a0c95490bfe5d7b7fb40178f281e4d872e47a0e955ce9736f3c333a6adf50ad31994eb9f45327facc8c5d113fad4713fe7f198010d42046bbfe68b0daa79dcb8755929be92f9caa150dfbde3fc9e392b2b701c3021c240e4679de41124b1888e5db5a83d05ceaf49eb440dc45026d450bc984b8d6f02850ecb570eee0a3819b12bc26367b5b98e1b141c9b0a9690ea4a3700dad12395f975d11cd77f96368831f21f4e968cc5ba9ef82474038bc7aa26122d218b743041506aebbd1f987959fd160d6eb7d58d4f576f8c0ca8af868e39b5ea87203937e0308acbeae91e10607e44e8ab495bc01dd573fbadc94479ff92082c7bb7513479c70f0407769025d34d72140c25d821f034a39851a93c623b71c9400e942639f28bbd032e1d8d3c059f7c2cd31d7476462d2776035d07880202dbfe9e07d154622d7ac6175a5afa79fed4dcc13712620c41994e11d924308fb2ff3a1eda44c761bc736f345122f02a40ae6f7dbd03d9fe96ee3d7a3b4a5eefbfcc56dc42ef27bd8085176038b9ebae63aa75035275ec34e4185739d636246770acccc6dc620e2fc9156fa9483e0d9cae0e8c463948a3d97ae8dda5966c88f07093292cce22bbda062baafa7fe84d0ba2d2dd295b23458bcaeb2ef742a2ed1c834483cd709385afeadcbc0a9c6a4f387babf7e3dc36c810db209beb66c8666404c661dfe9d32c4c08afc6f3b1257d6484a755f5ac701eb13f87763fee330ffa0422cd80a92038c6f45292bdee5f89e94c7a652197fc1906b48258372449b1081c6b97134c43c89ee2
SIG: 6d69e83b3e7ed55a85f9fc9d2519da0b0a1eb4daaee991a6651f5c89190c0de72373cd989d46be1367f9daf1b92fed3b52bba54a1e4cca5bc8726ed07f302501
TST: 967
SK: d336fd8408196d22fb698eb25b7654fda46f5de4c9b4d04950c398b59a44290a
PK: f3cd96347cea63e500a4c92c3bf215662dd0400784dbf8b595dd3d395f90cc12
MSG: fb49c19bc4444c28eb2625f31d996d5e36c57fa6fdd772e67b7199cec67eda5451712df7a69dbbd56e7c398796b2001def651c4b9c05ee31d95679535c812a37d31ddb3073199cd704ff7ca2981f7b9c927a7f7d776fb6f609f727e6ea709ce7f43a60793504169a8905d9b23109f0d867966aa3e300c7e11ddedb9cc117b904f62927e48e4d73fe1a6ceccc4ceb08e64ab55f25c98216cec937608ad793146998f14c2985e6c2910df7b1388f9dd863f1e4d7d1621479b8512cdb34e673eb02a48934e39c2d18d70f966d676a2bd75db543d25c5dcdc3ef3b8bc8201848c30961e915d968bdc31946b0d18ede7cb0166dbe1ffeff9439c9c3404af6016c73edeb253d93f562a1a6cdd57898a9b3422587d5f56af3d06b3f6c25751f44460fb3299656dc11227ef4837aabddee400fa53f69e5ced053c76dcecdf0adc9ef80f4b330542ff1fa2df0b8d43cd1c311b1b9955c632c8e5f0491931c04de434df8f7a394e5fef016db2eb7c87b2ac7a4a73043bd7f98ad0a4d453abfb0be8be4cb145742aa56aa5ef2dff12230a510e3b7f82f7847700eeea5905b0289696c4c142bf34bcf81a962d75b8d091055733779335b7fd47a20d17c948ab732947832674371e22e711134f5c919792357f79bf70c4470787528434fc0b4ca093ee92543420d1ca81124f5585317e250821a4f3d8ce0f919de9fbf0127087e676903f6cb39025bcc73a0762954b72e66a6be9b96c97b6f6030bf5ca0bc2727a9a179cf9d9405f3fe18f3492389079a5b65bcb13a0d5ef41c2cd97e702cee4a2feb1e6702bd4c63fe0a4ae994c4287a837bc3f64c2d898857cdb32acd4bd133676e51f77bc7110e3ce52d9204fd2691a6d37078f68e7bcef30fc9c483985822b661119238e40f9cfdcabef2d7b16b059ab24adc05003712bbb128096e37f91bc4c5c81508be27fa0b84940be36bced2e65cd36b39fbdc5ea68614159228ca65c5d8407baf663b528e7d87734c7bc77dc8431a1dd6873cfddfc3e757d9ad1fedd3c798f1fe60e715ee48a6bcbb13b616a89a38e336489d3d6ccb726914112a1bc5d977c9b2a3fac107ad094b038ab75468263c34bda817c056e07a6c56697cb64a0b1f966f6de0bb1c0a71c8a5fe133ba2036d24daccad3fa03b39cd27f832752751055a8155913d040f51dae78d71946ca04d83c7c894c280aaec285543e5fd5e327accca9abef156a13b9571446bd8007ff92dbc0fbaf23a9441b53c1cd740c34c282929101ad2ea8b85d70052991b774e92ff75cc85113e0900b51b863e1f2adaab2dbcf46af479ea248ec2889afbfe737408393a2b1b3301f65c1fac8b676795ab5bf447f05e0daf6776
SIG: af7e2df7529fd18d1b21b8fd4c0681505918e2511434fe4e4954e743c1cfa45e4109d36c3eecf2e25d209b9b5d25f7cbc380296d647752e30d3bea3b929b0903
TST: 968
SK: 6573227841f6f92831146c44c0e480cdf544bb876552cc5f9d42f15bdcc044b8
PK: 192257a54ce5d04c19439fdc9ede18ec856e29870e24d3731fe2224799949b7e
MSG: 6e7c6b122ab36bd135f69e2b85e7fccefb072c12cf088a3229d876eff532389f0577116f7af29f1195e3828839381380467178b229c5a18d7c4943ec970dd18bce723bd0ca91ffa95563546a324fe0b9bf6c0455d4276039e8d291fc7276aa55a1cd3ea05282654a7f9700adcbc78077c5dd0fc86eced48f4a60ccb76bfb8b4562bac22a02d19e4489394ab9719fc144f5db2ef039b37f3b51d1d657a0cf835d71f1a4af01eb9fd885c604a624cbe910bfde093ad3f0cbfd9a48307329d44234bd01191d56e522d72b54e1fe4733da3aec6827eab3554898e03e577b4e7b9dd3f308e616808d0294499f2886295e54c360199ca83a83ff46195ea3c484a66838d51acbe9611eee036ae281c6793cbd451f9271fb5d25ea7c1899ab5d43ed8b9d067bc56d8d4a15f1dab8d8d95d1b17af64cb18c1147551147addcbdd53fbccd9026f855547131bee95071639f649f2d035a25a3e42e38e22bbf038106ce8bc4ad6768ab92cd57afacd04ee55cf0714b768952dac240b1e9b2835ecf7b0d6c407c82524a923b9f54d1b8f12564a872144efad3f3a7d2397cd1217dc5a9c96e43b2960a8425e97e07a02b0dac90f346b91a346a23ed2bb7fe6919c22dff03f62da7dba176e8ddb22f3f3a668891d3f4e69548d0ac4e71e6d28ed5a67ab5ac611d460b67a201f4f56a5003ca7a7d1cd1db6c10075b09227cb8c5dc1666f8be710b4b7bc2b95ae60da4f64179a50d2f88744361591671d36b7296315f6996439ad79821da8e772dfbf55a90d5d52ef7d76b35ffebd42e3525f4530c54a0f23b4d07c5f5974470e89404d176eeff9ef2333619691c59b7aadd42c296b1d0d328d9a3bd59a54bba93a0c1f1d62418c2190c38174b6abea02db66e818320ec4b8bac1c12f18f30dade27e63c58f9e7caf4bf69b265a2f9d91800861acf479e65ec17e680577e058cb16c109bcf9b2909fce3361a2c2685c10be8540a1222db5ecf0cc4d53a4214b7bf6248adc3a861e34841a3779c46046c5364f1ea91a78c9700d462ecfaae36ba760c1bd6a237c961edf4022cedefe5e937bbed7051ae61b96d08b0487ce0568ff0d32740bbd49ad0db86e09102ab21a915616e9dfddc81ebfb36c903e07a40cd2dd119ff4a50b93fc6fdfc0f36e59e0148fcff3fe8e2cd6d30a9e4b8f015567d118b6274e1ed75b22e44ca9d9dbfc160742cfac581e1a0bf5ff3326bc5f7896b9ca05a811d55e97c834d37a6495cc26cf442bd2d90129895e9cc0ed01e2155293f47a07ab5880c6ca29ed44d9ccbcaada7f3eb60402181488654e04911578b1aa9cdd4b86b0dd2450df3a43081e4110ab58de763924d3c89152e99293e638f9acd8d7
SIG: 538eace493de53384b1e985bb907c094f8168430dab14d37791be6e78ff3f5a306ec70dcac86d993a4c1f75850786d795f022b79be6a547769e41569c5a9a30a
TST: 969
SK: a63c1f54b2ca058fed2ee2504b983ff33d570a9baba583c086cefe19f43ec49d
PK: 329b866bca4194297fc1ad5a0eba0df956699c74ab7da5fa5462bd0661471020
MSG: 791b86fd587713478f9234ff30cefc123cd7c3eb125fa74e4c6db64e7844f7c85b1686e71ed08d1a6a04e0ebbdff4ab160c976c8ab9b505f6a7eb0a18427e999a8828df10684f8c75b6a6b0a64c0afa4bb22bed1cb9325359cac3b8c508d98bcb0ebcd748dc132f1d6a360a4450d1292a1fefc4e57e4107a223f421e7d14a384b85c18844d0b9eed2ecb81bb74e8a12652d98505795a013116a7076ccb5493d6a711f7637e97a780e74da1b39b15cc7bbde2e6c4d0d3e8300597c836e80bcb8d8081d974e02432eac88368211d3aaae89a14417108e1ff6737083849c625b40d631f6c8357220c7f37380b3b2cc5d0e2df6b4d1196579dbc57b6c9ea0d41f4fa0e556f943c9448ef42fc78df5996648ce2f3de04d8a663f967f3d933d4f65357ab29ba5b6405fb162972578ddbb2367bed143c854c1088de921d79f5a92a854837eb7702e1ba925c6eac23d134ba1bafc5d46de2a1942c7f366f701b0afabb75cb1d808e1a1e4e3ae5de88e8e9989757458bddd8a806c110cc3a733d1d4ac58a405c4d81134fbc24ccde7d5afe420f9f1785f0a5020fafbb2261222508aa0528b7b48b567200958425efcb42934a880b133444bb109f2a954cfa35a2d17cb05ee3f16d06b321a15f91339abeda243ad6c0919fac51e907e053fdeed1cf03003734137793941b8adf9ab6af819c245d6d56f16964c8a75b0756a8cb0ca8c12ac6e6b3942eebec2f868835f81b109db498a4ca2e021fa765608d23d803dedc9e51453fc1d2a6a38a4aab257c0fe7d67d32a541e014b60e1013a92c1b3ad9e6f11be293b246f9a0c6440b0b54fee75fed2fb75cc91ecb32738c495831586a11242d87dcb4883edf6757a50b18843759b98dd0cef4a3fe10d76370ecda8c83fab87eee2656c5f261c340ea91a560d0e2c64289267f0036ba35944800a5a0aef3f1df839a724e181d79b8a3c16f65ae27953c4aae8ccd30ff5acc4b31e4765c68fb38319f10acf89247b5a39b3b08a191754a24aca9596a1f8a70b6e4f03a2004a9086ff6ed07652a926e1e2df7bdccd5bec16e5c4e968364a09abf9ded93df5fca0bcca5c812976e5cfb3c3493fc175d1d92ee8d1c98fb3382b3ab90c5c0e4bdf6a3ac94767b68d47e6b9c244265e3b1ab0623a8f0100273f2c607de89612c72d39be4c0b4d77a3c61368df40b3608652989d1e19c0aaf0e3c253e562c6409fe6448929b33753de162e6de5bd466a5114fc0e5f57102755e29544f03b28d4f78de9a024dd4c4e8c3c2d44115a7ae15edb4f558aa7dba6426e7e372c54f7940bd7714467f8c3a1add3c640189c31660d8cc01d3c5382e42abc104c723f948a804ca853047b6b87b5b6ef4
SIG: 283359be41290a51e6a7c5d5725ca4ea0a68f14aca14b0f02566dee21f490da3c7e95f7ab739bc35a7f4f232e971aa157657a633eba0e72dc97af32cdb928702
TST: 970
SK: 5b67a6d7c650dd92ddd036ce7a305bc959a497c5e515a68493035cb3850ee03d
PK: 4c6fc1640505fb46669f93048f8ef557099f3fd92a53064b163363a31b7f00aa
MSG: 62ccde31772c57e4853aaf2a8181fdb53fb82790ea6501bfc8f5d4ae8dbd52de42ce2e8961ac1731f4bc085fb561ef09a2442970b6297901aeaa2ee555b7d5e3951c7c351239ddee95ff54f924da95cae7b15ba6a9a1337b8ce4921ed913cd791c1c6941080e548f3c36e845acbfd8d8ce35e2fdc2a2ad6c7e2461bfcbf1aabc55cf0fae428885be5e86533308c9756805219abd7ffc1657b6f4632920a0c10e0e363319d900fcd61e7ddbcd6e762a7db92480c363b2c0640c6bf32d690dd829d8405fa66e4783ebe1cbde9547954a90baad9f774e94549abbff2c1f5caec2bfd28e415d36429d58518c3e17e8699e1989d47b8d627ef9ab4d1e7d120b372c2141304f7fabd0265b8be41f5467f4de9e65c125ee1f27a289c4f7c9a1fbf25bfc2f8d308e7ff52191cb7644c6af204522f2ac87b5f40525fd43d308c8dbc6a861d25db23ee276678a1b6e8e91283be02470482ed6cc9f6e396351d11b1c7e22329c091fe7d368f60653f93b0f6a3f712c20f9d2d8a9a0819872f0c71d7b1c0bc1683a152b484bc21cf556093ab4c0ac16d322ff0bf452e5581e1e7241673884023c7d6e17e2de8059f60e4c18e13bd55fcfee623fd0469c0d0911611d099a257020f2f31bf5078e6e65a135d5bf407620236d6cc759310fa728ff8bb5ec56abbe1a3cd15153f892d958d30d162d01ee665f5b562781d8dcf8428059e5fd225ad78a99ea760fe5d9ee8219c95acb18d05622e10a9b6c67f6d4f6ed11635c5e2e0f85dd5d3cbda65aa423d594a80b40427bc321e0eef9afd2bc8746ab7399ff6d0e1287b661ddc4062d072018f4c10e86cfaed72d9e686ed09d5255d360e3eea2c29b9eaea05fc78c8cdb8c9d4afc7adc6d4aa067b7abfb0a4e940a77580ec206456cb9e9f95f6d565d536e535a167ede8e20ec36081e2fc55aefaf24d227fffe5e6cb03093f443b4c51655d91ca6f275959d1a802adeab44701b31e8b0fd0222c499966c72d1020ad9370e2802be04c9933f6b774f6e8c69fc0bfd315939a127b4e06d0f6f5ede671ce11612126b5187b53329b0a9cb7da3b1ccd67b8c07bab99a662df8ce851f502fc4e1ed1632b6ba555544018f7527e362efc7e3b2ba6f75a1254f428b3b7e0bea69549e7f9c736275550080aee3af5914e3a34be656c77f6b29420e5433f3dff3811f3528208e9d850aa3c29b0f778a2427d5fde30732dfe50443a9c1ad55c72a08ab26ffaf8efb90bcafd3726b00c005c8c0f0dbf2a1353086721e446545b813441194a755fd26b963afd977278d1b10f09001c7ed975403c15cbe7f992ab07b8470c939f866f420f77db779af839700329e0777a6116365d76c36d09d860472a5
SIG: 0f073c9a586f6f5e08389a2a5e1808e270f0edb6af104496f93757623fea53133a731c445ac23578cd56a3883c08958668631fedf1446ce34f857f90822ba80a
TST: 971
SK: 2631c8c34d2948ddd5996b4149cefd238ea7452ec22e246124dfa279ccc27db8
PK: c3906786ffb8a7c27c44c2447f9dde7d666dfe588cfc54f2d25040512a371bc1
MSG: 6f9bdce1443f2856d4a2f22782835012b7818a0e020dbcc22a821658305f134234d14cea636100ed896c2a8fb0e87048ec6f8b31484f78eb171045add72c85710ec9f9b5d43623417b5653be86e7fbf8b4ff91110a808cb41acf66d436e89a737faea4eff3544960f114b833b0b4ebc2c14070b0bfb7b0057eebb842bd1c1ed458ad3428f8f72a1d1db3c4cb4797a399d47a1e6db74dcb2ee24ae81585cf66ef6d9bd223f0f54bc8c1cec1bb4460bef4ffd32ee805c3ca5ee976ff9c14559f8d756662a2bc19e4c5985406a07305c9950d866c9a79a3e5f6c5969753a170e0fc4cc09c6d87a12b44cdf3be1623159e90cab7a8a3e6f01f268595b021b1ef7d00769477270d5584c912e22a367438277f59df20c5620dd5beaa9bb60bee47f4af527d892957b2d12b678b5279a3f83264654c0a0f8d21e709668f30fb6e68f047d0d9a7c2ae9a28f7cb9dbf18f63fc1661f07d310e540c77631f5bdac5824685d7c9aba0fe1d09407a9662ef18eb3e28fd1e8bc892657bc38243a2e6453bdaeabb2791fc5489521295457ad04180ca871f6318792bd15fd1800ce59dd3ecc7e0b72979267d8183e804fdd45daad84fc4cafeb561ea8d6a74a7cde722d96253ab3e75f0adde02a61fd5e1f59cb1f5f1b2e052643589a9e4be4dd6ee64538cb0b109a113f30a58b3565624043662abe17f60e31e89c36c995e00ae07f56a9118a31aec24ad544bc965811218df827c1730bb904bb79b68613f6c994679b6990d775b5cb32db97194bd81019bea41f3a7eef501bf8491b0ea859388452e3ecbe16aa7d5691510a6606c493e4c293961bf40b4cd300d9d22ea1a7724c078b8bab1fd16504e989b136d9251ac9f1ed94a5e9acbd9c04f8058afe03049aed8ba29fa2e8fb44f8e8c04e8727f399e735e6c1496a91a9b2cd2ab02d43b285e9d7610293b6749df1044b30e2da99a564429a23e68c96fce92b08a00b7b742ba97a62ee58776d7dd565a490071d4b19dc648e03329cc5c825d387eba49e2eff6c4341865c464f13f1beb1827a7f268cc15a982480bf084fe3652c1b0e0b4ad26255859abf1c8a7f9b3bef098a9407fdea0a539eb008fdd749fa0186cc0169d9d9e68fe5e54cac32ce57b5c84c2d805eca39c2dbbdd2e02f7d228826712ff4a61411ca0aeb6f01a1f80ef29eeb071a43222d9497184bd85d9e44b166be97cfd2a732af4a233463d3ab543a7a3c7aec555656568840f4dfea217f6553aa98af324c12b2c3214ee76eec700670af68c8c1f36946efd7ff0933e5453f128e9715fdb3344ac10c4bb7ec8f10ddf5db71f1cf0efe40f75e5b6334ef8cf8429b3291e6e4ce379c178affcbc61030eb896d744d
SIG: 0adc6fa40ffb81f6ef4e4187554917775cf465e7b5e857f2e1e7f400977106d2377ebc76abb1db924c64867e3c6fe38c0b4fcb1d0f9468e8fb235029a81ce604
TST: 972
SK: 39769a66f0ca1290fda14375b35c663f6a4b2ab3607179abd99063e2efa2c6a8
PK: f9fd4c191f38f12190d3285e20c6cee54cfd6ff315300a4efdc8a90e80af4083
MSG: ff4d8987e3fa36012b7586736b793d659754698cd12b65e5ba9d758cac1649288d20224377283ea5425dec10ab9917d18cd13d1bdf4a769f37044c84faa2a449c689e004c14e005c49da4106ff75ce1303361c6e3e34ccfee75ee9c31cbd06a4bcdbb42fd649be4dfcd664006d6a5f61077c04a6a81db36be86ba42c2951f051aeda64acea496cb924982b9f7d234ac9723fef98a8e12755e326a52fbe35851f411eeb867606d45b513f54526391c554635c180b8fd0ee451afc96e4efd360b61e6baf03dd6d19ba515c31ec1cdd3affffdb27354e3e6b56e9e1a1a1b7d4b57d9d7689bb2fea6c8d3f9ce0df2d9ee919c4230a1f20b85dfefe1ea3d7f77db470e4022429ef609b0ff44946440acb44cd13445bcfa3f20503c26c2fb663c89065fb9334a603eb9ab7152e62629233c44cb00e77716d9b72c84fd1b340634ff1cea347501576100ecb0fd1bb76ae0dff1c2b0948eb71ee2cc31e79d3015d72dbee224a980e0f95a69f793da83a2daa56efe57b2f8ceaac9e55f443ca9e732b48c75fac21c36fa77273c3f34835ffd83c96f00ac6e86cffed08153646c1cea223da9ca360cab97e03b2b6c8fba7c195a39ae52eb2ee864300ae56a10f547f99a3169872249f97774b1798935536f2f5f011ce57613a94fcb7e7286a6d49c10fd929d7671cbb8cf17dfcad4b2485c3d8fd79128721e55d84808763c2afa9c55e3b0cd7bf2f0a66b5e467bec5ee89ad570b60f188b3f7b4a511ff859312ded078d8d0091134fd49bc792d2d7d60b304941c7f23206f99e863b1e2d8c9ecffd2ff0a3a3c754985615a9a92edcead00fe0e05493b198d1f7c90088446bba46038a71f32653b5912b24f43137748b75aec2c15fe4bf5a6f86b8a6cdd9c7447f2ebb0f43b01ca1523e0d496240006ad7ffffafe0df5754b342caff3555d72a27d0b92ca1667665cec43bfb583077a9c1741fa492ce3dc2c7529cded81b8281a3f375948b8a7ced096b2facc25e39029e221b66a53d3979e1f405fd88afc06ec6e4309dc85e69d6ef2b4b49266164a9d9d1c31ee3921127b13381bfb740dd38dc1c7315921f9c2fe58b61b631a7d9fde2dd8a4be3ded0490ae3b8376791955c1c4b4fed00b9f4c38ab7350fc2e37a3150c18162b1faf0337894bc23e74f595e4be33466deab35458be97b4f7565897f06852f71c60fef9101d726b72e0102a97b2ca5211e3806834b0ac1a7df87c2a078df263ef8ba457dc891b7f2e627811ab622b9946f8c6b731f24078d17b06b200c3447f8032aa3e7a243ee422dda2e652fd75713afbce8a59ef8536653a48dcf42a70e7621f9b2802409be1c1a61f32e36789a5c5055e1a8268e9dc438c2e1527
SIG: 1442dea2807e031159ec6a412d8e07bb3e299308090f218fa7c10a9c5068ef9b64ef11ca9fb92be1d0216b99318ff0f03cb871cd7dd63a38ae1702313e5b250c
TST: 973
SK: 0c808b066f0c8e8dbb1c23d6c2cedd0be866d8425f241a9285700ea54536cf6d
PK: 44ee72900450c56ab21f2686d29525d0663e0bdd87725beac5d68baceb69f1d2
MSG: c945714100581f4e24da11fc0f6c6d0210433f9777525124c55ee072d85d798b705f9d31c8f977db6edfb7a65c78ad2d7d31d6b7b5be40ff1178d303b6839bb0c63210c1d338c103afa0d453eca1bca277d930778ad50802272f03dbe2184fc31ef8ea6abe216997199f7c1b337737968907272aa51bd49c07389c95468cef4fd99ae78ca4542a2bbc0e8aa95214ad1cfff9d5085a434394473b84b74be9bf2f0202ad1ee4616604ca1dd75f4a195342ebbf8fc59f3f79616554dc7bfdd556be437221c10bfad39e119e06045be5fed683d3534fb6cfed33891c96f9c330f28b684f8fbad47c01418eab6ceecc2ed777f4c218a27ac22582392315c53aa7309ec54c6175236e4424dc978465ab628d9544b0be84103eb56f1bafe5e5eaed04c98bfe2e8a2418c6c52a61eace85236b66c7b3b8707ed55641dd9d5da97c99c11cbeb9aa2db147820dc724800a9d80f505fa5af20921cad2435683bb4fc60bddd475f863e2f5950d236399d8d75b404b394a546737f93a62408700b3ab3c1e922b1a859a2915c2d35368815cd45b85b2ac083121ff000f050dcdf415e5275a5c42dae3b15400f3ddaf9339f20a1261a88cd90205639763211152df414a9a6a6218f56b35a2de9e8482449f6da77c9e3d4af0493015a726217f82ac58954fe3e2e34440356b112e06a6f671fb5a6ef4619a6ea7b4e04db3757fb664c396b341ca89001dc1604b51fa9153f9130c1020ff88909287823ab3915ccc85c4e35df6c2f8e6f902be82ba21297fd3835aff5ce02f3c07dc093fcb1aba26e06dfe6f02df79291aaca069ecab9381404c9c3ea1ad409adf292a91e3a582d5a7b68ffbe10a0305248e0967e6df372f281bd192e139979c9866ca8fe1e10e0616dc2d4f85e119e0cb4bfe8cc31d9f5c018b65408524000a3016a23d9914d57e955576e2660b0e0d96c8495a12c3d73122d200b0f0e5ebd446562b08f47934ab499a96991dcf99c96a62880739845d29820150553eae9be0bb41d53d3af01d9867bb4732c90bf6e137316e3b1edcc209a8a09fb062a6ef05f37e57f2c5d1d0cabaf07a8ed7d41455407b096754180aa96d3d96591945dd7a1040a2de60d8e1c054f7854652b732e7a8f5b6474c3baa1840fbe81b1e6b54e201ef0bc8d0f213d7cec1d824d22209ac72525a64b903e773b83f1b68f640279f15053d21ec15ce2ff75922176b7584a16bf1a1f0d636b7942a3d61862f6fd1309972d3141eb769314ca975d020bf02bfddf17d14b60eb786bf9f55989fe473320d4429677e301c682633f813ff26c0a3da92f6d0680616105b0425af338c2ea6153bdd5216fae2afe461e9249c05e32f76ad7c429d92534b686dd1
SIG: 38c682cedefb13e46b11f7b5f800cc8120d45a83cd8d8dec10c577bb0153d509ba4fdf400998788b706007ce162b96945c7140beee74e19d0743afa4ecfd250a
TST: 974
SK: 049dac3c977d9df503496b43d76e5540e315001ad57f15ea9f0870cad2d4f9e9
PK: fc6f4b7eb39a711680f966d468a61abb13a9b6449bb99fda3d12ce1b506d1b4b
MSG: 7f31e346f68da73716aacb16eea19bb24142dc283e7263ffc3f704a22ae5275a0ef95f0669bae5a54c7feb84bc74873cca0f335d6cff3d8b4a20056c64f5e882cbbbd2ac74207676467e5466ddd56aedf56e097c7f59d945915eb0ebd0c3c83d48888d3e9ede51ad2dd8a0ee1eab4cf87ffa78635afc4d6ef3e87dda3b65565c2985a4ad0acfdfb81cb0e61c67826a6ea0bed4c08aa1a541de60458704ac21ca12f1c8118bb3092c35a40c921e684564562c2c1049dcdc2b8d6a97e3567d356bffb5692a41d89ddda0ec3552152a27577f1cce57d00986dca77edf5e2518158200adf690affb31aaf2b574836839440999f15791cea85342ac94a96c7af7a19e494310ae26675f43c35258e85b6840b99c6b09cfa58d19f1e43a77e397b08c0db1830bca67b39ecd8752da611e0832c6cae7bb8ce74a82e7e7330be5062ed05aa5c84457b007fb5ccdc20a55d54d8e0409c8bd83883d2e029dff26ea5db275dce099e418659a0400f13be9ffdc14e7d645a94677ca846970b7e6ac527fa009a359454b3c49364905189fb49c9bacb650c03cd82875894e3546ba03c32e336fc6516a87676c50d5b80b3054273b157c5d767514e54574b8a101985a8e967e95da8f929800260e08148beee2d7781e9e85d463a94ffefdbb75c28fa8898015680999429cee798b3fd2d96737868a263fba9fb6f4aad56a15c6412ff85e7d3752102daaf25e745fa5f6f174a231fcce8624dd70856f9babcc209144ff6864648dea0d6884566a4c39147805be084e4740bc509309bcb142964bb0cfcf6726a0e04bbf32ae6834732bda0384cea8f4a4849bba0d18646c1c34471896b5bef149f8cab9ec83722b0fb209efe8a04c4a235dc8ddb20acd92765afbf3058740ea70b9c10d9c5aef8606298fe4151593b21f797d92ae9f1e0881b0d271b0d5b10c6ed83c349ec2473fbf2ff780dcd076d8cf0aeafa71fe2b8c5128015f8fbbcfecd5281cd5eacb6fe9ac6eaa6e47d667b9ad4b7e411e6cb7463d567607afbfd0418c4eb06afe847f5e40b499443828d5a273a4a87e46def21a919d73863af0054a099e3adc5450b8e32f51ea52c599a4a2a35351788af7cb71e5c44bcb8df54a601e6ec2c1828b48c4b1ae4463106f10efa5caf3091abf99aaba5252f484d3bbc62bfa6b2a806d23c6331a62fc46bc627679e73ec82dcc08f79143f4b71ecf357ea2f0d74e6d3058e606043f6e8fed704282c16b1f988ffa365cfae9a3cf792e0c5baad70ca7e25776018b5e7f0e9544e1d73f3e5d1e416a5e50fbed296dc1bf4b29a3fbe32efbd7e99c83015d27f535adecf175fc36c1ea4f4423b36dcdc054ba993278e85ac3622d435f5237ba61b49a
SIG: 7532d1a61a981f303d7c2454354f99540cd484cde9ab337d6f7b51f179220f7fa2073476b41c71529f9836db6b1d0f5a482bbb4c68366176ed14d4d8eefade0d
TST: 975
SK: f07d61b5ca1c2700cb50f900c26b7c28f6c6940808c7bafff74fca4b11f425d4
PK: eb243dfacc2dc6435776d554eced8bf92390604b35557cda51fd203eddb493fa
MSG: c1c67843d69a0e62e7bf71f90206a3d5595ca3c482aaa767e931b0d6c2f4752ab86991f03583bb138e9f72fab58fd602a4b6b29602cf891408af5a1bfd3398c0178c441461e3f49bc81d64c0d97f5ded692c75d4d64dac5d80d63bd4dc5210c1d9350b142ba6e768f150807ab8a86cacdb59d84ddf660be56203c014fba1e0dc16fa6d32694e14b128edd1f6c6ab445a3ad34174fa9e4b01f25b1d5e6eb76983b4295ce4914d3ae48c704a30e554fc1f868b6272eff06da24bfe17e4e0f0fa46bb08ffb907cb61bebe52df311a64cb578b30fd627df11221ae4003a0b0c68e3c6f95a21c8500d41b2c589cc46a139cacff57dcf00759f52e9ca3dabdb1788ab6b38a5048f58e08e05c394f9d3c72113d452b7084c519f86c1689ffdbae506ed8450522cbe43de27aa3bfdd92a91b71e52a3cbf77c1bd2893eabd407a57fe5e146873bfb2043f4a6147df083e54a2208d1925813fa404e4c47406e7728643ebfb0b10142f909ef856fd3a916bc0851543b82a55f8cd529bd21d9e2909d6d7e77bdcea4673e545ff4a67fa37d65f1f63f11d5d0d55974a30abe188335db5dcbd356658f9b77682d96dabb258ea95951a0559aea4064d5ea1680501dcb4228f2c956f81d2101144af74c716bc8bf4296dc3b831725cc17d3bfd9066a29953b2ecd75059435b49a25ac525b4fbab1779022dfb6de525149dcd902ac8a7e21f344f5f0101480692d61608952c71413e30037945e206c5eeadfc3edc4bae0d796ca0c5f56d6ffb3f0969df9df8a794f5dc83a3b2f5c3ab36bb901bcc31551c550c63fa41d6a8d57bdb9b5c65bc610c3a989752ab28a015e7c2f6b2fbf199a76b9750c0d3d592119c8b4022fa45bade2fbb41432679b52acb4608a95c34aa40bffec10bc98f4729dfccb650b2a052dfb068959e648a92d5aa4dd2d17dde67cdf2e6377af0d4ae379607389d7e3596441b9f4222cff6af73b3300270ce54800bd934a9109a02563adc56ae46584451cdaf4a77538157e5870f4ae12dbc81870f5db41a2cb55e00db3d2231628f1727c3acb99ed3acd8b67156a8005a4cc8f3d3555b79a03773a931f14eebce40b9fe46ede5da0881fb220717e418e8b5a0fe5e477e7285c554e859e16441672b489934a3a9eeb88d78fcc5c1db2d1fbdde392773f6c939972ee8fa3189f4e9872b4abdc83b379c0c10e818dcff75c83d6870729284ced41f2ff55a87c960e63d1211f08071293f6ac63f9bdef38fd5919ca90b3f5e25a6c0c664c4ecf831c64e2d4c6e798a98a3a0f7be7a2463eadaa6a2a348f9a494717123cc0a28c0a5eae3f5b585f2cb8cb260c2c503e41578573cd9b7cba1408dca9d860ae4f8c3d3f322a45b58a2c4
SIG: c19b532b8248563932639701bf15bc015faebb17bb98d871616e1048d64ca5f955f558f63b5353a1576fa1acaef39bcbc9021756df5d1ab3bc741accf9059b04
TST: 976
SK: 50864a75aa0c69b59350077c204b20757f2b8b6855c37ed721b49f2ac917d6b2
PK: cff3ebd5ea0c8b5531d9211e2219e4cfe5ded991d8ec424df54cf53c8376f9bd
MSG: b365f476ac92e76012a7ffd8782af15a3f5ee147f603a367adf2f9724613e8765b037ac0eb1f673736e11363e352ed5ae9eb5a67125ed818900342ae93371c433b91f6021d4be2a052b0da43b3682e7f740ae801d0541057858eb0c9c28d98f03b45e128aaa342c6b602776792aa81241cad06f1338fa0c71757180f588c8301d91c27679b5021cd75d7f6171ee9f8d56e4377679812f6ec5ed46538caed500c1d15f5fc86eaf9ed9cf9a0606b22614faf676462134e3db3582332b483dfa54ca29a5eb0d6bae3380e19d060113453f32bbab7e118627b40bcabf1711bcfeab8957de339436c7088bb883101539a09d3bef088fc1f840764036ffbb33decd12aac57fd26f84823e19553d4d67e000e9436ca323de099bc1ce75ebf5ddccb448cd7a2e4bbd6b32e3f2024f96cc5c7152b8be8ed0bd8e436d324d1ce1dd3cfcc452a28c73a95af8482aa772ae53d5be1292e39d1716b43758fe563c8aa3b74bba5c02d04778d91e3d43dcc72bb7c7b043c05c8745b705ee75b5a4ec7b95b654359fb5e853338219851d40a8afbb4f91ecbb41eb81534196cc0cc9d3eb714396caf045b231722d4486503640419988480a7815808be974287372cfc489965aac5b8095c637581eb910f9055cd1c0a0a3b0b33aca90f7c5b8e6ef683abf0ce53aeba51bec4fc7b427a2347360fca8636d3f1469284f269a9abf0cb1a244a15d6b40465e75cf89092474a8beda033391dd311c499519a08c4f034e71918d7cad41845327c89e7b1e94afb0723782ce5c553ef36791bba63de17d746491894012cebd87b1837a821ef5c624bbc84cc5035f5e70cd9f21b42219a2dce30e0e65c250d0d194d2b52486b03ee66332981a5225174db17e5a8bb4a10ed9c8a445c41442f3bcdb6b4f49e4e1dc87661a7b6e41f35f55dd67bd4cbc6ff58bfbffaffd2c382fcad0cae8f0df9af6acf0940007618a54aee31d932cbd8e8b41ca03821c428a0ef8e58d2435eecd503c54da9c1628f3c749b770519f53bf2d57ed712d075d37337b77a2b10a72d2d590c20d5cec2cacc6c3a8dc113e2d16ef2d1b390ed96e4036acd304e0c7cef9d431f88218aa1f83828dda636b94aa761c7317ecf116cbfc611e5ba6d94c50e994693023bdf2d248ed603f85be73a0008b75adef951dccfa30e42e9f5bb05023ade797506cbf90bb6dce43cf3a1c3141a5cc5fd9a4f3cc557b90e18049b3c130f461e4f32299fa1d1cf9c7f2ea2053565e8160a341cddf99acddd491697fa705124abdab42a5e8fcf048dd9f179384ec92a469aeb11e8bc62b69dbcfcec6681754757e4c5d0fdd9b9cfda49af09b83a5a4a10aed9a4cf7ddfa289209d475ab3318cd4b965e007dce1
SIG: 177455a71694f12b762fd17e08bdf010a7fc91d19141d7ae2399bd241a998a6a50a9722ac1232c59e4e2aaa828078b2b92f4a54cdf0efebba2c16dbeaf072203
TST: 977
SK: e55f220fff8079148b254189bb294174f8e2c575e57f39d4bac8165c5e56e769
PK: 7fd507d03fe1d6e3f911f059597b0e292ea096f5bc851852916bf1217cafdc6c
MSG: 1e2ce8bf0ea7875df285b1dbd34bbe67307f2e8ac8bc142c3ba314c1642c65a2d62eb2c783f916283ca4ec3e536d3eeb65cfdcc0549ac4f6a45f539ac5df79a6d5768219739d0c9a0cdbb31242296c3312b7ed560043f536cd1de9a9c2b289641a1c2d84f9a68b7c03b8b8567e5dc7138c2cb967c628aa25b2eab434d4490b23507409717cde94da59dc1dc25c7be42a8aa02edcf4d995368e6ba0ee1f953600db98d22de0f8d257020e0a406ee1669bd527b9fe1c611f9be5a3d7528e8b6151670a8663d2ed1a58d3e369bb722a6302d7c172a19bdaf357eedb02279156e3b9034431a7d68a39528eb4023587573eb88f30f94e833e8a23b9d0ac7b5ca87824596bbb0a3d0ca1b16a6878fdf7e2cea34a6ffb95a9ff4e888a97593735b868da75d8707bbfdb1d93eb86a51e2d215f1dd9dcf78388729a3eb0f066ddc941e950c92127198bce63a54868d997029572ffa6f6fea1d3a69164c9996953dc8b6f9dad0635c9b081f55f983340f0814bf5470803090e7997f7ab796c2b15adaf4021d67cffaf6e1ef62867503945c21a329664e08a95a41582300da9bed208444ce6aa12b3f867795c6ee4c4c9257018627361293bd527821a29a339b404a2da4bd9944f877040798bb54abd2d76cbb18df4297f4ce3337f64d20580aa64bdecac376a6a4ff74d0144b2fe74cef82d50a5e6bdd799e55ff69662bac537adcb6881228cb63704500c143a4f4d1db28d4556bee604a399ffd206546597dee92252547f6c657f36841a87d565f6552716c25a21151477bee9ef961855fb1af2da8068f28ce9ff70d5252c7a63a2e14ded6b8977b1d7691a77ed2e57d22ff2e1fc4cdbceb5e805858d903896ea6707e48b345f60e2818b2fcec4dba48caea9efa38279fb83d5b0f46a45e42c41765d0171baacd8d6dda7991314b34e15fd36127c467d1de01c01a3a78a8c1b103bee17a7a0b7ac5576fdc226dd2459773146cf38261417ca19135dbda9bdbe54cd17aa7ddd38fdcac2aba396b365ceae98919f6c5177fc583f5bee3f48704914306aa19ee90e3fd0de5591c669ff35ab16fef38dee187bae1e5aaa566df10544b7d6d4eb00da7ebeb4ecdcc4d8e32b49cbbdc6e66640bdb0f72e05918a05c35d9bff7e0e88f241d7c6c8cb2fedccdf65560af0e7833efe34af790db63189022cfd71fc8acf88860127bd4fbf026bcbe360e33a8995e636d03bb86dfd0198ada959342d8e9c9ed93e23297da98d66a0d4fc965162733bc86541b95a6c9097cb55a973c6fac194e8f8a164274c479c510e62d8a035eb751181b502afb614d8c4467b5445c268dc3dd0abbd577004c0bc47b15fcb801b79359757b5ea89cf8cf77fc6d160e6cd73c4
SIG: c1023a7068743ec4668f495eb7bd4db58129c11e58299ea87d6facd302bf296a98e298fdb48eddf9c44e79ae8641f734503bb83dc0b31f610df1d1e9d619a705
TST: 978
SK: d5e3a40671bd45f08842ddc78abe57de3b9ce5646b730d2e59fecf5a7df80f40
PK: 416c37ae1ad15b632b0ea43932c17637282cd91d5979552e5eebb99a419d5c97
MSG: 09fe6ffa8bf0942a64921357659dbc6e4f8b63ca3b9ea475ea39d7925290a148d87bb155741dfa28ae1beadc1f3e1ab76737eb5d5ddaded0bb382d7e11ea81a5e7801612696260ba3bd09c80b623f636380aa0208fee0aff70812d5307b27183832343debaa3605ddad17ddd70d611400ddd10d638aa3d6c68a28cf0e97c1dedf6ccd9c731a84ff0405a3a22dcba00ab44d5b21844f14d1374ac0cb1e58df4a90c412563cfe69d882d350f6aafbfa64fa2f9ff826032326780aecf9305d8217c179dbb63c151541232eb65979265d876c4bc4305c02f40bc1d05dbaf7dcf4f7dd9232c17ee0f7a0555f504ba3774548488933e7571eb3f71c4cbb20cc4e4a7322f35ac0e79a59155798dd0f5b3c11319b7d8f3ea79ee3acc68bdb9f37c7d4c8f9caba1ebf8eb7f43b462aefd38e8c0d4c63979cf6631dec31ab5ced3937ef5b2362cb09c71dd096657700fd96bda555e22712f71aec11ae5e91b24bd1649498b8d9f867fb6c41e076080f740d074c2a25572d34e666b6367bf7cbb3dd42a2382dc1973961268605396810a456ac081bbfd3a54b44881fcfc45b4245ee72465b487d07f2ef3f74add71cdfdd16e92fe257d334645b0a9bc7d072613fb9c0cdea9db4c72bc87109e102d7cbaf366ecd67fbe3ded32747307a7aeef61735ad3aa5ce95deecc16a16eb2a0bcc7adc0a11d888032260e7c7ec9e54f5a2531702a7e5dfb87c36ce313a3147588aef962c72fa966d241637c388b83ddec9343bb86343e920b12ce1cc915c83b31e99862690674ea4935a48809d4d279054137546392ad9f08e7b8de61ae73e81e483d3c63b5ae734e18e7a22feed1233d0ca63355f3a48a33067e1a0e1971f36aa929fe0613c21c4aeff9418429c3b072a5984959287a5e5c40be02bd22b9a79c7f3f5359d2bbe493f556dacbb0cb4c293c7d941265e777392d148d68c07a13c8dec8e5d1e1c7f041e8983edddaa4649dac1572a39ae4c6480ca550e2e4462dcc849c1bab781d28a3552b2d98e02e1518e6555340fb76d68db58916d556a7b81563aba81d9a57ae50f04cf5686021847d79b6bb3da8017a60b1c3beefd48d2b3cd39c6f53c08bcc967d93069f562bb36e0c4f4ca6bccc5e57d35903cd800a61785a93770e377f4fe8e9f4b66680984968f9649e105e7a119d97636f3a05caeab1d7ea0bc81334b42d5cc080830ec24d369cf8673a490d59eb4cb08181da39a46d966e23fed8d38a5fabc7e843bcfb015a4474bfd46d4a43ff4a51a9567661e2696db87c3758d3b54ce7846d1391d7f46526ef30844d49320018d749b5d4dfd30d380c6e573fc414d8fefc5d710470756bec00d88ac4afc925d1ede37eaee6004a23ea0ef8b60e48
SIG: 63de6a981142365a3e592631c8277237809739d1c98f5a1cb2cccd34067d1ca5dc8f2fc63b8ae1a689dcaa291ba6b69b1a6795c579a5db6dccee73f6a420ac0a
TST: 979
SK: 4ed7048aa1284dbbcc248938b40c35742193597addafdde06413b8d4ccfbe137
PK: bf841fe444add1f7c3eacdfd0784b4e855d2405f4021cd9d8266071c32c8a273
MSG: dcff9587d6046c1132be07df26df6382ff92cfc8eb5345c51dd50dd188ee769f10a4de5e8883d116967bea97d3b32bc8aebb9f013d6df952f251c1a312346e72cee135a1bfd76bf3080a35c838b44d755f263d210310fa8d28c4ca52f08cac5b83a8a3b1dfc46d9b752d9fc73649d00bb9ee992650639c225deac1f39b9e803689d19e6d9f8ef4f51f1d11601facf410db648bcc82bf648769a7dd59c6e8a237db239d3f661d7852c426d394a90509526a859b476459dedbe6d89936c0f3989995511d4a576e542cce5e0dd7eeefeb0326d33f25c22ab6e7690633f4c9ed2aadf1d24f94862123a464042cea193a2f0479d39bcd1bbd1c7a0ca7e6258ed3732372f54e0ed5e3f1e2e4d4a04c510bee08d1c6d570cfd63abf14b4eef0b96f39ca29e43c52f2ca3dfd460f66e30235b159aaef2cc156012969fd3d159978d6caa0a94522291f7989d8af10831996137b68d97fc17f6a9bc2845ef3dd47cbc386e8977a8654363412dac3ac51c63817b7c051878dcf458ab3630dd7aef68d270f8da7880a467b3304f5baedfba9173e7efd007c412d17209c56d23968e340b8a0edb41b7e2a4088bec01b532df89b5215813131107b7b474f03c2e47d4317f11c4f5160904304997e76a121a9560235208d79b2dab4f7e196793202c0902ce9c4bfc10b8fe397e35ca0256454662ae878efb0a0a606fac0a952c9f6baaeb2d45b258c617559c0ed2528a88b49aa44ee43035b0d793aad3953c1a5a3463866bc815b1ffce2ff2b65e0fd47dbc15f4e7a06bfabc290fc62090bf7d94853f77c0444a9b90efe77d1ceb4bd39e203bc884011624e6846e2a371058daba63c23f86c42c3e31eaa4bd7d7a42af2d524896e31baa3e20763f85dcfd52775f28072d89f0bd4fae30d0b137ee37ab063ba06fe9d4ec62abb2fea0f81b8cbeefc030080b8026a58fd1867f66be1154e65bfea7dcec55fe32d51fb0b4a8a5a8a044263943d6ac8011c6e6701beec3a88655840c4892d450d312b7652d2514769f23bfd6e7046467df29a287ff3c4c9d0e64e6d9e4edee1b935d07681d47004352886e847b0c6d5762fd45a81a53cce9476c887221aea6c0c82bbf3b297932e5b11e538a3245d63d7b7b091dfa1d7b9a0e2db6698a4c5e9fe931662d7c6ec6d9d5b92bc7e041555df4df0ca11cabc485f9c556138a71745f03b9783bb200b72d233697e8bcf6b4117ee6763d792d7422264852f4f30f8d1890e2ea08098040f7f288e4abe90b63cab2c14373060840ef827ecc846cd560e90a20b8305f463c36ea03884a5df4c25f1ba9ea125952dc091b97516de1d287c0e2bf529775ba6d2f8ede03cb42c1e400ec804a9df08e46f44b5066346e3f7c7a1a8
SIG: 106a9deb2327f338ccb71bcc94e2fe3d2e973ce6dd8fa7baca808b4111813e3bc3b4d88efa6a00c4710bbfe53196f9ab3a150b1654b908feacf9c13df2d63802
TST: 980
SK: c7eca83e948576bd9f278fd7b82800a41d92da9b72d5a1ccdbbc65581052568b
PK: 076b8352dca8031e853c8d9099c2ef579337cc7b2b4c75d1a063ea3ec725b7fd
MSG: 8d8cefd673855ccd8eb8534c312d338005bb05f5b9507d58859e1e953b0a4d913be759d8edfa92898c6e70a53f81954fc344b4ad6246b0109481ba6f73ae6331abf2df108eb2e85ceb087c1f6fcfc9de2c1f139ba1771b72680302d811ccd0ccd4e0c7feb0132eb20b334e5aabe5f6119fd8947d9e8852e1eb1b74107e174100e3e6df0c3a68130ca6309402594bb50c1c8e2774f13214496a7b1f348385eabfbccbac165a5a2e7d9dea5ffd58b0bd88b49cb331ecb7f4e9d6bae9791ad788e6ab8926c1cc1615deaf4cc400c77a316197bca1904995e1365d1b9702648376116930f6f91166e6148629e75be2d06895f6a8d15d5a94ca69b712f33bcf95be0c1be6902bb78b8a230d7a8560c4d84e2389552a81571aa665c19c2e93b0d43e8c2cbd9e885d7052518b77c47e841d119dc28b65a7504f664271f06c7ff393f825b1e5930d02b9c70035e292411c4aedf66047006970e349dfca7fb41c10fd537e35252e109e3336d7a82a14de5d5540c6fc6571d5774f39b7c403e7b8875ec215877efc6cc8ea48b186b46821ea5ef2ba8bacd40d797e6add06413283145b60462b3503c5b881d79a592955d18afa08969e31457f5b27daec010338ed867f300878fd87ce321880b860a0c64284ca2dc15f5e5310e10e6a73a7ea650ea9d373694da4dd429ae7412ef9b29c83b3b068c74769f431ce0615f9ff4f82baac47b4bce90449ec41c2a2d573d92b92e05631486165bc710ef5840f80dae9f9dd5cffd4ebf5d10746510c5fcbfe62cb9703c0b154c86f10816672497670a3b0150bb4e1b03b3bd544c12a90c3edccd7900ebb5b31c91117cc8281a3c4ed04998e99aed41bb41fce9990a406485b14dbe3bc1a5fcf7719507990da3b0b3c68ad40d8950c0d49ced1019319a3f36aff6caf75d7f9a0933dd3abdd7692a1562f0613fe4a278d5ce4c8dafbb55b2ec2af2b24e8396f587b170c9ca6547508facde73490dfb01eb6657e3f4f272304b70bf047a43a2b58e5568bc52b2c8d4c03219a5a8bd3dc0643185913c0af7411f81b77be2a9bfd5cb26977113d2658a97192b41cf6c7011b0ff6a11cbff3505546322f0bef6097e46b36492b016a4562e092b67c3fccc7780ea274d96d595849f7e2a56d79edcb32d784049fc1324a5beefc24193a66e1cac4a13a811b909583cc910cf08d4b104dbdb8a6f2b21fbc1db1175a1a2356a63d3eea9dbb8537d2c68627543df0d1f8fd8d57a18b0dbd69b920cb9b286e3c07ae44ae2e1beec01cee6ba988b5d1afb99790b1dd910655c43d7f2a3ed3754ba46516d278705559f5741622a9abb5c8f23fa976a9d146948ade6ba6608a35e4e0d330e82e96a2be6c78ad0cd4d8704e57cea146
SIG: 86996a1b8e495d425277e97cc0830549349bc2b6f3dcda60f3b7d3501b8b50b5b458cda58b436e23c02cd4a22b234813aa9bcc3c61f983c0b7efeca0f1bec20d
TST: 981
SK: 7b469df9c8f78489ab47cc70a88503f1b8f3d929c33feab1c503f0969a3ac37b
PK: a814c7e373d0113b90624a8ab2bca5cf53bf528e39fc3d367de154b94bb22f1d
MSG: 1c0fd7450e29675c93091638c2ac933ca997766e380ec33a92b8a7e1a1ed9821c75fccb5c5f3760e76d0e8810311ddc624ea8742131c1c4308f4178e04d04960693d846c1f51d8773b6deb3443d874b9e2de3b77785185518b2e9ee736c63a39c8212ca8669e161d131b1ab2264fdd72dc5628b11c06f2af9f0789047bdd4ebb5d55899f74dc4e12e7975363f63a8da76b5585c16bb6d55b05fade8713d19cad1a211640262691aac9b437a9ecf89a9246ecdba1ff0bea78494cee15296216ea6bb882479d2437c9494ac7fa4f3015d1d3149d5564d7c11a7e7b614f7d3e9d454f0a05b040a1e06fe7837c2a9da2794d918bffa9e61a0c3f089f6c9f7eeac586e34bf94470d913da41371cacdfc7ee8bd1135655566924eadf096ac030a65902c103b172d12e88f053fc56ee73f31870817083afa802f7668b815ee790f7d40b437a2e6db2f0fb26836b4b2331eba55539614c0fe17240242dd3af7383bcff7d3f47d6544b08720c0a52441f7411935dd4a952d38651a80005fa3eb0eaecc735d290e8bd5e31b740140e136b2c002523d8eb2a0ab5bd687002b3b926f75eb690d1da73ad235892f3b23a756b605a437c00e0621304e810f99e314c4d63e322d9b69815f382ffa1ec6280fc0e641c8a6f6f7f61985bd3567e0f440de9f7621715dacd07428c0090154d59ce6db40169c658ac5bf44b67671fe19e4b5b38aad2d3d4e190a550aad4188352f7981a6d88062502df86791350392d41cefacb24e37bc700cb029190c3b1821477e117d5a462fb3e79133b1073598966f52b63256dbf326ace14db0c80058cf00d689a0a58111af1692744bf791bcbb427a372246e9501a85cd520c61a1e59ee180e8c97192f60fa5d3ab05df8d8551c1ac6ca0a9a012ffeceb3c1f521411edb6509bc278a651e129e96b0adc7aed707221caeac229884413daa10595d22d1db7082125f4f969500a1d48dacdae80f4029c163dcd79ddc6468fcda1637b87ddcf2a3d9b4d299a0e5394df90ed03b62137ba67b9fea8ae1f0d22f91c63a24b5934f74c265c43f1b923db980adfcee8313da520176730ef9736b27e6ba32d17ea69dcac6f4a016edfe2db5a5bb3b64932f7011f1c453bbe88bbac8c7035f93fe39b581fcaa7aaf082fbed004fd1fd5a4e2d9c19716604b19ce199e2169a7be518d5fadd2ac31b95478082ac91306008de4ec0ef4c9f9d6f96d2f66d62fafc2194082808af0d67b9fba0d189b055f061ccac24b27610bfbd5a2232dd6f3c890a9b1266471b322e9e1bf97757bef72abcee93b051fc923cfd4e723be3e17143f38eebb900b5bbcf7304732b9c0a1c5fc9509a693580ae73a4cdfc5fbf20ce81ebc835c6c909d831141b194f6
SIG: 18faf82d08e1068e9f983d812f05fdb6929d2723db1f77c45a74bb09cff27773b54ce8f43b3015419112e725ea7acda4b23b8120e7b0cf420153e5b03dd06109
TST: 982
SK: dfecde7a56a18c1f19d80a19a4f1daddd0bcecb01eecad6dfca0f957a914ed7a
PK: afbaa6e73e85b02b25a4b587ecb8c4dfb79aa9202761efa8d1df2cd0aa6316c4
MSG: ae6e8ff65ccde6f26484950826b43623058a5efe020bb19b7d8b4e25768b692734fe07c913b9e88126becbf14a0fd0205b39fcc2aec373f8c184c6a9bbbb84449a7ca3b920ada08801dfc66ff19aeb92f2555399a430277ae22d23754eaace3c73846797536dd71a56f4b5842c0f410d1989acac5d805d26572c0f3a64dd2071662212d52fe99e59d966047777f9030fa4fd2ee74b7a7c9f7c34a6dc7e03593a13d64ce62453ee3ca30d84672839f19f1c15d0c45d2755bb394acf4dcb7f7f0711ac40ea46612ea37a7607ad32e818265fab1933f5094e2d03bcfaa5f61667f3b37f00c4c58d9b41b9af3900482b0ffb4fa4376aa040009dec2f4525799cb005f39d74cb2d8dce8c20c2c3f5409703af156cfba28a9d916439cb29f83d2429ce6223519e75e15c7c7fa215119e073fa7974db14f7a01093faa94ad52ab1eadce1a89366ca13adb89066438a2beb73034170aa42d9c2ddb97c14a17c3094376d2a3ffd8095fc4053d91d16e06d27693a1310f01a75111cfeda892c3972a133a09addaa8f74145f88681b6d277964bfe38551a2c619fa3cae394acb29c9410b45e101b1740e8b2aa6febc3a45dadb9d9589d597e57cd947b684cc355246ce6c326dd98cf92b6eea3ba5ab03700622636324dc1222cd748fa07bfd39a1e069809e567141a613e2e8be9dd398ab6beaafd85ff3628ee2aa32d0a57bbacf956190b5c4242eb5b8587d2fdcb0741b9416a05f5fecb1fb2d64788dce783c1f63e60641fce5e1d2b18a9500cd6a1fd335cc1db46ef04752b2d22072e6dfcfcfa569bb25e457afeb63a4fbedc293ad9d1aba4e394aa1097e12b0fc90c89f76df0d6441fa99808b60be07dfcc7f9010bbf9033556d5ee2d448937b783493920f681e4da708671097e199481b8ef0e0150d7c2851df44c545122f9b0e5ba2eeff2d988d56d9bbb55d9896111151a436af065e0cad178a2c9fa8f6974ecdf09adf013300cffedaf4b8791b467ba7933ada5d632db44ed6dcf2aa648917be6337d2e2d206856d08f9ee7b5e2f14ddc6d3ac429215a87923ad32d5dcfee3686316ddd1b27bb193a5fc05c893a939a5b98987366c829e392f485ea15e22cd8f857a134afa98f37215576ddc5aab4f2d10caaf050059a335f24bcdcbac819f66db07aabdfb76271d17bce22cba463a80aa892d0d8e055f948df7f6e6c300daeffd3a236dddcf238fe10666a57c6e3ae7e3673d35578f8b8ea69d3c08e0140afd3ee030b22a372160f908a378f8101b5f5969fea310eed37a00d97302d5c2dbe8cc600075dccd33ad63d265aaf60e241ce311bed7dd5e2745241ae02ae532d15c18886e818138751afc51850e506c6d31a8eef451adfd4b3d266b415a7e
SIG: b4fde55b916cf60068f19b25351c1410dcf66bfc40f96d1ba2368bc2b9115aaa5b2d1cf0e3dfca02ac902a943e2489a5681bbafed39c6e33211a9cb2ff6e5409
TST: 983
SK: 07828c580ebf9e1d825a59c3bf35f072ae123355bdcc249eec7f2fc5755e29b5
PK: 58e5ed85100bbd9b2221afc9c93184330ad59e1385606244bf003b8d2018501b
MSG: 0edad5cae6ed9843e91c50d934cf55dd658f3d252039cd6c75be4f6b866fb75f35c8f98f1721d7e6d9d98a22e0b4934dcc129261bf6723b2fa7a995e35c4bd79c5816a321607d9dcce39fefa1d55de4e7617548ec385c3de01e366bf50c457a555e932070e2a5a0197b79efbe7006f0cec78b60ebb8fa8781d8eb7326edc30e62d3297a1e0a1117108c46ee5dbefc6594289335e780d55a084f552da3f36d3c4c6178ba74d4decefc5a3b8c47c16f534bdb60895d3d54cd2bb266b399e4d4fb48d7a8cde17f42412560737d3c06e29df524d0cbd3093efca1c8fedcaa124abb27abdac6a29e0e8246abd6f5f531950037f76323aa56cc3fefa603041d55f1929e277e72cda1f96541d2af3e90c0f0e28be196d8f6921f3cd57a7926b860aa1bc403576892a96b93190ae383f631b72802658b2e8451d52a2f45db4f8bc3b0e4e50b6d603a5bdd30c234200ad7debb963f58a4fa20330b3696449445aa371824842fbf326d901dfe3be045452a3740dd160e72733f6e2733525a29a865f6f50d53bf7191c599c876f5c9ca1e3fad7960648e0d471f7d5c01c673f42d659bc3d98dbf07d8febfb995d17f9a02cd6c39f2ddcd0f1d222b9e11f2dd7d3c7518224bb6bfb8b7c58fe8ac105405903a1b9da7516715b7afc38a555e6bbcdbad46e34e576fea34ce35734ed20af5d88eeb1047a2660648bbb113ad9db8c53edb6ed9871a1e44c9ed2df5656fb2b2806ecf03b1eca9eab50a6eaab55b933b2dd1f21d450de9d5cb2232f07a392081b0b4b885d54789e2f75bf2c4cdad878989b1d6dabd9ed23c7c5b0356a7d9e7335290d7c85b966e80184bd07998602886d7076193565c81cccda4cc7d33c85d905b1beb6e8e7418e8acaedf0d9a32a7d29d07cf44d3119d4e7896820b77de64b655e4f148800434af7bdb2a56b25eb94ea39f2169596bb2b11761f082baec08885f4a0eb6c95767135a7f7cd72e743d2dff144dd8bafb1b318006e5876f8e2cb44aa588f906266ac67119c17f5de114e72e42a1fb39944321a111fa795ff7017f2fb8caf482f55d77a80855428ded7ec20acecca83f8d1eb137b588ccb745c105f2b2ca41c3a9f49d3c6e9d7c648b003b9707c906462edad617a8cfbf9bcc6c5fb6fa984325d6582e28f62005383f338df5b38fa9d19c22a2a7ea1d68a92d1d93b7fb0b8f33bc8760f28aeb1439a8b07f3da58ddb155b498cb09c75a5596838a65013e24d5640d0842a7699322cf3ffcb5703f414ffd168860bad3e308b2b5bf3cdf7f363bf9aaf4b3bc424c146c6f5421430f9f476aa34a0c6ee80131fc4d4d970723a2186ae3625e286d17dddc435ccb00831678aba584a62dbff002bead6e11e23c54d33cf3a4b231a908
SIG: bb09360439a82dee5c7d85779e54c13f88e06d38f4b94960fe17a1ebcaa3ee2f330c649154bbc875a4076cf0bbf7eebf7b8d08d5aa4be7413881245fc2d2b601
TST: 984
SK: f08ee8daa73e1feb61a88e062dfb1003c8578a0d53bd3bc9e589efb92f68be14
PK: 76692ce8d116eccb897077edcaafdd3eb44ea1a486b90e49e97f966901015502
MSG: 64de90044d0e76bc02fcffcb75263667b3bd733b40bfb26c6c52fdb4b0782278cabae41e2129ea4017e94de86087964f66d86207987467a1688f9fab3ffb2f1d0063bf626c941367c12e319ab7ca3020c9b3a7215a19303e2d0e8988791de0d8e1632daa38c7f3e7f6e48ce122143d1e2cb661ba77c69e6a710911644bc110ff58bb00b5290820ce30970e7fde189e140e5c70c783eed53f0e2ac7ecae4f27db81d15b8646faa9c5a3ae2b7f47cd580d7707b002499b4cfeb8c591afdf1cc62af2595c184abcf0b2623a1bae60af7026b28d0540b41526e3020f81b894eb3fe31b72b21a3260dae3210c4ce4fd69e2e5ea0c8632a583262a12b3a8b16c9c1206ad73023037cf30653cb80aa7df8314b0f5bc6e9d5fa00b009d5552d83b7970b5bc4b9984f69d1cca9ce4cb74ddd2d879d37312a0e159d7a6afb77ac585e6b459c551304e1eebfbcab43a10b505924e03ea332f5d020a55c7aa683c541dcf7790a240af079baba94096b46060fd7afe9056ca99e688df280a9be8c8c73e6e6fb052a33eb3328a7f602542fe280c890e3ccaf22c7f34f87b5e5ba784b472b1e1a99347a9e0d240858d1277a5c6b349383fe4fd55cf92e69faad326b8d6db46233026221ee6d0a1c4246533c4a0e5bd172eb8936a9c0d30066538e3eb4ad5cb9877fd861b482b30150a06104161647e01d004d997403ee06726cb97e2e25f18c668eee4c5bf72529803189ee6a7aec238d5906ea5ae10722c9a61a78aea52af33eaac75406b1a60befbaad48476d9ff887fd283eb1655bcc07cf753331436db5b3b13032ff9c3d696380e9f5abf50d3556fda0df0b53897a737ac7a3b87c2a832b0c7273ea9fc54a767f1a812bf0164bf7521630b81b9dd930d92ee2ca28e3203b77bc082ceb37d55edbcb71df0b79236789a25d418cbb95544e2cef33bbdeb27a3f7909c1f498f47135ae9033adf250ad4f6575361e4cfcc9bcf4b90c3ad47a3442297a223cca843d7205ed08a9b87160a6d01b46a7d1c844e8d1f18f618682bfb22955f395b2a5790a51a696499d9e71a501f3fa546de9b10ae47bcee42ba7f869fb9ce4ed7c6453326c034cf05d9f1e3c200701ba752dabbd868521c3d8f80672d42f6cf4564f08cd7b390e6d49dd90090afdb84486ffcaa4e84d88682744dc0a878faa7cd440a8b276710902081f4dc84174619a66ea3a371f95505400d99fa999017710c8e2714be60949d461310f7d43a0dc123516d77d362213f9f75a5a1c393affc49ea151d46a81ffad239f28c07f65f59ea077d9a4d9c752de49b9ef36be60d112d795f588b00ef6e7730dea65e1016da0dd462370e0ba5c660001e457c08b436da2903b62906932084728c81671cbfb079bb29
SIG: 66dfa4c1575beff2f5a230b28c58c3eea0736df379d75559bc9d37a9579d121c05c373e8484c9747ef4477e80c4b2cb4ddf16ae9fdfa08a07547d107dcea1203
TST: 985
SK: 272d64de50b1312bee23d7f4cea508a8fccf3e9b324e97b1c8e72502f61fbf45
PK: 33498c3b712ab9c01ec76b2efe2b83add1e1f2b5eb78f21692323451820cbe10
MSG: d6260d7eec5d436208e7e737655e0971814270194405e36e39f8f17b649fbc16c0f3d7f2bef5ebc02bb1c4df48e8470a3eae8a3ccaf640abcc094aa91150ff1a8cf1169693ebf5ac0034b9b919ecf17db791dfe5fedc90918b23e54e9004a1ae771c213ed7ed7334434e5bc02c0dda2bd1a876fb824a197bc99613b1409e7052310b0820da71446929ae7cfd3afba042de54578a5bfd94c1544391a3d9acbd5663ef65c6920d78516dec1cd55f6eb7290ba0aaf9a171658200b24a47a071b96fea03c6ca7ed0d6fe675dd63761833d75bc5e58a958582db02a60c6ce0a63f42ba837ae77c17a32705fd9cafa587b555dd4619851079794e24eb44608835a6f4824920d577a270396c9573bc7d82fe2aa0465956613a2c508cf2432337a365e6c984cba917f0cf842af122dc89dea958d418cae44a6e4ed263a415ff994a5ffb2ff13913df214bbfe90a34b247e71ab73f7ff004c23acfd90c767611aa55814c66964168e568ba75bf34903597cdcac78c24bb9f14f5c86a51f364f9ab41e464aee64fa50a1c159cbd850832c504ab42a584a96d5aee082d82c1edda19338160b8dcfa3419b3af64d9cfb104f98f9d35e5394e23228e275c87db50ca867540b880c7af29fbf534294581c22240bcd4d7d2c20ffc36733ada27653d3ae1a8c2203eac626e2e9bb4b52ce523e5adb3b2c10dcf78c2a1e626a16ebfa1bdb8c161493a5aaa2d84bfaa0f2027ffe4e9eaeb332ebda7cbbb677769d78517adf72f823a7f844165a079878d258fd95225c21177837e69c19685a051ca92b120b7d86d78595471ffc42a5e6e6431be7b64f8076458bacd6c72903cc34fc63a40cf3df00eff9d6ee9a8f39d25ead81a8128888b0a1ac0e5e3ad927712c14146adf828770ff958709eb19288e77bb70734881e9e016cd29e7d0899341ff6b297ac796bbde486ec35949f6a32b2ca647385915ecba3b9f0225087145c18d6559d3a31d6f22fc49f8a6315f1d32abeeb7cf2c2c776ea7350fd5ebc0e0f265baccc2697a7c8ca40c135f6cfcb0b58a61431960ffa9065709a961a633d570b73fb4491de52ad0d7b204b6e997b037ede3f7eca820a7cdb2c69ac29148be3523508ae7e4c3d1a717f55a821d14c3b64f08ca9ae49613b115773ef618d321c908bd2156717a434e5089a5948c045c8da8a4bd86ed5fabc6b13466e6deda583207d2ada2b2ab9cb1543df7a3734dfbc6fc428106d4844724a13df42faab18ca89db20ac9bc27b85394667c5a2779ca63ed7ac2b7c0d4122391ee4602d61ea0381764fb72dcc224e65eae2bc4506b0f09e23205d0bb21c77d8287c165e0b42c551579778acb7258a2479d7cf25b902e8d0da429bde36b4590dae96f525481ac8378
SIG: 33814c6ef375ab963769b2de4a25e7020fcd97f78f8fc93455c4b1c2bd45d4b01e192900e3122265fc552cd5c5f00e931e3a183cca5ba0802dafdebb79ebeb03
TST: 986
SK: 0c9fe559ad1ed3ba164daceacb023567b2430320b6715de732a03c59c7303130
PK: e70fc466fb2acd74e099c36e2c22fa51290bdde96df9c31b6dfbfdc2e2c14a40
MSG: 26ebc648cf8c7965ec6ebe965d9c792bed90655ad440183c6d70ea6467bb8e6f04ec843f333156917bf4c51d0ed0f28b7cd31bc12cf840686b82b0c2c350bbdac805333725d6b69c2ab7f34ee593fa1cccedf3f0642a688fcc1cd98b0987d01f713a2fa6416c961921de0cc2c9ec7a555855e7fcd4c7ddaa14fd91ecb04224e1761b7d6b35f4aa5618a500ca00d1ca2451b5d368afde3a407e783135f39019a5b984e82ac279c05e48c295ebd1563821a0743c52246b5d2b2034e3aeb6ce7c5cf919e74a9c7bbc9e25da30430eb16ecf3837eb38a0f559792a729890ba8310260f8aeb9b5af00eb633c12dee022628ba418d75cf18de2f2e65e49b1a69684d6127ef481ca861ecbce3be86497e65df4c5fcd0817c9716b59f2a263d5e9eb606839f85c5a365837b0fbe2c4274d66cb2c65ed365fabf58f15be52b51cb60118ca4f730d447359f7ef346b750217d47b2e79c86c0c62816a0c7c18a2ce2b688e0cce0d752321e79b423857dac59f8fbeb09411e71669ef9a2643f2e99f387ac183e0b0ac72c59a0c3c18c0de8b010878074acc1a2b39f9df99d9f8f8b52fefe4943c525fd4d06ad878e46608abf27a54bc5006f647db724851db7c4578ae66583dc4bb518ef028890347e8fce0927d7d9af3ab5d0d2d202a4026aa2ea7487962676a603298e7d2e7b90921ee1b52806d71a764e03e25ddd6848f61d46fad3d008e10ee5cd5a3390f9d158a4437ef615fc90ac5bf3a9d682e12c3398ac77680d22cd1a6a56ec3b25cede867edd383159c6164d63e9cd1c956ac7235fffae936166ccd35898e29c9b4ca4e2925da323b6fbf67cfd596c88a1a35a8359851ddcba8f6134a9faa244dcb47e691276ee625cc20adcec21cbe77a3acb9ba72f0c9d3da7e9cd5be3b95990ba54a9f31af171f95aeead3331cb188a5b2c6f539acb48b98b3f7341f60251cb60429ccd9cf32f009205f2753fbbb26aa53174342ad184dab6870c0fb52930119d9f97d8489a60076aadb2e96054ac7cb7f84e13c75bbf9e4d924d2272afef0871915e243ce66fc2a8888513535b10bb4079c806bd949281e28283523d0d210b31ef62a95dcae0cd25290c7edf2c24b432822debe347f1cae945f5728c71b5403ef14e72c3d8342e198b362ee20f809e46aca015f35477ff89ac4b37e6615856f7ea251fbfe13f9065259b0946aaef24943270a854de889780033d63dda5447998a3ed7e506aeb51ea37b681ac3076797acdbfcc27883630adb72260a46af0a60d53f6654566e20d6088cd48e23b28d81f0eed205b92aafd96164d6d3ca3fc8b171804ee9fce7abaed2ea4ddf9cb2b3ae73a70ed63de45e14101428d0a7a226db39ab6cd04374080e6983f018ce93da4c89ac
SIG: 6cd8aed97d9c62d5fdae597d061c0c2bc37e42df06b8327a468f92b3f438a1e6b6b1ef2be78549a289fd3fc1a6299e5a33d5396cb4fac1e8e9982f0cb3d20d07
TST: 987
SK: 15d75ad8e4afb12634cc8e600f1a4267ef9584f4c4ac44fffe4b9fcb885c9d2a
PK: 09d126f017e0169774e8c37ab379263a8075746127c2d11ecb0e4cb454709ff1
MSG: d1cea2b7e9afc1f0fab890d2700a5ae41e15e7d34d3bf19d0f34d9f9f0ab9812dc7c2a8dc44c8ee7f3788761ecd988ee72c736b62a7cac3cc9b738e938df7787377eb9ffd120d4ff58cf1c0675633f7e83c4b115548f14d2f70c6d482211443a8499599558c14277980fa42a78427907f73a41f5f6693b2f75fe5e7a6ff0a6c3a4e2ed1d0d968d5cc9d6f13d41c3d291396ae7e434e664b2ff243e7f6d88010210078c39b5a576caf409bb4711b3eefc486b67b7ffeae0cbac6a0fbdf5343fb2ae4e057edc8c9d2ed31eae9ec83d2bedd219eb989b2d4419618c2d3ce4490e35fbcad432b0124795f9c5cbdc1eb0c3072b4aa801d26fbcc7b07b8257f5fe47acd9bc587b5657cf07ca545bb568c9e4e73cddf6254e22f78ab2f8064519f8abfd16fcfa90f87687db0c4209be2c6c79a5521f44189678d932c54585700a2437702e56aab588a17cb2cc94c00e87570ef3ac5133d753038aa46510a260c1fe80479bc02eed9a8d1de99354ac2648b48b96ab1b80cca6cae1877f37d70428bb50850e0308db0b423087bf7dde279e096766f2ab3ab2385b0464a5bed7bbd8d457e935e200aaaa8d951570e053076db18a6a62f72b319579884a0826ba2b436371dd218b01a0c5e58d0cd5ff9825e4466fe966df05cc31c803e5212183ddf29cef7fb91648a4f8ee19fd5f8dbd8a56be7abf33659a9224a1e27a1024effdfb88e8806148d0d1780906af1ebe3e5f14363190d88cc6e5089444f125d063155dcf86ca9263f2f5f183c26974fe000b9342d24c781e2058287cb6f3f1e3270c22b7707b8323a5cc8db81aa906bb59d696cb97cc74e359595ffb8373cad3710ea09ea9744c20e9a12e05be5a95f085ac561678d7da432e4c7cb53e1271df5cd5a339d2d7520f1c1848d15071d8c69846b23c5d2432c73890f2eded37c3d2964a4b5b55225888e892f526d1cac31eac356f361c2bf336c462d60c82e82b616f2a519c2f67bf01290369be9b55e9f5c8cec4f2e1b2ab302506c903dc3e7b9c978141dc904b01b1c23d25004399bf8b73d69cd539c79af5e9a0a511eca221078a1ff7b0f604aea84246c3cb32db9381be121767e097bea517bfcd82dfe921379840efb4b6f02a48ecdaf12d2cd38930d4473adf97cd71dc4ea10382f4f5d1dd7562cd4bf5115932f6c4700aa8fe8deca9d5e7277902b8f886529765db2486074b23a19fd4b04356bfa6226c82baf69a087d9ca18823f8e3e68308e16b804c363df5b6307e76240db1ed841b612d65548ddfbe8367da60772c6aff554dc85d041948345e567da9333151858fdf6993273925bfdc7181b5f646d063a8c8f310569b0ed093bd9dff04febf0b41c6dc55169a14a3c862e5416f1e582fdee8fe87dc
SIG: a8f2f4b9e2072ca9fade37fdd62d8d0242fd4daa09fd856e75f4e343c7260ea677f753a627aed08cb96c444e29bdb5b5385d43843bbe79a3dda36e1e1101c50f
TST: 988
SK: bf3c0cbbbe20be2acfafb27a3611b48921a728ab17334b8afdee8305178f613b
PK: 4500a03c3a3fc78ac79d0c6e03dfc27cfc3616a42ed2c8c187886d4e6e0c27fd
MSG: 8f30ba2f792e9a97f6eafe29f976a48028cb8857b5c798bc2b6168c46444c0ce696070374c5e6a40c3d18a5dc7669fc41db9a81cff759b8ca0159871c3442e8c7512698fa447b5783ee01d1b611449abad237162922b02d1aec5de1d666f17da1613106301d30586d116e2ac09007dd71e8123ede4c5a6a9ac077fe3d93909da628e865870a4e25cb35591675a0690bec4af0281714fe6661bd5c00a27d79f959fb4d4fb1636a6a3575f4f01470663899d737472b096be4db723715367a41a3a4c13f742d908f4d921cfdd156e75868261ba9c10d85874ca2d6c0c9e7295e5662bd916a363c7a796ead617c4251e6794da06c3d08f2fdc3886944a7509e6409c906b593113b4b1f9850132960d9f3a4eeb7386fa592f6193beab8e0ff0f28908a0d548db87bae978b05abbca9b3e96d8795b88077f620f2124e31590eb099e94e0e6e3cd620ae6290f3e2d01467e5bef4fabdef79d9ab9239e753ec4fa0bb110ff1d393fca02243502d7e987991eb76d08f8be7eb2b1ee00c3b68bbf72a623baa15be896b3215ebe8a82313109fc629b0cce6491f813c24970e4ffe6869e40b46b4ed22986d0042155276c230de4c05d678552f2e851cacf5a472157dbb1a99a2b42ff4037f0dc6380672921c909206e80050e61a6b3056b17e3ae835009b20419a3b9846d374892e719f1b35bc1257da93ccc6d8f8fcaa8e609a8d204df108be7193467e7f105935282c3fe6670a5329442ea3edda2376a03a1cfe8723a909c064d30fe9bb0212c33afe2bea30c9143c001da01c7ed504559b97fe2cea09beb9db51900dc136705921e20297845ba72a97aa7c953814571be3f08cef968045a5ac34004f67fbfa54e996b311bd8dc527d89e1d4f53453a6713720101c45a60ee3a05c2ee66f134b5af40e4b70ef37ba3f0afdefc039f342c28af9198251381a1079a5dd035a8c28976c6b7f4db09ea383a3a87f0f851fd331aea7fa4bfcd95631d652fa2f50f1c23ff2bc137a0604e3d9f39ccb965145bca48b06dc8a817547b625effa796d000c3774bad198db1241be7a2c0dc4a4641b9a8cb9cb8c8c3887576f5272c33aaffe45615f51a96fae76cf5125bc69ad0a4038790799b5c2624421a6433dbab39cccb0b1787b5bce289594489d17edb5f9310374807d36c6e6734726bb33004ecae8bb691dcd387601f4ea911b4b90ebff756d7d8d9eb422cbb9aaf7f4772e0a5436430685e57b697454e82eeadce4aba062b77682cf219be1fd9b00f1cb1135a1021349539a4b93ae213f193d2932738ef72920499b7be2a81c9baaed17c54641a5974d27223241e3c6a095226bd237e0591e002b3af0565df3e976420f9764a09ae8bfa2795f8fad7fc687bd2de23d1488f449d8
SIG: 8f8703bcf4c0329417339eb026f2b72d314d922e9accb5d8bb7eec87e07e6138551672a6132cb4f875508ed3299567b4a74134d2bdf0d857f980861d18be7e01
TST: 989
SK: 287fafd21374572f57810047d0d98cb1ff3d0120faa4886132245732c1a6ab78
PK: e8252063f5ad7e95bd05c502a8bc4a17556360869b9de0a3b858938e11117619
MSG: b3c443e4e5899c16d39e81b4f8074042a904a735074b2795d9ac06b1379ef7618d2a534b6bef81569e60719267bf29cd9d16acc9a174d8026b14b127d0d2d8b4583998895ad7ef72fedc53b8f08a2250100e1f1f0aab48bc7074643488e6b670e1b0727c385a34ff65a0d7e83ba86083b873dff0559209b14b2ac42bf7c572d0c5917ac42e4ae4dae1dd4235795276a076132cfe3e0c350b26580fbb3af81777b93ad95cb7ff17c2d980ce0d492f6d40fa90ba3fcaa21bb68735ee1ef208495ebf7b02276ffa1efc081658bb44cd2761ef5e3e1ca60ec8b5d816d4abacd0bcc80268d8f4df8b3a52049db0157e2b6e81acd6f3f28947c07627955cdac9eaa1de17d4b9daa361fb49782664d7d6d2ca5cec6d14893c3e80b6d16daacffcc0b75937e8bef6f9e112a87f4b035f9036070a2ccc55c2aad939df674f7e4e12685e016ea0e4902aaaafaffe38ddb2f90d9cf78537f61391696ff0330ae8f79a1c1ed5d52b4ee2a62d90fb82d9a48393fa33810b40d0455902d574ff052003e0160c0f47b5e580a078bceef06073dda8b2d1f104a595e90bb6a48eddd865f1cae4f178fe22e75f2f6124a9da0682447112b3db5be8c42472b241e944fd2370c2dc2715c05a41bdbc890c41c65fb08c2f593174391ac880f3cb67d1b74ff802ef962afef7b9f3ea326f9527e7fba698187924b64ccdd0866248c76ee64c79069be0a057b10ae190f38ff5aba844e39331cf1db13c900906bee0d7e7546ef52324e37c590675f139f58f573a494f4ae82c4ec81066a68e2d92900191c47d3062f0f9aaed191137cda9b83cd130e8262960e6244f8f6ef39f15a4fed13cb669edc19f5ce162ceb8d242b9addbfba8772ce74985a5f3720d590a920e1dca75a879b1aa459f7462fff2e95072761b209254fe38c54d833a8e2cb8fc40c598f3c7f7d6c5705715d0308dc30eaa84676d209d7b7b31344756e69a9a4cb4e4a251817a3786fea6728dd60822336b45ae5d47c704b45c4cad38c1e01ab93d141692d55d12fdb9740f1d181582f1c48ce5434860d930f0e7e70edcffb85560a53dba95d57b31e8924137bc2c19e34bb9c9866877174280e80c23978d57795864a7374aef383f3bf6375359bf63564740098461a6c76e8f238913288769a1cb1c95b22c32a9ebb3eceb048ee324cf0d7e85a389b04dedbbcbeef298d0527816085c0c83efaa298546e8390bd1bfe465ec1bafae69ee5218e72caedb9b649cf73eec454a2b484965179672debcf9441363995a8a907de17dc0684f2aea579a2fb4484195db4115ca32e970526dc00a5cacaf588711dbd469ce80bd297c4f41d6fa28a597c6372c0d214960b54598cd8bc849ebdca36d6225b20dec0d031169cebb36eadc3a
SIG: 6201e30591d36b7b226e36fdf56434c47cd3051837af31313a9917fd02dded2b5bbb4bbc368b3bd15d062045f105b6e7341b15150d36f90087591d839901b801
TST: 990
SK: 9ad049100851d0f79b711225c98847795acfc3601c14b8a9778d6270cd4c05ed
PK: e7cacf4f3714543c27a3e9ed833baf3bde4c09563bef59e763fab71fb5e4ff56
MSG: c284bdd8f8275b49ac808c39045e50e1ed50c8a1afd011afe5db3dda620be8aec37f45605762e225d04111f21b49fcefca3f3d5f813b2020a52c49f95c4ad61ca214618ade7eed6cd8d314dc4c6355955277d457462f03b9fba2e225b1b537cd4b5237505c90d43205e1715c3963ccfbec379e6c1705e08034a31afce646727e78a20eed88aeb0dcdabc5c86e86979e63a5c26c3e2177973b6983cebfeda9f31479361b661763aa7261c0939cad48b71908ea90768bb6c9583d8eaeb9e0338515aca1242626dc6be04ecc4429e4cbb4ff336096192f7501ec471b596a99d4c027582cc69e204b6fbcddf59f5bf7462ddcd5989121fd10f11a0675b6c4e4f6520d27d7c61431ba7d174f57395a0bf72d38c1142736ded6b91e4811c0e8541a6c0d996c5a17dc97db388f721d2357d3c6af5c86b1d5e476ea0ac0b1c11d4387f769039bdf538a0216edd0045ee6dd89eef82a425a83faa1b12807038ca19ebec002e8b3c15344c61cfd1e5f0e3b0273deb37278cf197d8a83b13d992308a51373eb38114c9e45b438780277d1e32f3972962a3e14a8d08db9f09aec3dd32a5b99423e61f5e79944ab57a36f6ec07cc3204f9165ee021ada93e6fecb7ec456aa0288c378a75afd6e9dad6c6f88e959a2cf28bfe56d2e61b2adaecf0d86dd8928bceda26b0540246b7337f5cdcec11fb0c1a59d631fcca19408f9522b68a39f86ef970b883a0f0bd6b7b1415ec9aa043b52e19bac176d67b79e2a5dca8bfd29102ac608e473e9f982c3ec8932d8aa8cd565284491de52f516b9ebfb7dbe1299511ae732c2ad1ee4992b077faffc65f488f1ba215da6979600971196d0ff3a08ad9f00e829c1de1afca10ca476be664aad261889b0eb7aeb6ed8637618900acf481e2d224ec64a6e6cf4fa4df731b7a4feeff2580c99b6d75b4dcd0976965cb2b0b5635227842d08a7d907aaebc2fded8009811dcdd73354921753bc5dec017689335f56d0fb7ae213b41792b1f4eb14a24535977a305b19eb9838dc6b51528b98a39bda06010717a208c347aa158eecdfd9a0472d3b8d920f969e12b65919bda38b461949850cc9cc18d8e3baa8c886d93cd096a209d543ca3375fc4e7d65103cb6424beab44e8bc4a5b62c29a01bcf44dcc61e7675c025dec0724200194bde74d72c02e94a946a752f3608457fd91f292715771487d26cad4e5cf6ef7c6f71627a4daf8a4c9b891c1ee8f04aeaa99fe0c8b4e833b7609066b6132a968890e2695da22b2d857c8c0ad9187c96069e476e27e4632c447ee76714a31d1e5149ecb337ee132f3552da33ab2d6fa9d7e93f68a77cbf191cb06bc22f3470af6d7581e3accbeca0b6feb08a14b9a80c1ef59374ccdc0523c3684504c0104bba22c10
SIG: fec0af34cbc5cffc56e96dd5ed5968e52cbd4269844fc30e3ab0d3472b5d180c8d1b7690518f41f14438e7f3a83d5e8976cb9a26151fc4149a3298d7e42c0503
TST: 991
SK: de54e13f9e2cc754546c99b33b3d72f4d1f7715038a9659f33636577bb526adb
PK: 36338db3326b005e5c61ff782be2eab166d4eb7234a98ea1cd855e1ad535e94c
MSG: dc4041ad61423a12a0411318a6e62a5ef64a19abe2d9852297be2d4a35eb8670ca36c521531b3038acdaeea2ea01a0b6187862a4e1a89d4b81c5318ed4d67131bc38f841a142a2f6f316dff076939dc0eb81b230fea9881f8f0ff7ed0b293f69b289fe770881fb3710808e8e59e64e190c1e379b9dd348b02c2347d7e20696790b62776a2e825bed6917037cb635c92fbc76b4c5851027e7f13852ee7e7c52573a9030b79f22b60d5869efe680c01664929fe9a06fa333052be1d6af3a0b482c332e18051e78b333839d6cb93d93ebfb277e4268fbeeeeba1e8f96a5c9e328c4267212cac251215bfaa78fd88a87417a80602dcd8828e80400da304e989862d13201082de3530925e0edc2c130a9a419071b31088da6f6ff4056301c129fc2135233628d16d8bf160f6ce86d83cd4e29ae0c73843d70b53056c5af3f3dc561271cb5aff393f0803ade072d9ceb745b6187b28d24696767d5c21f4d4ac58d5bb66c5cadfefb1626ef93f714c782b6ef3ccf4b44ee75f0bb757a25d9b46a9d931a03727d496a22810c634f5c1ae60cbdf2f1ea29b54607cff50d9f8e03a0a4513cf68dfb619773411b6180959a8aac30b2eee4ad327915f60ae52b90e04a9bcef8dc67e71ea10aca553db9895cd8008457d76f02ceb53500211109e89603f304d880aaf02861fe37c9534a9d672d83713cd326c9ab81c353764ca5ad5ac0e7f1ff880fb48acd9cbb949064e21183bc38fb1d90cfe619a8b8fbf5321889bb15c02a53e4d367fc668877b662281c4a2af678f86e691daa8afdcac1b820189fe5c2508ce36edd9c6f8f51575071839439a003352c1573e12768dd6debdf1ed4f94ac79df1ab6a0bc25079c0935477d9149988ec3b8793efcda859acc392ab3fa99493d7ae0a6575b695a1ce076532860287dd498967c46f7add49494c02e744c40280195782e2424476165e72cee23642e51cec432191116aec59b59fcf0a3683b95f760760a20bd67454d8de647c0f9ffc4f90f6e45ac93d802f338299ef280d3bb7a4a89db8c59a12526f2783024c8ade9002f00e3d529b78dcdd4903daf5767a2bed75145396efb69790712de6a5901e6d8c15280182388285021d0e70929215d9f2b799bb92f2ca56f48e8cbba2f19b085845126567cfafa603c2946ea1e7d274554a38bf7d86511f3e474f9fa5cb11105fb52fc68177f3385fe1397be584a70089dc741b4b0095bf7eb2993b418df87b14a1f97926e868df6e568beca2215f2dd7ce8a3c9ee849cb41346c684f7ffef0a792edf433ca99ef34c73f9272a7eb97587c8fce4a5136444737138d53eadf3a84f501bb10456e8e4a4047082c9e1435f576526c2164714d70b3d0a6e9c08a53e323840f4dcfe8f2d19f0be2c88e
SIG: 37aca8f248394a9e04d06a7da84a7defa39de4da2bcb18d5f64cc34db08651af4abb19fa2a92a7dda56ec9930b81aebd23990511f684c6d15ba595f7d4a2740e
TST: 992
SK: 8504fbcaaba67683f815499282b6ebd497a81a9156f53e025c2d3ecee0db6559
PK: e62da86493a0caf52921d5602fbdc3dd3a8436941f6be240b31509681238746d
MSG: 6c63edbd40a03874ecaef81602cd6850c09f4915b7aaf418258c568364538e8392a8c379838b0c95345bf64c3dbc175853fb641f350f0b53a05a8ec290288c0326d435ff776f8683a273333f9bb2802184ecc53b06b28c2c402a54bf134c1a23299749a6ce2b51a7ba22232148797e993ff258286e947778a8742d3f36cc7842976043fc23da8a97ecb9715fc05fb0f23fa7321ddc1932861631604eba2ef25d8b756ce4733656bfd1e14708923ac7c60a79846136d741973ba5514189720bc0f7774b7bd3574595bde2515031b25b62654b161035778070ace14971df1fe0be4ea1ef55cf8747d3716c1ce707b1a7c8520e6deb334eb186338fc93000768eb2be40c6e0dc3f5df831b32c3a2c33e28898d6762a1522d3d48daee56a0269bddf6cfc9d73f8d178aeccbffef7ce164f98afea224a9b60ede46a95fadc9fc5d94d209c166d9b8de253381ea2248862946b9cf534947455c24458cf56683a0ec47a2c65075c694c7c3d6adf9ae5e8ad31ac769f83aa26e312c5b01a9a09404b15b814baa7666b3e03f06a8d6348ab8ccb9b60a4a4faf86f7135df039d955c07bd92e7b8e327ee6c1b40196a28b4446aa5a9b2b9773ab76e3ce21180f09d6c08d277c6771d67e22d84540fa43b38f634cfc46e5b8c33f15a568a77e4914aad9ab8c9f7fea47f7677c01880b3e85d2d0e3fbd6dc6e99e437ddc736f92b5a2ff2927e0b442142f0897d0b8a19ac203633df413feaf8ef50a5f767bedaf20f1c13f3b89d1e8b7bd18d591f9de116ee34f9824e4ead1ae9da2e8caaef88b29516aa942de77a7467b6fb26a666f30648c715a2ee9f946743b543a4428e0dfd06178e7e93ec6f26e003e058bec14a4aa2e3b8de11295a764cab30b313fcc5743b2fb89962ddc5cdc6aa0d2e4a306e77af76a05a598923f628a85df1cc73ad3bc01c4b979bd7cb296590a88b0a41b445d50a08423e4ed80f1763c716b6c457d845dfaa68d12b0d03c55fde8ae6b2b92bc6322943dbe54c706bc8e5fcee70654b26f3bfd877f5f5339ac182d5417bd4c0735d825bf70e85eab8216edda632ae7e22b3e53d078a8b20b5a7e2385337cf92b3c16b023563e11cb5043b704d37eb5ed9e85fcdc95cf7a6eade40803175a008ef653ac6136f16129abae1137c5823400748a81256254d317cfc939e26ea0cef9f6548db42890c48beb0479103ba089e514118038b1b90943d716f7a8d4cda5983a674b83a002d8ac9c65734a28b77b760c8e3803f8781ea9199f797ce729e06bfffe8c29b20bc85227c09cc05219ff2ba38e18051083732f83cbfccc310756450b261d5be183d9fb44ec18529f2cc9848c40119c607676bc4d9015fd4bd2fc918dc8031ec19a05ff362c184043be7fe066019ac5
SIG: c0ea074bf9addee2e3350a969e7c569e3aea1a4188ee5af34cb73f388298653d299b5dbd94163fba209e8f7dc2e2634d3a52a02810a88c6152945bc16bbdfb0c
TST: 993
SK: eac0f06c2c14f37d434bc99897225dd2e3f1ed74aa7442c550339df77d0b7b32
PK: 43e62055db6e1349c94d89029187882020cbcf9d75e03eb656fa0a15b19002d7
MSG: 27b7fd0e71adf194cf5407b6771793060de0fca7ca0ae64835c43187408a704f533d5ea0c83a654387ba7db16ed58ec837226df57c1fe6382c5919e92213f6f18cbb5735d178a476af35d390b7cd2556217c530f3a1f8ab2339c1a5e8d969387efd39414b56bb784dfd5eb89b859e1f403a238eca2a941e6db56ac456b73450698d1455ec1e9b39a1e907d6bc7e6cff424a28eed579af16310115b67f5fcf7f8346b3fa0260c6da2e27755aca570babb3d303cc832460c963bfdd5c1ffb2fc19921929dda2a717fbcbeb2b8525761bd660ce4a0f7685285d7fad6115ab09f8e63f5f773914494e20be1b512d1114cce3f0f68c7d94f54857694f22af4c698d782ce837b0c1722bb7313bb2c41f6d3dd1a02877fb4296d8662a9e8625984dc1fd1a9510eba9d643ac58a886a045cd0e53c056a833f968b35d01320e9cc0b435d3f6bfad26f9eb5754d38ddf6d5c4bf615a7644a23f9826bcc976092d82d81d547000de0081b7a40a93fbddac13f7d99708ccdeeb9405cd634ca0748cad2c1d8f164f5d77a4f364ae488bedcf1f20eb954bc8a278af81432417856a900f8f152921afbe17914229a513bd71ab7e661cde129af93e25094c56118ed1f22db644428b474651fe36be82fa3695c41fc8699667e053743b0a41155c31f1e2679c6e8cb9c9d1f5f4b40a320a9fd9f47da9b94211ba601b22a115210d9f559c4496f01732458f49ac34eb386636c8b6c68c7bbc0078ab6f398a624b8bafb1c622958562d231dffd4db096196bb87479e42ea22acbdcde8deb10e311632f02fca14787fd3140569b9428991543ec6e834e10b149f23c74bb99ac7b3799a2096d22e387a712b6f9011ea34c5be4c468581ac62ce662063252e066a9a3b15c9570d065dc1619929f06bc75a3179468bc8a16e3ddc4fe185ceba0a92a546b8675fc1ade56307150c7e4c844f6aa5f1edbfb54ac632ca2b259c32a33ee2867856c3390a6740364cb0dfb976e53d0cc6c42a106a1c26918c8a6a033b2aa3c7f2e4392e79f8eca5b336bac5061d7698a3bfe7c2c292892554030de6ce7c0d06eefc54906f81e0097fcff27d14b9b7994a7970e1a5f5c6b6405dca22033dff0eae138ad899f6ee68120b8f22744b0269a9a8989b6f7e08affae77bca2168ade24058ae68a7f800e02e7c38391baf565dd40b55fa3ab3c247b9ceb4d967471775e663d6a1c6c7e17350bbd6b9a3eb1e484ac2e7a7a5c84f5083e5ace8730de89c47e8dcf8341e40ba345dbd66bae0f7f076a705b1bb7f470e3edfb2b78e4d6359413d18d33280b454a0dbb881d8606726fa9bea272475e79fea6a54cb4c0619541b4e77c170c8616874b954beb8d105b86bd1917e25cfba9267187ee2038b3f0078f4c318b587cf44
SIG: 45f2803afeb0fc44d3aa965b12659bf502e47295706184b2a1c6f16d050613f596a2001394e00e2a44c46cf6505d5cf5b8ab8412f07eda951a15005e338f3c0e
TST: 994
SK: e608d5de9797907db6d98e0345d5caf2ad33e0eddebf18b81d61e8373ecfb499
PK: 60e0c16ada586e3646912a5f2bb318fbc3d50b57d36fabb637696f9d8d4dc761
MSG: e610fa7d8385c09c78989ed5ef7a230547f013cb7e8ddf31749ffc31cee10ab3efaca3f14ea194510f0985a818ef8b040e10c3a5114de1ac080f14c3d65d3c244f9242f75492cabae800fcfc9bc275ea1f27728c920c258fe7aa73948060299cb87835792edcc072150b73cefeb0d51562e53b46810e27a4d7f6abd32e959f7d731dde01d94bc41ed835efcd42c922437037a87dd366ffad2eecab6abaeb4fcf07392b3ab40cfaefeaa4266bc537671693c9093dabe8a0538cafd12c639a04bd2ba80ce0f29adbfc66bd4637ca0543a53b0e371d0e2e470d31ba360642a45ab4cfe3e790f587f6c5a5583fd15b18997838a200921c1c399c0b16278b7dd6d3aaab6f325b16afdf761a1bbf867de2bdd48615f15b526770ed20d79f0f30714beeeda58f52a3cc0c5a618315e522b9ebe7cd99b65ed532a62e0f0df72764d6ec6d6d1ba40ef40e05426360795d6dd85bb39f7321d3fb06275de096aae4a2fa2293f31b33f4ad4d7c251ac13e8e15c2bfb1f98f4962c54b6ce033b08aa626f2905d463f55b71cbdadecdb3e0b365dae07b170301983aeb83b1e9f2f28cf65419fd6b0a1a9c26cb54b5949f4bc01a98681844b43034c372a453d38f0473d0ddc709d9f49c8753a75b856c7e9775517df574a09a3953bde5daedf8e4a8da9d773a215120e269fa1861133cd4ceaeb91d5cca2606325458e50cb966d14055b22447eb65dc10118da0831df28c3b4ee8b11f0732f1521bb9482b11f5a86b22f18e83dd1d967d3944285e5d63a5a989817ab2418bc7ed891a373846747a12b527c2f44ee0197b946c67e67fa4aa1c29f3379d46fe07d3aab83da17f9d76bedd38436a055e34ca1d3af5a8754d38c17b9ba4e6419cbab515f431a2595954e428c2670fae3bed62b4596179cb59e21108708d071bcf9c621c6dff03d3cdc9202029454013b9d133847f26544811c0169770fdc6fe5638bfd7a720d8b38f7e30a7e6879060b5f28c8ab17b00200713207e8637bff4844d842d9ca788391340198a3fe0172dfa74de1e55adefbc2e9bc7e885476d1b9c055813408a47528434355bf03fdd4e27d8b3461b0fb66ab3e15a879a184457e9ed9ea6c51b663b31edc8c4a3cd454f69d9ce518d1b87888ee3d9dd5416e43e114ac05721352dffc2ca88597377bbc414009b0c2fd369be5ba35a6dce3478b6c11b33c0a33918b6ee5ac4cd4c2f1ca6bd190a000a838da38f53077560335596d1358937793963810a79a21b8d46140e768898dcda88a0faf8ddd0d633847aaea0e030be6455b41e3ede1e2873730eb8481acaa7a519cf9195847a86afa57f9071d44f4af4ca0d343c90c0d22d946146585f00ef3aef57f0f9e55e818c0128ae255dbc3116cf0fe02166d54859decbfdccc
SIG: 0d8f095e42a2730a3c7bedf42d5c83398b5c0ee9c77c5a61d982291396a9182a0802a37f324bc4fb5d4aa4ed60444b66144bacbc865105d7690f140650691d03
TST: 995
SK: 0e86872c78620f10cb6dfc463d2c2872c4da660748c9cda01ab1456958afba7f
PK: de4989989269cabd8f4f409cf1a4d974038b275502273557f312d5553fab93c3
MSG: a900f3e9c643a5649b076fb69c3b2ac084d52ccbafcdca5a9db1daa70500de9933d23d153f74954e1bd5f57b899fe8a4b134c195412b49833b6e5095a6554eaa6d844b11f1584c85055b87f41c999669046c71aeb5c0453fd6a3c437f815f068987c3868cc07aa2af65819046c307bafb7530de84f7130aea78ef005d5fff52f8deaf1d5e9c326d3217fc55b94f628aa104f6a24a395e62d1b62bd9c0d82436319c5d73e5765435f3ba856a4734fd60ae617f7f0c3ba5722a73366c88a6dfeca85c444639f441f2c55fdc464ecb299eee36d8eae063bb94bb2439da04fa5ebc5092338a5035e480f0834aeee8d711f28c46dc960de1be9df307c18c5c178b26296dc567f15bf60863a36710867e92fd51048865674c2af0c53b2e7a248ae5bd09a49aa030618495f82480c420ae106889bec006278b92272075709fec95487cfb10061e6722b93eebfc0bc587bf7ba5f6692b074f55a98d5c302760b1bf1d09f7e8668479ca6f01eeda2fdaf584ac2058fbf7cf3100d06b8091bfeab51c0c0b1d4ee3a8257f69b1617604fce953bb5f7f271c6a1880ea1b3f66267e2439f34580628917877c66ec0fed76e44e8bb2b91a8806df4baca6cc92889b8805070c9a617f807157530751cc17c47b09eeba94d22b4e547c370ce7a496fcaa3412affffb8c9b4de89b9f121aaec5f544b0c725ec5ee9d4b3476adc9d050edb0fdbaf02ca9e38af15f515015a267292ec9aa5444ed1decd9cd9e1ead6487a0ccef995b1c600a036935838660acab276d8b0e5b07d9f36353214bf80f941ac88cf40a08af917926234112eccdaa162dc99de3e25baff65bb01e49898986332bdc2d705d5aea40f9bc4fbb2806894496038da236e9dc29600c9cedeac3b616cc56d89ec2fa67389666c6c4fe233b639105023e101b874a6330fe573f80ace55d037cc612e6dfd5a6e686f9a83054fc46e15bb6da453d810cf138a178bf039d1e181614ff40cbe6bb3b473663752ea8025ff7f739ee4b67110f968089b2473cd044d48b009d0677f791f54e2df6afdc3acb9e99dd6958a450c0e1b6dd5e97a2cc46298b4f48ac6adaf013d75b2c42072d2ee13f733687ee83c3f70c4fdd9720fd1798c662fef3ba012bedd445c4729f2130484fe77ac1b4c4ddeb81faf60f76e3bd7d21a9a6c57a69a9cd9cc203fc63b59ee84b8915b3c18a5954e227c86ebbb7d4c4c1a08d0c5e467c68a06970751ef584bdd611e1dd1b48900ab354b99cec6e1df3bd4146ea0755350dc11c3a3f600d470a74f475e4feedaf0865276fa8a97713471d0ca9955c713588339dee79656e567e6ab1dbf9830703817ae620929a0684a5caf20fef81a8ee897be7e505ade6496b9aef0272bd8f350860233b338c2e36d3138db69538
SIG: 2037e97741c3e6409c66fc6782aab389c5d778097ac778999e8576e49ef4f6a0c7730bd9e093dd3c0ae7ec76203380da657147d33a8d9dd65ed00cf76224d601
TST: 996
SK: 520354d85a87d7c22ca6f784714410ec98bf6a65f803ef9379bdc804359b2349
PK: d8511ceac2fd661acbffb01ba2741cad889934de6392961bdec6fa46123b7f0f
MSG: a1d4ad486ebb7c1a0acb8f117013e8e4746789c6244a56c9edfbf1ef37ac1309aaf51c9375fc12cacd6897a4479545f2bf390ab7c0c0e5c592f5506e9938378a11b636bf857029b968547aa506c4a0829a15fd3995fead4f860fd7c623c63e8695436eae55816414778347092f5f4d422bb1b5e5a06966241efec14f1e4fca06639114718c30ebcadd4c6d8abe7fe93b25d17173533954188b1ab03fcb7792cb635ce36e9bdbdde7a561c5f66920d910cb269c8c1c3f593265090072c48932e692a9c738c704897489a715c2b394d5a86f7036a4cac5dcb5b85cfa162156e0bc6bfe02fb4c38608cfb23c92b8b6a3cb46e487d60e0dc97aa2e33e3dada925e4e6612cc5af125e5aca45817a2fd6c3ff10b18938b44bd4dd20d7fccf7f26b40a66f48aaffc9a541e6d37138fc55469868e2d10365eff37fac360fab3dc55437ac2d8fea7474405fb3630f7963d2d45958f909d14830286ff152aa752f510ce980bd5754e3fa32c69924dd95d5c152a737a8fadcfd0a4560e0b114f8e8aaa618d438b9877111da1740ef817c441939ecec799ba16b1b171ca9b649b7d78fa052d1497a507688bede4900abc53a9648da5917035ceffe0da21c25c09b06d6185bdda2d778f7ede6153e3eaff495c9796d4d166d2d2ea418e4a4aa6e678faf0696e752a09e02eaade763070e088e9964919ff4aa4c82f8629a3d5c797c2a64594d206835da0bfa43ccd9ddfcdb6aac4d486e03c84122375939a5270bc1519e0707e51c3f46f1e5c566b33a245fa0c202838472363de9f0edde2e791d82293095f750bff545e6c34739dcc54db0a36ae2e2aa39b07cb4f6a9646240d2d31488f67815b29545d220be929e3339f8281a937e05a8c5c3887e06048ea7b18a48f8d91b1e3af5cab5ceda0ebd71bf54edec203d37165e4c9f9f80461cd29fcd99ddea439693941b5d53ff94379cf642571dd559a11f8f383d943f2255cf715800af776b1045bf19a9c9bb095155dfb646b65f4a280f2a97ef927ddabe24a2f971a8170dd42a089276825cb9148c015aae1e9dadf22c10e7548c59bf6b868b20e86c83a9e7343aec2754ee6225f9fdceaf8e51c40e955bda49c35ded38fa8bcc1e6c8fc9c2412e9104c5c2368b1f9923e010fa2ede911d42b139f4007e3426922ffb6158eca97b47cfc997853512bb9d4ca2f017c2c263dc199f3bf1eb4f1508ef828b0e00db21002736a7f22ec91298194583139ad75f58e21b518daa49a4076c6375faa60891a69e52a656699d8034a7ab7fcbe42175491441fe61b1783e837857522215a5fac5590bed2e9d206606096d3be8ee92873bfc30cab15ce9f9910d01a117f89926cc3afa8d104f799ff38098de28b8ff0f038725c2903b24c1429cea4925249d8781
SIG: 754e60d3f6f4ab4f5d0ddbb001532009166388487f780b76f60bd0bc9fefabfaab6be2ae7869573a64796ef2846e85e5cdae52db1044fefa796bacf48b968b0d
TST: 997
SK: 061bcf1aa6fd989897b322e591ccef5454ef4a5adb1a4800f32611cff2b5bc78
PK: 73c80b734bfc9417d576890c20166da5c7fabd613f75474f7649732e00295be2
MSG: d63bb9208c1f4c7d43326cf35fa5d83933151804ab891d49b0bdaf429e4c39a321428e0d90aa00318b97e08c7024c912cf388879f3cf974bb253a1e7a4c8eec193bf4c14af6fb9794df0d497850edb04d574c97ed76c702139968401b40eb54394ef4cfaa7e5d3cd943af12192538ddee593c2a24a267afa1371fd77feee2071f4369fbef87976e7ebd81d1e5b31d6e09e02d830357d36bff8596703e4146d0827bec9c0f87b26f31195c96c93b6d8c46767ec1bc6de39f0008a41ff875da050a3f865ab92cbf29c38a280f3bf69f68e92b5f430cdee3501981d0b3d189096e0aeacd64c33102421348812158bb61e51ae936592b2f8f1b910949ef3723258a9b44e4e1bdadf1ae2cfc18e37d2ed0dd1734404b8baa5f393cd56069ecebf7edd7c06cf6c8aa3e8e12fbf946d7b32d8453b6fbb6535526c8fb8fc1d5815560bb31b995df2adbd836add929a56fdd93a1747d93a40c05e129eb6f8583c2921cc9dbdda4225e176db386a02ec40af1032c9b62e95147025f4ac8dd58433b64ac073150c69b9c4154dcbb00344f308113cd9199ccfb5075801c705b8fc43b7c8bc167365e46293d06c4f4835c64ee5d5383f6890ca35a80af917748162df2518ab1468f153629899406cde66ce07fa7d2993dabe0c60089c91892488f3bcaaec408a0cd08c9aa98e0937e02c41ad52d241a99833e3b83f7d3f1b078c31d45c34fa0175abbd0f322b8fd2dc83491da292ad00762e3e577b9eee0aae08729070ac25e33bc94525bc0d2ab59704efec5c0148421a47928d34b1e45ce721ee6447fb082ac400b3e6846d204f7f9db6f0a32b2a69738b3ee9ddbb0dbd7e0f041d7ea53a5d647fb50b39ae24d78c8b07cfc4e052711f0d4639e721d5c36f31b588866712b757108a40cc7abbb9913083303aae05a0f1af0ec6878441a25cf8729aba42a3a94ce9b73888a0f5c9e40c9fc45410f0681fa7f90898562ccb4bbc55f0ab1fe9c70ea66026dda8d7090f7b38edb5aec1557b1166987cd41a7059cdee609b74d8fe06b7059b7724bff53007f7e110462f06ad14d07ee1b4d69ac823bcf576d2fa9e2e8ed7f3198040d471296063137c981adbf364cb20f0a1ad2054472f7cee2527f99809615d2e4b734b06f35deecbd62619663dde81d6e23528b0c97132af0a23bad63d9c08142a26e2743f8618ecfe723b19ffdd0b19abd9a3f4fe210b1e71acdfe38abebe23f7fdef66381cbc75f307e5577235b02e4cd9cfaa15030868ed1453da58f783b7352b04656844c042441efe6a3b4f8fec8f7de80744540c4fc7a107f4e1bfcbd99da25b9746095ddf0125d56da7e7f8603f04d359a088b4c044f936ccb7d8f89ed53cc991a3497ca952094ff3c33046f2609d07b29b633981369cb2f0eecd
SIG: 5adaa94330a0353712a34dbe973b7518f9a2c713f8aad100251b086ae8de26f6d2b6ccf0528cc5dedca318df19cc7e45deae281e1324b96e32fef45aaf60b10c
TST: 998
SK: 2e19cd442f22a4a99dffc55e7bf625f89d1344b563f6785313a7eee973b4aa36
PK: ee3da76a8fcf403a2958d4551da0a72b2e738522b2e6b20fba6aa26b32307357
MSG: 1bfc5c6aa6a5354fbb861469796348ac6319124da3f10d20d50bbdc7159d41b5abb136c7996a773797122b525e8e2dca1954f6391707301d90f2101b46c7b086efa15877cadcd05812db34b996cb4f531abcd1e98db08a5cf1368e8f4b1109142e9562bd0085ffae5e660f59c930793ebdb6e80b0a2f4f3f59bf9d395c48d26e0a72a60f9d1ff87fd2d7a3f5383aa902adededebc6cd1befd038336162749d91a957ca2e3dd47091c5593113da87c3d66a02c80a6eddb535c48ca1f34a97fd1c95ebc2e570fc8fafe6e5d6546d1f3a9ba8daac334cf47bf117e1280d0ebdf14b0fcdbb43b8d248cc6b61320fdb0449ed5f5de8bab121af0d8554956e6a12016b42677b44367892c3b20afcc2cb9cfb5b100a95b51e8b07da9f51415f4cd7781a313765e20db27f2343e0f719ecea9af026956f3387e9ea7ed0a293759b4a262202807b41309fb80f50185db6a5f8bdca178841bec06addc7610df76017b514bc4142f26a36bf5bacecb012fa41710dd849bef7a7e451432836fe9b3265fd5b59ee40b04dad85cf48f891465a842cd4500a1024eefdf0f554f0ca17ec9f7b715256a9b9dbe27966386d8ac37d3c515896de0f7cdf7cf5b320ff7a8ef6b34ba820aba9066dd253c5b7763777f94b2d6ad8c710221e1137535dff8a1b7565ec81bd8ddeb502e3d58ff8f1fe6e86b8dc15a3aaec688bbbecd4688281db0f818de0f7261ba9cc58c8bc0d02e06632efe7287ad7a84331a824d9287344efaaa74f1fc576d0269430f856a8565265b9d6ef71fe134d2510ab06b60bf3c153b57ecfd2e6342403fe678b5886b6b734b7d3690662b6c8c6f6e250e5af6a8183166ddcd0a17f0cddc8636ef1a68498be50b6599539d46b4cea97130e08f94ca53e884644eda75d23cd2c038a5f17b591e21369378cd3fb5762d1a7c3e66a11ae6e91cbae616ad055e39dc41e154f4fced7b2696d9dc67380bb8eef474e9aa83cec47fafafb941d626564b2075bcc0856da8d6e1b0b8f18baf7513bbd14e491ed517968c4f7241af25098ee8df130b7a34d59736d7836d323fe3f43f508cdcb755895f59a00c804ed164cc33992f3aee962ae9e990b74272eb987b12d90b27314d57400e737d1343e970985c4271060876abcd7049e7c9fe244ff3ef98560995b7482d31bc7c09d9969f7cd41f4e4e252750dc16ccdb29b985314a0b6e749c95f9bd2838d5ac49ee031fd079bec3028dd9dd07db6fa622ad621b3b1e127e8fca37bd146e3cf703e911701b7a16c2d30369c94648ecc03df10d7dd5c0558fa9593425d948727d6860c3a14f811245106616d2a5fa981c6b7f47ec9def65412d132acc6919da4e88597aa9190ca614b218066a0f7b16997ee747c5a09785e50d0a891d95937863d613ceff7
SIG: 28326b5b978e0dbdab5dde703785a667a7ef439d81ea47e066b089d116c25a34bb633f260d55f45bdf6bcda74803d7624b1927cec18eb1992260beefc399d90e
TST: 999
SK: 82109099d1eafeed5a85206046491b34d06dcde33f080960287b10fb23ff9f78
PK: 081cfdf2d758654c41c447e1e6273810f8a738a733afc42294a2b1bbb769efce
MSG: 84f47dd794977a6c1505ac8c05680c5615a2d5b057e39b04f85e3f9ff04960e0e016685a86eebcecf6fbce5fddcdac1a474c8a0d502c40e10f948646fdac6c81f1ffbb177a2a4963b67825903cde65b5dbe0d8941d546cffa2bf8a8ca8d6c6408530a6290f5d0882f1a1672dbf978e10c5c8af5e0a6239f0655ee7fd9e66963077a0e847137397d1f06999dc6f8a945c6003ea4ea7fd58378acb44ed5780eaa367796beea37ddc236999d012d6a716d7915649cc28e58875647e9f5ac0553c0f544df56469c67081d5e30395f3e960e6a52f0833192c548cd57c926b82db48c361bde70333a370083eaaa068dc2ae452d21ef1331aed190bd3e1289a104cf667834377cf7b5a29774807c3f1ea9e7b28831d0f6c4294785867b137b65028c14f932a1ba8e6f9f59624fe0c396843ea19e46fba09142cf9d42497312f360244032f1e00f38dd0de29f963b5ccc1ef12b2cc6204b994af1f3baf196d9e21e8fa4f097320c64404d0b7d5ab38560ca0655364b0b09cd6dc0f0e05b8c9110364f1424a9672b7efdf7e1f378e234550566dbe13b01578b04153e9c37b553e32a4441bc97e2953bec2e41455510f9802ef948dcbf13faddd722ede573627b258d55e83c0895b22919e4be5ce8d819ce6ad843b2dd09df64004c826c1dde7ce6480a271a858a1db169e1494d4469032bcc1ccd89653198b7c073f76a26a2999b5648cbadc1574c78ead8eece83b91e129c437f9eeec04c807459002e66dcca9bfc2caed9e6c0ba23d2355def75665749430ee92c532a695479fec929174f440ecb61a5ae8b2b7e958920558268978f7fb4da1b38b12014f5d61b0fdd7f6136ba4281b41a3a3cd188052b698765b6f05e41e78373ea830469787a37510993d12f93e96c72d72f4461984f691a41c7d3397ddd5a1b39237d1308864d415fc6c22b63f376cedde37f5252b51ec72e5155f3bdb4fcd5412498bd2e0c1f9850b3a85d1dfd25167a3cd771e8e4c9d868c95a7175e3775f6cef17e4e36497ce9e45532bd7f44b2776e40f91a07ca4fa1b95dbe81cf8f49e46b6c82a6ee4347918a7643b0d9a38857212c693eadacfd37a5f1d91558f5454dcdd05935f290e62d7e65006cd549f6553ce741df44d39644001eb479ca69568ad1f23bba099a41a47294db938731c530af1ceb9217d29bc2705613c1a1fe9c208d0b01ba6f4d9b4c7ba8f021df91ea2d578ce083123e83ba4b9c50407f6666fbe61158b0d1b9577772e3eaff8fb429d0f6d2e384126130f21b449fb1dc170db45af505bd3182678a9b5f9fdff65f0413b672c4786340fcf2522ea7f3d8ade8a059529649dbda9ce51ff05a2a2a3d66d2166bf2c9c6772ba0ef4105e68c055e0213d42c1ee123b3c1217843e6ec575d754df3c90a75
SIG: b3987f324bc7e776c0f287fa13ad28741695e2e7bce8d143e29fad5d00994758e225fb802100d23fd6ccafee8e0a95bc479be8c23a11319745765b7cd47e7006
TST: 1000
SK: 65fcbd626d002111334baad4e6a8006e47a1f91397bee6dd6cd7da5a0e0248a4
PK: 20409a146b42c96beab0b42ea7f2c25193119d0df44dc2bf14d11a32fd733615
MSG: e4c0947fc8ca78fa8863f4d044499d036e2e7ef8c17e838f2fac02675b7b5381e5f9abceafd0d8886a929d9d9b49fcb73861b29d1518ac5f83f7f8fc26bd1cebc22d873a9a08231406fb032e4866e5f55c7c0441c519041bb2cc73f9226dd5d07eceb660d6c967db23365574bee8fc10222928767713571a71c93a85278d42299a70599ca99326cc86f6d98daac000fdfa710562f481faa020c72a76e2067d154c235a7a4f29708cc544533bd799ed6363eb3b56aa4a6d0e379bbf07600595c23ab1f3f9f1708e0070261bbbf4bfeaf6d6ced4d7ff722c9cc52d9133ea68d495dc9489c3edf6830231351f65cb5272f5396e2c4a1a5c88661a101892249e23d6ce9fdb6a9abf74272c2f59c3d8fd8743cce461126ca0a8b832b4b218336b1ae14da677ba7f1b2cc5ca3c7158f727a9e1b8fdd9edf5c2187fcb83db862ad0c6b39216de3116919556465100ade0a42bd6ba10d95418b69a3e005e9f104589ea5948b2b51bc7b1a9a0749da8f013781bc05c805bb51e187761ac24c76414f668eb45fb0a5024dfe5a5ca06f0403a02e3b2fef7a2c4bcfb1d075d310d5197e659cd14023faec20e045cabcb86b221a1d4827113ff3267a64debe9939004cabac85e5c7461e7e82a975acfae0b6c516a1c605374cfea7d819044efd6d74654424fd5c90ff2574fcd8e007740d975861d0df5259fe43e43639e36e52895439ba2c27c1e889c93094104fe914921bd6f25d3985ab1f22ca557b0e49afc7375243c521c6d5fafe0381ccea828e88e647fd90976b3fbec19fe9adb113c6404bd352bfc000446d21005b5f950ae07e51c768ca3ff6177b2eac50f10dd2e64610fa8ab5788faeee29d129009d7fe46aa3da6b9d86c73065eb5161fbdbdfac5777c4e75452e6e16ae9fd66bb7d9aaa426bcb7a6915f0ff44a1f8ec71394e9352fdf20e02fafe1e0cefe50744c3194956f928f82533755373838dcc1296a891adf641c7382d69b4f5a43d4af7772a4a1ee879292d7a4f32ac35ee121c6c34ca5f98487a941fcb1e65b44d4456127eedb2fcc1c3f48eff9300981e52ac38b496ab8bbce144a85eb9c07638b31fdaa781744bce17e8d93dcdc60afeda488807617f88d6aa54422fd347ddaddeff37a563dbf19974b2a23be300fbfa6c7fc41f84c6905415269f195990b5b4de12668c71c87b504f41124bf94436f333045631518152c5162a2475c40efb6cbdaaf9af428fed325b3a7d94c17520fd89e00ddf08b22adf661f0acd723b3969dc6434ea6f92ef58e8dfae5b0cc2885ba987ea1d16c39b34ef65023009d6345e48e3691a41f02a77b7fe133ea9de7565f157a2078ae988bbb266d22d5fa91a7b263e98ad2dc0731fe5a29025a0cb436864a5a60db257f1e76b5c608f25cdecc87eae6
SIG: bc78e16ba674e0a7dba57a19094f9733c55d74b9d15f8a44d1bbc0a023f70155de2977111a417eefa8cb30ec12abc8384228167c70982a8206b1ffb72174af01
TST: 1001
SK: b500768a2823915c4a6848d35f6487d43bd766d2ce0945f8a3ccdb8d82a3892b
PK: b8cea215a0124eed27005725d897781ea064dcefb21422c8bd2402c56a10571c
MSG: 0a9fda8b8cfca7a5b05d78116fcee19ab803c1c6010ce11daa8e93a66d12c12e474eb91c2640d97a813d9a830d268868eb2e3770425f10c75840468e669dc7f61d3be2de88ae0e542bc809679113957a14da4eaff549bfde637d7cafdc6aa83994837397f86e4fde86d402fa9aef7f65549a214373e560e6d7a1c2769e0c7d5a0171e7cc00dff36e0429798b53aa621624bda74d6df0bffffbd8fd7bef1a64f36c000782f6ed031af5c2a74a18963598c9ba062392de9602036794b7b5e68c25c93fe7cfad47a7c5b979d476cd513a12bf0307cb1631740042a9fbf3eb0be5170620dafd5f16ed89342c2625d783e74ee0d784bf051943740c88b0bef7bc85e1a6a4a517d492fb737e776699590c93224cd4d9245d4e9371a367c0712f87490f9247c49add9313f277a4d9f26b75aae4ded6a3def85f83fc995910405548af670ed8aaa30524ab829ccb56a5005b58bce868c9e8074f07dd7f3818f299e4e086bed9eab902cf11b398d531b8632e7d523a8f877695f46ccf9ce24e62cab2c7cd0aaee17db52676a4b5058e9c1d7c47bffcb641b0ea2b0944f39a75665a7ef29b7f02a878db823883bdacfb0fbe5dfe5a9bed9fdac7e4142e3eb50d5e840bd0ac0becf4fa97e1fc4827c397a52465d916889954b3701b0fac61159b23092f4685f4788bad35d00da2679ecc54921f1a8647101657ab49477420567aed67c8605930444b5d07927c17eff1f8570cf2af29e719f85ca7849b895549f13dfeca68bbef71e3ce8b6cedd2ff68d32b02caf5951a0b3e6b0bae6a96c02058191f305e090711c46daddcd5aeee769c3a105e9a827bbd195d329231c26238479a9bb0071afb160ef955e874d7a420c56785f44ae0a18c52d8280c5998cf3888feaf89898134bc8d411fc9f6c5768ea7a249729413739e532b643937152cdfb8d2ff87fd48084dd8aeebeaf0f7b10d87b6e4423228c9fc8dc5e3852aa8b8acc545d18f25c55d73da1bb82e3eb376f9ef05b274d7ecb1845d65ca0cd2629f038a2d664d7a69781c84e98de2c209c46efc51162172856649469e673308dcc145eaf783f5cb5b4be7d9fd58ee0974c981a38fea8e31267abfa410e69e46482f5134f3da1ffe381bd69d8d0b78ea909b4af9396dcaff89960a049eda6946616fc27ccf9a9e5ba1a0135764f37719da4d28078185d04d72419c2c70f290d97e1f82b879f71b9e19d504d364cd3ba22cf905250fd37d58e5fe40209f6072a06d8b5ba70196230577877ec46153167a7c7aea270fa1098aba9e3a74acb36a11b09bd07a3b88ea654e268365625b589b2206c710d960f42ea419b7e4e3da4759fcbca50e4bf4cc55cf88f70b3180c805a7045086afa04c6be23223ecae5f82c146d54311d1807c2e4a53f9e0a4482b4e1e
SIG: e3db47a11e10e788925d14b1e28b54c9fcf9b6acc1df8c14f683a5672fd504dd4a475a3393b3ef8bceac2361dbba3530af25c246c3ec4c05899b517f6cd34f0a
TST: 1002
SK: 9eb5c9ef13535f808109f4a43cfad5684f80daf02eed5410ac0b0a09a6082d69
PK: 367eea1ecb4e5eecdf7e471b90bb34f9b7982c8cd66d42555c240b41cd8739db
MSG: 2d7cb05e61dbae26258e3861c639ef0e1d17fc711a00f335ba3c027137e00708d708c1ff457ff2c65112f7dcd7d02f24d56f072158ea1c71832550a58366fd9197296bbe61aa4d00de18a453ef9174fa81968305c41c3455f42d447a9234f06e13bf8bcaa1babb11695fafdc08f7a584b2ea1f61e9389260ce7335a07de72c8911a58a313f1088dcdf5c8d4c456cba2dcb4f2d156b4943b95bd493ea4fe1a82d4e3ea02aa02972400b5ee17842832d59979fc179f843c44b03eb3c302416d0cdaf11c4ca8a66ccbb6997395edf6fca2ea004cf3486971004a42042af8ece005b94461d86dcde212a2eb1be3b914c783e48ac1ad46cacd73e1eb448368322d2678efcb2abff52093db0f259dce5c1e19a512820f235d6aeaf0e1a723c2c650cff1ee3b6b4f4cc989c0b7d6de3cd7e6daa39bb690710df00a7194c17201f0e81be64b6739e1c1e8176b7e12a353427c067c19314db642e5c76266b640eb1cc0c73f84fc0227e5a96060d814071cde2fed944767b7466f9001dfc223685429bc4e5e48f5c13a63a4e0d826133ad920d11772145ad6e13c93897398a8a401f93dbd103005c7dae44387f3e80b793607d05d2d8bc0d0351a3a452b8ce759c1ad48df7b9ba9e4a17df61fdabb9b577b5cec3e9461fbb5e128155a3c9c89f8f6bebb7322a16678e8ecb98953d958310db1b063448c349f36e168fac484cb3c0d4cb2c251bd92ef8e9262b44093d7e650a7d3bed3791fa88100fee6ef0d5e23d1e9a8099cc0335202a4f106c24777e98f81d26efba15c9ad1541e0adbf1d1d76076b0dfd7b7d6c8b82f9c093468cd196672dc5478e91ce701cdd7b68b353c97111f0429760635762f8683ae970564bceba9120517642e8b3a2baaa85c25b54a943766184904c72d929634ec5f0c28473415f12538906c678fca4e682db4879758492537e7850b9bfef3eb9053b43920d810e55be966aec68c9dd3b62ccf57e8178cb5ef6d16d172a56dd924f00f2d3b5e93aaa92b29fb8336d73e29e59d1c47ea6230cda1d5b03bba5dfdb331feb19443f123d2a03ff4f10eca166c2998588f1e584ed194dd6f73c8aca846631904d9fe4a98b367823e46edba2885129879e9277e150f029b8fa7bd11eab9ce1336777c80b56b3a1f0811adbca0f5b4025a5503c8196661aee90006e9c85bbfa4c5a0e902885c8ce51212ee67f0fe0b6afbc8bad453727543b3c68b890ddaba269d25fc1643f54835136a1a25ba18d916cedd6a47fc07adf6fc69fa508949dc10d9dc5e0261b52f3657170384eccd9c80541354b1ce0f6fb5ed3e8d54af0b5bf0a92835125c7d9bc4f092ff380e5e896fbf302552b14d5b61a224d86e301c7a66a66e4e4329aac0a66b156772374dc1c7168d5b561652f8f4387e4f289b6366a
SIG: 429ce1fe846d250849eca7d456f8c59f8675b1f4c13f2be41688dfb8ca2a3b24ae29d5b6bf471157bcb6e2ec9d4a26b038e6ec28584cc23f2a03556dbb37e900
TST: 1003
SK: ef0948e13281f3cf352cbfaf8d89d117768552d5a1548ecbaf37412e97670fac
PK: 58c2457f5a5e3cfbf47119a87f2aff1918f1e67ae6fa9171d3f41eee07a86872
MSG: 7ec47f2f1fe3b70a6d1d82c7cd924b4bf9b2029fc12c52a6e1cc06cf5abfc0a442e7cf145c1542b9b135049665711035e3c29a91d4fdaed6127057a812c22cd75ad1879be1d2c6110e79e987524e4e8f27f16eda90cbd4733f111825b516d1067f81eca5e6948576d5bfedb3277c1abc1e60f374d0701b32ccfd6a5e9c8d1659aaf3d0818613613b7e288d845e9aaaba2e3e9b411d501dffe856fd313e9fcc9e7430b9983f20ab4ebf4eb616bd63e2c57743658995ed0a149ae620a395613719b3ed7ced4588d5915d70a2f0c687680ec34fe3e9f72392e189e13a4749d5ca9fac651b92c084c4066fdf98a869223e4e0c9bec5812b5c1900e6e60d3a188d48a74dfd415b5cad2e91ff76df75089d20a755f260756c8f1382a29f7b93726e731071cd477458c6f2022dfad7d4fc7ab2380541864f6b58774f9ae8e5f077c1a8da073c39853eb2fd477220b45a3d92263dc7e14d3bb2b36fca466c7ef8a247538725f2fce5c7221bc751cde1394604f5931d733360ccd47ce087712958180ad84fae713b543f05eef6abc0661433121ed3b4506a1465025316fb8f9d64535cc4538acd4064dd576b0740e1beb13bceaf155543dc89097ca5ca1cffa0ad65a10bcb759354eab8a42de734af909c2feba380d66409f325d5f17af9ca7f8cb4134fd6a2b6a528d9e60d9612b8e8b4062f8e0fad1e7eeb9cbfef6e9738ec7973e1cb2ba2327deca4ea46568f31e12f730e247c1d07029fd4422b298ff2398023b4120a3a425ffb652880c19ea69f3639e0f6df4f00876cc4528e267e81d5943199d0feb6cb4e1baf404bb6f8b39b12dbce9fdc35dc158066e9975ae5bd3b55f2a41a791baf3e8351ec604944790a22c933c80b1590ba197a4706f7f5128682edcd74dd78d435e787c2b76a57b3f4e7d7be2efd26da5f9a829119b01508b7072c7699ce52bb578cc5b1b93661b5172fb84daf1ba364d2cbd80e2c99bca9caea873cc0a1629eac384e9b206842a6e6183387591b4aa34a95fd89b49d8d15d91e21940e17dcaf1eff8a0a47a0d7a95daead82aa3df8204a0cd206924ae510fec8a9c4e8d85d466fdb4dd365dc99336b22ce0b956b5ee0017f29d25ee66fbdcecb0d996ffb97c8defde40a9ff9993193ca8f1685067c19c526e0efed236f8edb8def6c2a03e21952c8612d624e6886a311ffb9e2f15da44abe180d26a14b15f63561e097a730ecabb792c7c235fdd360f571f27ef68677a7d63beb4975982cb199a560f816ee12989445f7f75b83eb278d62825947d84099af2a6ff2eadbbf589b5eb2f72ed114c73151153ae0022bc9564d15c2d5cdbbaabbef638f03095f53eebac9683409ad3060cfb7c7037b9b0befe069c92a02be953388e9ea45d36ddf4f5a8389432ccf504c50808b07f69
SIG: cc12f69db63a678ec477a605a505c57dc2b810ef85e3e34519cb25c51063aa66355d3f1e2974695866edf6f17171ce37842fbab5075fc895d18ed743c546080c
TST: 1004
SK: 903f3b5399892e29ccfafbafbd7cc4533c154a625682406c89bf894c889e43f4
PK: 8fa5ff5b6b26bd67df864046429df124b523005dd89444275c8ab7ebddb6f4db
MSG: a2c11b5fb884a822fae64da8dcb4452cfd7a04ca6d7a5abc8d8271e93f93449e1feb8e02975f496b9034400d3599ab97aa3997dad1c9ffab5b9f8df4aaa5b840d90d862fff7ff0cf73a60c66150009e01c937bd1af6807b5ba2ef612ee13d6def40bb09c46811a2d4e468e038b323055f9dfbd01829ae2f1a535ef0295ca1ed176e46de996cc87bace45356233211835b6f4757c99bd527e766a5f0b127c8cff8e6d66f8bab86d0000452cd7f67be557788513ec0709b537b007b42016e7a89683469bd8ff8d21eb10c14917d47f2dc4f826324f7c01b24f8dcff04aa6d85095d9ab154ba5c3bd919c9d728dbdc990d19ceb237b452907bdbe21f9f08cddae5be479276709b8ae73f8974c4b113841ad535d6ff6223eea47d185c8e8a65fdee2c2d45800c17cb556eafd676647d9968e55ca9c59232b9770ad10f955fcb5858edf0b7483adc1817c0f8d02240482caa76f43c6d2e96a4ff9591cd7b878ea619ea56d1b588631e7633c5ecb2ba6998398cb06e3cf75aeb3e08dab19632d454ff7dc0e2a41f09737e8ee823d1b9e24dda84a2ce0313cb9fce31cb663c55c05645e63401756e8ad38f5174c02a663d815ad64422ff7727d4fda16e48d4bf8f6602e7260da62330e6878c34764e129afbd552208f6bed4f7cee9b671f488388815d74b4951b8682ce76cfe31e938c470b8f7a45fd63a9691f426a75c58ed3dbce3ae8fd9d10a8352e47cc1b12c9192ac8626d1b384b77a18b986e71a998646c137992b67c4817e346345faf50a2659fdc5cad5c719648efee3847c0ff6bd7095c28b4c5195967c90cf84e1ef68a1ada01f6274ede363fb82e0b549a870245d608cae8234f6d84abeb61b718466093620d85c584ab01eeda091ee8aff1cf67a4675679a1f4003e66aaf43871b88ecda6a16dc5acb05395f2da9df70d3bdb61438e1c3d40981e034627d026ee1d2e79f65cbb8189fcbb3cc8b5c2e7e796b5d2889411d5641fb869c7b0a589c43254f8c5438aaf5ac423832f018d79a51b96f242e2de0c851cc5fc2b206bca4b5be836125aca144bbc38c8c638be0d3bbe025a1be8b3d03d5929baa649c3544a32a915e926a38791b134a971bc52d1b6ca625efb7c2f3bb47ab51d43c8e374d16cda882204b71cafe9093cb6078ef2bdfad59edeaf36d0c1a4dc425b9e718c45185225a9c3084b782bfe163492f8e8482ec9aa073f6901ff3d1117ce917e19122fa67650d858f8f82b37669723c226d721697e7ae3359f5a6b02424ee8794cbeaa641edbbf753b103a5fe158be0ba60d8a212d42f8c5c2af254bf1b9c80df6f1cf09d70793cae1abb4627b1780f1bce7f617ee50f6bd4b083b2fc7cd844afb72380d5cb6b255bf47ea71cad6c6c4df021f81b548f432c18ac366c6aecd03b6c8ce2
SIG: 495a8f991941c629bd641a67471ab860bfd39b72f23355f7270909d5307c77b1b94bae3ed19450780e9085305f31b1e1683facf0d1fc8840aec77df67aeab302
TST: 1005
SK: ee81e0fb052e23ad759de6aa9838de98e36d4820dc0e1b7b3ef1141ab9de3340
PK: 98f3c9880794de64fa269bdf336095e0e01b1a3b375f965b93700bbdf4b96869
MSG: 28d99e9518b88283c220e76de205d7b6162359b1dfec1fbaab98ec0ef1df8da40b6b7a775e9728450aeb2351fe5c16afda3aec0d71049da4cb7d4c63713a2410abb022f81611cc064587c8047d4383c00c3c562e9ceea35775095391b5f3dda0e373c4a77ff618a28ef68787ebfc3ebcccc5d1ce32ddf43bfce57203da76a8664b3c616a8869282db0b72811b5fd5a2a03a4ff66724b0489ea2e1073d781c3f189115d79ba20a46d1dfaf5b1a5847b2a2e31b2808737569e60b57231e6a99af26f58afeb15770810474812fe4afacf884506b8c314bc6751bb42b4bd6e87d2e5de70fec5f0014c4257b13472a3b0111a7a8cf83b1dc0cf962022cd44468a3ab1f0016b70cafb1d0246acd7053937c9ac40207cf13b50dd15e2a2e15f50a05bca2f28e770262371dacee02e25b2a59658ed90c0600fa265b7de3d44f8ef0721bf39ec4d4eca5888527b778067b1d659c00514c8d7056273a294cbafe45090d069bbd09f92f461e648f3e682882c71576e974debb0cb7e0e8316406660150dabb58e76246614a291c12ce9e0346c02774d4d09cecc23696712fee250c0bb5df7a2a4c43a5563331bcbbf84be3f2eeb0654532e85ec597b53b32f3954ccaf0cd426def91ec4b208416948af27de04d832705897a04c5e24a2e88b20040fd4eca3089fdb918a92e35c4d31da26850b9dd34118c74449a855ff4bc9fff0d1447839654b00417999fa4eb89102133cd320409153584957c10489db4b7244c95907988e83dc821271dc1ab643d6992d0fd820492ae642e24d19a179fa75d9363b321662606fd94a47fdb2e68d3f30c04673f809de0144945ea4d4183d48f175079eed50323c6b192e020e162a3503aa582fb08b403624a23e357eeda08d904386f358c36c64d314c77cd9d4d23d581ee53d81ff97ada019cfcf04eb9dcc1de9b74c3db6b811578bd4f219c5ca48ef4c826b09e6c96d031f65dd48b6e73d0c100586b21df0293a03d2ed7e5009ad025340c21d09060691f5cd8af2ab12f9b860ee87815e1a9f400c2a6f634ea8f9b3425a08d10b3c815367388f4d1be356318ecf9035d0ee975affa859caac28ebccd0599bb2f6f3523661bd178fc9e4cac378bb9dd4716bb06923fd2bbd56c959c42b95d50193f8bf299fcca3b2eea94ec5f98583924c080416e28b54fe57658458b055ce4de8a75fc82715cae91d375cf69281378051bb61fdd7bb0068f63efa6d6e83d8fd4257af80970f4a9e6924b2de0ad966dffe6fa4a113b0e772f1768785b3b42049f76c48ad80f2c67fb0f91a5fc4107912520d8d683c062c3a222bcda7e710bacd478ee88367b6a059a452fd26f114a5acbd6979ba019f7da68ac04a193026bc1c27e4837b1de29cce090e3380d5051a586409e628e3145665bb1d84ecd8
SIG: f0d873be15cf454c7434deab71de25cfe99e81a48d2dce6a35d1633714df0f8b4029e0582511efc4d06892f672850246bcf070c46fadc2faab44dc435045de00
TST: 1006
SK: 69d01d829113081cbf5d0c6ef77b21775c8d9b680000056f03c75a7d0a0587d2
PK: ee8469dd61cf5de400da7d7a479a4418e6772e69ff5330ce5ca77859fe271755
MSG: 0b9e110f29d19816a17b2c75478f13cee953811a1983014cb7eb0f75526912044c3ea6829780e657f817c5597d4661080d9034c9778722418f2c3aeecaef6b690c5bd3b593701086988e4340aec34e0172758eb24087d03a8f76e7cbca53aaafc4d2155c7532ab54be48872653066fa1fdd54acfe9daaeca356c290e6be63355b6d9fc52eb5e4fccbbc6083507132de485bfae9f42e19712232b716402c23fea74efa69d73c8c2e3a8662b8b65b0fd007741013e1f6e3cfe4345d5c830682fe60021d708e10a9e9f4052ff7a6abf28acb1d6b5fb038eed3f72513c355bbfd5c2274fa85fc4f446974b2d1bc036507a1eb5fcf55dbd44210e538274de808b900bf1c0fcc0241270db8dbdcd88349d67224f087e5f07f699b0bae68b2ebc9a4e27c70d3ac7d996fa7d4dabd568378e3f93905b1c89c652d384c16c2bcb1c9844c38f71bb13e0c6a2ea95b612e390c5f86d248ea531f2ec6f639a402dfaccf37217005344030745d1f1e520cc195dafdd7f295f377b8d614716703836219bb7b09fea7aae9ac33e42dcab65cc6142fcd8ce15e97717fdb33e9538c44f6cd9c1c65db62751f552f870f10142c96f9df1855abb39e42706a563ab154511fdce687c9576f9edc3b4ba55346ce66802fffef4b1b5e12015ce8b57de5458caa0daf341968128584288c2f27cbfb76eab286bac5f66aad0049e0ca60a9014e17901c4130e83ceaeb4c2713e971a235eff995a813ae4ea64a583ffdefdac82ac76eaf4d47c4ac8250fcbafd6b88faeb48015f5b42b5334a50b31d4502ea491da90dce93c08fd56f5c58eedb379166a23762be5e4adeaa6f4ae1c24e0cac4ddca0383458560cdc48b8cd1f42a3ba2f6ffb6077909fcb294ad1ef4a44c22ec4b3987ddbeef325b98ced56815ea7d5fccf5afdfe98e0e6d920f7ada2eb5c91624c76cbba2993a9c7a55021d127a667b39e235df4f81dee7dd142898778dbd92135b70b3acf59f6c29a2c9d4a7006ef11a918b3a2906264a15d6b529308cbc89f85601fc1ea1314d67f7566cf109165c7f92de1a18d70debe024349db3560a6e527e2ac3e06789468704e6b8f1871f16bae9827392b418f1086cc497086ced14b1249d6d8794f23bb8779d418648f2155656a6fda7440c56284d9b2188fa7d1736bccc9cff0be5b1e1f551ff8137ff5966ed9d0f7f01c3dff298e9102ffbd324bfca5ffe0968e66f9d82f487d303934f27f78b28378eb72c38272962a5f735d7392e5d333fd86de167269c17a165b92d31a4880a41e136f718960a919b3d7c4e74cbd73c73f921be513f739affb2e41f80426bb8cfb4564b98fc4de53255ce3f98b4d22ae6fce9190b55bf2c93861c1dcac101b5e16cf09991c5defa33f8d51056d934bb4b477b6520d4c7ae22ea7fb3109de7f4
SIG: 408cefcf01417e2dc6a8a18284e411657f039250c31278db2819f9eaea4293fbf6831a2801fc1ea6871657b841e173f451b0d575a9379e35857e8c7297fa1404
TST: 1007
SK: 4b8ed29731f104795e97dee7c8b401a02afaa9a795e613353d2b95001765027a
PK: f22298210b09fd617fc8b35074ca1801e6075dc92a8f50344b80e85405a038f5
MSG: cbb5f13a0ef2837b805d3b785109f9f2e0d0a017bfe7692d91ec23ddab7817330bef247fd91ab2c77dd4412519cbd38475ce0cb39b1480092bc738d4152b8a6d55248e3b9f32cdcd15ec5d059ec3c8847554ee47005394974d8eb23592d17f5a396e3c19f8e898370679fef5318c4dd299c6217d6abcc9b61a5b2d0cfef695d170ca20a83d6fd3c666c8fd1c10ad970e2fa6af10ff0ed0cbfe752246d03f3a3c6032dbb319bcfdac4dafc50bc3e6bf595f491dec388b3441b8cee0df91f55cc7807d07f8f541ed7322ffc39d18f89560e4123aec1d77969cf1877786f4cf94b1770b1090655e8c72eecea4572e46f580f963966db2a1085eeabc57bf4a84724b9c8599a433abf58bca804091d3d5e6e5048ec27bf8129b670cc2c88d9cac471859f469b918f3f6d70f7d6663501ffbefef026d79ea70927ccf6075ee5105423321e11aee9ad16f987efbdd00b62aff698e521adf9203b15e9f0f3ad07dcad9ddccaae9b490247f12c311dee6b73b8f9124fdce1299b47fb1914cee7e3a07814e312c3ce56927672c51b3185980cde57f3a759b50bcfc4cb0753b954d97135deb2a0532e98b66f39a7c08cf4d548539e2eb9f422f6649658893a7c3c25a4fc901f8c398b8c72733911a0072ed6bd2f4189389ae10a814f648d71f69c37e8295784428183b93c8013b964a9fef86b48f489316bc222e96b3bd15ff149b96820329551c15e0d095d1569b1e2131c78751565c3041f29785395b97151317f62e3582e407b1649e60d03a8599120a302a4695fa862b4120f94d22ecae72398d2094d108ad2dbc1b959735902142aa5fe6e7996559f6f601448aea02f356f8dcdd144340eb3619f9865bf7672aea326c4e93c99f0ed1f9ed866be15d3af2675f6dd6e296602ca373a815b0be46bc2a3fbba06b8805c731fe08007daa06050961b24d14693a72898ccfb8b8fedc60a4eef8ff79b6dd7592591833b576ef48294e5e0485942e57c119602eddf88b1faea517f2fc2e3d14d246a52cbd71a108c66b6cc4f2d45804a282ecedb1b0ad3dc3b4880ab2ff78b8ddde48f7466c14fed349e95b5053abf1bf0991126031d97547d143c2ae164928b61c0708af8ca3e4f55154d13d75e97db4ba3e69d36e9b37082368c2f721bd3f95126a1e004eb2a1bf268343ae21d2995044a2cadd67ffac9e1538175b3cc44db5d26f1d5cc89ca0e1c1ee8537a8a91d324c2e02e18b9fb9730d6dda55f72d843389693ebfcba7fbe1a0bcffb9aa284f4ae66f44a8b89302983b22736d0c72d6a044e4291624243a4e0ce65d5e5346d67fed3760ddb0c510b50ff3eef0a18a267de730476dd82dff7072cba0984825a004dd4bcd8c37fdaf1f683d1d9380e135a95d24b89fad0be941c548251bec90ccae015bc0567da84b371e50
SIG: 2345886686eb39b5199caaa9615bc6b4896f076e8bd736c0038a6517f9c2b167e759f37372268a697e9b78605f2ed94725f6905a7900153fc9e8beed31ffae05
TST: 1008
SK: 080d7f76182ee6bcea894b1e0060558b3b125a3499df3973b8dd6693408ee469
PK: 4124713d7c2df50f93055730d1b281daec3028cf2c1e4858d128707a23d6deb0
MSG: ab0a6de2351b9a8498f68272d9a0a7a057365d34efa0fd34cc3bf862e49cdc302b2bd5a30d601a130ec4032f541ae6cb7ba97f84183d2d2581287ca701d7d7a9aba110ce58b946ac0824305df7929f3dd7fc9c8732238637e2b181d6e116c7f66e3226aae3ced1610262da1a0a4aa50a1b9443ec828329e4734d28fc25ab9c1de9b8987e5dc0c8131916c5f18928704a71e80622b1492bf2fec5d4b6dbe415c8af2ce3ef109b34dd5e64d56846f085935a4a5d1073497fb3fb8fb77e8f5d5e3fd00c30652e3c5cde40a335d14e5425ffba942885ed17bd36df506924237e75be84da821950b91424fd9f16c1b2c783e90f8cc2ccc7980ce915c7696b06a586730259e6d14588582bab9d2a39f69e98e7f2ae9bc0c2610d7e0457f26a5d66543be1d65b79c4b7c0d8ee73d0c2b67bf50d8082f006f96d119505873193dfdbd432bb1c9ee0d03ee54cf95d20e91f7f3a069b6256f42159cdc1e600a9a1c2f5a8e467d5c2a9dff8730e6be826fb2a1e6448bfc4fcaaaacdaa7662351faadc91f7caa7737dc82ec3d4b21936bca1bd7ce373ad66264af13241167549318cdd78e563827f85eab20e0b42bc554a712c0051a5010dc2f2c7db85acf6549f9d102c903c1be5a05292c30f21ab1b2b8abcbbf104723c63f0ebc554fbee42020ccb14f443478df77c6aa44db9a57f8fd44d97ea099e4774823ebe123fcf5016a66e837b2f65c1845e681ee2a7059fb1290cd0a933129855cc83c87e0b3bb61e44134addd3637850246cdcdaa29f15c41a3d4dd2c1d760062124333124cf091435fdce711f52316368999befa4c80a39b3750e4e386289e4e2855e97b619b0a25799912408b7d58a4dd9819571e901430f6d555529dd630a1867459b8022d0e0add6ab4f12f60baac75979bbff7f6258d28d6760b1ff243c39e4bbd6cf9bea572a9c082d05adcfd4ccf9fa026f2c904b6e782ed709df7748a307cd2dc3a0fc4123df580cbf49e05ceeabc9f39e57b7f300905d8b310091fb953f3def36deb3e8bf372f5916b51597df024ce85cc4c36eabdc580b5cf152994648f1d7f35fed5cd10f6e2949161a3359b3034d450ea6f61cdf1d5af76d40102b60294f4e49078249026d62fe35fdf224928b0c49ba2b5339ebb192c5ab7f05cdb946e37d671a4a5ef2a5827220b4438cbda05736292806648f5bdd52420fa76b84a6addb1263eb0c500e81566d718d5066026da097054a86631016ddfb706a5677d502ef84aa73b5863bc40fdc42cb7321ac5f00e2928fed7b0418596db4b6151dd6bc6e818f0253552bf13741e69680e966c92c293e13c90f7c9999bd1ec6afe3b4affb47340c89859829feb599db3a8c3d33fc8d45fa5381078ae9f75d85c1496f5fb5addf4e4009b764bcc9118e9275dc7219f281d0d1ef7158
SIG: 185fb1b6d86dc4444810cf5ec6fef0abdafa2a6fccb45d11cfb54ba16a6843f280d380471002ae0d71508556c78ed5415e42338c161f2b621e74cba4f6a1d402
TST: 1009
SK: 49846ada7ae684971dd91710799090b37fe5ad561d72a35f2efb405f196ab0ec
PK: 4d370a8194a3045b09b3bdafa27fb9acd59943a54ae14cbaaa2200eb0f3da71b
MSG: ab398d94f928b1d42102a3e513ccd1cb10899011039410a8888bba26df1a0372bdba0ce8d854af51e9330a8daa93c10580906a8ac72d294aeb9566fe1c78ba8471c06c4a8a75113b34893f6276ed813292053b956a465d847d2ece86e2da8a9f0fe3db52a5aac746ef96485ef81f1362b5a42eaaee1fbb0646704471a21bf76367beaa07812b3d32adcdedded7539e3a501b83c05b19a49b520ededc9a78a5fc2d5012f1d4e381844e792ed90b0f57bce375c75a658b2c78c6ff7d9efcd4bfa35c4768cbb195e4823d9bbd835a374fa04ca1eaae9c566d8fd5aa7ca5efe0dfc317fffa409ef1022f1c3b376a935af557083e95287b07a98ac6c1b7bd8bb26b60fa7c4bc91973b201b29922b4b9d03dd6882a0bd3b7d9e5b81ee74c36bec665e4343c8c9ad336da3850c9b2697fe1cce29c378622a33c248f448c88f48df0260143b2a342f1ddee74d3b97ca3e1166b156993dad30c49d810d74048bc6d467652004d7edb65c6dac3a2c5d300b97ee3a10a9e14b69f3cad675972962e1f8ed97547adedc47d1cf3471ef3b22fdbf78e34f31a3bb7669c41bd9292c380bce9a42d84bc27ac928b8bfc3c63d20ccdb478df7ddf421fb1cd905ffc4c04786fd9aef06b8938ab8ef522217b2c04515f61a1c312ea83253f8458c0918fcfe874e6e7fb11275db2a2ec79a2d868303233c1b697952a3bfd3ad0a6f6cdd5e72cc9409f7410a40d5b4536dd46eb1611ae86703671b3a0515a0377bea15654ba0a0d1e4e9602632842f2acd4ef993236e993f2650d59923f24e2cd30932d8bf8aeec644472ba46a07881496c92a0135c675aeb0ce6181088db8f156cfe7435cac6c97da637db4a89f51331da13731e741fccc0355542ce11efa69d0538d3ef127aa68745ed3085d29da90dc583701b6b3a70a3ef3e16a924b33203b92396c4b945f127a7888fa05015c0603007566729237cc0782b30c020d9959547feec9f4d676460bfe0c5c19ceabaee0682db8be69135181ec0fdd9f7a66d50bdc379e4a2c598178f9593946aca6405b177fcade0f86421583ed67eba187222a1e44495b3ae544fdca28e2c14485eab0471aaa803c29a9d8a48926764fca1df51407ad33ec17e941e6e2617237a84309873dc71365587bde4274b5dc327ccb1e1e9c857e042ccca8d8552ba288c978cfa0af99d67cd034060628e23525dbca207679ce29690878448553cd38675bce07bf97b9317dc44468b768b158b0c111d63a572235655c40e16597ca059f40c3d8ac5bd61a487c15313846a704a7811b8bc0cee61e34762b6c1b7cea1c46e6087e9a36f89918a258b3fa77620be10c184c3fc39739024e98278fd65b82cad83699f3ad8c6eccbec8b7b1bd7914d3f6c3d02bf40283b1c1f1e98e308beaebbf894b8f5e91bbbc62535f923
SIG: a5c809d1ca4cfbb3dc70a2a3a1f267c27330420719e3606218a1471cac57cb674b9b42827c5e9a7b25c8139c13dff60bde6c2dbad3a8361197c1fb19d2cd520b
TST: 1010
SK: 83343e37ad091a85eec370701b81a58f9370a4b0423a070d60f92d8d1809844e
PK: 50b68bf726eabca53ac6c90d4eac554703712d22105554f05bf79f9d08fcc493
MSG: c7dadcac5d8795e174b69138912e70ff41e7a725faf385b773ed15098972b30d9b739372d975b480ccfdfc580e2e2ddf5e3c27ee791279ab95e4382b1459dd8d41ae360d4a878846692924feef390c0dbbfa35e4b82d7cbc33ee1581c52bd949385b2ee40263a57da1174bb4acad37cd8ae2a6b45f7a6d6bbef5a798ce85b9e05e7647e334ecfc776378de174c497c0f4075e625af7aed502cd1cf7f588d0d807f02e32f4300f228a50a667b5ad1fbbc17e0b3c57051ddc602f576079f6fc5889b7f2900711334420fc666f66dbaff4126336c353f1e5b564a664537f83786da5c5627745406d7b2fe3233bfd58ef464a06c95cfd0b988a76d053a644bcc159cad53a7c5dbb40eef5cd047056a3f09265b1325699c7d159d5c902440173357ffab8f7a5e389f468c333b782f80170ae90983af153f2e73bd2bef125e3d3868c2ab9ecf03aff76ecbeb18167ca2f711cd565851d7f04ee9d9b01b6d83a7605722620d28c84d6c1af42f6a769258f53c1f66da36666da5caa9bd9e8fbc169211b1aed9c2558f6aaf5b145abc721abb00720194e027035468bde3fe0b88884f4e9b26e771e6c7a0a55ea36fc50dec8cef162f9bba5b4b16105afd6e374e038d5c8587cfd7dd88290b2c9cab45a264d6540ea1416e6e4e74a12f45a2ef13cc8a36e7b0a26b902c3d96e2e2229202e25765694b943373d16e600bd786d955a4b3f1021640c39a0b6c691500281ae0d098cc7f385e18a07e62fa4a101ef5b78551fa29bd15ee0353a1a5ef9b216e8b0fa50750a34162b635a0bc5e5d7230aa19afa128aba6422d38eb77a3f0bb9dd8e4652f12070a37361c3725503c9d22e2face2ea74a7002406247dd86975f07575c9e7c6f41b53b26d5cf52c5acc2c5d98271434e9fa509c6dfbd724372aa5c13451aae393de0a186464f5d337e9f627b4f1c2909467065e89a422ec40ee1d80a133900a62f4e4f7e94eb72615e7ec2996c6c2430c3e957ceae2105a1e90eaeac0d31affa9f57926d71d972a9a2de11258cc1e728599c9fb3872491847e10c67efaef6b696a030ff0533a583bea1d04df25f7eef3a13b8e31aad133857df1b4e5ffbdee37f40f38d224c70ae04ef33b41b02e7191a86656b0d72b2cbb53c4908ca206f75734b27708154fcd8a97429cfd1f2da2429778438003f5b5b9c21d9ed23b8ad8a228eb4f65c24c1c59699a5c90aff773e5c676db362a1930ba16aba76ef8daa42b3eb2ccc45c934d23d4929a7ad9e3ef468b06a4995c80dd236a7bcf3879d8b79467f72b3384c160cc181714e92f2035e7b972a2cc5242d932525eae7c50bd263b0fa09cbd9d6f984b9cf6152d9a133c27843202d1e87fa5a6e1235d9c756bb8e68b05b98da54195223fdf0210253250633c11c5f60b5e67d7eefcaa6c2daa523137
SIG: 9c6989cbe17e16caa253ffb1a64a106fb01782c99b1722baf1acaa42ae5b36b79b2a2cd8fc91f5ad8923817025a77825a05df8c417ec53c4a3aa1c0efd5bbe0f
TST: 1011
SK: da013221b2f588af40e211a0f975d44f9d65028160514c396189f27c7b0666ea
PK: 07117c6b0db5b6fda1edc4396c47c22b54ee0ce5375c3ec633c83afc53ad6ce4
MSG: bc93ee1ec4728ac636a6248fcc4551c9d15980db8e5f54b0ef075a71970e176a3cb9182e32da7a8c2ac0cd7e595774575f9c83506a606face89512135d032ab05e39fff9c8ca6c25cd5d78ecc3ac323290c9c81626735e190eb5ae345ca7a958409f7743b0b1614916832217c57eee1b4f8e622ac052a93dd5b39d0761e40e9fbd8396f60a3bf6660c5fa99cd8139f68cbe0894e5c67e168cc74b2724e9d91d6000a0cec587a11463f72ee6ed255bd87eb30fd457596f688ca0ea73f30497238de21c93fbb1294db61e4a56089106d1cf7ce5a65ec3d12170ce7840f088a8d0e3aef17e531de478003570258e927f156e7961065afa666af38582b353cc477ba775cae45946d08db75215914da3261b62294e92afb381459c21dda4ea6ed795f79257c094dd608dc8e1b7c40cd29fea222088f65697ea88895d10acea8797360dcbacee269c606600adffdcf9c7c381d0ad6696967d9ff03e61a24906502b295e76f4d0875655b01e6ffcacc8ef01129c72a5846b60ec80017374e75d306403d9eccf26495d298120a0633835c5d1eff17c9c62476f752c89710adfa4d51617b5918173cba722540e388ffbffb966874db00404d06b0ce1139ba74143c76b8f4d33b2116e1cce175173a96fc151ea239bfc20d66fbb6f52a666c0e81cc2b80209106e2480e4111c70e7be4aabb68422f0b8c6ba15c142f82e6c7f378d7800a09eaa4da253c2fd91e1263c6b655bf70255d7e3bb4775523a0a9e7ff03797ee3ffca8a50d10f20d5e5a889ec5e334ef26cf7998b0836f656456888e137f39d3e43e2ce3c6ef540d95d9a20c42cb8ae2d9d0f25a891c363ead9cc423f9a323fe232281fb67f5be1c0784361460468a87e95dfa35d7f0ffa2211be6b5fb32d42ba6518ab6ea93780f431d3006731be4440e712974f74baea419f4022fa2502e1b2398e9386167d93eca92ca60dd7d91fe82324f682d94aa7a86ab034f8a9e952e8fc95bff4dfed6a43313abb92401b30c33c79a7ba3efdbe1628040fbaf443f3f980846fdb283dccd93fab09708b7d54861d74b1fe8f10701f211ba3d390e8a6ae407739646a79a58337a717a872009c2df6761c2425a32a0018aaf9646470cbc87c3a65c0e0effbaa528fe4783c772ab266b8f28268cf14af234b15816d1a3a491af5f297e33d5729715d512c373fef5ecc3f3954a60a2a0f64d829474119ca1a18f10578d04d638d5eeafc371a946f6ce7efbd2acce34e20441cde9a37d5a87dc619b0a727596cd12e15cd9784bb91f1399a59fc0a7a4af68b0d575d93387172973375c465df5d2d5e061a2a9b23b4915a0a8b8c1f0942094af728c8c31145fa7aaf74a21a3b032bb09c392205bf095bda986e5dd6627c1e417f650326dfe3a9c9994c6e0e01276f91f2987d2b85deda965491
SIG: 10cb52d610e4a81d32869bffce3807e6391f782fcd538b554d09037fda72285b9662b1b1107c408178ac009f0525967388a7d85fa12359d3ce3875037dcf6a04
TST: 1012
SK: 5a868fb75ea0721f7e86c7bc106d7413c8cf4d033ce14005df23ce4c155bbd27
PK: 6d1e29f39deda2bbfbb57cb01cb39e58808278e5196ada1c027646f20487d252
MSG: d5aa11825b99448c80630623d8c746017cfe3de6fa8a0c6ed6627127cfc1f84d4e0a54e6a7d908d3719f1421d1d4c78b3cdd94769ab6033bce979dd90e106802eba9a03295d48f9b9a95d57ee7745402a48023bf3bddd5c6b91c773e491913a38ac3462605cf282deac75742fbd27529276e81dcce8dff9605035e8cf05df6a43db151f0415765bcbd1f1bb668ad6273b891c0dc4f3dba590ea82f8363769b9c77511947117375dc4904d48b88b68a255b28011b11048194093e98207ab1cf756ab8331f8d6f9d5be2e1190573e95e710f2a3501b53aa0825d6c12dcfb94ac80dc1082cb4ad262e6d493adceb6bc19145fbf738df76f2134fa04cbbe44ffc55ffe5f9d3e9bebd159a001aa9bf78892a16538a520823cde5d61e29a56a77ab96e49e300d9865962c7e7fb8bcf5de0b938297c3f4d6f6021e24dfdad9861652f340f421e7af2c71ed9a71587fc753b115549b2f7f7cb29690ea2b158a94cd2bc42e7063d619b939d523e3c237eb1f40810de0b44aa6937863d629edd5575e6c0475261b627473092775c84360011d57c57209c2e875a3f8963e8b241a7aa75ef30c4a718ac4dd466dc7a3e40e5874f157a849ed3a3a9d4aeb7d94df09bb55a0b2bc9f8b695c37179302367606367c5f324828ce75a944f50703a47906a8088f3a11cfe4a854e01f1741252c486337d06b1cc6c6b9b1295431ee07359357b3a78ef5075b65d7fed5eb742e5101598444b46623f89a303acc10c732449513b70dc456a79d37c48e5e726c2f558da0a1c46efbd2d920326a678b8a22f0944be4af55b6c71f453fbae400e6acc04e0e95ca200167e96ee98ea839316da93a12c2d76f11aeebeb78e65ea48f7feebbb137b2ac67eaef02a2d9e6471dd634a037d4f5d35a2f78af41a8ea5af5bc8150a99ed68a6a0ccff2b1d7965d8bc3ef9285ba6421d87c33aad8103a587be01926845bfbddbafc69c4b9252886720d418509f40f3dcf55765dccc3deed8277215e69f056ba31b8a30b50094ea8f144720760c8f8c055cf1a86964ffcbb8ee1bb2181276ea99a7b8e71067fa310ba4471e84279037bc492a55de205548e77b014504ee6664c4988cbb9ed91ff32e2259ed4cfd61a197d0dbc32c68f6549c0d29fc45f36acb26b164de97ccdc37900d93cdbcf9687ef53f1f4da1b1ae4225b884209e81ba4311520477ed4211b09240bd7b825e54739fe25d8624af04b86f6d1106d18170e5064d1a73c1fb1a27b289a948d771a2f6b8b09a635db96c6251c35a1876d369626699416c0e40298a681fdaf5255f58c2557759d8f5df148dec9dbe1ce6df041c36f83e69ccfb4aaca5cb48fa6a85c8ff66061524d8b11bd7ffaed99d0cd45c42010f21d36cc316ca860955635bffaa7d9aac572dccf3153d42ee8a2b12baa57c160bd0ad
SIG: 38c48dba99a6524a188d5cd78a98e677dd263ef6b4df446b310b3dd89cafddb9b17a65bba8e13968bdc25b1d84b6e2436edf31aa756e3a48726d6f91c808ee0e
TST: 1013
SK: c54bd3431f2659281d31e93b30787668bcba6e5ee47db46e50deabe3f48c9ed8
PK: 1eba6eb3f7f24cdf80abf8a19d308c24f1e25ba15970eda7116707b0f12cf932
MSG: 6f8cdd75e1b856bbbe9cdc25537fdf7e8236cb029acd3984492110d0c30441d42184b5fb183da9f3140378dfa7d74ccc9ef500193cc9579fffa60bd2a8ab9e09581500cf06cd35abc171d9d12c6580d9682f9f49fe36d0a3177238fa50e7eb4c27e460f5e4580a56568a19e03d95b0ff4f4a231824cd2f3442e0ba400bc11b7a989d501f5df35e4301508f72a852014bfbf4001e28095473d9659eed6067baf68f92bef312c09b19aaf7c4fba3d902b9f6cf952eb9b9a53ca8bcbd042d842e9853b672a1d009d823838bebe5637c4c07ed1b1948554b23b32de1d6c116f933b354f28bbb779fa6548c48292b612c7f551a75fbc46c02736bf99e9c8ead56f05ab0427a6ec616e3dcc7757efdb7628d4e96325fe0ae254cef5cb7a704b35a920cb3fa2a03e961daf371821be0b30f19ae4952441e08a7d22f5431390a5be8097fd5797a1a6297664da42c2008d0321060ebe3181eb795a728925808da7867293b7208f377d3a771185e6d2c1c8ce18376fe3c0c1458c7f5be34f428a0d575931074c97cbfce8ad81313ecca73a9f3db434fbad4bbbff502bf7297e17a97a8864211e6789ba192036ea59a34d84ff2a111074c3f2373b10111b5daa789560cb35490954c88ea00c410df850ad00cae2f28e719fb06716988a9bb0bfc6c989d587e5685ae883c2c2e74ddbf915c9856aae8f3288fc625bfb2fe268d74f59f8b7d8363749769169007d5e67b7d0b8c8f5a9d9f9c7b745c0a4294762cbeca42d5384961e921a7efb65da8d1e03b6745cdf308097fb13d64fd2f8c10fa9509eb2d91387f00645ca7d0483b2cd14c206b8d7ae0a3fb7c09bc6843d102adcda19f8bbd851eb683c4435ceb4b3d23d38f56d4d1114eef0fc6f24df52770d8f1f3f82f4720e892b315244ef56c36b23fcd407978524140382e11740fd46fe4299923f52b88b4a9cff4b2b4b23a2e760ad81c78ba876931d9aaa4beed40fb10a799eb30d37f754778bac85bf0631d852be7d74a6431f384a4025c1091421d67a4e9c94c1be3690c6bf81d06bdaf32feabbaf1dc263f273a0b9ed65460baefcefcf6acccda0edd23df9e05128e29d661c4b44bd92d640faa853afd8370e563b40ae0149a1428e06e3dd8e66b79da21cc753ddc476e3d76e2f36f2b6c6bc1b65087d5f86c8ac354711a8c08f3486e479d6ae943f8846332d4e5b4bb2e8257e3083df4f81dd4f0c1ee1d97182166161a18597ee0b959de1c45591abf7c51033d7c66352deeb682e777aeae2fa8d3a77f470db78ddc1b1fc82840c4065776d9bfca9d392d9288ee9132aa3e4f2d19d0d93e01b666f3647abaf225c292419c8a82eba3e11ab103846fcd4935f41241477c0f152b7965ad54bb72bc3de2e0b79d6225e8fa7a6286b5fccbb35822e80c8bfea74cb48a22d241385395c2
SIG: df4541dff1a9797feb617f98e4b57aa7714131ee8ff545ed5082e3568efd1c399cdc56f5582991eb8785fb33864eef7f553f3e248262ed548a1a6888f92e920e
TST: 1014
SK: ea60da0179bcaf6b218142b1119046ffe6d85a741b0d166230bc6de3304f6773
PK: 506b2ebb49bd9b9ff66e6b7b1fab9668cb181b4fb5e4343dddd3f8a9d702031c
MSG: 612d6ef6e4349ffae516e983e8fa7b52d9fd134282240d95143824bd4aae03234b76a8cd6d4068cf009e481c2685361c755042c4e6ab8703ecbf8f020cf5739a4c2a03c3731e9cf75aee25966153b9711515c6c39afa95f221ac3395b089c97ac9b514e17d55f796a3ecc135faaaee907aab1029647b48ac81749bab26627cf7095d74c2fcee35671c8bb46053f5151b0c2e5dabe0f2d6aa20413305020b2afd9ee3387b2c9ed0bc3fe2902af4100cec23327b0f1e4ca39ef6eaf6fdf5d5acf93fc868536d8cba401769329fbe93effc7ee6bf93a6e588bd551eaa512853952c81b245e5d229d294e41370b867808667887a6f9eba2a8d56a7a704e66b1c02f96e73895f483e44a5c566cb1af26573bfe2afce06b1fb5877e51ef3126a3f210fbf213ed65d5ca46c46ce4aa945bd8ca611e3836250f564f7ea35423982f9705fcd6bef46ae16cb0f6bc912c3f28642b8d87775b818e4e4e8061167899bd27a7e2fb8187ee9917d2d586bf9d499e8fabca83ddf58c7437eaacec4f444fb2bf745dccd8cae38944571dede2037dc41f0818a3d91e3020a7274c6674247876083d0e39746c9684061bf74ad588436ce1b763dbf4bfcf8de6e35c5a7626675c127292b21df3c16f81063322a75f3438886f1f0cebfc1a96f41384cbdd861b04f519ff6a9344d94f3d3a0aba8409dfcf18d01f2b5b455171639eea77dee706ea83dcd2b8b1fc5ec0d740761a5f05f7ec8d87ad1f292a50c8bae0ad32b03419a950d9fe3b3ecc4d8d3aa95e02b51b1831d83eadeaa44238635f9c65efe2f6744a70b9ae41ef15d97908c0533934412f79583d0e9b3d706a128e88fb51eedb65e46d8a2b38bbdd6455554967a8dc0c68bddfeae0f8f72f0b886c3c741fac4f91e5c491dbae9da4594836cf1d9fb6ee130025089aed350ef247bc9887a2050159dded1428ffd9b07b9ec2e3d4bbdc2ddb54e873b63f2475233e19133a14b6658509457008186d6225995a96726b529f44281aa24fefd1cff8f815d93a5986931662290b3ee16833c60f0afcef2cbc000623f3931909ca976a094e2b0fdb7dcf7c485e14988a36f19b66425385f5632cef65d1d3414623ae3ee816e763a5f606466622be6602114502951cf0c097c1648a72e2c43d9afa9689f2c3cfe026cdce3bd1bf9ebf777562ecd8ff1b0d775306d900443f30a843310b8de6a38ff108b723913d7899b9fbe7c3d766ef8bdfb6d8b0b52956cb1cec9936d70b487c01440a842b2fabe38e7b8851a387d358be7ef12a7e4f2b527e83090d67eb013c9c2cfd3de5a1a3f99748a41f4819d9036e500c504c988bfd24f617d6ebdcab2ddeaa61579414f360b469a33a6ded96ba1d8c140c4ffc94990d8adf78cd38780bd68663d1a0ee33f537cdf892d562e82dcd1d912cad38d65567d291406
SIG: 27fb6b5f06528a64198a3e7d67c738840a8cff4b482b4d524b122d17d2aebcc0389be2c6e28e2cdfc484c18de425db56cdfa561c507cd970602d3a385d3aea0f
TST: 1015
SK: b62c241878273513e0bf6f33d2104365b2ce9c5a1b786058e9c5b4d1d192f87f
PK: bbf6fc5198f3fba5ab007f8a632d28d1af865d290fa0a90faa9a9b5b9c13f3fb
MSG: 26a3c26a5a189cad407cbaa3a6867ac0a26088c75f9d0fa19bd50274cec5755a497109a473284d6fc81ad4b9ec29fa7ec9764fd3099f060e36836552ff2413e3d5095fe0b1a8bfcf67ee06aa9032e7bb3249698047714d281415273c9834ad9eb665a7d97220e72d9ca73f31afa7738675ba3162efefe7479a5bc4bce2e8b7af4741d703dc9bbd60b4cf4b9087f6cf86cf53aed02bf4ca6a18f607cb52a303d78e85ad88fdfc86dcb7187727b03be227745bea744fd006525bc59a4dddab915cef40a8f30802913b7913eaf974336552e2f1456ad803dc58c9b4b18efaf7f7e357e2cd77d138d90080e296d1364a2f324d3e0d6edc20b8bdaa9d2e871f5e7b051fb6fcdb5595f21d3f8de29fb78678fa479eaa32579c784d513ac5f836d954d0d3fc0e5fc8a6eeab90202b4c4a2bec24cf63ea67c470096218cd431e883105fc9c27f9ea77c18eda69bc00a2242bd420f095c9b9a92d956ccc5a8572b057a7fe173eeb2a3166cb2089d113a816462b25805b8abaff5b0b2287c508ec2b8c34b2195c332870d3cc396017a16b9e0da6182d071d3bf363d3f1e7b7da11d711250a58afd74ed3e3158d4718bad4d274bb3444cfc318074b53beba44a2a34ff8eb726e4a1daa911051621651898b887169f62b9c0f4020483ef544f8f572fa6a6640a4cffce976cb7024f847bdc95d1d7ce653505debfc6988ed289dd47a9eb261259e3e65e45fc9d714946935cd8ea13bc6db5eaab9e8b10dae0fdd6979c2035cfb8098252f2205443b808816bf7787b7f1e78bc98a7285e733d45fc4610c20977ca3229889bb8cd2b694ce9e3fe78303af83e106422542fb7961d32eb1d2c5fbe60751674b074773ee0616e02973f6a74a3ae4664a2650915a3e10493b9e66a39fa5c89c61d44735f107d33757ae679b43a8d43a01757ae1f3279e862442e150715550ee82e49c0d4943faf13f22791f0e66f24ac50ab3c003852b21e15b2f006edc2cd6a879c476ab5b352eb1099dad4c50372400faa5498d78c6b857034c25caf7b933faf6bd7c59fa3da57397b603de9cb9d80e51f7997baa462acd537e2c4194c76c7e0be6512bce4d63660b36c7cc46631fb9671ad8c5d28e2f2ee2edce81954421b8a3d9ff6f66699f4bce88bcb8ef192c262a74ab7e191eee9101a28d4b66282b5122093d141c6496c7aba4d352e472ee7440e05af60da0cfc93e303642ba8fb8e5c568687abd63afb3ed6a32b6dae56a7e5d73debaf41d35ca36adb97a22c0adbe718bec1fa51998de9b4b96a79c5b9655b0165d5e1b9a8cc552e8c9329ede58df74c67b2ba1a842fd3e8158c1fea3a99b56a2c2a96207853d26022cec170d7e79944d2f56aab1f191bfd48d725490ca82b8d906f0680e69eeb9575774fb9d604513fbc26f5d303b6885cac0bf8efee0538f92
SIG: c59039587b38dc141e055a93850104d629e380705b8fc918847c5e2a352da3a02fce7f7199f4ae2b1e2a59483418932e185f7e45b5050c642cecc7e781998507
TST: 1016
SK: 0f77f77a1c7e04bda8e534f4e3eff9a238cc14876b7e3eca8bede1923a336406
PK: 1045ea9fe214583a0cdbc494932bc44afeeb080bec485cc234fddcff139cce00
MSG: 0ecb746dbdb0161421afeb7adea7a37c2ea4408a592c9d781ed6ac6f4ee5cc65d5270e4cf27632f7c5c133d439b78d1f71aa6dd80713d90b151e19121bfa87710e84a4850a3b5b0265ba2603d0716e9b7e1122109c39c6f1027fce18798cbb4f6bc5e4d7aca4704690f5c981510871c313595798338681107f2b5794d46f6e0bde2cd064b3b1fc00ca47188bbbc1f4a0ce305cc6d8a896920eb9ebae579fd3385f8f1f35976288f4c58ffc4760f359b003c872e9a24055355ea9585e951069dca25fd0cc0b9db52aaeaf19d43f2eab4f835603ad12d2dc49b310256b94bed54896a16b69b09cb4c8ff5c23cce5593d87ade2a82ada50859e1544c18618a65c007ef424c9854a175b6e6c0e64b2c8eb8ad4d28b977d68e78169915198975394d3b9b269cab0d3261b2b56cd2cc4bddbd4f1439e0dbe2c9b3f3f7514edac5ebb4622b92a69a840a9028550b221db59ddfb001396f86392a17f08ccb194cd9e1a0081d7dd9cca2357feb8b795e517029f79c82a3be6f9a031dd1af1e79e4982bf8e76b310f9d355efcd5b1efa9f359c17cf3b510d513e8cd5786a0d3445dc59a8433a46488687b0f58b1bd6567c2af4873b51fc845e767e243005192f8f0674f281265a55d76cea322260c932cea6717adb98a2dda8c698e2e89255feb77da7648167bc1e58877feb72d1d14b0c304f07372d955675237c49f7a6dbc915e6814abae6cce4caf9f48087e9dfb282d8f340377c1e29c6731ccc2667da6695b712be0312d865111934f168d5544365ddae27abc64aefbcb322db7d97d90d957a637bd826c227e9eb180b45a431626a6fd890c0e5f4ed7e856474752f80b5aef6e73efdaa6c2c451bd74c1ef466ca3aaa2573bb52cb2b1ca96a1b574403ceae1cf05ffc53430e1e4cd5593bd1ef84bcbfe219f08160d166f2731d99b8d7a32b12991f77775a267ec08297ec512d7b72435632525c04000fb00a793f8b5f8f3747b55359df21b7e2c49f2b0b9ae082afc70a146871370b8d50086de00f9448be8902174ba2cc851fa379dd7031ca457a8869af4b6c2729dac519556b8bb4ab519ef1bb024ea8b7f01771c9aab748e57381a0192a6e398cbe6dd9f367cc7b3354f83b79bcda46b793a4ada85549c8d6bdd6168124362ff908aa1a0cb78aa330c42d5a5d481235acac3a919b969c50987266d404d15d0e706fd9007634f69e13c56ec47133884fcaddc16beeeed19e0cd917aa496367867dfcea274e1a47da774f3c9363021e7c8d6bf8f00053facc11cb68a9d6e1fc2d6d19175d6324ff7ca6c23058b8b693d8fd4e0b51dcbb113543f2fcc0452eb9d967ac0fa9b23e9e0b1da8d83a3c1fc9e9ec971f0f67fc745bb17376bc46245f528cb6e5fee11bcdda867b7f79019cf9db591858230aecb4d1e93d167cd86b42dd879a13fa0e
SIG: b20b9c4246f0d2970138af7dc9af629b68fbc37df87afdcadcb545c1768376a09c3babc3eb1af3b7519852f75fab1c9c119c662c5877fb2f7299cab57fad3d0e
TST: 1017
SK: c5a5053477ae31158e7469dd1504867650d46f1589067f5cd881caf25c26cb21
PK: 70f85db9807b26fcf3e6690b91724f7ae3d20ec3604ab7d6308d9094308b2d59
MSG: 8571ff3903486a43a6126c323e7b3a74141d1385d4bd703f19e2d1b64b50281d27168ae3e769c6dd9df7d97864fb37822f0021852e3168ab7d845a6545ed0c377d9f7c048a2b96e8dcf445779684a058c2b9c21ac68a0c341d1d6c0981456457458eb7cebf66678740777eca26e01e1c8f53b5d4756cc5f0b90f0c5db05393cd4b8e44f6810caa5a116a33577724395d413af619632a6fed14e215c2f19d105ce2bf1498e6d2ab4f650f61ba5cf6d0c73bbbde98e30429910a4e67dfbc717cb091182d597058b5d765d097e6875831b588aaeb3e7327e856b42fa983fd254ef1f918b043d1dd3d7b7e30b315386eec91e7f94d598f4beb3b27b42f4ee1fbf7afb486bdcc6081ccb867f04111044f4bbbe3c8122edeadefa9d693906e0d6e133bf6f2da6158feedbda024410f12086e7accf1c68e1557f00c14e9c7ea76a5ed1337a054ac2c949c05977e030274f6a4f2a6b30a15c570ec9433f74f47528087c9ce9a6292951c54354996fb283c0dc4cf33c001bc96875ea6e1f46f837ff18dd9545fb9934655342b12c2990b9f1c6ff4d66489d6aedce75c7cb03ac134bfd39b181dfb7f9a97ce737fe570ad5f81345939a6de5a40a33a0e44bf957503d5ca0283512e57fba8a3a6f2c390687b1b7708676e0fd03b7c188d4561c1879163eaf2b596ddd5f3c1f4dadbc139c2164892820b2fe09cbc3d19088076364510254f2b6d410329e70f2e5a945bbacd2ca89bd4b6e1f5e2e1d4f4ed2fe0113bcf32962f00d5c33b1df988402ba0dc8804c1af66ccae2670efa3134c67fc90feed8d8deedccf6a46f22940454af2bb6754cf235ddbb0001c6c741bf874bcd8d41d9dba8162581c3746d7f30e73def69415af5181c149914295122d45982f94943e20b0ffc7fe6ddf19a022e87a52133357a1e80f37f28a4c4a8a61c148dd875c1e8ecdcd840dd863e44d9bcb16b6e5af0147b34a7a9052c8d3f452013d2d354f6803f9eaf6056f3b013c616e47f398819146320a5e3dbdf16843ea29def262cc9a343672cf96bccc6e87e6a6baf0712e6ee89aa60489f17cb72ddc44bad161587d87f54d67cc0a2778497d831088315ffeee3d268c59befe884c3aa0e0ae2296bbb60eac9097cdf8dc0987ceb1742b0586dfce79ec10425b28f4e64520d712e3f46ea83be2de6a1574073bc5c7557b8e25b6411184ea283d8800232c79069421811f883c2994e7b7e2ad9f8dc489c9347724394609c98909a6c26017b50f20d50ccacbde36b76ba646a76dc6a5b0f50649c5658bbdfdd3b5cafc5479a2f48ee51542f23e9fc92132060fd635eff452111cdaf3efbdb7db9e7d4716d0d6011c29118a55d4c1a436abe24e3cbf40235b76dd1923503c5f3598124e2df55a2d1f246e90de4b71645d5175b61b0174e7e57df1285ccf8c86b8382c258079
SIG: f5191b44bd6cc3ea281771df12549ba2be228b51eb791b9e5ed2815f862aa630b56967cdef8b6af0b9d21ab8c97a6dff681cced9f5019713d4357cb3e54c0d08
TST: 1018
SK: 05c719cae06e2bb7d87863ab3150272cb2f8c3aa2421912d87f98e7589638ce9
PK: 90211796fed3d53b81f8feeb1bad1ffc933e5f10d3bc1b36ddf210a47923df03
MSG: ec241918418e60522042e67339e6649499f31a6c7cf8925f1f61dde894603602ae8bb5f58809821f83344f23cd31e64ec9ffe79a986b7e29e4319a63414316bd6ee20e02a50da44012bd2d6f9f679e88ed0c8bb1e2cad55e565789883345b7546f3d54b1b362b1c650502c019d7313afbc82689b23a3a52d8f1af9f81e188dbdf203fb5300b4225bfb6773337be6750b3db88ce097343f62ee2c118574ef150cbd4c62760c3e43dcbc39218bd6d98565fa389811b1a674f617fd756733dcb567a92dbf3855b57b1f4a46d5b8974b39ac0d0e24d99d2037c04f60d9140f64b07a77d7eaa1ce8a78e844b1dcf0e37424f3f9d253a548561a0375a8d4341297bfedb7048c7935e1481418f9bba9271f9fd6026224e78e055d8a0939fa2fe1dbc0fc7b583e4cff3490e1d0f610b252e30d8497d00e4aacb375f19a4719f79ca1ea583a2f8b1406a4aa5cb55c08b6593b676eb5c34abe89392d62d23308a3348b57affbba7739cde8e1909d3425eeb20926a977d3a94a86e0ba10b386926698827e86b4fd6c6180047c87ec3b31619d05a9df34efd3d76a836962b2ef604d07af0975eb8f3dd22594323802564c929b3f65dacb572b32553d69b31a197690a9bb860b080a77cfbb3c175aafce0146a82a4d06e8c750521b726ef1cb29d021e5915e5e8462ede5395445245c9ae882eec4b1745e11791f7621d3fe702cac1525e1f7b46e1105cdd06da2afde26475dc1f78df8e2d72b0ec3ef7dd956193c996842a432696538cf123d7687211ffcd090b9381eabec879f769aac0d3564e16df794fa24728d7172fd07732eab077ed81c22084f6f781b626dac67428a9ddf3b0db0465251220d18b8bf620464c51a578decccbbaba545ed442cf12c4c66f6cb6e6901ea54aeda236ec45eef886a7ddd2c041caba3a6cee339715b6ce97e765ec3479f3d52824a8194bec2a89647e8c63ff7645ff6d05367c767bc48cc96baf05d6a415b2a5aff9bfb217948fad357b98f47dfed62ff1285eb9f468f0f29edd75adc0c8c2ff6a565edb8edfb48bea03b70c447369c52d881eea0eedb08c315cdf0bfeb979c1c0250946bb100c2866b4169b8cbd44d658f0236e1e9f3aa13bb8e8022a38ce997c94b5baf97e0ba621f7e09671ce638c2a39ee6c6e25a688019dd167675ceaec21c6b42a7c8c476d129dcc693c392a02be91b87437a08a0ebf1a7bd976ba23774766838b8d6024f5bb9b07f3c6b719b4de15b72448048ab70db3d4bea77ba359b51b1ec17dbe8010aef0244a8079ca8b9a2a797f3b1fe047c8dd5cab7fb486829239c4ef6d9a38370d488c47b7c030e49a5500c9abb39a9a5abfe72e918b76384ecaafe1627266cd14e696c09d2512e312582a8a911e7b7bfa04c21819af687f04c5e0cbe9a2ce24d4d3fd12190b253dabc12c63cabfa94
SIG: ba6eb751371df721b7707a5b3339edb55f138640b97be6334d6cda5191a3ff6367911761882a4a007f161b748cec95b19e995f2858c257cd6169256662301102
TST: 1019
SK: 5311f3c96101cb8b7abc622bb9326b8f513c2b16d294df797f56dfd8203dda27
PK: 230b7002f57c79ae2e6bfdb8df30db3e900756b54af3968c670ee2f32bb11e0a
MSG: 61b15be37c4eb397d9e77e00151a28ed3e86d50a9552bb4850b621763f012e7e77bb5db8f3df7dcf769f2d1d46d8d60bae40c8ca6e25c6410b60078a93fd05902114bd91045c06192c70c42c9f41f8161ca46564ebc21a4bdd8190eba2aeb309823072ec2c0200ce6498f9d72b37b3fb466774326df37ad880d8eddb32af673e45d88eec49b1577b43b8639111c2e0b94187d2d4e0173c000f4c37be845d68810b7889ff2a049f3f9f245ec70f21def97780b611400a83c31a79d93a8e98b608fdcf2488b068fe1ae4217293a9367bb734b5bc7bd8819b377f090b4f8fdbff50799c76880d19133580e1ddfc2b9baaddbab34fc6fdc078014bd1ff739daafe5476f3f79d4dbec216fa7680ee8e84002dcb9ddbc7fc1e1c8ef4f1b2a2081b9282243da6153c1fce0905cf35f83a684c01b04557ec84f7e9a94fc2882e2ff19fea21d2ce6167861ce01df8b8d3c3e8d255610b7af2596cd5cf0016734942cc714c272c05fda9d34723626646a46130182cebcf179ec00a6a173bd8577fa845c44d19c6997944755f2b4e468563a75e9016523b87ddac3eee21bcbca08fcc29546a43cbe0d8d10a0e8ddcba172d1ded150378e18b368c7763913e4b407012fd76a872d2cb04930b8e22b308243d4cc278fdf2e1f940ae89ac891b9e0661aee553937bf350b407070a1bdfc4f7a3787ef399d2caf4ec74439c587376c77be0c3de539d3ac26089765b9be10b9038694636e262d7baa0b3a8941a2015967639f6044c67e59bc81cf2fba704ac0df48da6037405a8e8b8a7ce3c58ef38a883538b247ffe18097af095242b058bdd1e3e245eece0a71b75b97d52f20d6d51bb9766b0da0fc09c8ac2a30fb6e7b32ee06dadf46d7359cc066aa94785d8a882ff097d78a86be2d45600dd3d3060125f01c063e488d5c3efee1bca1e58516455ffcaec1b81ef433876bf09ffa51d6f5018585224579cb67b56ce1c216ec0a883e06c8e1563421ea72b0c10d4bb31e491c2ae2fe8139f249ec927d806ba08db52b1b506669047f0c116ff37ac5ba6cdb1eaaf33fdadb0705c799d35ac6d9c80da90c1438b585ffd59350a2686b1ec35166cb9b69ad0f56586aa03274d782e3f858db64adfbf04d5228a7b1c4a2048bbcdb941153a436d742c38b58b4d7d13c9f1d60e152aa2792349a3d94e7e6b1104aa1b870998c18dd7065654a85281bb6f027faad556b1f532e7a1e22d564069289587a0efc9c1585d135f31233c41f440466e71fe9012e5f9a0d74a7282ee392fb0165db79ff1d3176ed08afe1daa66cfbf4305ae16ac1792334399f71b1917ddec270acff665ea05d184c2c5cd2ccd902b22f9b7195e66a65556ca884ba6f5da04dcd4617f33dc2b44a0ea742aeb2b93f3a41df7957a026797a585ceee814b1975f523d2db5dbb9be0ca649d1d45dcfd
SIG: 3cbbb2608870dea1efeebb3fbf681e27705c35e4ddeea86c1b342a77dc296b498419808eacbc78855611ffbc9265a74798e51827e6e5d811816d3ca21e8b9c06
TST: 1020
SK: d290ffd93395bd5fc587d1ab511866e72b371a1735732d9d5c6a18dd465e9363
PK: fd4aad73b032461ca0aae871ca7016383b2be0169053fdbf6c5914fdd6dd6f92
MSG: ebd900bc910c5ecc4d97daf7cb5ebb5491500b7ad116e30660950709d8084bb6434c5bea4a8ccc1ed5a801bebb1a117878c03747003e148ed91434832e8966241a7fff22fe1d6d8c3c3ddd7215a1efaf4b07afee1b25673a1439eaac324e895d4be839e976c03ac001254876888ccaaf3912727a60106a87be69247c9e438c31fca8d9c61bae368c83e40901a99700dff839b513ba8dc42d93ce0987a2333470a9f983313f91988659da54039e499cd1af2b8fa0ebe750e24d55c2a5bd1ade3f680092542bd1be0b9735ba393ad5697d241e8e8b28646db27d2fb5a940e8faeaf0b6c9efda88615dec891ce732930813bfbbd0bc5f8210abe843beb5e4f028f49bea34f1e5b09eac4c6662c74fba39de4a9602a9694a85c7c1375fdadfda6a1957fc5b5987a687b03995e51697a1ab5bb6cb11b663c1372fade4c0aca8fbebb4eb54ce7ce36c6904eaf6eab2f34facd8c768c8d36da2397b1a02735aea72cfaad0393410db527a8ab236d4cdabdc888fac6f182148b132614425d390ff036e54855e4203c51203c1f43e37bbf6b9bf27f5b7e7c665151465401ac32cbe9e3350535edf48a7bc3603e2232e938f9a815ac4d1deec991ef9620948441f7a2f4a46e2c400ab914c4be51dcaad8ed8239cbbe977a9f09c02698319d9fe2a8c6eb60b799f29ae7659970d2ebdff3c6cf709bbf6f4bb55b9df4f61a241dec144b5993f087e784b97be1e53608c2e817ce3d9aaf914e6b723f5b4afffd2a6b9fe9d2d73915c7ad1ffb13efcb73c56238195645203984c99aafd0235f73b3f882e073939bf786657280138db05b86fcc9460b385ef4559204ecd81e2f12f5f062aa448dccc82ea8d89466dd1be46f82c4f87bf0db2b878acbb0d9112c8db6f51d35f6d42f749856b99e550b6c454e9e8be4da175f0b5e86be66c979fd878237e57f691f0d2acd028fbffa5b0668775034db1f21ddbe7114ee3dc0b44daca64c5a03a2feeaeabeb7063bfcccc559baf27f1ccb2202fa4d1b2bf44c04b2c2f81f94e281b1a5adc850da1b9479fcabddadea56a115bb5f06cc016f141c0fcb5e83ab248eaec90158d8be647aff12e7eeb5e57dbcc293cb3b6aacb55236d4a839a0620f4762387dd1714df5c135e3d9d6824f93b7c90d3ae38c518d607120c839570413b46b8ccd7370492d8ae5c609e00cf8251e2e7df81e5b4f9c16a5a539f0afcce41bb4362e5eaa5f940a1706f4afb6b14432c81d4ba1a33d322dbf10645ab63737eadc86fe6e0976f763397fb898637595dfd36934792d779e24c2a3f0bacf53e0473c5fda9c61284e4419bdc0eef5d22f4d9bf42e8c04933bb93b53c295d7ac9395abb6dcbd742b1e1bc3b0ea4434ea21b8eca9ae682d3315a41e9c3c3371840761dc59cac45da7e3813e28788dc89de355b5aee088090a38dd39d83e5e4
SIG: 21704d5e626dcf6a9dcdef935429eb7fb5b257eecd7bf74acb0cd30ecfcf608d0c5b633a4a8a9ba2cc82a21e03355e01d85dae7ecac8896dc15dae0485707104
TST: 1021
SK: d7fd73d1d229a65894420e4ba734270d5a20758364de897d8555e24197453c19
PK: 3c22772aec0a0c1559077f2cfd1f2465d4b48495c5d05f1f837c31845f34cad1
MSG: c9225859d555bc42011af1b4f14998e6e9b0a65e2172713e968380fb6ceedda22e022c51303031d9931ccef2f7bc705c9e215c1d089d488daddaee155c939b6202ca53bfc7f6e88e1529d82fb45e02b5d05a82bbb9db5f415c58ba8bd56cffd92270b24749e56d12c99ae90c7800f54f55254ea42da5dcfbe0e1d989cd2f6897e232df04707b34af75fa7fec33e55ed56aee39c22b045bedd161083bc5514c1f81ca907b7c760317a7fd5a5a02a5d40e2e823e24ad96aef6da8ea982b5161cc39d84aa2ffd9544c11b634037ab0a1c8e36ac63019da1b2d995cb7bd3d62fe574deabccbd0d3ae7a56e5bec91e4ba3f3db8bfea88e67da62e88278a6e3b418dceea0589f25f7dd8ad19dd845089419b472efccc879c172b32ee4a4dbc2e6c2e865bb3b8ca0adcb71fdf89e1973910ef242915f33e236d2f7c8e9f1ee5b07c6e3c25360f8cb1460be87db31a291d4dee34953e75c675bf181bb7a0b7b5c1befdc86ada072a48f6ac755d499bd68d625d8514525cc3ab8f54ce15a871291778de1305d2219361aa30e332a2e069077c5c53457520379d8b90d24bd8a3a7700ff766231cb5697f9ace521a99e896da54c40793bc7c1fb1584bb1c86194d2fb7a4b802f30885e0ee8af88d6886e3a3a4d4c854649cc01abdf35319a0856cc65d092a386f8869625cd0acac087e9351790ccb4a865f651a881c3ebf109072774f940f5aa98a2a2aa3dd36647d0de83001aa7cdc031cc4a4d75dc11ce551676a2ad43a3f6a16a4bc5aee80e5364206087364eb8b2b15fb705380a072d7c8b51995943aa762e8deb4c568cdaa1411ab68f28489e1323bb6156ce2500b06e7793c510a3de29150840bfdb0b2b7b21c2bb8a7746167c929dd0adad44fed8f36e8381b342080b2a7d82a3f81ff72630cb78df91f7b65a44eff6ed64d48afed109dd7a693a1ba8c37e008fcb157e37297d32eba765a6c7193e73bd97647985b16038c74a084a8f25654cd8cd2cdd27ff17334e06adaa058264017a3b2da78e5738a27e350d882f5fae199278d4e50b8badf57c2141dfdc3cff99df5de86fec293c76cb94b6b19ba3034e460f84c280a2e6412fab5698ce890207cababca0a95b5ad533ce114bf71a404a87590d35fa7cedba43131c4ee92344839f25cbfaeb12aeebc8040893951a346bd28fdd167bd20f71a1e59fb60d55e1c567f478f027cf679a37d1d9db867e17bfdd60b347d89d322639d315bb7a2c9134f00ea03a367f305ea4d60dc9d567cf924851e469ea954ed3ea63ea8606f79f077339bfa2b51ae49baa0fb25377821d7c11ef9ad4bb4c0fe489acbab0ef000d618c7af5efd205d68599fcbdd95e28f836e0916f9ff548d0ba17da62536e74646801eeb6122ba32c41073ae04e42c6c1d5d8d22976a56226ddf4b6ac95455fb53099f20215b2ebc907
SIG: 400c3505f1dfa80df4b26db24c027eb81977f0fb9b5aca524ad51200f4bfb133db834823314195f4edc292d5f530d08556e7809caf2339768aa38029fdbc280f
TST: 1022
SK: fda7cb084016ba513c7c4f8f7180480bb181e95695ea68737fa34a40ecbdf3ef
PK: a2de3a0ef97298fd716106e2f3f54513057a40072d234c3518154c1bd12de037
MSG: c21bb3f8e37befa367c913673101ba30d3b5c74bd8bdb09cd28640012db41120c2bcc4085de2a0f95c9215ddef8cb5fc8d8b1251b41527c67dfaa3f95ba3578391ea5a6629a733095fd0a43fdba40ffe260fff82acee2ebe980e9ececcfe7e10b2ed8c2e6b410d547a1286571df3d701174e579fcf19d3bd8086c0423f37117789f305d9670ad28c99674f52cf64211a081d0c6c3096da2c71bf5f5799a7910e6f38104a37a6557c2daef340814a1f830d593773c6cf48d83ea07294b94eb080b85d6970e28f4051d5066db10e961973a626a826aeaf8a06ec0d566b7e0c4ef60f0c5678fcbb5b2ac63f7bed06448a247b3d427b87086d33573fb2d7228c5c34ea6640eefa9564485a79638e9c97c0af84cfee7ce4a739220c8429e067143953d550668dadc84e7bed9ab070a5943390c611d75b1cb12873a37d9850661a0077bfa9ca9b8b263766c149ff0ee4b4adba25eaf7d7f501f362454256bc1269378ef3359a8ed6b960b86621fa3b613eb132122f49f2eb2ceb6832a3991e961cb0e78b742ef4d65e8de3469666fec7c5b874789571c5c99a2c02a053ff7d2fc90076bafe1f267fa81a3990f27ff14f03000af00c59286cb9bb98e204e90190ae2a50edef049ea92a1f785088f94adf6588fb43bb40fbe2324235cc7e168b80264b069f944f503692c949234d5b76bcffabe29ff9064bd7cbed9e00e5b7fdda4312eb801465f127d0ca68832a7f4ed0eaed8f559c1631cd4d34f0dc414d9fcfe849a91e25f3e0ff013a8cffa806ed8e93d08a1e5a757682ca3d26abc869c76f1c79007d559dfe67e78d8af0195808b0e771c71e64b5716fb36309c25025fae6414c28bbdbd4de597a74996c9da974920d59e6f4c2edfe110ff817fd480a5080978048865712058c5fe7b560b12b67f737ea6e2af9242cf07ad0a8a679f26430046adc3e70664cc9c0ee5abcef6d726b4e04176048b795be12851bdb74003a13204119b86864d6535ba095040a85d9781cf4f3480a304e227f787ad538e68f4bab014179e30d3fdef9eff11bcf471fa3a0bc74b5576f302d3a6b499f11f2ef326ac026c98db10e2741413f322228b3cff0f337ba2f294c78ef73f0e877878f8fc7ff6d10bce66ad6284379b80ca89327d4db0bf14e6d8f01b22ab202b716cc07e3c8866d168a5094bac5a495e73868eedc27222e6444f83bcf65acdc3ec89120bb50e8abfc28b78e6d980c775f4849a0e8cada80240bca245e39966e89a0344df8363a7dcc81b201ce9c753ad544e1124e21020d4c62deda9ed9b9d1f2fb7c54ca7ab09f383bef48cfc6848c271302a10fa687f56e00e0a7d093c927b4fdd8f1bedf6288a0e302848a8012f127a79d2d30a06ce17d94aa6f7f8a1e6eb9d0681c3774f614cc6dbcb2a813f925c6306a630572a83ec109d5f533c0584cb421d919
SIG: 33614b7a94f75e036534d76e30147eccdd2a04e00cd4704ab6e807d6a2acc1e1d963b8eee0810d412d9d56e54556302b10730c15abf89c29a027303ea88ae701
TST: 1023
SK: a1ac48aa5ffa3d800819d03b7f62babf291f20904c11a6400e4f45205f103e38
PK: 0854e0340f814985fb122b78729479e3fde855c211cadeae56f0d4dc0828d5fa
MSG: d6f124ed752021c10926972a0c26f3b1838b3c7af247c18009a231ecce964bf6698637833f607dca836f8a606c72ae3cb170174447a2cce583f6e244dbc163e215b9820de7496ffc5b7050c48f2830246678cba4dc5caa07c1458563aa2d10dcb7770ef8fede027dd7f20ddc8cc78c3a2e2e958bd18c0006cf8fb82d44e53e1da7aa80fd1006f3b2300c9b079d8a66f1e4a3f47061f9e2f45dae35dc295204b19460ca5707ab57ce215a24c10faab3fa20bccd101e7a7d70077599f3d6725707552129cad757d6514c1b28997e471f94b0fded8fbbd065dead196d2c07d3dfa7b9fb3bae7680f76621200d099eebebbea0e8957df5b5e204ca3e9e2952b8a30f0a131a6867b1381e394b1b444310f076326656cf9341678008e9525147d8d61ce93d3bf53900cab912663717e0987293833d1902d7fb047b997b86026c467d7bb17cf45796738f7a774ac126764ed4eb45124309f4586260176ba465918d48330a9cc18c4ecea0ddaf38946acc0e361dd40a7e9133ceb50e1c317ea42bd0980a72b8ba3d8a6c7693dd5602f374f2664df4ba56df01e882fca42cb4db621f476c76e1ea9fd105911a74b77952d9914a5ac0f98a900c1b2e1a56c4ea8518a9ee47c4ed14d0bd35eca560319c8ea24755d71a4e030850bc4dc60389f325804021204ccebc25fedbd32edd8d8446aa23ce56a85f779e858d36af7c073c115e341f412c660fab800fe74c50e714ee086e2fbc8d7abbf3e98fb40ca27f1f01a9aadd8cc2275c2dd3f76e4c1d81c4b792daecc9fe66044941b8b2918486dd4acb562a7b58ad8c60c21b83cf48aefa7256a1ed809e669811f484364970bc5695089919bc32d28ea752e8e318ceff467f77ae1977c5ffd79c17c2da8bc7f823dd94398683189945f8b79238a4e815b142b866acbdbcb7aea7f143fffb7cc2b4b54bbf361afda913ad6df1e49dfd6b532642e63f55d893a470d40370665cfb74efd3f59cb0ff6006174ca35f53b97c543e08af4bf5bb75ff9031610652a3f6f2a0cfe97e7a521f3d2a289114ded34772b0e49817bde1cb924ff514e2866a09e3ede0782d2c0c98e6814b8c1e778cf8306348c933adb2e472dba09db954ff49648373395a2f0181958feb1ea2834c99532873db5c88eb5289c77e90015203ef502ac8e1c48fa1a06dafa6519d52dae3c5567570dd2434e671927c66363f783156893f138a84c75664b30ae4275112736d53d4f399ddda3d23067c073f521afba1f7be585513c2cec9c8f08d2a22c3c85392cd2ae50f3928251f86b310c69a0f8c4e853ab3f3e8129b0566ef4bbbe80b8c02c8928a4de56c0d119a45bbf5af1808d488852d8a45beb0d683248a4d65de1526b3d1d2ffc1f22215b608468cbc3bd39514b397fc0db0f113dbe6fce4652e82ff895b2b4387e041d7e4e7bde4694769665e81
SIG: c57e3c091ed24e5e84665bd9bb102db49797df9008f05557fa0d5ad7a295e5e4d2a4716b17f8c91cb12f5abfb1af027fb0411199acc5d285d842a4b65bde4902
TST: 1024
SK: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5
PK: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
MSG: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0
SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03
# Now an additional test with the data from test 1 but using an
# uncompressed public key.
TST: 1025
SK: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
PK: 0455d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7
MSG:
SIG: e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b
# Now an additional test with the data from test 1 but using an
# compressed prefix.
TST: 1
SK: 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
PK: 40d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a
MSG:
SIG: e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b
diff --git a/tests/t-lock.c b/tests/t-lock.c
index 7e5732e0..f5378adf 100644
--- a/tests/t-lock.c
+++ b/tests/t-lock.c
@@ -1,458 +1,458 @@
/* t-lock.c - Check the lock functions
* Copyright (C) 2014 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#if HAVE_PTHREAD
# include <pthread.h>
#endif
#define PGM "t-lock"
#include "t-common.h"
#include "../src/gcrypt-testapi.h"
/* Mingw requires us to include windows.h after winsock2.h which is
included by gcrypt.h. */
#ifdef _WIN32
# include <windows.h>
#endif
#ifdef _WIN32
# define THREAD_RET_TYPE DWORD WINAPI
# define THREAD_RET_VALUE 0
#else
# define THREAD_RET_TYPE void *
# define THREAD_RET_VALUE NULL
#endif
/* Number of threads to run. */
#define N_NONCE_THREADS 8
/* Number of interations. */
#define N_NONCE_ITERATIONS 1000
/* Requested nonce size. */
#define NONCE_SIZE 11
/* This tests works by having a a couple of accountant threads which do
random transactions between accounts and a revision threads which
checks that the balance of all accounts is invariant. The idea for
this check is due to Bruno Haible. */
#define N_ACCOUNT 8
#define ACCOUNT_VALUE 42
static int account[N_ACCOUNT];
/* Number of transactions done by each accountant. */
#define N_TRANSACTIONS 1000
/* Number of accountants to run. */
#define N_ACCOUNTANTS 5
/* Maximum transaction value. A quite low value is used so that we
would get an integer overflow. */
#define MAX_TRANSACTION_VALUE 50
/* Flag to tell the revision thread to finish. */
static volatile int stop_revision_thread;
struct thread_arg_s
{
int no;
};
/* Wrapper functions to access Libgcrypt's internal test lock. */
static void
external_lock_test_init (int line)
{
gpg_error_t err;
err = gcry_control (PRIV_CTL_EXTERNAL_LOCK_TEST, EXTERNAL_LOCK_TEST_INIT);
if (err)
fail ("init lock failed at %d: %s", line, gpg_strerror (err));
}
static void
external_lock_test_lock (int line)
{
gpg_error_t err;
err = gcry_control (PRIV_CTL_EXTERNAL_LOCK_TEST, EXTERNAL_LOCK_TEST_LOCK);
if (err)
fail ("taking lock failed at %d: %s", line, gpg_strerror (err));
}
static void
external_lock_test_unlock (int line)
{
gpg_error_t err;
err = gcry_control (PRIV_CTL_EXTERNAL_LOCK_TEST, EXTERNAL_LOCK_TEST_UNLOCK);
if (err)
fail ("releasing lock failed at %d: %s", line, gpg_strerror (err));
}
static void
external_lock_test_destroy (int line)
{
gpg_error_t err;
err = gcry_control (PRIV_CTL_EXTERNAL_LOCK_TEST, EXTERNAL_LOCK_TEST_DESTROY);
if (err)
fail ("destroying lock failed at %d: %s", line, gpg_strerror (err));
}
/* The nonce thread. We simply request a couple of nonces and
return. */
static THREAD_RET_TYPE
nonce_thread (void *argarg)
{
struct thread_arg_s *arg = argarg;
int i;
char nonce[NONCE_SIZE];
for (i = 0; i < N_NONCE_ITERATIONS; i++)
{
gcry_create_nonce (nonce, sizeof nonce);
if (i && !(i%100))
info ("thread %d created %d nonces so far", arg->no, i);
}
gcry_free (arg);
return THREAD_RET_VALUE;
}
/* To check our locking function we run several threads all accessing
the nonce functions. If this function returns we know that there
are no obvious deadlocks or failed lock initialization. */
static void
check_nonce_lock (void)
{
struct thread_arg_s *arg;
#ifdef _WIN32
HANDLE threads[N_NONCE_THREADS];
int i;
int rc;
for (i=0; i < N_NONCE_THREADS; i++)
{
arg = gcry_xmalloc (sizeof *arg);
arg->no = i;
threads[i] = CreateThread (NULL, 0, nonce_thread, arg, 0, NULL);
if (!threads[i])
die ("error creating nonce thread %d: rc=%d",
i, (int)GetLastError ());
}
for (i=0; i < N_NONCE_THREADS; i++)
{
rc = WaitForSingleObject (threads[i], INFINITE);
if (rc == WAIT_OBJECT_0)
info ("nonce thread %d has terminated", i);
else
fail ("waiting for nonce thread %d failed: %d",
i, (int)GetLastError ());
CloseHandle (threads[i]);
}
#elif HAVE_PTHREAD
pthread_t threads[N_NONCE_THREADS];
int rc, i;
for (i=0; i < N_NONCE_THREADS; i++)
{
arg = gcry_xmalloc (sizeof *arg);
arg->no = i;
pthread_create (&threads[i], NULL, nonce_thread, arg);
}
for (i=0; i < N_NONCE_THREADS; i++)
{
rc = pthread_join (threads[i], NULL);
if (rc)
fail ("pthread_join failed for nonce thread %d: %s",
i, strerror (errno));
else
info ("nonce thread %d has terminated", i);
}
#endif /*!_WIN32*/
}
/* Initialize all accounts. */
static void
init_accounts (void)
{
int i;
for (i=0; i < N_ACCOUNT; i++)
account[i] = ACCOUNT_VALUE;
}
/* Check that the sum of all accounts matches the initial sum. */
static void
check_accounts (void)
{
int i, sum;
sum = 0;
for (i = 0; i < N_ACCOUNT; i++)
sum += account[i];
if (sum != N_ACCOUNT * ACCOUNT_VALUE)
die ("accounts out of balance");
}
static void
print_accounts (void)
{
int i;
for (i=0; i < N_ACCOUNT; i++)
printf ("account %d: %6d\n", i, account[i]);
}
/* Get a a random integer value in the range 0 to HIGH. */
static unsigned int
get_rand (int high)
{
return (unsigned int)(1+(int)((double)(high+1)*rand ()/(RAND_MAX+1.0))) - 1;
}
/* Pick a random account. Note that this function is not
thread-safe. */
static int
pick_account (void)
{
return get_rand (N_ACCOUNT - 1);
}
/* Pick a random value for a transaction. This is not thread-safe. */
static int
pick_value (void)
{
return get_rand (MAX_TRANSACTION_VALUE);
}
/* This is the revision department. */
static THREAD_RET_TYPE
revision_thread (void *arg)
{
(void)arg;
while (!stop_revision_thread)
{
external_lock_test_lock (__LINE__);
check_accounts ();
external_lock_test_unlock (__LINE__);
}
return THREAD_RET_VALUE;
}
/* This is one of our accountants. */
static THREAD_RET_TYPE
accountant_thread (void *arg)
{
int i;
int acc1, acc2;
int value;
(void)arg;
for (i = 0; i < N_TRANSACTIONS; i++)
{
external_lock_test_lock (__LINE__);
acc1 = pick_account ();
acc2 = pick_account ();
value = pick_value ();
account[acc1] += value;
account[acc2] -= value;
external_lock_test_unlock (__LINE__);
}
return THREAD_RET_VALUE;
}
static void
run_test (void)
{
#ifdef _WIN32
HANDLE rthread;
HANDLE athreads[N_ACCOUNTANTS];
int i;
int rc;
external_lock_test_init (__LINE__);
stop_revision_thread = 0;
rthread = CreateThread (NULL, 0, revision_thread, NULL, 0, NULL);
if (!rthread)
die ("error creating revision thread: rc=%d", (int)GetLastError ());
for (i=0; i < N_ACCOUNTANTS; i++)
{
athreads[i] = CreateThread (NULL, 0, accountant_thread, NULL, 0, NULL);
if (!athreads[i])
die ("error creating accountant thread %d: rc=%d",
i, (int)GetLastError ());
}
for (i=0; i < N_ACCOUNTANTS; i++)
{
rc = WaitForSingleObject (athreads[i], INFINITE);
if (rc == WAIT_OBJECT_0)
info ("accountant thread %d has terminated", i);
else
fail ("waiting for accountant thread %d failed: %d",
i, (int)GetLastError ());
CloseHandle (athreads[i]);
}
stop_revision_thread = 1;
rc = WaitForSingleObject (rthread, INFINITE);
if (rc == WAIT_OBJECT_0)
info ("revision thread has terminated");
else
fail ("waiting for revision thread failed: %d", (int)GetLastError ());
CloseHandle (rthread);
#else /*!_WIN32*/
pthread_t rthread;
pthread_t athreads[N_ACCOUNTANTS];
int rc, i;
external_lock_test_init (__LINE__);
stop_revision_thread = 0;
pthread_create (&rthread, NULL, revision_thread, NULL);
for (i=0; i < N_ACCOUNTANTS; i++)
pthread_create (&athreads[i], NULL, accountant_thread, NULL);
for (i=0; i < N_ACCOUNTANTS; i++)
{
rc = pthread_join (athreads[i], NULL);
if (rc)
fail ("pthread_join failed for accountant thread %d: %s",
i, strerror (errno));
else
info ("accountant thread %d has terminated", i);
}
stop_revision_thread = 1;
rc = pthread_join (rthread, NULL);
if (rc)
fail ("pthread_join failed for the revision thread: %s", strerror (errno));
else
info ("revision thread has terminated");
#endif /*!_WIN32*/
external_lock_test_destroy (__LINE__);
}
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, "--help"))
{
puts (
"usage: ./t-lock [options]\n"
"\n"
"Options:\n"
" --verbose Show what is going on\n"
" --debug Flyswatter\n"
);
exit (0);
}
if (!strcmp (*argv, "--verbose"))
{
verbose = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = debug = 1;
argc--; argv++;
}
}
srand (time(NULL)*getpid());
if (debug)
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);
check_nonce_lock ();
init_accounts ();
check_accounts ();
run_test ();
check_accounts ();
/* Run a second time to check deinit code. */
run_test ();
check_accounts ();
if (verbose)
print_accounts ();
return error_count ? 1 : 0;
}
diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c
index f2378bff..8f945d90 100644
--- a/tests/t-mpi-point.c
+++ b/tests/t-mpi-point.c
@@ -1,1347 +1,1347 @@
/* t-mpi-point.c - Tests for mpi point functions
* Copyright (C) 2013 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#define PGM "t-mpi-point"
#include "t-common.h"
static struct
{
const char *desc; /* Description of the curve. */
const char *p; /* Order of the prime field. */
const char *a, *b; /* The coefficients. */
const char *n; /* The order of the base point. */
const char *g_x, *g_y; /* Base point. */
const char *h; /* Cofactor. */
} test_curve[] =
{
{
"NIST P-192",
"0xfffffffffffffffffffffffffffffffeffffffffffffffff",
"0xfffffffffffffffffffffffffffffffefffffffffffffffc",
"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
"0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
"0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
"0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
"0x01"
},
{
"NIST P-224",
"0xffffffffffffffffffffffffffffffff000000000000000000000001",
"0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
"0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
"0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
"0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
"0x01"
},
{
"NIST P-256",
"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
"0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
"0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
"0x01"
},
{
"NIST P-384",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000ffffffff",
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
"ffffffff0000000000000000fffffffc",
"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
"c656398d8a2ed19d2a85c8edd3ec2aef",
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
"581a0db248b0a77aecec196accc52973",
"0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
"5502f25dbf55296c3a545e3872760ab7",
"0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
"0a60b1ce1d7e819d7a431d7c90ea0e5f",
"0x01"
},
{
"NIST P-521",
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
"0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
"9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
"0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
"baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
"62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
"0x01"
},
{
"Ed25519",
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC",
"0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3",
"0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
"0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
"0x6666666666666666666666666666666666666666666666666666666666666658",
"0x08"
},
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
/* A sample public key for NIST P-256. */
static const char sample_p256_q[] =
"04"
"42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E"
"E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
static const char sample_p256_q_x[] =
"42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E";
static const char sample_p256_q_y[] =
"00E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
/* A sample public key for Ed25519. */
static const char sample_ed25519_q[] =
"04"
"55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce"
"1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
static const char sample_ed25519_q_x[] =
"55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce";
static const char sample_ed25519_q_y[] =
"1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
static const char sample_ed25519_q_eddsa[] =
"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
static const char sample_ed25519_d[] =
"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
static void
print_mpi_2 (const char *text, const char *text2, 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%s: [error printing number: %s]\n",
text, text2? text2:"", gpg_strerror (err));
else
{
fprintf (stderr, "%s%s: %s\n", text, text2? text2:"", buf);
gcry_free (buf);
}
}
static void
print_mpi (const char *text, gcry_mpi_t a)
{
print_mpi_2 (text, NULL, a);
}
static void
print_point (const char *text, gcry_mpi_point_t a)
{
gcry_mpi_t x, y, z;
x = gcry_mpi_new (0);
y = gcry_mpi_new (0);
z = gcry_mpi_new (0);
gcry_mpi_point_get (x, y, z, a);
print_mpi_2 (text, ".x", x);
print_mpi_2 (text, ".y", y);
print_mpi_2 (text, ".z", z);
gcry_mpi_release (x);
gcry_mpi_release (y);
gcry_mpi_release (z);
}
static void
print_sexp (const char *prefix, gcry_sexp_t a)
{
char *buf;
size_t size;
if (prefix)
fputs (prefix, stderr);
size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
buf = gcry_xmalloc (size);
gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
fprintf (stderr, "%.*s", (int)size, buf);
gcry_free (buf);
}
static gcry_mpi_t
hex2mpi (const char *string)
{
gpg_error_t err;
gcry_mpi_t val;
err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (err)
die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
return val;
}
/* 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 gcry_mpi_t
hex2mpiopa (const char *string)
{
char *buffer;
size_t buflen;
gcry_mpi_t val;
buffer = hex2buffer (string, &buflen);
if (!buffer)
die ("hex2mpiopa '%s' failed: parser error\n", string);
val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
if (!buffer)
die ("hex2mpiopa '%s' failed: set_opaque error\n", string);
return val;
}
/* Compare A to B, where B is given as a hex string. */
static int
cmp_mpihex (gcry_mpi_t a, const char *b)
{
gcry_mpi_t bval;
int res;
if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
bval = hex2mpiopa (b);
else
bval = hex2mpi (b);
res = gcry_mpi_cmp (a, bval);
gcry_mpi_release (bval);
return res;
}
/* Wrapper to emulate the libgcrypt internal EC context allocation
function. */
static gpg_error_t
ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
{
gpg_error_t err;
gcry_sexp_t sexp;
if (p && a)
err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m)(a %m))", p, a);
else if (p)
err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m))", p);
else if (a)
err = gcry_sexp_build (&sexp, NULL, "(ecdsa (a %m))", a);
else
err = gcry_sexp_build (&sexp, NULL, "(ecdsa)");
if (err)
return err;
err = gcry_mpi_ec_new (r_ctx, sexp, NULL);
gcry_sexp_release (sexp);
return err;
}
static void
set_get_point (void)
{
gcry_mpi_point_t point, point2;
gcry_mpi_t x, y, z;
wherestr = "set_get_point";
info ("checking point setting functions\n");
point = gcry_mpi_point_new (0);
x = gcry_mpi_set_ui (NULL, 17);
y = gcry_mpi_set_ui (NULL, 42);
z = gcry_mpi_set_ui (NULL, 11371);
gcry_mpi_point_get (x, y, z, point);
if (gcry_mpi_cmp_ui (x, 0)
|| gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
fail ("new point not initialized to (0,0,0)\n");
gcry_mpi_point_snatch_get (x, y, z, point);
point = NULL;
if (gcry_mpi_cmp_ui (x, 0)
|| gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
fail ("snatch_get failed\n");
gcry_mpi_release (x);
gcry_mpi_release (y);
gcry_mpi_release (z);
point = gcry_mpi_point_new (0);
x = gcry_mpi_set_ui (NULL, 17);
y = gcry_mpi_set_ui (NULL, 42);
z = gcry_mpi_set_ui (NULL, 11371);
gcry_mpi_point_set (point, x, y, z);
gcry_mpi_set_ui (x, 23);
gcry_mpi_set_ui (y, 24);
gcry_mpi_set_ui (z, 25);
gcry_mpi_point_get (x, y, z, point);
if (gcry_mpi_cmp_ui (x, 17)
|| gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
fail ("point_set/point_get failed\n");
gcry_mpi_point_snatch_set (point, x, y, z);
x = gcry_mpi_new (0);
y = gcry_mpi_new (0);
z = gcry_mpi_new (0);
gcry_mpi_point_get (x, y, z, point);
if (gcry_mpi_cmp_ui (x, 17)
|| gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
fail ("point_snatch_set/point_get failed\n");
point2 = gcry_mpi_point_copy (point);
gcry_mpi_point_get (x, y, z, point2);
if (gcry_mpi_cmp_ui (x, 17)
|| gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
fail ("point_copy failed (1)\n");
gcry_mpi_point_release (point);
gcry_mpi_point_get (x, y, z, point2);
if (gcry_mpi_cmp_ui (x, 17)
|| gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
fail ("point_copy failed (2)\n");
gcry_mpi_point_release (point2);
gcry_mpi_release (x);
gcry_mpi_release (y);
gcry_mpi_release (z);
}
static void
context_alloc (void)
{
gpg_error_t err;
gcry_ctx_t ctx;
gcry_mpi_t p, a;
wherestr = "context_alloc";
info ("checking context functions\n");
p = gcry_mpi_set_ui (NULL, 1);
a = gcry_mpi_set_ui (NULL, 1);
err = ec_p_new (&ctx, p, a);
if (err)
die ("ec_p_new returned an error: %s\n", gpg_strerror (err));
gcry_mpi_release (p);
gcry_mpi_release (a);
gcry_ctx_release (ctx);
p = NULL;
a = gcry_mpi_set_ui (NULL, 0);
err = ec_p_new (&ctx, p, a);
if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
fail ("ec_p_new: bad parameter detection failed (1)\n");
gcry_mpi_release (a);
a = NULL;
err = ec_p_new (&ctx, p, a);
if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
fail ("ec_p_new: bad parameter detection failed (2)\n");
}
static int
get_and_cmp_mpi (const char *name, const char *mpistring, const char *desc,
gcry_ctx_t ctx)
{
gcry_mpi_t mpi;
mpi = gcry_mpi_ec_get_mpi (name, ctx, 1);
if (!mpi)
{
fail ("error getting parameter '%s' of curve '%s'\n", name, desc);
return 1;
}
if (debug)
print_mpi (name, mpi);
if (cmp_mpihex (mpi, mpistring))
{
fail ("parameter '%s' of curve '%s' does not match\n", name, desc);
gcry_mpi_release (mpi);
return 1;
}
gcry_mpi_release (mpi);
return 0;
}
static int
get_and_cmp_point (const char *name,
const char *mpi_x_string, const char *mpi_y_string,
const char *desc, gcry_ctx_t ctx)
{
gcry_mpi_point_t point;
gcry_mpi_t x, y, z;
int result = 0;
point = gcry_mpi_ec_get_point (name, ctx, 1);
if (!point)
{
fail ("error getting point parameter '%s' of curve '%s'\n", name, desc);
return 1;
}
if (debug)
print_point (name, point);
x = gcry_mpi_new (0);
y = gcry_mpi_new (0);
z = gcry_mpi_new (0);
gcry_mpi_point_snatch_get (x, y, z, point);
if (cmp_mpihex (x, mpi_x_string))
{
fail ("x coordinate of '%s' of curve '%s' does not match\n", name, desc);
result = 1;
}
if (cmp_mpihex (y, mpi_y_string))
{
fail ("y coordinate of '%s' of curve '%s' does not match\n", name, desc);
result = 1;
}
if (cmp_mpihex (z, "01"))
{
fail ("z coordinate of '%s' of curve '%s' is not 1\n", name, desc);
result = 1;
}
gcry_mpi_release (x);
gcry_mpi_release (y);
gcry_mpi_release (z);
return result;
}
static void
context_param (void)
{
gpg_error_t err;
int idx;
gcry_ctx_t ctx = NULL;
gcry_mpi_t q, d;
gcry_sexp_t keyparam;
wherestr = "context_param";
info ("checking standard curves\n");
for (idx=0; test_curve[idx].desc; idx++)
{
/* P-192 and Ed25519 are not supported in fips mode */
if (gcry_fips_mode_active())
{
if (!strcmp(test_curve[idx].desc, "NIST P-192")
|| !strcmp(test_curve[idx].desc, "Ed25519"))
{
info ("skipping %s in fips mode\n", test_curve[idx].desc );
continue;
}
}
gcry_ctx_release (ctx);
err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
if (err)
{
fail ("can't create context for curve '%s': %s\n",
test_curve[idx].desc, gpg_strerror (err));
continue;
}
if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
continue;
if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
continue;
if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
continue;
if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
continue;
if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
continue;
if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
continue;
if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
test_curve[idx].desc, ctx))
continue;
if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
continue;
}
info ("checking sample public key (nistp256)\n");
q = hex2mpi (sample_p256_q);
err = gcry_sexp_build (&keyparam, NULL,
"(public-key(ecc(curve %s)(q %m)))",
"NIST P-256", q);
if (err)
die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
gcry_mpi_release (q);
/* We can't call gcry_pk_testkey because it is only implemented for
private keys. */
/* err = gcry_pk_testkey (keyparam); */
/* if (err) */
/* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
/* gpg_strerror (err)); */
gcry_ctx_release (ctx);
err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
if (err)
fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n",
gpg_strerror (err));
else
{
gcry_sexp_t sexp;
get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx);
get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256",
ctx);
/* Delete Q. */
err = gcry_mpi_ec_set_mpi ("q", NULL, ctx);
if (err)
fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err));
if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
fail ("clearing Q for nistp256 did not work\n");
/* Set Q again. */
q = hex2mpi (sample_p256_q);
err = gcry_mpi_ec_set_mpi ("q", q, ctx);
if (err)
fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err));
get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx);
gcry_mpi_release (q);
/* Get as s-expression. */
err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
gcry_sexp_release (sexp);
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
gcry_sexp_release (sexp);
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
gpg_strerror (err));
gcry_sexp_release (sexp);
}
/* Skipping Ed25519 if in FIPS mode (it isn't supported) */
if (gcry_fips_mode_active())
goto cleanup;
info ("checking sample public key (Ed25519)\n");
q = hex2mpi (sample_ed25519_q);
gcry_sexp_release (keyparam);
err = gcry_sexp_build (&keyparam, NULL,
"(public-key(ecc(curve %s)(flags eddsa)(q %m)))",
"Ed25519", q);
if (err)
die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
gcry_mpi_release (q);
/* We can't call gcry_pk_testkey because it is only implemented for
private keys. */
/* err = gcry_pk_testkey (keyparam); */
/* if (err) */
/* fail ("gcry_pk_testkey failed for sample public key: %s\n", */
/* gpg_strerror (err)); */
gcry_ctx_release (ctx);
err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
if (err)
fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
gpg_strerror (err));
else
{
gcry_sexp_t sexp;
get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx);
get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y,
"Ed25519", ctx);
get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx);
/* Set d to see whether Q is correctly re-computed. */
d = hex2mpi (sample_ed25519_d);
err = gcry_mpi_ec_set_mpi ("d", d, ctx);
if (err)
fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
gcry_mpi_release (d);
get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx);
/* Delete Q by setting d and then clearing d. The clearing is
required so that we can check whether Q has been cleared and
because further tests only expect a public key. */
d = hex2mpi (sample_ed25519_d);
err = gcry_mpi_ec_set_mpi ("d", d, ctx);
if (err)
fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
gcry_mpi_release (d);
err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
if (err)
fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err));
if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
fail ("setting d for Ed25519 did not reset Q\n");
/* Set Q again. We need to use an opaque MPI here because
sample_ed25519_q is in uncompressed format which can only be
auto-detected if passed opaque. */
q = hex2mpiopa (sample_ed25519_q);
err = gcry_mpi_ec_set_mpi ("q", q, ctx);
if (err)
fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err));
gcry_mpi_release (q);
get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx);
/* Get as s-expression. */
err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
gcry_sexp_release (sexp);
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
gcry_sexp_release (sexp);
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
gpg_strerror (err));
gcry_sexp_release (sexp);
}
cleanup:
gcry_ctx_release (ctx);
gcry_sexp_release (keyparam);
}
/* Create a new point from (X,Y,Z) given as hex strings. */
gcry_mpi_point_t
make_point (const char *x, const char *y, const char *z)
{
gcry_mpi_point_t point;
point = gcry_mpi_point_new (0);
gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
return point;
}
/* This tests checks that the low-level EC API yields the same result
as using the high level API. The values have been taken from a
test run using the high level API. */
static void
basic_ec_math (void)
{
gpg_error_t err;
gcry_ctx_t ctx;
gcry_mpi_t P, A;
gcry_mpi_point_t G, Q;
gcry_mpi_t d;
gcry_mpi_t x, y, z;
wherestr = "basic_ec_math";
info ("checking basic math functions for EC\n");
P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
"7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
"1");
d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
Q = gcry_mpi_point_new (0);
err = ec_p_new (&ctx, P, A);
if (err)
die ("ec_p_new failed: %s\n", gpg_strerror (err));
x = gcry_mpi_new (0);
y = gcry_mpi_new (0);
z = gcry_mpi_new (0);
{
/* A quick check that multiply by zero works. */
gcry_mpi_t tmp;
tmp = gcry_mpi_new (0);
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))
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");
if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
|| cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
fail ("computed affine coordinates of public key do not match\n");
if (debug)
{
print_mpi ("q.x", x);
print_mpi ("q.y", y);
}
gcry_mpi_release (z);
gcry_mpi_release (y);
gcry_mpi_release (x);
gcry_mpi_point_release (Q);
gcry_mpi_release (d);
gcry_mpi_point_release (G);
gcry_mpi_release (A);
gcry_mpi_release (P);
gcry_ctx_release (ctx);
}
/* This is the same as basic_ec_math but uses more advanced
features. */
static void
basic_ec_math_simplified (void)
{
gpg_error_t err;
gcry_ctx_t ctx;
gcry_mpi_point_t G, Q;
gcry_mpi_t d;
gcry_mpi_t x, y, z;
gcry_sexp_t sexp;
wherestr = "basic_ec_math_simplified";
info ("checking basic math functions for EC (variant)\n");
d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
Q = gcry_mpi_point_new (0);
err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
if (err)
die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
G = gcry_mpi_ec_get_point ("g", ctx, 1);
if (!G)
die ("gcry_mpi_ec_get_point(G) failed\n");
gcry_mpi_ec_mul (Q, d, G, ctx);
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");
if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
|| cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
fail ("computed affine coordinates of public key do not match\n");
if (debug)
{
print_mpi ("q.x", x);
print_mpi ("q.y", y);
}
gcry_mpi_release (z);
gcry_mpi_release (y);
gcry_mpi_release (x);
/* Let us also check whether we can update the context. */
err = gcry_mpi_ec_set_point ("g", G, ctx);
if (err)
die ("gcry_mpi_ec_set_point(G) failed\n");
err = gcry_mpi_ec_set_mpi ("d", d, ctx);
if (err)
die ("gcry_mpi_ec_set_mpi(d) failed\n");
/* FIXME: Below we need to check that the returned S-expression is
as requested. For now we use manual inspection using --debug. */
/* Does get_sexp return the private key? */
err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
gcry_sexp_release (sexp);
/* Does get_sexp return the public key if requested? */
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
gcry_sexp_release (sexp);
/* Does get_sexp return the public key after d has been deleted? */
err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
if (err)
die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
if (err)
fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
else if (debug)
print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
gcry_sexp_release (sexp);
/* Does get_sexp return an error after d has been deleted? */
err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
gpg_strerror (err));
gcry_sexp_release (sexp);
/* Does get_sexp return an error after d and Q have been deleted? */
err = gcry_mpi_ec_set_point ("q", NULL, ctx);
if (err)
die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
gpg_strerror (err));
gcry_sexp_release (sexp);
gcry_mpi_point_release (Q);
gcry_mpi_release (d);
gcry_mpi_point_release (G);
gcry_ctx_release (ctx);
}
/* Check the math used with Twisted Edwards curves. */
static void
twistededwards_math (void)
{
gpg_error_t err;
gcry_ctx_t ctx;
gcry_mpi_point_t G, Q;
gcry_mpi_t k;
gcry_mpi_t w, a, x, y, z, p, n, b, I;
wherestr = "twistededwards_math";
info ("checking basic Twisted Edwards math\n");
err = gcry_mpi_ec_new (&ctx, NULL, "Ed25519");
if (err)
die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
k = hex2mpi
("2D3501E723239632802454EE5DDC406EFB0BDF18486A5BDE9C0390A9C2984004"
"F47252B628C953625B8DEB5DBCB8DA97AA43A1892D11FA83596F42E0D89CB1B6");
G = gcry_mpi_ec_get_point ("g", ctx, 1);
if (!G)
die ("gcry_mpi_ec_get_point(G) failed\n");
Q = gcry_mpi_point_new (0);
w = gcry_mpi_new (0);
a = gcry_mpi_new (0);
x = gcry_mpi_new (0);
y = gcry_mpi_new (0);
z = gcry_mpi_new (0);
I = gcry_mpi_new (0);
p = gcry_mpi_ec_get_mpi ("p", ctx, 1);
n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
b = gcry_mpi_ec_get_mpi ("b", ctx, 1);
/* Check: 2^{p-1} mod p == 1 */
gcry_mpi_sub_ui (a, p, 1);
gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, p);
if (gcry_mpi_cmp_ui (w, 1))
fail ("failed assertion: 2^{p-1} mod p == 1\n");
/* Check: p % 4 == 1 */
gcry_mpi_mod (w, p, GCRYMPI_CONST_FOUR);
if (gcry_mpi_cmp_ui (w, 1))
fail ("failed assertion: p %% 4 == 1\n");
/* Check: 2^{n-1} mod n == 1 */
gcry_mpi_sub_ui (a, n, 1);
gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, n);
if (gcry_mpi_cmp_ui (w, 1))
fail ("failed assertion: 2^{n-1} mod n == 1\n");
/* Check: b^{(p-1)/2} mod p == p-1 */
gcry_mpi_sub_ui (a, p, 1);
gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_TWO, -1);
gcry_mpi_powm (w, b, x, p);
gcry_mpi_abs (w);
if (gcry_mpi_cmp (w, a))
fail ("failed assertion: b^{(p-1)/2} mod p == p-1\n");
/* I := 2^{(p-1)/4} mod p */
gcry_mpi_sub_ui (a, p, 1);
gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_FOUR, -1);
gcry_mpi_powm (I, GCRYMPI_CONST_TWO, x, p);
/* Check: I^2 mod p == p-1 */
gcry_mpi_powm (w, I, GCRYMPI_CONST_TWO, p);
if (gcry_mpi_cmp (w, a))
fail ("failed assertion: I^2 mod p == p-1\n");
/* Check: G is on the curve */
if (!gcry_mpi_ec_curve_point (G, ctx))
fail ("failed assertion: G is on the curve\n");
/* Check: nG == (0,1) */
gcry_mpi_ec_mul (Q, n, G, ctx);
if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
fail ("failed to get affine coordinates\n");
if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 1))
fail ("failed assertion: nG == (0,1)\n");
/* Now two arbitrary point operations taken from the ed25519.py
sample data. */
gcry_mpi_release (a);
a = hex2mpi
("4f71d012df3c371af3ea4dc38385ca5bb7272f90cb1b008b3ed601c76de1d496"
"e30cbf625f0a756a678d8f256d5325595cccc83466f36db18f0178eb9925edd3");
gcry_mpi_ec_mul (Q, a, G, ctx);
if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
fail ("failed to get affine coordinates\n");
if (cmp_mpihex (x, ("157f7361c577aad36f67ed33e38dc7be"
"00014fecc2165ca5cee9eee19fe4d2c1"))
|| cmp_mpihex (y, ("5a69dbeb232276b38f3f5016547bb2a2"
"4025645f0b820e72b8cad4f0a909a092")))
{
fail ("sample point multiply failed:\n");
print_mpi ("r", a);
print_mpi ("Rx", x);
print_mpi ("Ry", y);
}
gcry_mpi_release (a);
a = hex2mpi
("2d3501e723239632802454ee5ddc406efb0bdf18486a5bde9c0390a9c2984004"
"f47252b628c953625b8deb5dbcb8da97aa43a1892d11fa83596f42e0d89cb1b6");
gcry_mpi_ec_mul (Q, a, G, ctx);
if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
fail ("failed to get affine coordinates\n");
if (cmp_mpihex (x, ("6218e309d40065fcc338b3127f468371"
"82324bd01ce6f3cf81ab44e62959c82a"))
|| cmp_mpihex (y, ("5501492265e073d874d9e5b81e7f8784"
"8a826e80cce2869072ac60c3004356e5")))
{
fail ("sample point multiply failed:\n");
print_mpi ("r", a);
print_mpi ("Rx", x);
print_mpi ("Ry", y);
}
gcry_mpi_release (I);
gcry_mpi_release (b);
gcry_mpi_release (n);
gcry_mpi_release (p);
gcry_mpi_release (w);
gcry_mpi_release (a);
gcry_mpi_release (x);
gcry_mpi_release (y);
gcry_mpi_release (z);
gcry_mpi_point_release (Q);
gcry_mpi_point_release (G);
gcry_mpi_release (k);
gcry_ctx_release (ctx);
}
/* Check the point on curve function. */
static void
point_on_curve (void)
{
static struct {
const char *curve;
int oncurve; /* Point below is on the curve. */
const char *qx;
const char *qy;
} t[] = {
{
"NIST P-256", 0,
"015B4F6775D68D4D2E2192C6B8027FC5A3D49957E453CB251155AA3FF5D3EC9974",
"4BC4C87B57A25E1056831208AB5B8F091142F891E9FF19F1E090B030DF1087B3"
}, {
"NIST P-256", 0,
"D22C316E7EBE7B293BD66808E000806F0754398A5D72A4F9BBC21C26EAC0A651",
"3C8DB80CC3CDE5E530D040536E6A58AAB41C33FA70B30896943513FF3690132D"
}, {
"NIST P-256", 0,
"0130F7E7BC52854CA493A0DE87DC4AB3B4343758F2B634F15B10D70DBC0A5A5291",
"86F9CA73C25CE86D54CB21C181AECBB52A5971334FF5040F76CAE9845ED46023"
}, {
"NIST P-256", 1,
"14957B602C7849F28858C7407696F014BC091D6D68C449560B7A38147D6E6A9B",
"A8E09EFEECFE00C797A0848F38B61992D30C61FAB13021E88C8BD3545B3A6C63"
}, {
"NIST P-256", 0,
"923DE4957241DD97780841C76294DB0D4F5DC04C3045081174764D2D32AD2D53",
"01B4B1A2027C02F0F520A3B01E4CE3C668BF481346A74499C5D1044A53E210B600"
}, {
"NIST P-256", 1,
"9021DFAB8B4DAEAADA634AAA26D6E5FFDF8C0476FF5CA31606C870A1B933FB36",
"9AFC65EEB24E46C7B75712EF29A981CB09FAC56E2B81D3ED024748CCAB1CB77E"
}, {
"NIST P-256", 0,
"011529F0B26DE5E0EB2DA4BFB6C149C802CB52EE479DD666553286928A4005E990",
"0EBC63DB2104884456DC0AA81A3F4E99D93B7AE2CD4B1489655EA9BE6289CF9E"
}, {
"NIST P-256", 1,
"216EC5DE8CA989199D31F0DFCD381DCC9270A0785365EC3E34CA347C070A87BE",
"87A88897BA763509ECC1DBE28D9D37F6F4E70E3B99B1CD3C0B934D4190968A6D"
}, {
"NIST P-256", 1,
"7ABAA44ACBC6016FDB52A6F45F6178E65CBFC35F9920D99149CA9999612CE945",
"88F7684BDCDA31EAFB6CAD859F8AB29B5D921D7DB2B34DF7E40CE36235F45B63"
}, {
"NIST P-256", 0,
"E765B4272D211DD0064189B55421FB76BB3A7756364A6CB1627FAED848157A84",
"C13171CFFB243E06B203F0996BBDD16F52292AD11F2DA81106E9C2FD87F4FA0F"
}, {
"NIST P-256", 0,
"EE4999DFC3A1871EE7A592BE26A09BEC9D9B561613EE9EFB6ED42F17985C9CDC",
"8399E967338A7A618336AF70DA67D9CAC1C19267809652F5C5183C8B129E0902"
}, {
"NIST P-256", 0,
"F755D0CF2642A2C7FBACCC8E9E442B8B047A99C6E052B2FA5AB0544B36B4D51C",
"AA080F17657B6565D9A4D94BD260B54D92FEE8DC4A78C4FC9C19209933AF39B0"
} , {
"NIST P-384", 0,
"CBFC7DBEBF15BEAD682549757F9BBA0E3F67669DF13FCE0EBE8024B725B38B00"
"83EC46A8F2FF3203C5C7F8C7E722A5EF",
"0548FE281BEAB18FD1AB86F59B0CA524479A4A81373C83B78AFFD801FAC75922"
"96470753DCF46173C9AA4A8A4C2FBE51"
}, {
"NIST P-384", 0,
"1DC8E054A883DB81EAEDE6C487B26816C927B8196780525A6CA8F675D2557752"
"02CE06CCBE705EA8A38AA2894D4BEEE6",
"010191050E867AFAA96A199FE9C591CF8B853D81486786DA889124881FB39D2F"
"8E0875F4C4BB1E3D0F8535C7A52306FB82"
}, {
"NIST P-384", 1,
"2539FC368CE1D5E464B6C0FBB12D557B712327DB086975255AD7D17F7E7E4F23"
"D719ED4116E2CC907AEB92CF22331A60",
"8843FDBA742CB64323E49CEBE8DD74908CFC9C3AA0015662DFBB7219E92CF32E"
"9FC63F61EF19DE9B3CEA98D163ABF254"
}, {
"NIST P-384", 0,
"0B786DACF400D43575394349EDD9F9CD145FC7EF737A3C5F69B253BE7639DB24"
"EC2F0CA62FF1F90B6515DE356EC2A404",
"225D6B2939CC7F7133F43353946A682C68DAC6BB75EE9CF6BD9A1609FA915692"
"72F4D3A87E88529754E109BB9B61B03B"
}, {
"NIST P-384", 0,
"76C660C9F58CF2051F9F8B06049694AB6FE418009DE6F0A0833BC690CEC06CC2"
"9A440AD51C94CF5BC28817C8C6E2D302",
"012974E5D9E55304ED294AB6C7A3C65B663E67ABC5E6F6C0F6498B519F2F6CA1"
"8306976291F3ADC0B5ABA42DED376EA9A5"
}, {
"NIST P-384", 0,
"23D758B1EDB8E12E9E707C53C131A19D9464B20EE05C99766F5ABDF9F906AD03"
"B958BF28B022E54E320672C4BAD4EEC0",
"01E9E72870C88F4C82A5AB3CC8A3398E8F006BF3EC05FFBB1EFF8AEE88020FEA"
"9E558E9F58ED1D324C9DCBCB4E8F2A5970"
}, {
"NIST P-384", 0,
"D062B96D5A10F715ACF361F99262ABF0F7693A8BB60ECB1DF459CF95750E4293"
"18BCB9FC60499D009F949298F3F9F47B",
"9089C6328E4B39A73D7EE6FAE1A77E48CE354B83BBCE432082C32C8FD6784B86"
"CFE9C552E2E720F5DA5806503D3784CD"
}, {
"NIST P-384", 0,
"2A951D4D6EB35C43D94866280D37365B82441BC84D62CBFF3365CAB1FD0A3E20"
"823CA8F84D2BBF4EA687885437DE7839",
"01CC7D762AFE613F7B5568BC516568A421159C40599E8D52DE10E8F9488931E1"
"69F3656C322DE45C4A70DC6DB9A661E599"
}, {
"NIST P-384", 1,
"A4BAEE6CDAF3AEB69032B3FBA811707C54F5753670DA5173D891547E8CBAEEF3"
"89B92C9A55573A596123415FBFA26991",
"3241EA716583C11C71BB30AF6C5E3A6637956F17ADBBE641BAB52E8539F9FC7B"
"F3B04F46DBFFE08151E0F0950CC70081"
}, {
"NIST P-384", 0,
"5C0E18B0DE3261BCBCFC7B702C2D75CF481336BFBADF420BADC616235C1966AB"
"4C0F876575DDEC1BDB3F3F04061C9AE4",
"E90C78550D1C922F1D8161D8C9C0576E29BD09CA665376FA887D13FA8DF48352"
"D7BBEEFB803F6CC8FC7895E47F348D33"
}, {
"NIST P-384", 1,
"2015864CD50F0A1A50E6401F44191665C19E4AD4B4903EA9EB464E95D1070E36"
"F1D8325E45734D5A0FDD103F4DF6F83E",
"5FB3E9A5C59DD5C5262A8176CB7032A00AE33AED08485884A3E5D68D9EEB990B"
"F26E8D87EC175577E782AD51A6A12C02"
}, {
"NIST P-384", 1,
"56EBF5310EEF5A5D8D001F570A18625383ECD4882B3FC738A69874E7C9D8F89C"
"187BECA23369DFD6C15CC0DA0629958F",
"C1230B349FB662CB762563DB8F9FCB32D5CCA16120681C474D67D279CCA6F6DB"
"73DE6AA96140B5C457B7486E06D318CE"
}, {
"NIST P-521", 0,
"01E4D82EE5CD6DA37080252295EFA273BBBA6952012D0120EAF131E73F1E5024"
"36E3324624471040030E1C345D65490ECEE9B64E03B15B6C7EB69A39C618BAFEED70",
"03EE3A3C88A6933B7B16016BE4CC4E3BF5EA0625CB3DB2604CDCBBD02CABBC90"
"8904D9DB42998F6C5101D4D4318ACFC9643C9CD641F636D1810ED86F1840EA74F3C0"
}, {
"NIST P-521", 0,
"01F3DFCB5433387B6B2E3F74177F4F3D7300F05E1AD49DE112630E27B1C8A437"
"1E742CB020E0039B5477FC897D17332034F9660B3066764EFF5FB440EB8856E782E3",
"02D337616C9D202DC5E290C486F5855CBD6A8470AE62CA96245834CF49257D8D"
"96D4041B15007650DEE668C00DDBF749054256C571F60980AC74D0DBCA7FB96C2F48"
}, {
"NIST P-521", 1,
"822A846606DC9E96452CAC373567A8B57D9ACA15B177F75DD7EF10C635F52CE4"
"EF6ABEEDB90D3F48F50A0C9015A95C955A25C45DE8413DE3BF899B6B1E62CF7CB8",
"0102771B5F3EC8C36838CEC04DCBC28AD1E38C37DAB0EA89B5EE92D21F7A35CE"
"ABC8B155EDC70154D6DFA2E77EC1D8C4A3406A6BD0ECF8F1EE2AC33A02464CB70C97"
}, {
"NIST P-521", 0,
"F733D48467912D1FFE46CF442F27FDD218D190E7B8A829D822DA3B6BAF9B987E"
"5B4BCCE34499248F59EEAF74F63ED15FF73F243C6FC3FD5E5842F6A3BA34C2022D",
"0281AAAD1B7EEBABEB6EC67932CB7E95717AFA3B4CF7A2DB151CD537C419C3A5"
"156ED9160758190B47696CDC15E81BBAD12975283907A571604DB23F702AEA4B38FF"
}, {
"NIST P-521", 0,
"03B1B274175AAEB5907152E5114CCAEADA28A7ADD4A2B1831C3D8302E8596489"
"E2C98B9B8D0CAE98C03BB11E28CE66D4736449758AF58BAFE40EF5A5FA22C9A43117",
"94C5951F81D544E959EDFC5DC1D5F42FE427871D4FB91A43A0B4A6BEA6B35B9E"
"BC5FB444C70BE4FD47B4ED16704F8C86EF019FC47C7FF2271F8B0DDEA9E2D3BCDD"
}, {
"NIST P-521", 1,
"F2248C318055DE37CD706D4FCAF7E7D96737A4A7B6B8067A66DCD58B6B8DFC55"
"90ECE67F6AA67F9C51B57E7B023075F2F42909BF47361CB6881C10F55FB7215B56",
"0162F735CE6A2ADA54CAF96A12D6888C02DE0A74638CF34CE39DABBACA4D651B"
"7E6ED1A65B551B36BAE7BE474BB6E6905ED0E33C7BA2021885027C7C6E40C5613004"
}, {
"NIST P-521", 0,
"9F08E97FEADCF0A391CA1EA4D97B5FE62D3B164593E12027EB967BD6E1FA841A"
"9831158DF164BCAD0BF3ADA96127745E25F349BDDD52EEA1654892B35960C9C023",
"AE2A25F5440F258AFACA6925C4C9F7AEAD3CB67153C4FACB31AC33F58B43A78C"
"B14F682FF726CEE2A6B6F6B481AEEB29A9B3150F02D1CFB764672BA8294C477291"
}, {
"NIST P-521", 0,
"01047B52014748C904980716953206A93F0D01B34CA94A997407FA93FE304F86"
"17BB6E402B2BB8B434C2671ECE953ABE7BADB75713CD9DF950943A33A9A19ACCDABE",
"7433533F098037DEA616337986887D01C5CC8DEC3DC1FDB9CDF7287EF27CC125"
"54FCF3A5E212DF9DAD9F8A3A7173B23FC6E15930704F3AEE1B074BDDB0ED6823E4"
}, {
"NIST P-521", 0,
"01C2A9EBF51592FE6589F618EAADA1697D9B2EC7CE5D48C9E80FC597642B23F1"
"F0EBE953449762BD3F094F57791D9850AFE98BBDA9872BE399B7BDD617860076BB03",
"0B822E27692F63DB8E12C59BB3CCA172B9BBF613CAE5F9D1474186E45E8B26FF"
"962084E1C6BE74821EDBB60941A3B75516F603719563433383812BFEA89EC14B89"
}, {
"NIST P-521", 0,
"99390F342C3F0D46E80C5B65C61E8AA8ACA0B6D4E1352404586364A05D8398E9"
"2BC71A644E8663F0A9B87D0B3ACAEE32F2AB9B321317AD23059D045EBAB91C5D93",
"82FCF93AE4467EB57766F2B150E736636727E7282500CD482DA70D153D195F2B"
"DF9B96D689A0DC1BB9137B41557A33F202F1B71840544CBEFF03072E77E4BB6F0B"
}, {
"NIST P-521", 1,
"018E48E80594FF5496D8CC7DF8A19D6AA18805A4EF4490038AED6A1E9AA18056"
"D0244A97DCF6D132C6804E3F4F369922119544B4C057D783C848FB798B48730A382C",
"01AF510B4F5E1C40BC9C110216D35E7C6D7A2BEE52914FC98258676288449901"
"F27A07EE91DF2D5D79259712906C3E18A990CBF35BCAC41A952820CE2BA8D0220080"
}, {
"NIST P-521", 1,
"ADCEF3539B4BC831DC0AFD173137A4426152058AFBAE06A17FCB89F4DB6E48B5"
"335CB88F8E4DB475A1E390E5656072F06605BFB84CBF9795B7992ECA04A8E10CA1",
"01BCB985AFD6404B9EDA49B6190AAA346BF7D5909CA440C0F7E505C62FAC8635"
"31D3EB7B2AC4DD4F4404E4B12E9D6D3C596179587F3724B1EFFF684CFDB4B21826B9"
}
};
gpg_error_t err;
int tidx;
const char *lastcurve = NULL;
gcry_ctx_t ctx = NULL;
gcry_mpi_t qx = NULL;
gcry_mpi_t qy = NULL;
gcry_mpi_point_t Q;
int oncurve;
wherestr = "point_on_curve";
for (tidx=0; tidx < DIM (t); tidx++)
{
if (!t[tidx].curve)
{
if (!lastcurve || !ctx)
die ("invalid test vectors at idx %d\n", tidx);
}
else if (!ctx || !lastcurve || strcmp (t[tidx].curve, lastcurve))
{
lastcurve = t[tidx].curve;
gcry_ctx_release (ctx);
err = gcry_mpi_ec_new (&ctx, NULL, lastcurve);
if (err)
die ("error creating context for curve %s at idx %d: %s\n",
lastcurve, tidx, gpg_strerror (err));
info ("checking points on curve %s\n", lastcurve);
}
gcry_mpi_release (qx);
gcry_mpi_release (qy);
qx = hex2mpi (t[tidx].qx);
qy = hex2mpi (t[tidx].qy);
Q = gcry_mpi_point_set (NULL, qx, qy, GCRYMPI_CONST_ONE);
if (!Q)
die ("gcry_mpi_point_set(Q) failed at idx %d\n", tidx);
oncurve = gcry_mpi_ec_curve_point (Q, ctx);
if (t[tidx].oncurve && !oncurve)
{
fail ("point expected on curve but not identified as such (i=%d):\n",
tidx);
print_point (" Q", Q);
}
else if (!t[tidx].oncurve && oncurve)
{
fail ("point not expected on curve but identified as such (i=%d):\n",
tidx);
print_point (" Q", Q);
}
gcry_mpi_point_release (Q);
}
gcry_mpi_release (qx);
gcry_mpi_release (qy);
gcry_ctx_release (ctx);
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
else if (argc > 1 && !strcmp (argv[1], "--debug"))
verbose = debug = 1;
if (!gcry_check_version (GCRYPT_VERSION))
die ("version mismatch\n");
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);
set_get_point ();
context_alloc ();
context_param ();
basic_ec_math ();
point_on_curve ();
/* The tests are for P-192 and ed25519 which are not supported in
FIPS mode. */
if (!gcry_fips_mode_active())
{
basic_ec_math_simplified ();
twistededwards_math ();
}
info ("All tests completed. Errors: %d\n", error_count);
return error_count ? 1 : 0;
}
diff --git a/tests/t-secmem.c b/tests/t-secmem.c
index baf013d3..44910c15 100644
--- a/tests/t-secmem.c
+++ b/tests/t-secmem.c
@@ -1,201 +1,201 @@
/* t-secmem.c - Test the secmem memory allocator
* Copyright (C) 2016 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/>.
+ * 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define PGM "t-secmem"
#include "t-common.h"
#include "../src/gcrypt-testapi.h"
#define DEFAULT_PAGE_SIZE 4096
#define MINIMUM_POOL_SIZE 16384
static size_t pool_size;
static size_t chunk_size;
static void
test_secmem (void)
{
void *a[28];
void *b;
int i;
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++)
a[i] = gcry_xmalloc_secure (chunk_size);
/* Allocating another 2k should fail for the default 16k pool. */
b = gcry_malloc_secure (chunk_size*4);
if (b)
fail ("allocation did not fail as expected\n");
for (i=0; i < DIM(a); i++)
xfree (a[i]);
xfree (b);
}
static void
test_secmem_overflow (void)
{
void *a[150];
int i;
memset (a, 0, sizeof a);
/* Allocating 150*512=75k should require more than one overflow buffer. */
for (i=0; i < DIM(a); i++)
{
a[i] = gcry_xmalloc_secure (chunk_size);
if (verbose && !(i %40))
xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
}
if (debug)
xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
if (verbose)
xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
for (i=0; i < DIM(a); i++)
xfree (a[i]);
}
/* This function is called when we ran out of core and there is no way
* to return that error to the caller (xmalloc or mpi allocation). */
static int
outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
{
static int been_here; /* Used to protect against recursive calls. */
(void)opaque;
/* Protect against a second call. */
if (been_here)
return 0; /* Let libgcrypt call its own fatal error handler. */
been_here = 1;
info ("outofcore handler invoked");
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);
die ("stopped");
/*NOTREACHED*/
return 0;
}
int
main (int argc, char **argv)
{
int last_argc = -1;
long int pgsize_val = -1;
size_t pgsize;
#if HAVE_MMAP
# if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
pgsize_val = sysconf (_SC_PAGESIZE);
# elif defined(HAVE_GETPAGESIZE)
pgsize_val = getpagesize ();
# endif
#endif
pgsize = (pgsize_val > 0)? pgsize_val : DEFAULT_PAGE_SIZE;
pool_size = (MINIMUM_POOL_SIZE + pgsize - 1) & ~(pgsize - 1);
chunk_size = pool_size / 32;
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);
}
if (!gcry_check_version (GCRYPT_VERSION))
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);
gcry_set_outofcore_handler (outofcore_handler, NULL);
xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
/* 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);
test_secmem ();
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);
}
info ("All tests completed. Errors: %d\n", error_count);
xgcry_control (GCRYCTL_TERM_SECMEM, 0 , 0);
return !!error_count;
}
diff --git a/tests/t-sexp.c b/tests/t-sexp.c
index 2b33520f..696852c4 100644
--- a/tests/t-sexp.c
+++ b/tests/t-sexp.c
@@ -1,1192 +1,1192 @@
/* t-sexp.c - S-expression regression tests
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
* Copyright (C) 2014 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/>.
+ * License along with this program; if not, see <https://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 <assert.h>
#include "../src/gcrypt-int.h"
#define PGM "t-sexp"
#include "t-common.h"
/* 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 gcry_mpi_t
hex2mpi (const char *string)
{
gpg_error_t err;
gcry_mpi_t val;
err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
if (err)
die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
return val;
}
static gcry_mpi_t
hex2mpiopa (const char *string)
{
char *buffer;
size_t buflen;
gcry_mpi_t val;
buffer = hex2buffer (string, &buflen);
if (!buffer)
die ("hex2mpiopa '%s' failed: parser error\n", string);
val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
if (!buffer)
die ("hex2mpiopa '%s' failed: set_opaque error\n", string);
return val;
}
/* Compare A to B, where B is given as a hex string. */
static int
cmp_mpihex (gcry_mpi_t a, const char *b)
{
gcry_mpi_t bval;
int res;
if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
bval = hex2mpiopa (b);
else
bval = hex2mpi (b);
res = gcry_mpi_cmp (a, bval);
gcry_mpi_release (bval);
return res;
}
/* Compare A to B, where A is a buffer and B a hex string. */
static int
cmp_bufhex (const void *a, size_t alen, const char *b)
{
void *bbuf;
size_t blen;
int res;
if (!a && !b)
return 0;
if (a && !b)
return 1;
if (!a && b)
return -1;
bbuf = hex2buffer (b, &blen);
if (!bbuf)
die ("cmp_bufhex: error converting hex string\n");
if (alen != blen)
return alen < blen? -1 : 1;
res = memcmp (a, bbuf, alen);
xfree (bbuf);
return res;
}
/* fixme: we need better tests */
static void
basic (void)
{
int pass;
gcry_sexp_t sexp;
int idx;
char *secure_buffer;
size_t secure_buffer_len;
const char *string;
static struct {
const char *token;
const char *parm;
} values[] = {
{ "public-key", NULL },
{ "dsa", NULL },
{ "dsa", "p" },
{ "dsa", "y" },
{ "dsa", "q" },
{ "dsa", "g" },
{ NULL }
};
info ("doing some pretty pointless tests\n");
secure_buffer_len = 99;
secure_buffer = gcry_xmalloc_secure (secure_buffer_len);
memset (secure_buffer, 'G', secure_buffer_len);
for (pass=0;;pass++)
{
gcry_mpi_t m;
switch (pass)
{
case 0:
string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
"(q #61626364656667#) (g %m)))");
m = gcry_mpi_set_ui (NULL, 42);
if ( gcry_sexp_build (&sexp, NULL, string, m ) )
{
gcry_mpi_release (m);
fail (" scanning `%s' failed\n", string);
return;
}
gcry_mpi_release (m);
break;
case 1:
string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
"(q %b) (g %m)))");
m = gcry_mpi_set_ui (NULL, 42);
if ( gcry_sexp_build (&sexp, NULL, string,
15, "foo\0\x01\0x02789012345", m) )
{
gcry_mpi_release (m);
fail (" scanning `%s' failed\n", string);
return;
}
gcry_mpi_release (m);
break;
case 2:
string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
"(q %b) (g %m)))");
m = gcry_mpi_set_ui (NULL, 17);
if ( gcry_sexp_build (&sexp, NULL, string,
secure_buffer_len, secure_buffer, m) )
{
gcry_mpi_release (m);
fail (" scanning `%s' failed\n", string);
return;
}
gcry_mpi_release (m);
if (!gcry_is_secure (sexp))
fail ("gcry_sexp_build did not switch to secure memory\n");
break;
case 3:
{
gcry_sexp_t help_sexp;
if (gcry_sexp_new (&help_sexp,
"(foobar-parms (xp #1234#)(xq #03#))", 0, 1))
{
fail (" scanning fixed string failed\n");
return;
}
string = ("(public-key (dsa (p #41424344#) (parm %S) "
"(y dummy)(q %b) (g %m)))");
m = gcry_mpi_set_ui (NULL, 17);
if ( gcry_sexp_build (&sexp, NULL, string, help_sexp,
secure_buffer_len, secure_buffer, m) )
{
gcry_mpi_release (m);
fail (" scanning `%s' failed\n", string);
return;
}
gcry_mpi_release (m);
gcry_sexp_release (help_sexp);
}
break;
default:
return; /* Ready. */
}
/* now find something */
for (idx=0; values[idx].token; idx++)
{
const char *token = values[idx].token;
const char *parm = values[idx].parm;
gcry_sexp_t s1, s2;
gcry_mpi_t a;
const char *p;
size_t n;
s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
if (!s1)
{
fail ("didn't found `%s'\n", token);
continue;
}
p = gcry_sexp_nth_data (s1, 0, &n);
if (!p)
{
gcry_sexp_release (s1);
fail ("no car for `%s'\n", token);
continue;
}
/* info ("car=`%.*s'\n", (int)n, p); */
s2 = gcry_sexp_cdr (s1);
if (!s2)
{
gcry_sexp_release (s1);
fail ("no cdr for `%s'\n", token);
continue;
}
p = gcry_sexp_nth_data (s2, 0, &n);
gcry_sexp_release (s2);
if (p)
{
gcry_sexp_release (s1);
fail ("data at car of `%s'\n", token);
continue;
}
if (parm)
{
s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
gcry_sexp_release (s1);
if (!s2)
{
fail ("didn't found `%s'\n", parm);
continue;
}
p = gcry_sexp_nth_data (s2, 0, &n);
if (!p)
{
gcry_sexp_release (s2);
fail("no car for `%s'\n", parm );
continue;
}
/* info ("car=`%.*s'\n", (int)n, p); */
p = gcry_sexp_nth_data (s2, 1, &n);
if (!p)
{
gcry_sexp_release (s2);
fail("no cdr for `%s'\n", parm );
continue;
}
/* info ("cdr=`%.*s'\n", (int)n, p); */
a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
gcry_sexp_release (s2);
if (!a)
{
fail("failed to cdr the mpi for `%s'\n", parm);
continue;
}
gcry_mpi_release (a);
}
else
gcry_sexp_release (s1);
}
gcry_sexp_release (sexp);
sexp = NULL;
}
gcry_free (secure_buffer);
}
static void
canon_len (void)
{
static struct {
size_t textlen; /* length of the buffer */
size_t expected;/* expected length or 0 on error and then ... */
size_t erroff; /* ... and at this offset */
gcry_error_t errcode; /* ... with this error code */
const char *text;
} values[] = {
{ 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " },
{ 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" },
{ 14, 0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" },
{ 15, 0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" },
{ 2, 0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"},
{ 4, 0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"},
{ 5, 5, 0, GPG_ERR_NO_ERROR, "(1:x)"},
{ 2, 2, 0, GPG_ERR_NO_ERROR, "()"},
{ 4, 2, 0, GPG_ERR_NO_ERROR, "()()"},
{ 4, 4, 0, GPG_ERR_NO_ERROR, "(())"},
{ 3, 0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"},
{ 3, 0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"},
{ 9, 9, 0, GPG_ERR_NO_ERROR, "(3:abc())"},
{ 10, 0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"},
/* fixme: we need much more cases */
{ 0 },
};
int idx;
gcry_error_t errcode;
size_t n, erroff;
info ("checking canoncial length test function\n");
for (idx=0; values[idx].text; idx++)
{
n = gcry_sexp_canon_len ((const unsigned char*)values[idx].text,
values[idx].textlen,
&erroff, &errcode);
if (n && n == values[idx].expected)
; /* success */
else if (!n && !values[idx].expected)
{ /* we expected an error - check that this is the right one */
if (values[idx].erroff != erroff)
fail ("canonical length test %d - wrong error offset %u\n",
idx, (unsigned int)erroff);
if (gcry_err_code (errcode) != values[idx].errcode)
fail ("canonical length test %d - wrong error code %d\n",
idx, errcode);
}
else
fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n",
idx, (unsigned int)n, (unsigned int)erroff, errcode);
}
}
/* Compare SE to the canonical formatted expression in
* (CANON,CANONLEN). This is done by a converting SE to canonical
* format and doing a byte compare. Returns 0 if they match. */
static int
compare_to_canon (gcry_sexp_t se, const unsigned char *canon, size_t canonlen)
{
size_t n, n1;
char *p1;
n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
if (!n1)
{
fail ("get required length in compare_to_canon failed\n");
return -1;
}
p1 = gcry_xmalloc (n1);
n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
if (n1 != n+1)
{
fail ("length mismatch in compare_to_canon detected\n");
xfree (p1);
return -1;
}
if (n1 != canonlen || memcmp (p1, canon, canonlen))
{
xfree (p1);
return -1;
}
xfree (p1);
return 0;
}
static void
back_and_forth_one (int testno, const char *buffer, size_t length)
{
gcry_error_t rc;
gcry_sexp_t se, se1;
unsigned char *canon;
size_t canonlen; /* Including the hidden nul suffix. */
size_t n, n1;
char *p1;
rc = gcry_sexp_new (&se, buffer, length, 1);
if (rc)
{
fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
return;
}
n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
if (!n1)
{
fail ("baf %d: get required length for canon failed\n", testno);
return;
}
p1 = gcry_xmalloc (n1);
n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
if (n1 != n+1) /* sprints adds an extra 0 but does not return it. */
{
fail ("baf %d: length mismatch for canon\n", testno);
return;
}
canonlen = n1;
canon = gcry_malloc (canonlen);
memcpy (canon, p1, canonlen);
rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
if (rc)
{
fail ("baf %d: gcry_sexp_create failed: %s\n",
testno, gpg_strerror (rc));
return;
}
gcry_sexp_release (se1);
/* Again but with memory checking. */
p1 = gcry_xmalloc (n1+2);
*p1 = '\x55';
p1[n1+1] = '\xaa';
n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
{
fail ("baf %d: length mismatch for canon\n", testno);
return;
}
if (*p1 != '\x55' || p1[n1+1] != '\xaa')
fail ("baf %d: memory corrupted (1)\n", testno);
rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
if (rc)
{
fail ("baf %d: gcry_sexp_create failed: %s\n",
testno, gpg_strerror (rc));
return;
}
if (*p1 != '\x55' || p1[n1+1] != '\xaa')
fail ("baf %d: memory corrupted (2)\n", testno);
gcry_sexp_release (se1);
if (*p1 != '\x55' || p1[n1+1] != '\xaa')
fail ("baf %d: memory corrupted (3)\n", testno);
gcry_free (p1);
/* Check converting to advanced format. */
n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, NULL, 0);
if (!n1)
{
fail ("baf %d: get required length for advanced failed\n", testno);
return;
}
p1 = gcry_xmalloc (n1);
n = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, p1, n1);
if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
{
fail ("baf %d: length mismatch for advanced\n", testno);
return;
}
rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
if (rc)
{
fail ("baf %d: gcry_sexp_create failed: %s\n",
testno, gpg_strerror (rc));
return;
}
if (compare_to_canon (se1, canon, canonlen))
{
fail ("baf %d: converting to advanced failed: %s\n",
testno, gpg_strerror (rc));
return;
}
gcry_sexp_release (se1);
/* FIXME: we need a lot more tests */
gcry_sexp_release (se);
xfree (canon);
}
static void
back_and_forth (void)
{
static struct { const char *buf; int len; } tests[] = {
{ "(7:g34:fgh1::2:())", 0 },
{ "(7:g34:fgh1::2:())", 18 },
{
"(protected-private-key \n"
" (rsa \n"
" (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n"
" (e #010001#)\n"
" (protected openpgp-s2k3-sha1-aes-cbc \n"
" (\n"
" (sha1 #C2A5673BD3882405# \"96\")\n"
" #8D08AAF6A9209ED69D71EB7E64D78715#)\n"
" #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
" )\n"
" )\n", 0 },
{ "((sha1 #8B98CBF4A9823CA7# \"2097\") #3B6FC9#)", 0 },
{ "((4:sha18:\x8B\x98\xCB\xF4\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
{ "((4:sha18:\x8B\x98\xCB\x22\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
{ "((sha1 #64652267686970C9# \"2097\") #3B6FC9#)", 0 },
{ "((4:sha18:\x64\x65\x22\x67\x68\xc3\xa4\x71""4:2097)3:\x3B\x6F\xC9)", 0},
{ "((sha1 \"defghäq\" \"2097\") #3B6FC9#)", 0 },
{ "((sha1 \"de\\\"ghäq\" \"2097\") #3B6FC9#)", 0 },
{ NULL, 0 }
};
int idx;
for (idx=0; tests[idx].buf; idx++)
back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
}
static void
check_sscan (void)
{
static struct {
const char *text;
gcry_error_t expected_err;
} values[] = {
/* Bug reported by Olivier L'Heureux 2003-10-07 */
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
GPG_ERR_NO_ERROR },
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
GPG_ERR_SEXP_UNMATCHED_PAREN },
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
GPG_ERR_SEXP_UNMATCHED_PAREN },
{ NULL, 0 }
};
int idx;
gcry_error_t err;
gcry_sexp_t s;
info ("checking gcry_sexp_sscan\n");
for (idx=0; values[idx].text; idx++)
{
err = gcry_sexp_sscan (&s, NULL,
values[idx].text,
strlen (values[idx].text));
if (gpg_err_code (err) != values[idx].expected_err)
fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
gcry_sexp_release (s);
}
}
static void
check_extract_param (void)
{
/* This sample data is a real key but with some parameters of the
public key modified. */
static char sample1[] =
"(key-data"
" (public-key"
" (ecc"
" (curve Ed25519)"
" (p #6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
" (a #EF#)"
" (b #C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
" (g #14"
" 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
" 6666666666666666666666666666666666666666666666666666666666666658#)"
" (n #0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
" (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
"))"
" (private-key"
" (ecc"
" (curve Ed25519)"
" (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
" (a #FF#)"
" (b #D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
" (g #04"
" 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
" 6666666666666666666666666666666666666666666666666666666666666658#)"
" (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
" (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
" (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
")))";
static char sample1_p[] =
"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
static char sample1_px[] =
"6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
static char sample1_a[] = "FF";
static char sample1_ax[] = "EF";
static char sample1_b[] =
"D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
static char sample1_bx[] =
"C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
static char sample1_g[] =
"04"
"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
"6666666666666666666666666666666666666666666666666666666666666658";
static char sample1_gx[] =
"14"
"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
"6666666666666666666666666666666666666666666666666666666666666658";
static char sample1_n[] =
"1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
static char sample1_nx[] =
"0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
static char sample1_q[] =
"30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
static char sample1_qx[] =
"20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
static char sample1_d[] =
"56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
static struct {
const char *sexp_str;
const char *path;
const char *list;
int nparam;
gpg_err_code_t expected_err;
const char *exp_p;
const char *exp_a;
const char *exp_b;
const char *exp_g;
const char *exp_n;
const char *exp_q;
const char *exp_d;
} tests[] = {
{
sample1,
NULL,
"pabgnqd", 6,
GPG_ERR_MISSING_VALUE,
},
{
sample1,
NULL,
"pabgnq", 7,
GPG_ERR_INV_ARG
},
{
sample1,
NULL,
"pab'gnq", 7,
GPG_ERR_SYNTAX
},
{
sample1,
NULL,
"pab''gnq", 7,
GPG_ERR_SYNTAX
},
{
sample1,
NULL,
"pabgnqd", 7,
0,
sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
sample1_qx, sample1_d
},
{
sample1,
NULL,
" pab\tg nq\nd ", 7,
0,
sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
sample1_qx, sample1_d
},
{
sample1,
NULL,
"abg", 3,
0,
sample1_ax, sample1_bx, sample1_gx
},
{
sample1,
NULL,
"ab'g'", 3,
0,
sample1_ax, sample1_bx, sample1_gx
},
{
sample1,
NULL,
"x?abg", 4,
0,
NULL, sample1_ax, sample1_bx, sample1_gx
},
{
sample1,
NULL,
"p?abg", 4,
GPG_ERR_USER_1,
NULL, sample1_ax, sample1_bx, sample1_gx
},
{
sample1,
NULL,
"pax?gnqd", 7,
0,
sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
sample1_qx, sample1_d
},
{
sample1,
"public-key",
"pabgnqd", 7,
GPG_ERR_NO_OBJ, /* d is not in public key. */
sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
sample1_qx, sample1_d
},
{
sample1,
"private-key",
"pabgnqd", 7,
0,
sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
sample1_q, sample1_d
},
{
sample1,
"public-key!ecc",
"pabgnq", 6,
0,
sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
sample1_qx
},
{
sample1,
"public-key!ecc!foo",
"pabgnq", 6,
GPG_ERR_NOT_FOUND
},
{
sample1,
"public-key!!ecc",
"pabgnq", 6,
GPG_ERR_NOT_FOUND
},
{
sample1,
"private-key",
"pa/bgnqd", 7,
0,
sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
sample1_q, sample1_d
},
{
sample1,
"private-key",
"p-a+bgnqd", 7,
0,
sample1_p, "-01", sample1_b, sample1_g, sample1_n,
sample1_q, sample1_d
},
{NULL}
};
int idx, i;
const char *paramstr;
int paramidx;
gpg_error_t err;
gcry_sexp_t sxp;
gcry_mpi_t mpis[7];
gcry_buffer_t ioarray[7];
char iobuffer[200];
info ("checking gcry_sexp_extract_param\n");
for (idx=0; tests[idx].sexp_str; idx++)
{
err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
if (err)
die ("converting string to sexp failed: %s", gpg_strerror (err));
memset (mpis, 0, sizeof mpis);
switch (tests[idx].nparam)
{
case 0:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
NULL);
break;
case 1:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, NULL);
break;
case 2:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, NULL);
break;
case 3:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, mpis+2, NULL);
break;
case 4:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, mpis+2, mpis+3, NULL);
break;
case 5:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
NULL);
break;
case 6:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
mpis+5, NULL);
break;
case 7:
err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
mpis+5, mpis+6, NULL);
break;
default:
die ("test %d: internal error", idx);
}
if (tests[idx].expected_err
&& tests[idx].expected_err != GPG_ERR_USER_1)
{
if (tests[idx].expected_err != gpg_err_code (err))
fail ("gcry_sexp_extract_param test %d failed: "
"expected error '%s' - got '%s'", idx,
gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
}
else if (err)
{
fail ("gcry_sexp_extract_param test %d failed: %s",
idx, gpg_strerror (err));
}
else /* No error - check the extracted values. */
{
for (paramidx=0; paramidx < DIM (mpis); paramidx++)
{
switch (paramidx)
{
case 0: paramstr = tests[idx].exp_p; break;
case 1: paramstr = tests[idx].exp_a; break;
case 2: paramstr = tests[idx].exp_b; break;
case 3: paramstr = tests[idx].exp_g; break;
case 4: paramstr = tests[idx].exp_n; break;
case 5: paramstr = tests[idx].exp_q; break;
case 6: paramstr = tests[idx].exp_d; break;
default:
die ("test %d: internal error: bad param %d",
idx, paramidx);
}
if (tests[idx].expected_err == GPG_ERR_USER_1
&& mpis[paramidx] && !paramstr && paramidx == 0)
; /* Okay Special case error for param 0. */
else if (!mpis[paramidx] && !paramstr)
; /* Okay. */
else if (!mpis[paramidx] && paramstr)
fail ("test %d: value for param %d expected but not returned",
idx, paramidx);
else if (mpis[paramidx] && !paramstr)
fail ("test %d: value for param %d not expected",
idx, paramidx);
else if (cmp_mpihex (mpis[paramidx], paramstr))
{
fail ("test %d: param %d mismatch", idx, paramidx);
gcry_log_debug ("expected: %s\n", paramstr);
gcry_log_debugmpi (" got", mpis[paramidx]);
}
else if (tests[idx].expected_err && paramidx == 0)
fail ("test %d: param %d: expected error '%s' - got 'Success'",
idx, paramidx, gpg_strerror (tests[idx].expected_err));
}
}
for (i=0; i < DIM (mpis); i++)
gcry_mpi_release (mpis[i]);
gcry_sexp_release (sxp);
}
info ("checking gcry_sexp_extract_param/desc\n");
memset (ioarray, 0, sizeof ioarray);
err = gcry_sexp_new (&sxp, sample1, 0, 1);
if (err)
die ("converting string to sexp failed: %s", gpg_strerror (err));
ioarray[1].size = sizeof iobuffer;
ioarray[1].data = iobuffer;
ioarray[1].off = 0;
ioarray[2].size = sizeof iobuffer;
ioarray[2].data = iobuffer;
ioarray[2].off = 50;
assert (ioarray[2].off < sizeof iobuffer);
err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
ioarray+0, ioarray+1, ioarray+2, NULL);
if (err)
fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
else
{
if (!ioarray[0].data)
fail ("gcry_sexp_extract_param/desc failed: no P");
else if (ioarray[0].size != 32)
fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
else if (ioarray[0].len != 32)
fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
else if (ioarray[0].off)
fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
{
fail ("gcry_sexp_extract_param/desc failed: P mismatch");
gcry_log_debug ("expected: %s\n", sample1_p);
gcry_log_debughex (" got", ioarray[0].data, ioarray[0].len);
}
if (!ioarray[1].data)
fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
else if (ioarray[1].size != sizeof iobuffer)
fail ("gcry_sexp_extract_param/desc failed: A size changed");
else if (ioarray[1].off != 0)
fail ("gcry_sexp_extract_param/desc failed: A off changed");
else if (ioarray[1].len != 1)
fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
else if (cmp_bufhex ((char *)ioarray[1].data + ioarray[1].off,
ioarray[1].len, sample1_a))
{
fail ("gcry_sexp_extract_param/desc failed: A mismatch");
gcry_log_debug ("expected: %s\n", sample1_a);
gcry_log_debughex (" got",
(char *)ioarray[1].data + ioarray[1].off,
ioarray[1].len);
}
if (!ioarray[2].data)
fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
else if (ioarray[2].size != sizeof iobuffer)
fail ("gcry_sexp_extract_param/desc failed: B size changed");
else if (ioarray[2].off != 50)
fail ("gcry_sexp_extract_param/desc failed: B off changed");
else if (ioarray[2].len != 32)
fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
else if (cmp_bufhex ((char *)ioarray[2].data + ioarray[2].off,
ioarray[2].len, sample1_b))
{
fail ("gcry_sexp_extract_param/desc failed: B mismatch");
gcry_log_debug ("expected: %s\n", sample1_b);
gcry_log_debughex (" got",
(char *)ioarray[2].data + ioarray[2].off,
ioarray[2].len);
}
xfree (ioarray[0].data);
}
gcry_sexp_release (sxp);
info ("checking gcry_sexp_extract_param long name\n");
memset (ioarray, 0, sizeof ioarray);
memset (mpis, 0, sizeof mpis);
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",
"&'curve'+p",
ioarray+0, mpis+0, NULL);
if (err)
fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
if (!ioarray[0].data)
fail ("gcry_sexp_extract_param long name failed: no curve");
else if (ioarray[0].size != 7)
fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
else if (ioarray[0].len != 7)
fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
else if (ioarray[0].off)
fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
else if (strncmp (ioarray[0].data, "Ed25519", 7))
{
fail ("gcry_sexp_extract_param long name failed: curve mismatch");
gcry_log_debug ("expected: %s\n", "Ed25519");
gcry_log_debug (" got: %.*s\n",
(int)ioarray[0].len, (char*)ioarray[0].data);
}
if (!mpis[0])
fail ("gcry_sexp_extract_param long name failed: p not returned");
else if (cmp_mpihex (mpis[0], sample1_p))
{
fail ("gcry_sexp_extract_param long name failed: p mismatch");
gcry_log_debug ("expected: %s\n", sample1_p);
gcry_log_debugmpi (" got", mpis[0]);
}
gcry_free (ioarray[0].data);
gcry_mpi_release (mpis[0]);
gcry_sexp_release (sxp);
}
/* A test based on bug 1594. */
static void
bug_1594 (void)
{
static char thing[] =
"(signature"
" (public-key"
" (rsa"
" (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
" 6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
" 6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
" C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
" CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
" 54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
" 13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
" A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
" F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
" A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
" E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
" E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
" 923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
" EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
" 2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
" 95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
" 67#)"
" (e #010001#))))";
gcry_sexp_t sig, pubkey, n, n_val;
info ("checking fix for bug 1594\n");
if (gcry_sexp_new (&sig, thing, 0, 1))
die ("scanning fixed string failed\n");
pubkey = gcry_sexp_find_token (sig, "public-key", 0);
gcry_sexp_release (sig);
if (!pubkey)
{
fail ("'public-key' token not found");
return;
}
n = gcry_sexp_find_token (pubkey, "n", 0);
if (!n)
{
fail ("'n' token not found");
gcry_sexp_release (pubkey);
return;
}
n_val = gcry_sexp_nth (n, 1);
/* Bug 1594 would require the following test:
* if (n_val)
* fail ("extracting 1-th of 'n' list did not fail");
* However, we meanwhile modified the S-expression functions to
* behave like Scheme to allow the access of any element of a list.
*/
if (!n_val)
fail ("extracting 1-th of 'n' list failed");
/*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)" */
gcry_sexp_release (n_val);
n_val = gcry_sexp_nth (n, 2);
if (n_val)
fail ("extracting 2-th of 'n' list did not fail");
n_val = gcry_sexp_nth (n, 0);
if (!n_val)
fail ("extracting 0-th of 'n' list failed");
/*gcry_log_debugsxp ("0-th", n_val); => "(n)" */
if (gcry_sexp_nth (n_val, 1))
fail ("extracting 1-th of car of 'n' list did not fail");
gcry_sexp_release (n_val);
gcry_sexp_release (n);
gcry_sexp_release (pubkey);
}
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"))
{
puts (
"usage: " PGM " [options]\n"
"\n"
"Options:\n"
" --verbose Show what is going on\n"
" --debug Flyswatter\n"
);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = debug = 1;
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);
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 ();
return error_count? 1:0;
}

File Metadata

Mime Type
application/octet-stream
Expires
Sun, May 12, 1:25 AM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
HPykZs.924Fx

Event Timeline